| 
									
										
										
										
											2009-09-24 21:35:06 +00:00
										 |  |  | // Copyright (C) 2003 Dolphin Project.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // 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/
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-01-27 05:01:00 +00:00
										 |  |  | #include <CoreServices/CoreServices.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-24 21:35:06 +00:00
										 |  |  | #include "CoreAudioSoundStream.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-02 18:21:20 +00:00
										 |  |  | OSStatus CoreAudioSound::callback(void *inRefCon, | 
					
						
							|  |  |  | 	AudioUnitRenderActionFlags *ioActionFlags, | 
					
						
							|  |  |  | 	const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, | 
					
						
							|  |  |  | 	UInt32 inNumberFrames, AudioBufferList *ioData) | 
					
						
							| 
									
										
										
										
											2010-05-30 04:21:01 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-05-31 05:05:53 +00:00
										 |  |  | 	for (UInt32 i = 0; i < ioData->mNumberBuffers; i++) | 
					
						
							| 
									
										
										
										
											2011-02-02 18:21:20 +00:00
										 |  |  | 		((CoreAudioSound *)inRefCon)->m_mixer-> | 
					
						
							|  |  |  | 			Mix((short *)ioData->mBuffers[i].mData, | 
					
						
							|  |  |  | 				ioData->mBuffers[i].mDataByteSize / 4); | 
					
						
							| 
									
										
										
										
											2010-05-30 04:21:01 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-31 05:05:53 +00:00
										 |  |  | 	return noErr; | 
					
						
							| 
									
										
										
										
											2009-09-24 21:35:06 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | CoreAudioSound::CoreAudioSound(CMixer *mixer) : SoundStream(mixer) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | CoreAudioSound::~CoreAudioSound() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2010-05-30 04:21:01 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-31 05:05:53 +00:00
										 |  |  | bool CoreAudioSound::Start() | 
					
						
							| 
									
										
										
										
											2009-09-24 21:35:06 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-10-23 17:10:27 +00:00
										 |  |  | 	OSStatus err; | 
					
						
							|  |  |  | 	AURenderCallbackStruct callback_struct; | 
					
						
							|  |  |  | 	AudioStreamBasicDescription format; | 
					
						
							| 
									
										
										
										
											2011-01-04 02:09:29 +00:00
										 |  |  | 	ComponentDescription desc; | 
					
						
							| 
									
										
										
										
											2011-02-03 21:11:06 +00:00
										 |  |  | 	Component component; | 
					
						
							| 
									
										
										
										
											2010-05-30 04:21:01 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-23 17:10:27 +00:00
										 |  |  | 	desc.componentType = kAudioUnitType_Output; | 
					
						
							| 
									
										
										
										
											2010-06-01 20:45:30 +00:00
										 |  |  | 	desc.componentSubType = kAudioUnitSubType_DefaultOutput; | 
					
						
							| 
									
										
										
										
											2010-05-30 04:21:01 +00:00
										 |  |  | 	desc.componentFlags = 0; | 
					
						
							|  |  |  | 	desc.componentFlagsMask = 0; | 
					
						
							| 
									
										
										
										
											2009-10-23 17:10:27 +00:00
										 |  |  | 	desc.componentManufacturer = kAudioUnitManufacturer_Apple; | 
					
						
							| 
									
										
										
										
											2011-02-03 21:11:06 +00:00
										 |  |  | 	component = FindNextComponent(NULL, &desc); | 
					
						
							| 
									
										
										
										
											2010-05-31 05:05:53 +00:00
										 |  |  | 	if (component == NULL) { | 
					
						
							| 
									
										
										
										
											2010-06-01 20:45:30 +00:00
										 |  |  | 		ERROR_LOG(AUDIO, "error finding audio component"); | 
					
						
							| 
									
										
										
										
											2010-05-31 05:05:53 +00:00
										 |  |  | 		return false; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2010-05-30 04:21:01 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-31 05:05:53 +00:00
										 |  |  | 	err = OpenAComponent(component, &audioUnit); | 
					
						
							|  |  |  | 	if (err != noErr) { | 
					
						
							| 
									
										
										
										
											2010-06-01 20:45:30 +00:00
										 |  |  | 		ERROR_LOG(AUDIO, "error opening audio component"); | 
					
						
							| 
									
										
										
										
											2010-05-31 05:05:53 +00:00
										 |  |  | 		return false; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-10-23 17:10:27 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-30 04:21:01 +00:00
										 |  |  | 	FillOutASBDForLPCM(format, m_mixer->GetSampleRate(), | 
					
						
							|  |  |  | 				2, 16, 16, false, false, false); | 
					
						
							| 
									
										
										
										
											2010-05-31 05:05:53 +00:00
										 |  |  | 	err = AudioUnitSetProperty(audioUnit, | 
					
						
							| 
									
										
										
										
											2010-05-30 04:21:01 +00:00
										 |  |  | 				kAudioUnitProperty_StreamFormat, | 
					
						
							|  |  |  | 				kAudioUnitScope_Input, 0, &format, | 
					
						
							|  |  |  | 				sizeof(AudioStreamBasicDescription)); | 
					
						
							| 
									
										
										
										
											2010-05-31 05:05:53 +00:00
										 |  |  | 	if (err != noErr) { | 
					
						
							| 
									
										
										
										
											2010-06-01 20:45:30 +00:00
										 |  |  | 		ERROR_LOG(AUDIO, "error setting audio format"); | 
					
						
							| 
									
										
										
										
											2010-05-31 05:05:53 +00:00
										 |  |  | 		return false; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-10-23 17:10:27 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	callback_struct.inputProc = callback; | 
					
						
							| 
									
										
										
										
											2010-05-31 05:05:53 +00:00
										 |  |  | 	callback_struct.inputProcRefCon = this; | 
					
						
							|  |  |  | 	err = AudioUnitSetProperty(audioUnit, | 
					
						
							| 
									
										
										
										
											2010-05-30 04:21:01 +00:00
										 |  |  | 				kAudioUnitProperty_SetRenderCallback, | 
					
						
							|  |  |  | 				kAudioUnitScope_Input, 0, &callback_struct, | 
					
						
							|  |  |  | 				sizeof callback_struct); | 
					
						
							| 
									
										
										
										
											2010-05-31 05:05:53 +00:00
										 |  |  | 	if (err != noErr) { | 
					
						
							| 
									
										
										
										
											2010-06-01 20:45:30 +00:00
										 |  |  | 		ERROR_LOG(AUDIO, "error setting audio callback"); | 
					
						
							| 
									
										
										
										
											2010-05-31 05:05:53 +00:00
										 |  |  | 		return false; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2010-05-30 04:21:01 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-12-14 12:15:01 -06:00
										 |  |  |     err = AudioUnitSetParameter(audioUnit, | 
					
						
							|  |  |  | 					kHALOutputParam_Volume, | 
					
						
							|  |  |  | 					kAudioUnitParameterFlag_Output, 0, | 
					
						
							|  |  |  | 					m_volume / 100., 0); | 
					
						
							|  |  |  | 	if (err != noErr) | 
					
						
							|  |  |  | 		ERROR_LOG(AUDIO, "error setting volume"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-31 05:05:53 +00:00
										 |  |  | 	err = AudioUnitInitialize(audioUnit); | 
					
						
							|  |  |  | 	if (err != noErr) { | 
					
						
							| 
									
										
										
										
											2010-06-01 20:45:30 +00:00
										 |  |  | 		ERROR_LOG(AUDIO, "error initializing audiounit"); | 
					
						
							| 
									
										
										
										
											2010-05-31 05:05:53 +00:00
										 |  |  | 		return false; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2010-05-30 04:21:01 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-31 05:05:53 +00:00
										 |  |  | 	err = AudioOutputUnitStart(audioUnit); | 
					
						
							|  |  |  | 	if (err != noErr) { | 
					
						
							| 
									
										
										
										
											2010-06-01 20:45:30 +00:00
										 |  |  | 		ERROR_LOG(AUDIO, "error starting audiounit"); | 
					
						
							| 
									
										
										
										
											2010-05-31 05:05:53 +00:00
										 |  |  | 		return false; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-10-23 17:10:27 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-24 21:35:06 +00:00
										 |  |  | 	return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-01-02 02:49:30 +00:00
										 |  |  | void CoreAudioSound::SetVolume(int volume) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	OSStatus err; | 
					
						
							| 
									
										
										
										
											2012-12-14 12:15:01 -06:00
										 |  |  |     m_volume = volume; | 
					
						
							| 
									
										
										
										
											2011-01-02 02:49:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	err = AudioUnitSetParameter(audioUnit, | 
					
						
							|  |  |  | 					kHALOutputParam_Volume, | 
					
						
							|  |  |  | 					kAudioUnitParameterFlag_Output, 0, | 
					
						
							|  |  |  | 					volume / 100., 0); | 
					
						
							|  |  |  | 	if (err != noErr) | 
					
						
							|  |  |  | 		ERROR_LOG(AUDIO, "error setting volume"); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-31 05:05:53 +00:00
										 |  |  | void CoreAudioSound::SoundLoop() | 
					
						
							| 
									
										
										
										
											2009-09-24 21:35:06 +00:00
										 |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void CoreAudioSound::Stop() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-05-31 05:05:53 +00:00
										 |  |  | 	OSStatus err; | 
					
						
							| 
									
										
										
										
											2009-10-23 17:10:27 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-31 05:05:53 +00:00
										 |  |  | 	err = AudioOutputUnitStop(audioUnit); | 
					
						
							| 
									
										
										
										
											2011-01-02 02:49:30 +00:00
										 |  |  | 	if (err != noErr) | 
					
						
							| 
									
										
										
										
											2010-06-01 20:45:30 +00:00
										 |  |  | 		ERROR_LOG(AUDIO, "error stopping audiounit"); | 
					
						
							| 
									
										
										
										
											2010-05-31 05:05:53 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	err = AudioUnitUninitialize(audioUnit); | 
					
						
							| 
									
										
										
										
											2011-01-02 02:49:30 +00:00
										 |  |  | 	if (err != noErr) | 
					
						
							| 
									
										
										
										
											2010-06-01 20:45:30 +00:00
										 |  |  | 		ERROR_LOG(AUDIO, "error uninitializing audiounit"); | 
					
						
							| 
									
										
										
										
											2010-05-31 05:05:53 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	err = CloseComponent(audioUnit); | 
					
						
							| 
									
										
										
										
											2011-01-02 02:49:30 +00:00
										 |  |  | 	if (err != noErr) | 
					
						
							| 
									
										
										
										
											2010-06-01 20:45:30 +00:00
										 |  |  | 		ERROR_LOG(AUDIO, "error closing audio component"); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:35:06 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2010-05-30 04:21:01 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-24 21:35:06 +00:00
										 |  |  | void CoreAudioSound::Update() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2009-10-23 17:10:27 +00:00
										 |  |  | } |