00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
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
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
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
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
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
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
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
00363
00364
00365
00366
00367
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 }