| 
									
										
										
										
											2013-04-21 02:17:03 -04:00
										 |  |  | // Copyright 2013 Dolphin Emulator Project
 | 
					
						
							|  |  |  | // Licensed under GPLv2
 | 
					
						
							|  |  |  | // Refer to the license.txt file included.
 | 
					
						
							| 
									
										
										
										
											2009-09-24 21:35:06 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-01-27 05:01:00 +00:00
										 |  |  | #include <CoreServices/CoreServices.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-17 05:18:15 -05:00
										 |  |  | #include "AudioCommon/CoreAudioSoundStream.h"
 | 
					
						
							| 
									
										
										
										
											2009-09-24 21:35:06 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											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; | 
					
						
							| 
									
										
										
										
											2014-03-09 21:14:26 +01:00
										 |  |  | 	component = FindNextComponent(nullptr, &desc); | 
					
						
							| 
									
										
										
										
											2014-08-30 16:29:15 -04:00
										 |  |  | 	if (component == nullptr) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											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); | 
					
						
							| 
									
										
										
										
											2014-08-30 16:29:15 -04:00
										 |  |  | 	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)); | 
					
						
							| 
									
										
										
										
											2014-08-30 16:29:15 -04: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); | 
					
						
							| 
									
										
										
										
											2014-08-30 16:29:15 -04: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
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-08-30 16:29:15 -04:00
										 |  |  | 	err = AudioUnitSetParameter(audioUnit, | 
					
						
							| 
									
										
										
										
											2012-12-14 12:15:01 -06:00
										 |  |  | 					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); | 
					
						
							| 
									
										
										
										
											2014-08-30 16:29:15 -04:00
										 |  |  | 	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); | 
					
						
							| 
									
										
										
										
											2014-08-30 16:29:15 -04:00
										 |  |  | 	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; | 
					
						
							| 
									
										
										
										
											2014-08-30 16:29:15 -04: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
										 |  |  | } |