1 /************************** BEGIN coreaudio-ios-dsp.h **************************/ 2 /************************************************************************ 3 FAUST Architecture File 4 Copyright (C) 2003-2017 GRAME, Centre National de Creation Musicale 5 --------------------------------------------------------------------- 6 This Architecture section is free software; you can redistribute it 7 and/or modify it under the terms of the GNU General Public License 8 as published by the Free Software Foundation; either version 3 of 9 the License, or (at your option) any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with this program; If not, see <http://www.gnu.org/licenses/>. 18 19 EXCEPTION : As a special exception, you may create a larger work 20 that contains this FAUST architecture section and distribute 21 that work under terms of your choice, so long as this FAUST 22 architecture section is not modified. 23 ************************************************************************/ 24 25 #ifndef __coreaudio_ios_dsp__ 26 #define __coreaudio_ios_dsp__ 27 28 #include <stdlib.h> 29 #include <stdio.h> 30 #include <string.h> 31 #include <limits.h> 32 #include <math.h> 33 #include <errno.h> 34 #include <time.h> 35 36 #include "faust/audio/audio.h" 37 #include "faust/dsp/dsp.h" 38 39 #include <AudioToolbox/AudioConverter.h> 40 #include <AudioToolbox/AudioServices.h> 41 #include <AudioUnit/AudioUnit.h> 42 43 using namespace std; 44 45 /****************************************************************************** 46 ******************************************************************************* 47 48 COREAUDIO INTERFACE 49 50 ******************************************************************************* 51 *******************************************************************************/ 52 53 #define OPEN_ERR -1 54 #define NO_ERR 0 55 56 class TiPhoneCoreAudioRenderer 57 { 58 59 protected: 60 61 AudioUnit fAUHAL; 62 63 int fDevNumInChans; 64 int fDevNumOutChans; 65 66 int fHWNumInChans; 67 int fHWNumOutChans; 68 69 dsp* fDSP; 70 71 audio* fAudio; 72 73 AudioBufferList* fCAInputData; 74 PrintStreamDesc(AudioStreamBasicDescription * inDesc)75 static void PrintStreamDesc(AudioStreamBasicDescription *inDesc) 76 { 77 printf("- - - - - - - - - - - - - - - - - - - -\n"); 78 printf(" Sample Rate:%f\n", inDesc->mSampleRate); 79 printf(" Format ID:%.*s\n", (int) sizeof(inDesc->mFormatID), (char*)&inDesc->mFormatID); 80 printf(" Format Flags:%lX\n", inDesc->mFormatFlags); 81 printf(" Bytes per Packet:%ld\n", inDesc->mBytesPerPacket); 82 printf(" Frames per Packet:%ld\n", inDesc->mFramesPerPacket); 83 printf(" Bytes per Frame:%ld\n", inDesc->mBytesPerFrame); 84 printf(" Channels per Frame:%ld\n", inDesc->mChannelsPerFrame); 85 printf(" Bits per Channel:%ld\n", inDesc->mBitsPerChannel); 86 printf("- - - - - - - - - - - - - - - - - - - -\n"); 87 } 88 printError(OSStatus err)89 static void printError(OSStatus err) 90 { 91 switch (err) { 92 case kAudioConverterErr_FormatNotSupported: 93 printf("error code : kAudioConverterErr_FormatNotSupported\n"); 94 break; 95 case kAudioConverterErr_OperationNotSupported: 96 printf("error code : kAudioConverterErr_OperationNotSupported\n"); 97 break; 98 case kAudioConverterErr_PropertyNotSupported: 99 printf("error code : kAudioConverterErr_PropertyNotSupported\n"); 100 break; 101 case kAudioConverterErr_InvalidInputSize: 102 printf("error code : kAudioConverterErr_InvalidInputSize\n"); 103 break; 104 case kAudioConverterErr_InvalidOutputSize: 105 printf("error code : kAudioConverterErr_InvalidOutputSize\n"); 106 break; 107 case kAudioConverterErr_UnspecifiedError: 108 printf("error code : kAudioConverterErr_UnspecifiedError\n"); 109 break; 110 case kAudioConverterErr_BadPropertySizeError: 111 printf("error code : kAudioConverterErr_BadPropertySizeError\n"); 112 break; 113 case kAudioConverterErr_RequiresPacketDescriptionsError: 114 printf("error code : kAudioConverterErr_RequiresPacketDescriptionsError\n"); 115 break; 116 case kAudioConverterErr_InputSampleRateOutOfRange: 117 printf("error code : kAudioConverterErr_InputSampleRateOutOfRange\n"); 118 break; 119 case kAudioConverterErr_OutputSampleRateOutOfRange: 120 printf("error code : kAudioConverterErr_OutputSampleRateOutOfRange\n"); 121 break; 122 default: 123 printf("error code : unknown\n"); 124 break; 125 } 126 } 127 Render(void * inRefCon,AudioUnitRenderActionFlags * ioActionFlags,const AudioTimeStamp * inTimeStamp,UInt32,UInt32 inNumberFrames,AudioBufferList * ioData)128 static OSStatus Render(void *inRefCon,AudioUnitRenderActionFlags *ioActionFlags, 129 const AudioTimeStamp *inTimeStamp, 130 UInt32, 131 UInt32 inNumberFrames, 132 AudioBufferList *ioData) 133 { 134 return static_cast<TiPhoneCoreAudioRenderer*>(inRefCon)->Render(ioActionFlags, inTimeStamp, inNumberFrames, ioData); 135 } 136 Render(AudioUnitRenderActionFlags * ioActionFlags,const AudioTimeStamp * inTimeStamp,UInt32 inNumberFrames,AudioBufferList * ioData)137 OSStatus Render(AudioUnitRenderActionFlags *ioActionFlags, 138 const AudioTimeStamp *inTimeStamp, 139 UInt32 inNumberFrames, 140 AudioBufferList *ioData) 141 { 142 OSStatus err = noErr; 143 144 if (fDevNumInChans > 0) { 145 err = AudioUnitRender(fAUHAL, ioActionFlags, inTimeStamp, 1, inNumberFrames, fCAInputData); 146 } 147 148 if (err == noErr) { 149 float* fInChannel[fDevNumInChans]; 150 float* fOutChannel[fDevNumOutChans]; 151 152 for (int chan = 0; chan < fDevNumInChans; chan++) { 153 fInChannel[chan] = (float*)fCAInputData->mBuffers[chan].mData; 154 } 155 156 for (int chan = 0; chan < fDevNumOutChans; chan++) { 157 fOutChannel[chan] = (float*)ioData->mBuffers[chan].mData; 158 } 159 160 fDSP->compute((int)inNumberFrames, fInChannel, fOutChannel); 161 162 fAudio->runControlCallbacks(); 163 } 164 return err; 165 } 166 InterruptionListener(void * inClientData,UInt32 inInterruption)167 static void InterruptionListener(void *inClientData, UInt32 inInterruption) 168 { 169 TiPhoneCoreAudioRenderer *obj = (TiPhoneCoreAudioRenderer*)inClientData; 170 printf("Session interrupted! --- %s ---", (inInterruption == kAudioSessionBeginInterruption) ? "Begin Interruption" : "End Interruption"); 171 172 if (inInterruption == kAudioSessionEndInterruption) { 173 // Make sure we are again the active session 174 AudioSessionSetActive(true); 175 obj->SetupMixing(); 176 AudioOutputUnitStart(obj->fAUHAL); 177 } 178 179 if (inInterruption == kAudioSessionBeginInterruption) { 180 AudioOutputUnitStop(obj->fAUHAL); 181 } 182 } 183 SetupMixing()184 int SetupMixing() 185 { 186 OSStatus err; 187 188 /* 189 01/07/2014 : cause iRig to fail, so deactivated for now... 190 CFStringRef route; 191 UInt32 routesize = sizeof(route); 192 OSStatus err = AudioSessionGetProperty(kAudioSessionProperty_AudioRoute, &routesize, &route); 193 if (err == noErr) { 194 if (CFStringCompare(route, CFSTR("ReceiverAndMicrophone"), 0) == kCFCompareEqualTo || CFStringCompare(route,CFSTR("Receiver"), 0) == kCFCompareEqualTo) { 195 // Re-route audio to the speaker (not the receiver, which no music app will ever want) 196 printf("Rerouting audio to speaker\n"); 197 UInt32 newRoute = kAudioSessionOverrideAudioRoute_Speaker; 198 AudioSessionSetProperty(kAudioSessionProperty_OverrideAudioRoute, sizeof(newRoute), &newRoute); 199 } 200 } 201 */ 202 203 UInt32 allowMixing = true; 204 err = AudioSessionSetProperty(kAudioSessionProperty_OverrideCategoryMixWithOthers, sizeof(allowMixing), &allowMixing); 205 if (err != noErr) { 206 printf("Could not set audio session mixing\n"); 207 printError(err); 208 return -1; 209 } else { 210 return 0; 211 } 212 } 213 AudioSessionPropertyListener(void * inClientData,AudioSessionPropertyID inID,UInt32 inDataSize,const void * inData)214 static void AudioSessionPropertyListener(void* inClientData, AudioSessionPropertyID inID, UInt32 inDataSize, const void* inData) 215 { 216 TiPhoneCoreAudioRenderer *obj = (TiPhoneCoreAudioRenderer*)inData; 217 switch (inID) { 218 case kAudioSessionProperty_ServerDied: { 219 printf("kAudioSessionProperty_ServerDied\n"); 220 break; 221 } 222 case kAudioSessionProperty_AudioRouteChange: { 223 printf("kAudioSessionProperty_AudioRouteChange\n"); 224 obj->SetupMixing(); 225 break; 226 } 227 case kAudioSessionProperty_AudioInputAvailable: { 228 printf("kAudioSessionProperty_AudioInputAvailable\n"); 229 obj->SetupMixing(); 230 break; 231 } 232 } 233 } 234 SetAudioCategory(int input,int output)235 static int SetAudioCategory(int input, int output) 236 { 237 // Set the audioCategory the way Faust DSP wants 238 UInt32 audioCategory; 239 if ((input > 0) && (output > 0)) { 240 audioCategory = kAudioSessionCategory_PlayAndRecord; 241 printf("AudioCategory kAudioSessionCategory_PlayAndRecord\n"); 242 } else if (input > 0) { 243 audioCategory = kAudioSessionCategory_RecordAudio; 244 printf("AudioCategory kAudioSessionCategory_RecordAudio\n"); 245 } else if (output > 0) { 246 audioCategory = kAudioSessionCategory_MediaPlayback; 247 printf("AudioCategory kAudioSessionCategory_MediaPlayback\n"); 248 } 249 250 OSStatus err = AudioSessionSetProperty(kAudioSessionProperty_AudioCategory, sizeof(audioCategory), &audioCategory); 251 if (err != noErr) { 252 printf("Couldn't set audio category\n"); 253 printError(err); 254 return OPEN_ERR; 255 } 256 257 // 09/07/2015 : https://developer.apple.com/library/ios/qa/qa1754/_index.html 258 if (audioCategory == kAudioSessionCategory_PlayAndRecord) { 259 260 // 21/09/2017 Compatible with bluetooth devices. Deactivate bluetooth micro which run at 16khz, use internal micro instead. 261 /* 262 UInt32 overrideAudioRoute = 1; 263 err = AudioSessionSetProperty(kAudioSessionProperty_OverrideCategoryDefaultToSpeaker, sizeof(UInt32), &overrideAudioRoute); 264 if (err != noErr) { 265 printf("Error setting kAudioSessionProperty_OverrideCategoryDefaultToSpeaker\n"); 266 printError(err); 267 } 268 269 UInt32 allowBluetoothInput = 1; 270 err = AudioSessionSetProperty(kAudioSessionProperty_OverrideCategoryEnableBluetoothInput, sizeof(UInt32), &allowBluetoothInput); 271 if (err != noErr) { 272 printf("Error setting kAudioSessionProperty_OverrideCategoryEnableBluetoothInput\n"); 273 printError(err); 274 } 275 */ 276 277 // On devices with more than one built-in microphone, the microphone closest to the video camera is used. 278 UInt32 allowInternalInput = kAudioSessionMode_VideoRecording; 279 err = AudioSessionSetProperty(kAudioSessionProperty_Mode, sizeof(UInt32), &allowInternalInput); 280 if (err != noErr) { 281 printf("Error setting kAudioSessionMode_VideoRecording\n"); 282 printError(err); 283 } 284 285 } 286 287 #if NOAGC 288 // If input is used, disable AGC 289 if (audioCategory == kAudioSessionCategory_RecordAudio || audioCategory == kAudioSessionCategory_PlayAndRecord) { 290 291 UInt32 sessionMode = kAudioSessionMode_Measurement; 292 err = AudioSessionSetProperty(kAudioSessionProperty_Mode, sizeof(sessionMode), &sessionMode); 293 if (err != noErr) { 294 printf("Error setting kAudioSessionMode_Measurement\n"); 295 printError(err); 296 } 297 298 UInt32 availableGain; 299 UInt32 outSize = sizeof(availableGain); 300 err = AudioSessionGetProperty(kAudioSessionProperty_InputGainAvailable, &outSize, &availableGain); 301 if (err != noErr) { 302 printf("Error getting kAudioSessionProperty_InputGainAvailable\n"); 303 printError(err); 304 } else { 305 Float32 gain; 306 printf("Getting kAudioSessionProperty_InputGainAvailable OK\n"); 307 outSize = sizeof(Float32); 308 AudioSessionGetProperty(kAudioSessionProperty_InputGainScalar, &outSize, &gain); 309 printf("Getting kAudioSessionProperty_InputGainScalar : %f\n", gain); 310 gain = 1.0f; 311 err = AudioSessionSetProperty(kAudioSessionProperty_InputGainScalar, sizeof(Float32), &gain); 312 if (err != noErr) { 313 printf("Error setting kAudioSessionProperty_InputGainScalar\n"); 314 printError(err); 315 } else { 316 printf("Setting kAudioSessionProperty_InputGainAvailable to 1.0 OK\n"); 317 } 318 } 319 } 320 #endif 321 322 return NO_ERR; 323 } 324 SetParameters(int bufferSize,int samplerate)325 int SetParameters(int bufferSize, int samplerate) 326 { 327 OSStatus err; 328 UInt32 outSize; 329 UInt32 enableIO; 330 AudioStreamBasicDescription srcFormat, dstFormat; 331 332 printf("SetParameters fDevNumInChans = %d fDevNumOutChans = %d bufferSize = %d samplerate = %d\n", fDevNumInChans, fDevNumOutChans, bufferSize, samplerate); 333 334 err = AudioSessionSetActive(true); 335 if (err != noErr) { 336 printf("Couldn't set audio session active\n"); 337 printError(err); 338 return OPEN_ERR; 339 } 340 341 AudioSessionAddPropertyListener(kAudioSessionProperty_AudioRouteChange, AudioSessionPropertyListener, this); 342 AudioSessionAddPropertyListener(kAudioSessionProperty_AudioInputAvailable, AudioSessionPropertyListener, this); 343 AudioSessionAddPropertyListener(kAudioSessionProperty_ServerDied, AudioSessionPropertyListener, this); 344 345 if (SetAudioCategory(fDevNumInChans, fDevNumOutChans) != NO_ERR) { 346 return OPEN_ERR; 347 } 348 349 // Scan Hardware 350 outSize = sizeof(fHWNumInChans); 351 err = AudioSessionGetProperty(kAudioSessionProperty_CurrentHardwareInputNumberChannels, &outSize, &fHWNumInChans); 352 if (err != noErr) { 353 fHWNumInChans = 0; 354 printf("Couldn't get hw input channels\n"); 355 printError(err); 356 } else { 357 printf("Get hw input channels %d\n", fHWNumInChans); 358 } 359 360 outSize = sizeof(fHWNumOutChans); 361 err = AudioSessionGetProperty(kAudioSessionProperty_CurrentHardwareOutputNumberChannels, &outSize, &fHWNumOutChans); 362 if (err != noErr) { 363 fHWNumOutChans = 0; 364 printf("Couldn't get hw output channels\n"); 365 printError(err); 366 } else { 367 printf("Get hw output channels %d\n", fHWNumOutChans); 368 } 369 /* 370 // Possibly reset the audioCategory the way hardware allows 371 // 21/09/2017 cause problem when use bluetooth, deactive for now 372 if (SetAudioCategory(fHWNumInChans, fHWNumOutChans) != NO_ERR) { 373 return OPEN_ERR; 374 } 375 */ 376 if (SetupMixing() < 0) { 377 return OPEN_ERR; 378 } 379 380 Float64 hwSampleRate; 381 outSize = sizeof(hwSampleRate); 382 err = AudioSessionGetProperty(kAudioSessionProperty_CurrentHardwareSampleRate, &outSize, &hwSampleRate); 383 if (err != noErr) { 384 printf("Couldn't get hw sample rate\n"); 385 printError(err); 386 return OPEN_ERR; 387 } else { 388 printf("Get hw sample rate %f\n", hwSampleRate); 389 } 390 391 Float32 hwBufferSize; 392 outSize = sizeof(hwBufferSize); 393 err = AudioSessionGetProperty(kAudioSessionProperty_CurrentHardwareIOBufferDuration, &outSize, &hwBufferSize); 394 if (err != noErr) { 395 printf("Couldn't get hw buffer duration\n"); 396 printError(err); 397 return OPEN_ERR; 398 } else { 399 printf("Get hw buffer duration %f\n", hwBufferSize); 400 } 401 402 Float32 preferredPeriodDuration = float(bufferSize) / float(samplerate); 403 printf("preferredPeriodDuration %f \n", preferredPeriodDuration); 404 405 err = AudioSessionSetProperty(kAudioSessionProperty_PreferredHardwareIOBufferDuration, sizeof(preferredPeriodDuration), &preferredPeriodDuration); 406 if (err != noErr) { 407 printf("Couldn't set i/o buffer duration\n"); 408 printError(err); 409 return OPEN_ERR; 410 } 411 412 Float32 actualPeriodDuration; 413 outSize = sizeof(actualPeriodDuration); 414 err = AudioSessionGetProperty(kAudioSessionProperty_PreferredHardwareIOBufferDuration, &outSize, &actualPeriodDuration); 415 if (err != noErr) { 416 printf("Couldn't get hw buffer duration\n"); 417 printError(err); 418 return OPEN_ERR; 419 } 420 421 printf("preferredPeriodDuration %f actualPeriodDuration %f\n", preferredPeriodDuration, actualPeriodDuration); 422 if (preferredPeriodDuration != actualPeriodDuration) { 423 printf("Couldn't set hw buffer duration\n"); 424 return OPEN_ERR; 425 } 426 427 Float64 preferredSamplerate = float(samplerate); 428 err = AudioSessionSetProperty(kAudioSessionProperty_PreferredHardwareSampleRate, sizeof(preferredSamplerate), &preferredSamplerate); 429 if (err != noErr) { 430 printf("Couldn't set i/o sample rate\n"); 431 printError(err); 432 return OPEN_ERR; 433 } 434 435 Float32 inputLatency; 436 outSize = sizeof(inputLatency); 437 err = AudioSessionGetProperty(kAudioSessionProperty_CurrentHardwareInputLatency, &outSize, &inputLatency); 438 if (err != noErr) { 439 printf("Couldn't get inputLatency\n"); 440 printError(err); 441 } else { 442 printf("inputLatency in sec : %f\n", inputLatency); 443 } 444 445 Float32 outputLatency; 446 outSize = sizeof(outputLatency); 447 err = AudioSessionGetProperty(kAudioSessionProperty_CurrentHardwareOutputLatency, &outSize, &outputLatency); 448 if (err != noErr) { 449 printf("Couldn't get outputLatency\n"); 450 printError(err); 451 } else { 452 printf("outputLatency in sec : %f\n", outputLatency); 453 } 454 455 // AUHAL 456 AudioComponentDescription cd = {kAudioUnitType_Output, kAudioUnitSubType_RemoteIO, kAudioUnitManufacturer_Apple, 0, 0}; 457 AudioComponent HALOutput = AudioComponentFindNext(NULL, &cd); 458 459 err = AudioComponentInstanceNew(HALOutput, &fAUHAL); 460 if (err != noErr) { 461 printf("Error calling OpenAComponent\n"); 462 printError(err); 463 goto error; 464 } 465 466 enableIO = 1; 467 err = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, 0, &enableIO, sizeof(enableIO)); 468 if (err != noErr) { 469 printf("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output\n"); 470 printError(err); 471 goto error; 472 } 473 474 if (fDevNumInChans > 0) { 475 enableIO = 1; 476 } else { 477 enableIO = 0; 478 } 479 err = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, 1, &enableIO, sizeof(enableIO)); 480 if (err != noErr) { 481 printf("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input\n"); 482 printError(err); 483 goto error; 484 } 485 486 UInt32 maxFPS; 487 outSize = sizeof(maxFPS); 488 err = AudioUnitGetProperty(fAUHAL, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0, &maxFPS, &outSize); 489 if (err != noErr) { 490 printf("Couldn't get kAudioUnitProperty_MaximumFramesPerSlice\n"); 491 printError(err); 492 goto error; 493 } else { 494 printf("Get kAudioUnitProperty_MaximumFramesPerSlice %d\n", (unsigned int)maxFPS); 495 } 496 497 err = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 1, (UInt32*)&bufferSize, sizeof(UInt32)); 498 if (err != noErr) { 499 printf("Error calling AudioUnitSetProperty - kAudioUnitProperty_MaximumFramesPerSlice\n"); 500 printError(err); 501 goto error; 502 } 503 504 err = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0, (UInt32*)&bufferSize, sizeof(UInt32)); 505 if (err != noErr) { 506 printf("Error calling AudioUnitSetProperty - kAudioUnitProperty_MaximumFramesPerSlice\n"); 507 printError(err); 508 goto error; 509 } 510 511 err = AudioUnitInitialize(fAUHAL); 512 if (err != noErr) { 513 printf("Cannot initialize AUHAL unit\n"); 514 printError(err); 515 goto error; 516 } 517 518 // Setting format 519 if (fDevNumInChans > 0) { 520 outSize = sizeof(AudioStreamBasicDescription); 521 err = AudioUnitGetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &srcFormat, &outSize); 522 if (err != noErr) { 523 printf("Error calling AudioUnitGetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Output\n"); 524 printError(err); 525 } 526 PrintStreamDesc(&srcFormat); 527 528 srcFormat.mFormatID = kAudioFormatLinearPCM; 529 srcFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked | kLinearPCMFormatFlagIsNonInterleaved; 530 srcFormat.mBytesPerPacket = sizeof(AudioUnitSampleType); 531 srcFormat.mFramesPerPacket = 1; 532 srcFormat.mBytesPerFrame = sizeof(AudioUnitSampleType); 533 srcFormat.mChannelsPerFrame = fDevNumInChans; 534 srcFormat.mBitsPerChannel = 32; 535 536 PrintStreamDesc(&srcFormat); 537 538 err = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &srcFormat, sizeof(AudioStreamBasicDescription)); 539 if (err != noErr) { 540 printf("Error calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Output\n"); 541 printError(err); 542 } 543 } 544 545 if (fDevNumOutChans > 0) { 546 outSize = sizeof(AudioStreamBasicDescription); 547 err = AudioUnitGetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &dstFormat, &outSize); 548 if (err != noErr) { 549 printf("Error calling AudioUnitGetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Input\n"); 550 printError(err); 551 } 552 PrintStreamDesc(&dstFormat); 553 554 dstFormat.mFormatID = kAudioFormatLinearPCM; 555 dstFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked | kLinearPCMFormatFlagIsNonInterleaved; 556 dstFormat.mBytesPerPacket = sizeof(AudioUnitSampleType); 557 dstFormat.mFramesPerPacket = 1; 558 dstFormat.mBytesPerFrame = sizeof(AudioUnitSampleType); 559 dstFormat.mChannelsPerFrame = fDevNumOutChans; 560 dstFormat.mBitsPerChannel = 32; 561 562 PrintStreamDesc(&dstFormat); 563 564 err = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &dstFormat, sizeof(AudioStreamBasicDescription)); 565 if (err != noErr) { 566 printf("Error calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Input\n"); 567 printError(err); 568 } 569 } 570 571 if (fDevNumInChans > 0 && fDevNumOutChans == 0) { 572 AURenderCallbackStruct output; 573 output.inputProc = Render; 574 output.inputProcRefCon = this; 575 err = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_SetInputCallback, kAudioUnitScope_Global, 0, &output, sizeof(output)); 576 if (err != noErr) { 577 printf("Error calling AudioUnitSetProperty - kAudioUnitProperty_SetRenderCallback 1\n"); 578 printError(err); 579 goto error; 580 } 581 } else { 582 AURenderCallbackStruct output; 583 output.inputProc = Render; 584 output.inputProcRefCon = this; 585 err = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &output, sizeof(output)); 586 if (err != noErr) { 587 printf("Error calling AudioUnitSetProperty - kAudioUnitProperty_SetRenderCallback 0\n"); 588 printError(err); 589 goto error; 590 } 591 } 592 593 // Possibly prepare input buffers 594 if (fDevNumInChans > 0) { 595 fCAInputData = (AudioBufferList*)malloc(sizeof(float) + fDevNumInChans * sizeof(AudioBuffer)); 596 fCAInputData->mNumberBuffers = fDevNumInChans; 597 for (int i = 0; i < fDevNumInChans; i++) { 598 fCAInputData->mBuffers[i].mNumberChannels = 1; 599 fCAInputData->mBuffers[i].mDataByteSize = bufferSize * sizeof(float); 600 fCAInputData->mBuffers[i].mData = malloc(bufferSize * sizeof(float)); 601 } 602 } 603 604 return NO_ERR; 605 606 error: 607 AudioUnitUninitialize(fAUHAL); 608 AudioComponentInstanceDispose(fAUHAL); 609 return OPEN_ERR; 610 } 611 612 public: 613 TiPhoneCoreAudioRenderer(audio * audio)614 TiPhoneCoreAudioRenderer(audio* audio) 615 :fAUHAL(0), fDevNumInChans(0), fDevNumOutChans(0), 616 fHWNumInChans(0), fHWNumOutChans(0), 617 fDSP(0), fAudio(audio), fCAInputData(NULL) 618 {} 619 ~TiPhoneCoreAudioRenderer()620 virtual ~TiPhoneCoreAudioRenderer() 621 { 622 if (fCAInputData) { 623 for (int i = 0; i < fDevNumInChans; i++) { 624 free(fCAInputData->mBuffers[i].mData); 625 } 626 free(fCAInputData); 627 } 628 } 629 Open(dsp * dsp,int inChan,int outChan,int buffersize,int samplerate)630 int Open(dsp* dsp, int inChan, int outChan, int buffersize, int samplerate) 631 { 632 fDSP = dsp; 633 fDevNumInChans = inChan; 634 fDevNumOutChans = outChan; 635 636 // Initialize and configure the audio session 637 OSStatus err = AudioSessionInitialize(NULL, NULL, InterruptionListener, this); 638 if (err != noErr && err != kAudioSessionAlreadyInitialized) { 639 printf("Couldn't initialize audio session\n"); 640 printError(err); 641 return OPEN_ERR; 642 } 643 644 if (SetParameters(buffersize, samplerate) < 0) { 645 printf("Cannot set parameters to CoreAudio device\n"); 646 return OPEN_ERR; 647 } 648 649 return NO_ERR; 650 } 651 Close()652 int Close() 653 { 654 AudioUnitUninitialize(fAUHAL); 655 AudioComponentInstanceDispose(fAUHAL); 656 return NO_ERR; 657 } 658 Start()659 int Start() 660 { 661 AudioSessionSetActive(true); 662 663 if (AudioOutputUnitStart(fAUHAL) != noErr) { 664 printf("Error while opening device : device open error\n"); 665 return OPEN_ERR; 666 } else { 667 return NO_ERR; 668 } 669 } 670 Stop()671 int Stop() 672 { 673 AudioSessionSetActive(false); 674 675 if (AudioOutputUnitStop(fAUHAL) != noErr) { 676 printf("Error while closing device : device close error\n"); 677 return OPEN_ERR; 678 } else { 679 return NO_ERR; 680 } 681 } 682 GetNumInputs()683 int GetNumInputs() { return fHWNumInChans; } GetNumOutputs()684 int GetNumOutputs() { return fHWNumOutChans; } 685 686 }; 687 688 /****************************************************************************** 689 ******************************************************************************* 690 691 CORE AUDIO INTERFACE 692 693 ******************************************************************************* 694 *******************************************************************************/ 695 696 class iosaudio : public audio { 697 698 protected: 699 700 TiPhoneCoreAudioRenderer fAudioDevice; 701 int fSampleRate, fBufferSize; 702 703 public: 704 iosaudio(int srate,int bsize)705 iosaudio(int srate, int bsize) 706 :fAudioDevice(this), fSampleRate(srate), fBufferSize(bsize) 707 {} 708 ~iosaudio()709 virtual ~iosaudio() { fAudioDevice.Close(); } 710 init(const char *,dsp * DSP)711 virtual bool init(const char* /*name*/, dsp* DSP) 712 { 713 DSP->init(fSampleRate); 714 if (fAudioDevice.Open(DSP, DSP->getNumInputs(), DSP->getNumOutputs(), fBufferSize, fSampleRate) < 0) { 715 printf("Cannot open iOS audio device\n"); 716 return false; 717 } 718 return true; 719 } 720 start()721 virtual bool start() 722 { 723 if (fAudioDevice.Start() < 0) { 724 printf("Cannot start iOS audio device\n"); 725 return false; 726 } 727 return true; 728 } 729 stop()730 virtual void stop() 731 { 732 fAudioDevice.Stop(); 733 } 734 getBufferSize()735 virtual int getBufferSize() { return fBufferSize; } getSampleRate()736 virtual int getSampleRate() { return fSampleRate; } 737 getNumInputs()738 virtual int getNumInputs() { return fAudioDevice.GetNumInputs(); } getNumOutputs()739 virtual int getNumOutputs() { return fAudioDevice.GetNumOutputs(); } 740 741 }; 742 743 #endif 744 745 /********************END ARCHITECTURE SECTION (part 2/2)****************/ 746 /************************** END coreaudio-ios-dsp.h **************************/ 747