| 
									
										
										
										
											2009-07-28 21:32:10 +00:00
										 |  |  | // Copyright (C) 2003 Dolphin Project.
 | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +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/
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "aldlist.h"
 | 
					
						
							|  |  |  | #include "OpenALStream.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined HAVE_OPENAL && HAVE_OPENAL
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-20 13:54:14 +00:00
										 |  |  | //
 | 
					
						
							|  |  |  | // AyuanX: Spec says OpenAL1.1 is thread safe already
 | 
					
						
							|  |  |  | //
 | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | bool OpenALStream::Start() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	ALDeviceList *pDeviceList = NULL; | 
					
						
							|  |  |  | 	ALCcontext *pContext = NULL; | 
					
						
							|  |  |  | 	ALCdevice *pDevice = NULL; | 
					
						
							|  |  |  | 	bool bReturn = false; | 
					
						
							| 
									
										
										
										
											2009-12-18 19:52:04 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	soundSyncEvent.Init(); | 
					
						
							| 
									
										
										
										
											2009-12-10 21:00:52 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | 	pDeviceList = new ALDeviceList(); | 
					
						
							|  |  |  | 	if ((pDeviceList) && (pDeviceList->GetNumDevices())) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2010-12-07 22:38:03 +00:00
										 |  |  | 		char *defDevName = pDeviceList-> \ | 
					
						
							|  |  |  | 			GetDeviceName(pDeviceList->GetDefaultDevice()); | 
					
						
							|  |  |  | 		pDevice = alcOpenDevice(defDevName); | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | 		if (pDevice) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			pContext = alcCreateContext(pDevice, NULL); | 
					
						
							|  |  |  | 			if (pContext) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				alcMakeContextCurrent(pContext); | 
					
						
							| 
									
										
										
										
											2011-01-27 20:47:58 +00:00
										 |  |  | 				thread = std::thread(OpenALStream::ThreadFunc, this); | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | 				bReturn = true; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			else | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				alcCloseDevice(pDevice); | 
					
						
							| 
									
										
										
										
											2011-01-13 02:05:58 +00:00
										 |  |  | 				PanicAlertT("OpenAL: can't create context " | 
					
						
							| 
									
										
										
										
											2010-12-07 22:38:03 +00:00
										 |  |  | 					"for device %s", defDevName); | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2009-12-20 02:23:26 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2011-01-13 02:05:58 +00:00
										 |  |  | 			PanicAlertT("OpenAL: can't open device %s", defDevName); | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		delete pDeviceList; | 
					
						
							| 
									
										
										
										
											2009-12-20 02:23:26 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2011-01-13 02:05:58 +00:00
										 |  |  | 		PanicAlertT("OpenAL: can't find sound devices"); | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return bReturn; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void OpenALStream::Stop() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	threadData = 1; | 
					
						
							|  |  |  | 	// kick the thread if it's waiting
 | 
					
						
							|  |  |  | 	soundSyncEvent.Set(); | 
					
						
							| 
									
										
										
										
											2009-12-18 19:52:04 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-01-27 20:47:58 +00:00
										 |  |  | 	thread.join(); | 
					
						
							| 
									
										
										
										
											2009-12-18 19:52:04 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-20 02:23:26 +00:00
										 |  |  | 	alSourceStop(uiSource); | 
					
						
							|  |  |  | 	alSourcei(uiSource, AL_BUFFER, 0); | 
					
						
							| 
									
										
										
										
											2009-12-18 19:52:04 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Clean up buffers and sources
 | 
					
						
							| 
									
										
										
										
											2009-12-20 02:23:26 +00:00
										 |  |  | 	alDeleteSources(1, &uiSource); | 
					
						
							| 
									
										
										
										
											2009-12-20 13:54:14 +00:00
										 |  |  | 	uiSource = 0; | 
					
						
							| 
									
										
										
										
											2009-12-20 02:23:26 +00:00
										 |  |  | 	alDeleteBuffers(OAL_NUM_BUFFERS, uiBuffers); | 
					
						
							| 
									
										
										
										
											2009-12-18 19:52:04 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-20 02:23:26 +00:00
										 |  |  | 	ALCcontext *pContext = alcGetCurrentContext(); | 
					
						
							|  |  |  | 	ALCdevice *pDevice = alcGetContextsDevice(pContext); | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	alcMakeContextCurrent(NULL); | 
					
						
							|  |  |  | 	alcDestroyContext(pContext); | 
					
						
							|  |  |  | 	alcCloseDevice(pDevice); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	soundSyncEvent.Shutdown(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-20 13:54:14 +00:00
										 |  |  | void OpenALStream::SetVolume(int volume) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	fVolume = (float)volume / 100.0f; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (uiSource) | 
					
						
							|  |  |  | 		alSourcef(uiSource, AL_GAIN, fVolume);  | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | void OpenALStream::Update() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2009-12-20 02:23:26 +00:00
										 |  |  | 	soundSyncEvent.Set(); | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-13 11:51:29 +00:00
										 |  |  | void OpenALStream::Clear(bool mute) | 
					
						
							| 
									
										
										
										
											2009-11-07 20:01:39 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-12-13 11:51:29 +00:00
										 |  |  | 	m_muted = mute; | 
					
						
							| 
									
										
										
										
											2009-12-18 19:52:04 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-13 11:51:29 +00:00
										 |  |  | 	if(m_muted) | 
					
						
							| 
									
										
										
										
											2009-12-12 22:30:53 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2009-12-20 02:23:26 +00:00
										 |  |  | 		alSourceStop(uiSource); | 
					
						
							| 
									
										
										
										
											2009-12-12 22:30:53 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2009-12-20 02:23:26 +00:00
										 |  |  | 		alSourcePlay(uiSource); | 
					
						
							| 
									
										
										
										
											2009-12-12 22:30:53 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-11-07 20:01:39 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-01-27 20:47:58 +00:00
										 |  |  | void OpenALStream::ThreadFunc(OpenALStream* alstream) | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2011-01-27 20:47:58 +00:00
										 |  |  | 	alstream->SoundLoop(); | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void OpenALStream::SoundLoop() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	ALenum err; | 
					
						
							|  |  |  | 	u32 ulFrequency = m_mixer->GetSampleRate(); | 
					
						
							| 
									
										
										
										
											2009-12-20 02:23:26 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	memset(uiBuffers, 0, OAL_NUM_BUFFERS * sizeof(ALuint)); | 
					
						
							|  |  |  | 	uiSource = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | 	// Generate some AL Buffers for streaming
 | 
					
						
							| 
									
										
										
										
											2009-12-20 02:23:26 +00:00
										 |  |  | 	alGenBuffers(OAL_NUM_BUFFERS, (ALuint *)uiBuffers); | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | 	// Generate a Source to playback the Buffers
 | 
					
						
							|  |  |  | 	alGenSources(1, &uiSource); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-23 15:34:14 +00:00
										 |  |  | 	// Short Silence
 | 
					
						
							|  |  |  | 	memset(realtimeBuffer, 0, OAL_MAX_SAMPLES * 4); | 
					
						
							| 
									
										
										
										
											2009-12-20 02:23:26 +00:00
										 |  |  | 	for (int i = 0; i < OAL_NUM_BUFFERS; i++) | 
					
						
							| 
									
										
										
										
											2009-12-23 15:34:14 +00:00
										 |  |  | 		alBufferData(uiBuffers[i], AL_FORMAT_STEREO16, realtimeBuffer, OAL_MAX_SAMPLES, ulFrequency); | 
					
						
							| 
									
										
										
										
											2009-12-20 02:23:26 +00:00
										 |  |  | 	alSourceQueueBuffers(uiSource, OAL_NUM_BUFFERS, uiBuffers); | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | 	alSourcePlay(uiSource); | 
					
						
							| 
									
										
										
										
											2010-02-07 19:36:29 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	// Set the default sound volume as saved in the config file.
 | 
					
						
							|  |  |  | 	alSourcef(uiSource, AL_GAIN, fVolume);  | 
					
						
							| 
									
										
										
										
											2009-12-23 15:34:14 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | 	err = alGetError(); | 
					
						
							| 
									
										
										
										
											2009-12-20 02:23:26 +00:00
										 |  |  | 	// TODO: Error handling
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ALint iBuffersFilled = 0; | 
					
						
							|  |  |  | 	ALint iBuffersProcessed = 0; | 
					
						
							|  |  |  | 	ALuint uiBufferTemp[OAL_NUM_BUFFERS] = {0}; | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	while (!threadData)  | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2009-12-20 02:23:26 +00:00
										 |  |  | 		if (iBuffersProcessed == iBuffersFilled) | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | 		{ | 
					
						
							|  |  |  | 			alGetSourcei(uiSource, AL_BUFFERS_PROCESSED, &iBuffersProcessed); | 
					
						
							| 
									
										
										
										
											2009-12-20 02:23:26 +00:00
										 |  |  | 			iBuffersFilled = 0; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-23 15:34:14 +00:00
										 |  |  | 		unsigned int numSamples = m_mixer->GetNumSamples(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (iBuffersProcessed && (numSamples >= OAL_THRESHOLD)) | 
					
						
							| 
									
										
										
										
											2009-12-20 02:23:26 +00:00
										 |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2009-12-23 15:34:14 +00:00
										 |  |  | 			numSamples = (numSamples > OAL_MAX_SAMPLES) ? OAL_MAX_SAMPLES : numSamples; | 
					
						
							| 
									
										
										
										
											2009-12-20 02:23:26 +00:00
										 |  |  | 			// Remove the Buffer from the Queue.  (uiBuffer contains the Buffer ID for the unqueued Buffer)
 | 
					
						
							|  |  |  | 			if (iBuffersFilled == 0) | 
					
						
							|  |  |  | 				alSourceUnqueueBuffers(uiSource, iBuffersProcessed, uiBufferTemp); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			m_mixer->Mix(realtimeBuffer, numSamples); | 
					
						
							|  |  |  | 			alBufferData(uiBufferTemp[iBuffersFilled], AL_FORMAT_STEREO16, realtimeBuffer, numSamples * 4, ulFrequency); | 
					
						
							|  |  |  | 			alSourceQueueBuffers(uiSource, 1, &uiBufferTemp[iBuffersFilled]); | 
					
						
							|  |  |  | 			iBuffersFilled++; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if (iBuffersFilled == OAL_NUM_BUFFERS) | 
					
						
							|  |  |  | 				alSourcePlay(uiSource); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2009-12-23 15:34:14 +00:00
										 |  |  | 		else if (numSamples >= OAL_THRESHOLD) | 
					
						
							| 
									
										
										
										
											2009-12-20 02:23:26 +00:00
										 |  |  | 		{ | 
					
						
							|  |  |  | 			ALint state = 0; | 
					
						
							|  |  |  | 			alGetSourcei(uiSource, AL_SOURCE_STATE, &state); | 
					
						
							| 
									
										
										
										
											2009-12-23 15:34:14 +00:00
										 |  |  | 			if (state == AL_STOPPED) | 
					
						
							| 
									
										
										
										
											2009-12-20 02:23:26 +00:00
										 |  |  | 				alSourcePlay(uiSource); | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2009-12-18 19:52:04 +00:00
										 |  |  | 		soundSyncEvent.Wait(); | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #endif //HAVE_OPENAL
 | 
					
						
							|  |  |  | 
 |