Jack2
1.9.8
|
00001 /* 00002 Copyright (C) 2010 Grame 00003 00004 This program is free software; you can redistribute it and/or modify 00005 it under the terms of the GNU General Public License as published by 00006 the Free Software Foundation; either version 2 of the License, or 00007 (at your option) any later version. 00008 00009 This program is distributed in the hope that it will be useful, 00010 but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 GNU General Public License for more details. 00013 00014 You should have received a copy of the GNU General Public License 00015 along with this program; if not, write to the Free Software 00016 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 00017 00018 */ 00019 00020 #include "TiPhoneCoreAudioRenderer.h" 00021 00022 static void PrintStreamDesc(AudioStreamBasicDescription *inDesc) 00023 { 00024 printf("- - - - - - - - - - - - - - - - - - - -\n"); 00025 printf(" Sample Rate:%f\n", inDesc->mSampleRate); 00026 printf(" Format ID:%.*s\n", (int) sizeof(inDesc->mFormatID), (char*)&inDesc->mFormatID); 00027 printf(" Format Flags:%lX\n", inDesc->mFormatFlags); 00028 printf(" Bytes per Packet:%ld\n", inDesc->mBytesPerPacket); 00029 printf(" Frames per Packet:%ld\n", inDesc->mFramesPerPacket); 00030 printf(" Bytes per Frame:%ld\n", inDesc->mBytesPerFrame); 00031 printf(" Channels per Frame:%ld\n", inDesc->mChannelsPerFrame); 00032 printf(" Bits per Channel:%ld\n", inDesc->mBitsPerChannel); 00033 printf("- - - - - - - - - - - - - - - - - - - -\n"); 00034 } 00035 00036 static void printError(OSStatus err) 00037 { 00038 switch (err) { 00039 case kAudioConverterErr_FormatNotSupported: 00040 printf("error code : kAudioConverterErr_FormatNotSupported\n"); 00041 break; 00042 case kAudioConverterErr_OperationNotSupported: 00043 printf("error code : kAudioConverterErr_OperationNotSupported\n"); 00044 break; 00045 case kAudioConverterErr_PropertyNotSupported: 00046 printf("error code : kAudioConverterErr_PropertyNotSupported\n"); 00047 break; 00048 case kAudioConverterErr_InvalidInputSize: 00049 printf("error code : kAudioConverterErr_InvalidInputSize\n"); 00050 break; 00051 case kAudioConverterErr_InvalidOutputSize: 00052 printf("error code : kAudioConverterErr_InvalidOutputSize\n"); 00053 break; 00054 case kAudioConverterErr_UnspecifiedError: 00055 printf("error code : kAudioConverterErr_UnspecifiedError\n"); 00056 break; 00057 case kAudioConverterErr_BadPropertySizeError: 00058 printf("error code : kAudioConverterErr_BadPropertySizeError\n"); 00059 break; 00060 case kAudioConverterErr_RequiresPacketDescriptionsError: 00061 printf("error code : kAudioConverterErr_RequiresPacketDescriptionsError\n"); 00062 break; 00063 case kAudioConverterErr_InputSampleRateOutOfRange: 00064 printf("error code : kAudioConverterErr_InputSampleRateOutOfRange\n"); 00065 break; 00066 case kAudioConverterErr_OutputSampleRateOutOfRange: 00067 printf("error code : kAudioConverterErr_OutputSampleRateOutOfRange\n"); 00068 break; 00069 default: 00070 printf("error code : unknown\n"); 00071 break; 00072 } 00073 } 00074 00075 OSStatus TiPhoneCoreAudioRenderer::Render(void *inRefCon, 00076 AudioUnitRenderActionFlags *ioActionFlags, 00077 const AudioTimeStamp *inTimeStamp, 00078 UInt32, 00079 UInt32 inNumberFrames, 00080 AudioBufferList *ioData) 00081 { 00082 TiPhoneCoreAudioRendererPtr renderer = (TiPhoneCoreAudioRendererPtr)inRefCon; 00083 AudioUnitRender(renderer->fAUHAL, ioActionFlags, inTimeStamp, 1, inNumberFrames, renderer->fCAInputData); 00084 00085 float coef = float(LONG_MAX); 00086 float inv_coef = 1.f/float(LONG_MAX); 00087 00088 for (int chan = 0; chan < renderer->fDevNumInChans; chan++) { 00089 for (int frame = 0; frame < inNumberFrames; frame++) { 00090 renderer->fInChannel[chan][frame] = float(((int*)renderer->fCAInputData->mBuffers[chan].mData)[frame]) * inv_coef; 00091 } 00092 } 00093 00094 renderer->PerformAudioCallback((int)inNumberFrames); 00095 00096 for (int chan = 0; chan < renderer->fDevNumOutChans; chan++) { 00097 for (int frame = 0; frame < inNumberFrames; frame++) { 00098 ((int*)ioData->mBuffers[chan].mData)[frame] = int(renderer->fOutChannel[chan][frame] * coef); 00099 } 00100 } 00101 00102 return 0; 00103 } 00104 00105 void TiPhoneCoreAudioRenderer::InterruptionListener(void *inClientData, UInt32 inInterruption) 00106 { 00107 TiPhoneCoreAudioRenderer *obj = (TiPhoneCoreAudioRenderer*)inClientData; 00108 printf("Session interrupted! --- %s ---", inInterruption == kAudioSessionBeginInterruption ? "Begin Interruption" : "End Interruption"); 00109 00110 if (inInterruption == kAudioSessionEndInterruption) { 00111 // make sure we are again the active session 00112 AudioSessionSetActive(true); 00113 AudioOutputUnitStart(obj->fAUHAL); 00114 } 00115 00116 if (inInterruption == kAudioSessionBeginInterruption) { 00117 AudioOutputUnitStop(obj->fAUHAL); 00118 } 00119 } 00120 00121 int TiPhoneCoreAudioRenderer::Open(int bufferSize, int samplerate) 00122 { 00123 OSStatus err1; 00124 UInt32 outSize; 00125 UInt32 enableIO; 00126 AudioStreamBasicDescription srcFormat, dstFormat; 00127 00128 printf("Open fDevNumInChans = %ld fDevNumOutChans = %ld bufferSize = %ld samplerate = %ld\n", fDevNumInChans, fDevNumOutChans, bufferSize, samplerate); 00129 00130 // Initialize and configure the audio session 00131 err1 = AudioSessionInitialize(NULL, NULL, InterruptionListener, this); 00132 if (err1 != noErr) { 00133 printf("Couldn't initialize audio session\n"); 00134 printError(err1); 00135 return OPEN_ERR; 00136 } 00137 00138 err1 = AudioSessionSetActive(true); 00139 if (err1 != noErr) { 00140 printf("Couldn't set audio session active\n"); 00141 printError(err1); 00142 return OPEN_ERR; 00143 } 00144 00145 UInt32 audioCategory = kAudioSessionCategory_PlayAndRecord; 00146 err1 = AudioSessionSetProperty(kAudioSessionProperty_AudioCategory, sizeof(audioCategory), &audioCategory); 00147 if (err1 != noErr) { 00148 printf("Couldn't set audio category\n"); 00149 printError(err1); 00150 return OPEN_ERR; 00151 } 00152 00153 //err1 = AudioSessionAddPropertyListener(kAudioSessionProperty_AudioRouteChange, propListener, self), "couldn't set property listener"); 00154 00155 Float64 hwSampleRate; 00156 outSize = sizeof(hwSampleRate); 00157 err1 = AudioSessionGetProperty(kAudioSessionProperty_CurrentHardwareSampleRate, &outSize, &hwSampleRate); 00158 if (err1 != noErr) { 00159 printf("Couldn't get hw sample rate\n"); 00160 printError(err1); 00161 return OPEN_ERR; 00162 } else { 00163 printf("Get hw sample rate %f\n", hwSampleRate); 00164 } 00165 00166 Float32 hwBufferSize; 00167 outSize = sizeof(hwBufferSize); 00168 err1 = AudioSessionGetProperty(kAudioSessionProperty_CurrentHardwareIOBufferDuration, &outSize, &hwBufferSize); 00169 if (err1 != noErr) { 00170 printf("Couldn't get hw buffer duration\n"); 00171 printError(err1); 00172 return OPEN_ERR; 00173 } else { 00174 printf("Get hw buffer duration %f\n", hwBufferSize); 00175 } 00176 00177 UInt32 hwInput; 00178 outSize = sizeof(hwInput); 00179 err1 = AudioSessionGetProperty(kAudioSessionProperty_CurrentHardwareInputNumberChannels, &outSize, &hwInput); 00180 if (err1 != noErr) { 00181 printf("Couldn't get hw input channels\n"); 00182 printError(err1); 00183 return OPEN_ERR; 00184 } else { 00185 printf("Get hw input channels %d\n", hwInput); 00186 } 00187 00188 UInt32 hwOutput; 00189 outSize = sizeof(hwOutput); 00190 err1 = AudioSessionGetProperty(kAudioSessionProperty_CurrentHardwareOutputNumberChannels, &outSize, &hwOutput); 00191 if (err1 != noErr) { 00192 printf("Couldn't get hw output channels\n"); 00193 printError(err1); 00194 return OPEN_ERR; 00195 } else { 00196 printf("Get hw output channels %d\n", hwOutput); 00197 } 00198 00199 Float32 preferredBufferSize = float(bufferSize) / float(samplerate); 00200 printf("preferredBufferSize %f \n", preferredBufferSize); 00201 00202 err1 = AudioSessionSetProperty(kAudioSessionProperty_PreferredHardwareIOBufferDuration, sizeof(preferredBufferSize), &preferredBufferSize); 00203 if (err1 != noErr) { 00204 printf("Couldn't set i/o buffer duration\n"); 00205 printError(err1); 00206 return OPEN_ERR; 00207 } 00208 00209 Float64 preferredSamplerate = float(samplerate); 00210 err1 = AudioSessionSetProperty(kAudioSessionProperty_PreferredHardwareSampleRate, sizeof(preferredSamplerate), &preferredSamplerate); 00211 if (err1 != noErr) { 00212 printf("Couldn't set i/o sample rate\n"); 00213 printError(err1); 00214 return OPEN_ERR; 00215 } 00216 00217 // AUHAL 00218 AudioComponentDescription cd = {kAudioUnitType_Output, kAudioUnitSubType_RemoteIO, kAudioUnitManufacturer_Apple, 0, 0}; 00219 AudioComponent HALOutput = AudioComponentFindNext(NULL, &cd); 00220 00221 err1 = AudioComponentInstanceNew(HALOutput, &fAUHAL); 00222 if (err1 != noErr) { 00223 printf("Error calling OpenAComponent\n"); 00224 printError(err1); 00225 goto error; 00226 } 00227 00228 enableIO = 1; 00229 err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, 0, &enableIO, sizeof(enableIO)); 00230 if (err1 != noErr) { 00231 printf("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output\n"); 00232 printError(err1); 00233 goto error; 00234 } 00235 00236 enableIO = 1; 00237 err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, 1, &enableIO, sizeof(enableIO)); 00238 if (err1 != noErr) { 00239 printf("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input\n"); 00240 printError(err1); 00241 goto error; 00242 } 00243 00244 UInt32 maxFPS; 00245 outSize = sizeof(maxFPS); 00246 err1 = AudioUnitGetProperty(fAUHAL, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0, &maxFPS, &outSize); 00247 if (err1 != noErr) { 00248 printf("Couldn't get kAudioUnitProperty_MaximumFramesPerSlice\n"); 00249 printError(err1); 00250 goto error; 00251 } else { 00252 printf("Get kAudioUnitProperty_MaximumFramesPerSlice %d\n", maxFPS); 00253 } 00254 00255 err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 1, (UInt32*)&bufferSize, sizeof(UInt32)); 00256 if (err1 != noErr) { 00257 printf("Error calling AudioUnitSetProperty - kAudioUnitProperty_MaximumFramesPerSlice\n"); 00258 printError(err1); 00259 goto error; 00260 } 00261 00262 err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0, (UInt32*)&bufferSize, sizeof(UInt32)); 00263 if (err1 != noErr) { 00264 printf("Error calling AudioUnitSetProperty - kAudioUnitProperty_MaximumFramesPerSlice\n"); 00265 printError(err1); 00266 goto error; 00267 } 00268 00269 err1 = AudioUnitInitialize(fAUHAL); 00270 if (err1 != noErr) { 00271 printf("Cannot initialize AUHAL unit\n"); 00272 printError(err1); 00273 goto error; 00274 } 00275 00276 // Setting format 00277 00278 if (fDevNumInChans > 0) { 00279 outSize = sizeof(AudioStreamBasicDescription); 00280 err1 = AudioUnitGetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &srcFormat, &outSize); 00281 if (err1 != noErr) { 00282 printf("Error calling AudioUnitGetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Output\n"); 00283 printError(err1); 00284 } 00285 PrintStreamDesc(&srcFormat); 00286 00287 srcFormat.mFormatID = kAudioFormatLinearPCM; 00288 srcFormat.mFormatFlags = kAudioFormatFlagsCanonical | kLinearPCMFormatFlagIsNonInterleaved; 00289 srcFormat.mBytesPerPacket = sizeof(AudioUnitSampleType); 00290 srcFormat.mFramesPerPacket = 1; 00291 srcFormat.mBytesPerFrame = sizeof(AudioUnitSampleType); 00292 srcFormat.mChannelsPerFrame = fDevNumInChans; 00293 srcFormat.mBitsPerChannel = 32; 00294 00295 PrintStreamDesc(&srcFormat); 00296 00297 err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &srcFormat, sizeof(AudioStreamBasicDescription)); 00298 if (err1 != noErr) { 00299 printf("Error calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Output\n"); 00300 printError(err1); 00301 } 00302 } 00303 00304 if (fDevNumOutChans > 0) { 00305 outSize = sizeof(AudioStreamBasicDescription); 00306 err1 = AudioUnitGetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &dstFormat, &outSize); 00307 if (err1 != noErr) { 00308 printf("Error calling AudioUnitGetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Input\n"); 00309 printError(err1); 00310 } 00311 PrintStreamDesc(&dstFormat); 00312 00313 dstFormat.mFormatID = kAudioFormatLinearPCM; 00314 dstFormat.mFormatFlags = kAudioFormatFlagsCanonical | kLinearPCMFormatFlagIsNonInterleaved; 00315 dstFormat.mBytesPerPacket = sizeof(AudioUnitSampleType); 00316 dstFormat.mFramesPerPacket = 1; 00317 dstFormat.mBytesPerFrame = sizeof(AudioUnitSampleType); 00318 dstFormat.mChannelsPerFrame = fDevNumOutChans; 00319 dstFormat.mBitsPerChannel = 32; 00320 00321 PrintStreamDesc(&dstFormat); 00322 00323 err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &dstFormat, sizeof(AudioStreamBasicDescription)); 00324 if (err1 != noErr) { 00325 printf("Error calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Input\n"); 00326 printError(err1); 00327 } 00328 } 00329 00330 if (fDevNumInChans > 0 && fDevNumOutChans == 0) { 00331 AURenderCallbackStruct output; 00332 output.inputProc = Render; 00333 output.inputProcRefCon = this; 00334 err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_SetInputCallback, kAudioUnitScope_Global, 0, &output, sizeof(output)); 00335 if (err1 != noErr) { 00336 printf("Error calling AudioUnitSetProperty - kAudioUnitProperty_SetRenderCallback 1\n"); 00337 printError(err1); 00338 goto error; 00339 } 00340 } else { 00341 AURenderCallbackStruct output; 00342 output.inputProc = Render; 00343 output.inputProcRefCon = this; 00344 err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &output, sizeof(output)); 00345 if (err1 != noErr) { 00346 printf("Error calling AudioUnitSetProperty - kAudioUnitProperty_SetRenderCallback 0\n"); 00347 printError(err1); 00348 goto error; 00349 } 00350 } 00351 00352 // Prepare buffers 00353 fCAInputData = (AudioBufferList*)malloc(sizeof(UInt32) + fDevNumInChans * sizeof(AudioBuffer)); 00354 fCAInputData->mNumberBuffers = fDevNumInChans; 00355 for (int i = 0; i < fDevNumInChans; i++) { 00356 fCAInputData->mBuffers[i].mNumberChannels = 1; 00357 fCAInputData->mBuffers[i].mDataByteSize = bufferSize * sizeof(int); 00358 fCAInputData->mBuffers[i].mData = malloc(bufferSize * sizeof(int)); 00359 } 00360 00361 /* 00362 // Add listeners 00363 err1 = AudioDeviceAddPropertyListener(fDeviceID, 0, true, kAudioDeviceProcessorOverload, DeviceNotificationCallback, this); 00364 if (err != noErr) { 00365 jack_error("Error calling AudioDeviceAddPropertyListener with kAudioDeviceProcessorOverload"); 00366 printError(err); 00367 return -1; 00368 } 00369 */ 00370 00371 return NO_ERR; 00372 00373 error: 00374 AudioUnitUninitialize(fAUHAL); 00375 AudioComponentInstanceDispose(fAUHAL); 00376 return OPEN_ERR; 00377 } 00378 00379 int TiPhoneCoreAudioRenderer::Close() 00380 { 00381 AudioUnitUninitialize(fAUHAL); 00382 AudioComponentInstanceDispose(fAUHAL); 00383 return NO_ERR; 00384 } 00385 00386 int TiPhoneCoreAudioRenderer::Start() 00387 { 00388 AudioSessionSetActive(true); 00389 OSStatus err = AudioOutputUnitStart(fAUHAL); 00390 00391 if (err != noErr) { 00392 printf("Error while opening device : device open error \n"); 00393 return OPEN_ERR; 00394 } else { 00395 return NO_ERR; 00396 } 00397 } 00398 00399 int TiPhoneCoreAudioRenderer::Stop() 00400 { 00401 OSStatus err = AudioOutputUnitStop(fAUHAL); 00402 00403 if (err != noErr) { 00404 printf("Error while closing device : device close error \n"); 00405 return OPEN_ERR; 00406 } else { 00407 return NO_ERR; 00408 } 00409 }