| 
									
										
										
										
											2009-07-28 21:32:10 +00:00
										 |  |  | // Copyright (C) 2003 Dolphin Project.
 | 
					
						
							| 
									
										
										
										
											2008-12-08 05:25:12 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | // This program is free software: you can redistribute it and/or modify
 | 
					
						
							|  |  |  | // it under the terms of the GNU General Public License as published by
 | 
					
						
							|  |  |  | // the Free Software Foundation, version 2.0.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // This program is distributed in the hope that it will be useful,
 | 
					
						
							|  |  |  | // but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
					
						
							|  |  |  | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
					
						
							|  |  |  | // GNU General Public License 2.0 for more details.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // A copy of the GPL 2.0 should have been included with the program.
 | 
					
						
							|  |  |  | // If not, see http://www.gnu.org/licenses/
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Official SVN repository and contact information can be found at
 | 
					
						
							|  |  |  | // http://code.google.com/p/dolphin-emu/
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-17 14:28:09 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-23 15:34:14 +00:00
										 |  |  | #include "Atomic.h"
 | 
					
						
							| 
									
										
										
										
											2008-12-08 05:25:12 +00:00
										 |  |  | #include "Mixer.h"
 | 
					
						
							| 
									
										
										
										
											2009-03-26 09:29:14 +00:00
										 |  |  | #include "AudioCommon.h"
 | 
					
						
							| 
									
										
										
										
											2008-12-08 05:25:12 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-23 15:34:14 +00:00
										 |  |  | // Executed from sound stream thread
 | 
					
						
							|  |  |  | unsigned int CMixer::Mix(short* samples, unsigned int numSamples) | 
					
						
							| 
									
										
										
										
											2008-12-08 05:25:12 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-12-23 15:34:14 +00:00
										 |  |  | 	if (!samples) | 
					
						
							| 
									
										
										
										
											2009-06-12 14:40:50 +00:00
										 |  |  | 		return 0; | 
					
						
							| 
									
										
										
										
											2008-12-08 05:25:12 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-23 15:34:14 +00:00
										 |  |  | 	if (g_dspInitialize.pEmulatorState) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2009-01-20 18:42:01 +00:00
										 |  |  | 		if (*g_dspInitialize.pEmulatorState != 0) | 
					
						
							| 
									
										
										
										
											2009-12-23 15:34:14 +00:00
										 |  |  | 		{ | 
					
						
							|  |  |  | 			// Silence
 | 
					
						
							|  |  |  | 			memset(samples, 0, numSamples * 4); | 
					
						
							|  |  |  | 			return numSamples; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2009-03-30 09:55:50 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-23 15:34:14 +00:00
										 |  |  | 	unsigned int numLeft = Common::AtomicLoad(m_numSamples); | 
					
						
							|  |  |  | 	numLeft = (numLeft > numSamples) ? numSamples : numLeft; | 
					
						
							| 
									
										
										
										
											2009-06-12 14:40:50 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-23 15:34:14 +00:00
										 |  |  | 	// Do re-sampling if needed
 | 
					
						
							| 
									
										
										
										
											2009-12-25 11:59:04 +00:00
										 |  |  | 	if (m_sampleRate == 32000) | 
					
						
							| 
									
										
										
										
											2009-06-12 14:40:50 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2009-12-23 15:34:14 +00:00
										 |  |  | 		for (unsigned int i = 0; i < numLeft * 2; i++) | 
					
						
							|  |  |  | 			samples[i] = Common::swap16(m_buffer[(m_indexR + i) & INDEX_MASK]); | 
					
						
							|  |  |  | 		m_indexR += numLeft * 2; | 
					
						
							| 
									
										
										
										
											2008-12-08 05:25:12 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-12-25 11:59:04 +00:00
										 |  |  | 	else | 
					
						
							| 
									
										
										
										
											2009-12-23 15:34:14 +00:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 		// AyuanX: Up-sampling is not implemented yet
 | 
					
						
							|  |  |  | 		PanicAlert("Mixer: Up-sampling is not implemented yet!"); | 
					
						
							| 
									
										
										
										
											2009-12-22 07:26:30 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  | 	static int PV1l=0,PV2l=0,PV3l=0,PV4l=0; | 
					
						
							|  |  |  | 	static int PV1r=0,PV2r=0,PV3r=0,PV4r=0; | 
					
						
							|  |  |  | 	static int acc=0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-27 11:06:52 +00:00
										 |  |  | 	while (num_stereo_samples) { | 
					
						
							| 
									
										
										
										
											2009-03-28 14:08:06 +00:00
										 |  |  | 		acc += core_sample_rate; | 
					
						
							| 
									
										
										
										
											2009-03-27 11:06:52 +00:00
										 |  |  | 		while (num_stereo_samples && (acc >= 48000)) { | 
					
						
							|  |  |  | 			PV4l=PV3l; | 
					
						
							|  |  |  | 			PV3l=PV2l; | 
					
						
							|  |  |  | 			PV2l=PV1l; | 
					
						
							|  |  |  | 			PV1l=*(samples++); //32bit processing
 | 
					
						
							|  |  |  | 			PV4r=PV3r; | 
					
						
							|  |  |  | 			PV3r=PV2r; | 
					
						
							|  |  |  | 			PV2r=PV1r; | 
					
						
							|  |  |  | 			PV1r=*(samples++); //32bit processing
 | 
					
						
							|  |  |  | 			num_stereo_samples--; | 
					
						
							|  |  |  | 			acc-=48000; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		// defaults to nearest
 | 
					
						
							|  |  |  | 		s32 DataL = PV1l; | 
					
						
							|  |  |  | 		s32 DataR = PV1r; | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		if (m_mode == 1) { //linear
 | 
					
						
							|  |  |  |          | 
					
						
							|  |  |  | 			DataL = PV1l + ((PV2l - PV1l)*acc)/48000; | 
					
						
							|  |  |  | 			DataR = PV1r + ((PV2r - PV1r)*acc)/48000; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else if (m_mode == 2) {//cubic
 | 
					
						
							|  |  |  | 			s32 a0l = PV1l - PV2l - PV4l + PV3l; | 
					
						
							|  |  |  | 			s32 a0r = PV1r - PV2r - PV4r + PV3r; | 
					
						
							|  |  |  | 			s32 a1l = PV4l - PV3l - a0l; | 
					
						
							|  |  |  | 			s32 a1r = PV4r - PV3r - a0r; | 
					
						
							|  |  |  | 			s32 a2l = PV1l - PV4l; | 
					
						
							|  |  |  | 			s32 a2r = PV1r - PV4r; | 
					
						
							|  |  |  | 			s32 a3l = PV2l; | 
					
						
							|  |  |  | 			s32 a3r = PV2r; | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 			s32 t0l = ((a0l    )*acc)/48000; | 
					
						
							|  |  |  | 			s32 t0r = ((a0r    )*acc)/48000; | 
					
						
							|  |  |  | 			s32 t1l = ((t0l+a1l)*acc)/48000; | 
					
						
							|  |  |  | 			s32 t1r = ((t0r+a1r)*acc)/48000; | 
					
						
							|  |  |  | 			s32 t2l = ((t1l+a2l)*acc)/48000; | 
					
						
							|  |  |  | 			s32 t2r = ((t1r+a2r)*acc)/48000; | 
					
						
							|  |  |  | 			s32 t3l = ((t2l+a3l)); | 
					
						
							|  |  |  | 			s32 t3r = ((t2r+a3r)); | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 			DataL = t3l; | 
					
						
							|  |  |  | 			DataR = t3r; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		int l = DataL, r = DataR; | 
					
						
							|  |  |  | 		if (l < -32767) l = -32767; | 
					
						
							|  |  |  | 		if (r < -32767) r = -32767; | 
					
						
							|  |  |  | 		if (l > 32767) l = 32767; | 
					
						
							|  |  |  | 		if (r > 32767) r = 32767; | 
					
						
							|  |  |  | 		sample_queue.push(l); | 
					
						
							|  |  |  | 		sample_queue.push(r); | 
					
						
							|  |  |  | 		m_queueSize += 2; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-12-22 07:26:30 +00:00
										 |  |  | */ | 
					
						
							| 
									
										
										
										
											2009-12-23 15:34:14 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-12-22 07:26:30 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-23 15:34:14 +00:00
										 |  |  | 	// Padding
 | 
					
						
							|  |  |  | 	if (numSamples > numLeft) | 
					
						
							|  |  |  | 		memset(&samples[numLeft * 2], 0, (numSamples - numLeft) * 4); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-25 11:59:04 +00:00
										 |  |  | 	// Add the DSPHLE sound, re-sampling is done inside
 | 
					
						
							|  |  |  | 	Premix(samples, numSamples); | 
					
						
							| 
									
										
										
										
											2009-12-23 15:34:14 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Add the DTK Music
 | 
					
						
							|  |  |  | 	if (m_EnableDTKMusic) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		// Re-sampling is done inside
 | 
					
						
							|  |  |  | 		g_dspInitialize.pGetAudioStreaming(samples, numSamples, m_sampleRate); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-25 11:59:04 +00:00
										 |  |  | 	Common::AtomicAdd(m_numSamples, -(s32)numLeft); | 
					
						
							| 
									
										
										
										
											2009-12-23 15:34:14 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return numSamples; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-25 11:59:04 +00:00
										 |  |  | void CMixer::PushSamples(short *samples, unsigned int num_samples) | 
					
						
							| 
									
										
										
										
											2009-12-23 15:34:14 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	// The auto throttle function. This loop will put a ceiling on the CPU MHz.
 | 
					
						
							|  |  |  | 	if (m_throttle) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		while (Common::AtomicLoad(m_numSamples) >= MAX_SAMPLES - RESERVED_SAMPLES) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			if (g_dspInitialize.pEmulatorState) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				if (*g_dspInitialize.pEmulatorState != 0)  | 
					
						
							|  |  |  | 					break; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2009-12-25 11:59:04 +00:00
										 |  |  | 			// Shortcut key for Throttle Skipping
 | 
					
						
							|  |  |  | 			#ifdef _WIN32
 | 
					
						
							|  |  |  | 			if (GetAsyncKeyState(VK_TAB)) break;; | 
					
						
							|  |  |  | 			#endif
 | 
					
						
							| 
									
										
										
										
											2009-12-23 15:34:14 +00:00
										 |  |  | 			SLEEP(1); | 
					
						
							| 
									
										
										
										
											2009-12-25 11:59:04 +00:00
										 |  |  | 			soundStream->Update(); | 
					
						
							| 
									
										
										
										
											2009-12-23 15:34:14 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Check if we have enough free space
 | 
					
						
							|  |  |  | 	if (num_samples > MAX_SAMPLES - Common::AtomicLoad(m_numSamples)) | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// AyuanX: Actual re-sampling work has been moved to sound thread
 | 
					
						
							| 
									
										
										
										
											2009-12-25 11:59:04 +00:00
										 |  |  | 	// to alleviate the workload on main thread
 | 
					
						
							| 
									
										
										
										
											2009-12-23 15:34:14 +00:00
										 |  |  | 	// and we simply store raw data here to make fast mem copy
 | 
					
						
							|  |  |  | 	int over_bytes = num_samples * 4 - (MAX_SAMPLES * 2 - (m_indexW & INDEX_MASK)) * sizeof(short); | 
					
						
							|  |  |  | 	if (over_bytes > 0) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		memcpy(&m_buffer[m_indexW & INDEX_MASK], samples, num_samples * 4 - over_bytes); | 
					
						
							|  |  |  | 		memcpy(&m_buffer[0], samples + (num_samples * 4 - over_bytes) / sizeof(short), over_bytes); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		memcpy(&m_buffer[m_indexW & INDEX_MASK], samples, num_samples * 4); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	m_indexW += num_samples * 2; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-25 11:59:04 +00:00
										 |  |  | 	 if (m_sampleRate != 32000) | 
					
						
							| 
									
										
										
										
											2009-12-23 15:34:14 +00:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 		PanicAlert("Mixer: Up-sampling is not implemented yet!"); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	Common::AtomicAdd(m_numSamples, num_samples); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return; | 
					
						
							| 
									
										
										
										
											2008-12-08 05:25:12 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2009-12-20 02:23:26 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-23 15:34:14 +00:00
										 |  |  | unsigned int CMixer::GetNumSamples() | 
					
						
							| 
									
										
										
										
											2009-12-20 02:23:26 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-12-23 15:34:14 +00:00
										 |  |  | 	return Common::AtomicLoad(m_numSamples); | 
					
						
							| 
									
										
										
										
											2009-12-20 02:23:26 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 |