| 
									
										
										
										
											2015-05-24 06:55:12 +02:00
										 |  |  | // Copyright 2009 Dolphin Emulator Project
 | 
					
						
							| 
									
										
										
										
											2015-05-18 01:08:10 +02:00
										 |  |  | // Licensed under GPLv2+
 | 
					
						
							| 
									
										
										
										
											2013-04-17 23:09:55 -04:00
										 |  |  | // Refer to the license.txt file included.
 | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-19 02:11:52 +01:00
										 |  |  | #include "AudioCommon/AudioCommon.h"
 | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  | #include "AudioCommon/AOSoundStream.h"
 | 
					
						
							|  |  |  | #include "AudioCommon/AlsaSoundStream.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/XAudio2Stream.h"
 | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  | #include "AudioCommon/XAudio2_7Stream.h"
 | 
					
						
							| 
									
										
										
										
											2015-09-28 10:57:16 -05:00
										 |  |  | #include "Common/Common.h"
 | 
					
						
							| 
									
										
										
										
											2014-02-17 05:18:15 -05:00
										 |  |  | #include "Common/FileUtil.h"
 | 
					
						
							| 
									
										
										
										
											2015-09-26 17:13:07 -04:00
										 |  |  | #include "Common/Logging/Log.h"
 | 
					
						
							| 
									
										
										
										
											2014-02-17 05:18:15 -05:00
										 |  |  | #include "Core/ConfigManager.h"
 | 
					
						
							| 
									
										
										
										
											2013-01-16 20:16:56 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | // This shouldn't be a global, at least not here.
 | 
					
						
							| 
									
										
										
										
											2016-07-31 12:35:08 -04:00
										 |  |  | std::unique_ptr<SoundStream> g_sound_stream; | 
					
						
							| 
									
										
										
										
											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
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  | static const int AUDIO_VOLUME_MIN = 0; | 
					
						
							|  |  |  | static const int AUDIO_VOLUME_MAX = 100; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-31 12:35:08 -04:00
										 |  |  | void InitSoundStream() | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  | { | 
					
						
							|  |  |  |   std::string backend = SConfig::GetInstance().sBackend; | 
					
						
							|  |  |  |   if (backend == BACKEND_OPENAL && OpenALStream::isValid()) | 
					
						
							| 
									
										
										
										
											2016-07-31 12:35:08 -04:00
										 |  |  |     g_sound_stream = std::make_unique<OpenALStream>(); | 
					
						
							| 
									
										
										
										
											2017-02-05 00:57:42 +01:00
										 |  |  |   else if (backend == BACKEND_NULLSOUND) | 
					
						
							| 
									
										
										
										
											2016-07-31 12:35:08 -04:00
										 |  |  |     g_sound_stream = std::make_unique<NullSound>(); | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   else if (backend == BACKEND_XAUDIO2) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     if (XAudio2::isValid()) | 
					
						
							| 
									
										
										
										
											2016-07-31 12:35:08 -04:00
										 |  |  |       g_sound_stream = std::make_unique<XAudio2>(); | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |     else if (XAudio2_7::isValid()) | 
					
						
							| 
									
										
										
										
											2016-07-31 12:35:08 -04:00
										 |  |  |       g_sound_stream = std::make_unique<XAudio2_7>(); | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   } | 
					
						
							|  |  |  |   else if (backend == BACKEND_AOSOUND && AOSound::isValid()) | 
					
						
							| 
									
										
										
										
											2016-07-31 12:35:08 -04:00
										 |  |  |     g_sound_stream = std::make_unique<AOSound>(); | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   else if (backend == BACKEND_ALSA && AlsaSound::isValid()) | 
					
						
							| 
									
										
										
										
											2016-07-31 12:35:08 -04:00
										 |  |  |     g_sound_stream = std::make_unique<AlsaSound>(); | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   else if (backend == BACKEND_COREAUDIO && CoreAudioSound::isValid()) | 
					
						
							| 
									
										
										
										
											2016-07-31 12:35:08 -04:00
										 |  |  |     g_sound_stream = std::make_unique<CoreAudioSound>(); | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   else if (backend == BACKEND_PULSEAUDIO && PulseAudio::isValid()) | 
					
						
							| 
									
										
										
										
											2016-07-31 12:35:08 -04:00
										 |  |  |     g_sound_stream = std::make_unique<PulseAudio>(); | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   else if (backend == BACKEND_OPENSLES && OpenSLESStream::isValid()) | 
					
						
							| 
									
										
										
										
											2016-07-31 12:35:08 -04:00
										 |  |  |     g_sound_stream = std::make_unique<OpenSLESStream>(); | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-05 00:57:42 +01:00
										 |  |  |   if (!g_sound_stream) | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   { | 
					
						
							|  |  |  |     WARN_LOG(AUDIO, "Could not initialize backend %s, using %s instead.", backend.c_str(), | 
					
						
							|  |  |  |              BACKEND_NULLSOUND); | 
					
						
							| 
									
										
										
										
											2016-07-31 12:35:08 -04:00
										 |  |  |     g_sound_stream = std::make_unique<NullSound>(); | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-31 12:35:08 -04:00
										 |  |  |   UpdateSoundStream(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (!g_sound_stream->Start()) | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   { | 
					
						
							| 
									
										
										
										
											2016-07-31 12:35:08 -04:00
										 |  |  |     ERROR_LOG(AUDIO, "Could not start backend %s, using %s instead", backend.c_str(), | 
					
						
							|  |  |  |               BACKEND_NULLSOUND); | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-31 12:35:08 -04:00
										 |  |  |     g_sound_stream = std::make_unique<NullSound>(); | 
					
						
							|  |  |  |     g_sound_stream->Start(); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-31 12:35:08 -04:00
										 |  |  |   if (SConfig::GetInstance().m_DumpAudio && !s_audio_dump_start) | 
					
						
							|  |  |  |     StartAudioDump(); | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void ShutdownSoundStream() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   INFO_LOG(AUDIO, "Shutting down sound stream"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (g_sound_stream) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     g_sound_stream->Stop(); | 
					
						
							| 
									
										
										
										
											2016-07-31 12:35:08 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |     if (SConfig::GetInstance().m_DumpAudio && s_audio_dump_start) | 
					
						
							|  |  |  |       StopAudioDump(); | 
					
						
							| 
									
										
										
										
											2016-07-31 12:35:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     g_sound_stream.reset(); | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   INFO_LOG(AUDIO, "Done shutting down sound stream"); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-05 02:15:38 +01:00
										 |  |  | std::string GetDefaultSoundBackend() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   std::string backend = BACKEND_NULLSOUND; | 
					
						
							|  |  |  | #if defined __linux__
 | 
					
						
							|  |  |  |   if (AlsaSound::isValid()) | 
					
						
							|  |  |  |     backend = BACKEND_ALSA; | 
					
						
							|  |  |  | #elif defined __APPLE__
 | 
					
						
							|  |  |  |   backend = BACKEND_COREAUDIO; | 
					
						
							|  |  |  | #elif defined _WIN32
 | 
					
						
							|  |  |  |   backend = BACKEND_XAUDIO2; | 
					
						
							|  |  |  | #elif defined ANDROID
 | 
					
						
							|  |  |  |   backend = BACKEND_OPENSLES; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |   return backend; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  | std::vector<std::string> GetSoundBackends() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   std::vector<std::string> backends; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-05 00:57:42 +01:00
										 |  |  |   backends.push_back(BACKEND_NULLSOUND); | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   if (XAudio2_7::isValid() || XAudio2::isValid()) | 
					
						
							|  |  |  |     backends.push_back(BACKEND_XAUDIO2); | 
					
						
							|  |  |  |   if (AOSound::isValid()) | 
					
						
							|  |  |  |     backends.push_back(BACKEND_AOSOUND); | 
					
						
							|  |  |  |   if (AlsaSound::isValid()) | 
					
						
							|  |  |  |     backends.push_back(BACKEND_ALSA); | 
					
						
							|  |  |  |   if (CoreAudioSound::isValid()) | 
					
						
							|  |  |  |     backends.push_back(BACKEND_COREAUDIO); | 
					
						
							|  |  |  |   if (PulseAudio::isValid()) | 
					
						
							|  |  |  |     backends.push_back(BACKEND_PULSEAUDIO); | 
					
						
							|  |  |  |   if (OpenALStream::isValid()) | 
					
						
							|  |  |  |     backends.push_back(BACKEND_OPENAL); | 
					
						
							|  |  |  |   if (OpenSLESStream::isValid()) | 
					
						
							|  |  |  |     backends.push_back(BACKEND_OPENSLES); | 
					
						
							|  |  |  |   return backends; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-09 19:18:16 -07:00
										 |  |  | bool SupportsDPL2Decoder(const std::string& backend) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | #ifndef __APPLE__
 | 
					
						
							|  |  |  |   if (backend == BACKEND_OPENAL) | 
					
						
							|  |  |  |     return true; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |   if (backend == BACKEND_PULSEAUDIO) | 
					
						
							|  |  |  |     return true; | 
					
						
							|  |  |  |   return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool SupportsLatencyControl(const std::string& backend) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   return backend == BACKEND_OPENAL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool SupportsVolumeChanges(const std::string& backend) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   // FIXME: this one should ask the backend whether it supports it.
 | 
					
						
							|  |  |  |   //       but getting the backend from string etc. is probably
 | 
					
						
							|  |  |  |   //       too much just to enable/disable a stupid slider...
 | 
					
						
							|  |  |  |   return backend == BACKEND_COREAUDIO || backend == BACKEND_OPENAL || backend == BACKEND_XAUDIO2; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  | void UpdateSoundStream() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   if (g_sound_stream) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     int volume = SConfig::GetInstance().m_IsMuted ? 0 : SConfig::GetInstance().m_Volume; | 
					
						
							|  |  |  |     g_sound_stream->SetVolume(volume); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void ClearAudioBuffer(bool mute) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   if (g_sound_stream) | 
					
						
							|  |  |  |     g_sound_stream->Clear(mute); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-31 19:14:20 -04:00
										 |  |  | void SendAIBuffer(const short* samples, unsigned int num_samples) | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  | { | 
					
						
							|  |  |  |   if (!g_sound_stream) | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (SConfig::GetInstance().m_DumpAudio && !s_audio_dump_start) | 
					
						
							|  |  |  |     StartAudioDump(); | 
					
						
							|  |  |  |   else if (!SConfig::GetInstance().m_DumpAudio && s_audio_dump_start) | 
					
						
							|  |  |  |     StopAudioDump(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   CMixer* pMixer = g_sound_stream->GetMixer(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (pMixer && samples) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     pMixer->PushSamples(samples, num_samples); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   g_sound_stream->Update(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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
										 |  |  | } |