| 
									
										
										
										
											2013-04-17 23:09:55 -04:00
										 |  |  | // Copyright 2013 Dolphin Emulator Project
 | 
					
						
							|  |  |  | // Licensed under GPLv2
 | 
					
						
							|  |  |  | // Refer to the license.txt file included.
 | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-17 05:18:15 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include "AudioCommon/AlsaSoundStream.h"
 | 
					
						
							| 
									
										
										
										
											2014-02-19 02:11:52 +01:00
										 |  |  | #include "AudioCommon/AOSoundStream.h"
 | 
					
						
							|  |  |  | #include "AudioCommon/AudioCommon.h"
 | 
					
						
							| 
									
										
										
										
											2014-02-17 05:18:15 -05:00
										 |  |  | #include "AudioCommon/CoreAudioSoundStream.h"
 | 
					
						
							|  |  |  | #include "AudioCommon/Mixer.h"
 | 
					
						
							|  |  |  | #include "AudioCommon/NullSoundStream.h"
 | 
					
						
							|  |  |  | #include "AudioCommon/OpenALStream.h"
 | 
					
						
							|  |  |  | #include "AudioCommon/OpenSLESStream.h"
 | 
					
						
							|  |  |  | #include "AudioCommon/PulseAudioStream.h"
 | 
					
						
							|  |  |  | #include "AudioCommon/XAudio2_7Stream.h"
 | 
					
						
							|  |  |  | #include "AudioCommon/XAudio2Stream.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "Common/FileUtil.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "Core/ConfigManager.h"
 | 
					
						
							|  |  |  | #include "Core/Movie.h"
 | 
					
						
							| 
									
										
										
										
											2013-01-16 20:16:56 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | // This shouldn't be a global, at least not here.
 | 
					
						
							| 
									
										
										
										
											2014-09-29 21:35:57 -04:00
										 |  |  | SoundStream* g_sound_stream = nullptr; | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-15 20:03:31 -04:00
										 |  |  | static bool s_audio_dump_start = false; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-03-29 11:05:44 +01:00
										 |  |  | namespace AudioCommon | 
					
						
							| 
									
										
										
										
											2013-10-29 01:23:17 -04:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2014-12-28 22:03:21 +01:00
										 |  |  | 	static const int AUDIO_VOLUME_MIN = 0; | 
					
						
							|  |  |  | 	static const int AUDIO_VOLUME_MAX = 100; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-08-30 23:36:00 -04:00
										 |  |  | 	SoundStream* InitSoundStream() | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2014-04-10 18:28:19 -07:00
										 |  |  | 		CMixer *mixer = new CMixer(48000); | 
					
						
							| 
									
										
										
										
											2014-03-27 16:00:14 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-03-22 07:27:23 +00:00
										 |  |  | 		// TODO: possible memleak with mixer
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-16 20:16:56 -05:00
										 |  |  | 		std::string backend = SConfig::GetInstance().sBackend; | 
					
						
							| 
									
										
										
										
											2013-10-19 02:27:57 -07:00
										 |  |  | 		if (backend == BACKEND_OPENAL           && OpenALStream::isValid()) | 
					
						
							| 
									
										
										
										
											2014-09-29 21:35:57 -04:00
										 |  |  | 			g_sound_stream = new OpenALStream(mixer); | 
					
						
							| 
									
										
										
										
											2013-10-19 02:27:57 -07:00
										 |  |  | 		else if (backend == BACKEND_NULLSOUND   && NullSound::isValid()) | 
					
						
							| 
									
										
										
										
											2014-09-29 21:35:57 -04:00
										 |  |  | 			g_sound_stream = new NullSound(mixer); | 
					
						
							| 
									
										
										
										
											2013-10-19 02:27:57 -07:00
										 |  |  | 		else if (backend == BACKEND_XAUDIO2) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			if (XAudio2::isValid()) | 
					
						
							| 
									
										
										
										
											2014-09-29 21:35:57 -04:00
										 |  |  | 				g_sound_stream = new XAudio2(mixer); | 
					
						
							| 
									
										
										
										
											2013-10-19 02:27:57 -07:00
										 |  |  | 			else if (XAudio2_7::isValid()) | 
					
						
							| 
									
										
										
										
											2014-09-29 21:35:57 -04:00
										 |  |  | 				g_sound_stream = new XAudio2_7(mixer); | 
					
						
							| 
									
										
										
										
											2013-10-19 02:27:57 -07:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		else if (backend == BACKEND_AOSOUND     && AOSound::isValid()) | 
					
						
							| 
									
										
										
										
											2014-09-29 21:35:57 -04:00
										 |  |  | 			g_sound_stream = new AOSound(mixer); | 
					
						
							| 
									
										
										
										
											2009-12-22 07:26:30 +00:00
										 |  |  | 		else if (backend == BACKEND_ALSA        && AlsaSound::isValid()) | 
					
						
							| 
									
										
										
										
											2014-09-29 21:35:57 -04:00
										 |  |  | 			g_sound_stream = new AlsaSound(mixer); | 
					
						
							| 
									
										
										
										
											2013-10-19 02:27:57 -07:00
										 |  |  | 		else if (backend == BACKEND_COREAUDIO   && CoreAudioSound::isValid()) | 
					
						
							| 
									
										
										
										
											2014-09-29 21:35:57 -04:00
										 |  |  | 			g_sound_stream = new CoreAudioSound(mixer); | 
					
						
							| 
									
										
										
										
											2009-12-22 07:26:30 +00:00
										 |  |  | 		else if (backend == BACKEND_PULSEAUDIO  && PulseAudio::isValid()) | 
					
						
							| 
									
										
										
										
											2014-09-29 21:35:57 -04:00
										 |  |  | 			g_sound_stream = new PulseAudio(mixer); | 
					
						
							| 
									
										
										
										
											2013-02-26 13:49:00 -06:00
										 |  |  | 		else if (backend == BACKEND_OPENSLES && OpenSLESStream::isValid()) | 
					
						
							| 
									
										
										
										
											2014-09-29 21:35:57 -04:00
										 |  |  | 			g_sound_stream = new OpenSLESStream(mixer); | 
					
						
							| 
									
										
										
										
											2013-10-29 01:23:17 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-29 21:35:57 -04:00
										 |  |  | 		if (!g_sound_stream && NullSound::isValid()) | 
					
						
							| 
									
										
										
										
											2013-10-19 02:27:57 -07:00
										 |  |  | 		{ | 
					
						
							|  |  |  | 			WARN_LOG(DSPHLE, "Could not initialize backend %s, using %s instead.", | 
					
						
							|  |  |  | 				backend.c_str(), BACKEND_NULLSOUND); | 
					
						
							| 
									
										
										
										
											2014-09-29 21:35:57 -04:00
										 |  |  | 			g_sound_stream = new NullSound(mixer); | 
					
						
							| 
									
										
										
										
											2013-10-19 02:27:57 -07:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-29 21:35:57 -04:00
										 |  |  | 		if (g_sound_stream) | 
					
						
							| 
									
										
										
										
											2009-09-09 21:26:33 +00:00
										 |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2013-01-16 20:16:56 -05:00
										 |  |  | 			UpdateSoundStream(); | 
					
						
							| 
									
										
										
										
											2014-09-29 21:35:57 -04:00
										 |  |  | 			if (g_sound_stream->Start()) | 
					
						
							| 
									
										
										
										
											2009-09-09 21:26:33 +00:00
										 |  |  | 			{ | 
					
						
							| 
									
										
										
										
											2014-10-15 20:03:31 -04:00
										 |  |  | 				if (SConfig::GetInstance().m_DumpAudio && !s_audio_dump_start) | 
					
						
							|  |  |  | 					StartAudioDump(); | 
					
						
							| 
									
										
										
										
											2011-02-11 18:59:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-29 21:35:57 -04:00
										 |  |  | 				return g_sound_stream; | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2011-01-13 02:05:58 +00:00
										 |  |  | 			PanicAlertT("Could not initialize backend %s.", backend.c_str()); | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2013-10-19 02:27:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-01-13 02:05:58 +00:00
										 |  |  | 		PanicAlertT("Sound backend %s is not valid.", backend.c_str()); | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-29 21:35:57 -04:00
										 |  |  | 		delete g_sound_stream; | 
					
						
							|  |  |  | 		g_sound_stream = nullptr; | 
					
						
							| 
									
										
										
										
											2013-10-19 02:27:57 -07:00
										 |  |  | 		return nullptr; | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-29 01:23:17 -04:00
										 |  |  | 	void ShutdownSoundStream() | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2009-12-22 07:26:30 +00:00
										 |  |  | 		INFO_LOG(DSPHLE, "Shutting down sound stream"); | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-29 21:35:57 -04:00
										 |  |  | 		if (g_sound_stream) | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2014-09-29 21:35:57 -04:00
										 |  |  | 			g_sound_stream->Stop(); | 
					
						
							| 
									
										
										
										
											2014-10-15 20:03:31 -04:00
										 |  |  | 			if (SConfig::GetInstance().m_DumpAudio && s_audio_dump_start) | 
					
						
							|  |  |  | 				StopAudioDump(); | 
					
						
							| 
									
										
										
										
											2014-09-29 21:35:57 -04:00
										 |  |  | 			delete g_sound_stream; | 
					
						
							|  |  |  | 			g_sound_stream = nullptr; | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-29 01:23:17 -04:00
										 |  |  | 		INFO_LOG(DSPHLE, "Done shutting down sound stream"); | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-29 01:23:17 -04:00
										 |  |  | 	std::vector<std::string> GetSoundBackends() | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 		std::vector<std::string> backends; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-13 22:20:33 -06:00
										 |  |  | 		if (NullSound::isValid()) | 
					
						
							| 
									
										
										
										
											2010-11-02 00:16:49 +00:00
										 |  |  | 			backends.push_back(BACKEND_NULLSOUND); | 
					
						
							| 
									
										
										
										
											2013-10-19 02:27:57 -07:00
										 |  |  | 		if (XAudio2_7::isValid() || XAudio2::isValid()) | 
					
						
							| 
									
										
										
										
											2010-11-10 08:28:26 +00:00
										 |  |  | 			backends.push_back(BACKEND_XAUDIO2); | 
					
						
							| 
									
										
										
										
											2013-01-13 22:20:33 -06:00
										 |  |  | 		if (AOSound::isValid()) | 
					
						
							| 
									
										
										
										
											2009-12-22 07:26:30 +00:00
										 |  |  | 			backends.push_back(BACKEND_AOSOUND); | 
					
						
							| 
									
										
										
										
											2013-01-13 22:20:33 -06:00
										 |  |  | 		if (AlsaSound::isValid()) | 
					
						
							| 
									
										
										
										
											2009-09-30 06:49:08 +00:00
										 |  |  | 			backends.push_back(BACKEND_ALSA); | 
					
						
							| 
									
										
										
										
											2013-01-13 22:20:33 -06:00
										 |  |  | 		if (CoreAudioSound::isValid()) | 
					
						
							| 
									
										
										
										
											2009-12-22 07:26:30 +00:00
										 |  |  | 			backends.push_back(BACKEND_COREAUDIO); | 
					
						
							| 
									
										
										
										
											2013-01-13 22:20:33 -06:00
										 |  |  | 		if (PulseAudio::isValid()) | 
					
						
							|  |  |  | 			backends.push_back(BACKEND_PULSEAUDIO); | 
					
						
							| 
									
										
										
										
											2013-01-15 23:14:11 +11:00
										 |  |  | 		if (OpenALStream::isValid()) | 
					
						
							|  |  |  | 			backends.push_back(BACKEND_OPENAL); | 
					
						
							| 
									
										
										
										
											2013-02-26 13:49:00 -06:00
										 |  |  | 		if (OpenSLESStream::isValid()) | 
					
						
							|  |  |  | 			backends.push_back(BACKEND_OPENSLES); | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | 		return backends; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2010-03-24 11:22:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-12-30 20:16:12 -08:00
										 |  |  | 	void PauseAndLock(bool doLock, bool unpauseOnUnlock) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2014-09-29 21:35:57 -04:00
										 |  |  | 		if (g_sound_stream) | 
					
						
							| 
									
										
										
										
											2011-12-30 20:16:12 -08:00
										 |  |  | 		{ | 
					
						
							|  |  |  | 			// audio typically doesn't maintain its own "paused" state
 | 
					
						
							|  |  |  | 			// (that's already handled by the CPU and whatever else being paused)
 | 
					
						
							|  |  |  | 			// so it should be good enough to only lock/unlock here.
 | 
					
						
							| 
									
										
										
										
											2014-09-29 21:35:57 -04:00
										 |  |  | 			CMixer* pMixer = g_sound_stream->GetMixer(); | 
					
						
							| 
									
										
										
										
											2011-12-30 20:16:12 -08:00
										 |  |  | 			if (pMixer) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				std::mutex& csMixing = pMixer->MixerCritical(); | 
					
						
							|  |  |  | 				if (doLock) | 
					
						
							|  |  |  | 					csMixing.lock(); | 
					
						
							|  |  |  | 				else | 
					
						
							|  |  |  | 					csMixing.unlock(); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-12-28 22:03:21 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-16 20:16:56 -05:00
										 |  |  | 	void UpdateSoundStream() | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2014-09-29 21:35:57 -04:00
										 |  |  | 		if (g_sound_stream) | 
					
						
							| 
									
										
										
										
											2013-01-16 20:16:56 -05:00
										 |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2014-12-28 22:03:21 +01:00
										 |  |  | 			int volume = SConfig::GetInstance().m_IsMuted ? 0 : SConfig::GetInstance().m_Volume; | 
					
						
							|  |  |  | 			g_sound_stream->SetVolume(volume); | 
					
						
							| 
									
										
										
										
											2013-01-16 20:16:56 -05:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-03-27 17:56:05 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	void ClearAudioBuffer(bool mute) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2014-09-29 21:35:57 -04:00
										 |  |  | 		if (g_sound_stream) | 
					
						
							|  |  |  | 			g_sound_stream->Clear(mute); | 
					
						
							| 
									
										
										
										
											2014-03-27 17:56:05 -07:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	void SendAIBuffer(short *samples, unsigned int num_samples) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2014-09-29 21:35:57 -04:00
										 |  |  | 		if (!g_sound_stream) | 
					
						
							| 
									
										
										
										
											2014-03-27 17:56:05 -07:00
										 |  |  | 			return; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-15 20:03:31 -04:00
										 |  |  | 		if (SConfig::GetInstance().m_DumpAudio && !s_audio_dump_start) | 
					
						
							|  |  |  | 			StartAudioDump(); | 
					
						
							|  |  |  | 		else if (!SConfig::GetInstance().m_DumpAudio && s_audio_dump_start) | 
					
						
							|  |  |  | 			StopAudioDump(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-29 21:35:57 -04:00
										 |  |  | 		CMixer* pMixer = g_sound_stream->GetMixer(); | 
					
						
							| 
									
										
										
										
											2014-03-27 17:56:05 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if (pMixer && samples) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			pMixer->PushSamples(samples, num_samples); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-29 21:35:57 -04:00
										 |  |  | 		g_sound_stream->Update(); | 
					
						
							| 
									
										
										
										
											2014-03-27 17:56:05 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-10-15 20:03:31 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	void StartAudioDump() | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		std::string audio_file_name_dtk = File::GetUserPath(D_DUMPAUDIO_IDX) + "dtkdump.wav"; | 
					
						
							|  |  |  | 		std::string audio_file_name_dsp = File::GetUserPath(D_DUMPAUDIO_IDX) + "dspdump.wav"; | 
					
						
							|  |  |  | 		File::CreateFullPath(audio_file_name_dtk); | 
					
						
							|  |  |  | 		File::CreateFullPath(audio_file_name_dsp); | 
					
						
							|  |  |  | 		g_sound_stream->GetMixer()->StartLogDTKAudio(audio_file_name_dtk); | 
					
						
							|  |  |  | 		g_sound_stream->GetMixer()->StartLogDSPAudio(audio_file_name_dsp); | 
					
						
							|  |  |  | 		s_audio_dump_start = true; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	void StopAudioDump() | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		g_sound_stream->GetMixer()->StopLogDTKAudio(); | 
					
						
							|  |  |  | 		g_sound_stream->GetMixer()->StopLogDSPAudio(); | 
					
						
							|  |  |  | 		s_audio_dump_start = false; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-12-28 22:03:21 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	void IncreaseVolume(unsigned short offset) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		SConfig::GetInstance().m_IsMuted = false; | 
					
						
							|  |  |  | 		int& currentVolume = SConfig::GetInstance().m_Volume; | 
					
						
							|  |  |  | 		currentVolume += offset; | 
					
						
							|  |  |  | 		if (currentVolume > AUDIO_VOLUME_MAX) | 
					
						
							|  |  |  | 			currentVolume = AUDIO_VOLUME_MAX; | 
					
						
							|  |  |  | 		UpdateSoundStream(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	void DecreaseVolume(unsigned short offset) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		SConfig::GetInstance().m_IsMuted = false; | 
					
						
							|  |  |  | 		int& currentVolume = SConfig::GetInstance().m_Volume; | 
					
						
							|  |  |  | 		currentVolume -= offset; | 
					
						
							|  |  |  | 		if (currentVolume < AUDIO_VOLUME_MIN) | 
					
						
							|  |  |  | 			currentVolume = AUDIO_VOLUME_MIN; | 
					
						
							|  |  |  | 		UpdateSoundStream(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	void ToggleMuteVolume() | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		bool& isMuted = SConfig::GetInstance().m_IsMuted; | 
					
						
							|  |  |  | 		isMuted = !isMuted; | 
					
						
							|  |  |  | 		UpdateSoundStream(); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | } |