1 /************************************************************************
3 IMPORTANT NOTE : this file contains two clearly delimited sections :
4 the ARCHITECTURE section (in two parts) and the USER section. Each section
5 is governed by its own copyright and license. Please check individually
6 each section for license and copyright information.
7 *************************************************************************/
9 /*******************BEGIN ARCHITECTURE SECTION (part 1/2)****************/
11 /************************************************************************
12 FAUST Architecture File
13 Copyright (C) 2003-2011 GRAME, Centre National de Creation Musicale
14 ---------------------------------------------------------------------
15 This Architecture section is free software; you can redistribute it
16 and/or modify it under the terms of the GNU General Public License
17 as published by the Free Software Foundation; either version 3 of
18 the License, or (at your option) any later version.
20 This program is distributed in the hope that it will be useful,
21 but WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 GNU General Public License for more details.
25 You should have received a copy of the GNU General Public License
26 along with this program; If not, see <http://www.gnu.org/licenses/>.
28 EXCEPTION : As a special exception, you may create a larger work
29 that contains this FAUST architecture section and distribute
30 that work under terms of your choice, so long as this FAUST
31 architecture section is not modified.
34 ************************************************************************
35 ************************************************************************/
47 #include <sys/ioctl.h>
51 #include <sys/types.h>
65 #include <AudioToolbox/AudioConverter.h>
66 #include <AudioToolbox/AudioServices.h>
67 #include <AudioUnit/AudioUnit.h>
71 /******************************************************************************
72 *******************************************************************************
76 *******************************************************************************
77 *******************************************************************************/
81 /******************************************************************************
82 *******************************************************************************
86 *******************************************************************************
87 *******************************************************************************/
90 #include "audio/dsp.h"
93 /********************END ARCHITECTURE SECTION (part 1/2)****************/
95 /**************************BEGIN USER SECTION **************************/
99 /***************************END USER SECTION ***************************/
101 /*******************BEGIN ARCHITECTURE SECTION (part 2/2)***************/
105 /******************************************************************************
106 *******************************************************************************
110 *******************************************************************************
111 *******************************************************************************/
113 #define MAX_CHANNELS 256
117 class TiPhoneCoreAudioRenderer
130 AudioBufferList
* fCAInputData
;
132 float* fInChannel
[MAX_CHANNELS
];
133 float* fOutChannel
[MAX_CHANNELS
];
135 static OSStatus
Render(void *inRefCon
,
136 AudioUnitRenderActionFlags
*ioActionFlags
,
137 const AudioTimeStamp
*inTimeStamp
,
139 UInt32 inNumberFrames
,
140 AudioBufferList
*ioData
);
142 static void InterruptionListener(void *inClientData
, UInt32 inInterruption
);
146 TiPhoneCoreAudioRenderer(int input
, int output
)
147 :fDevNumInChans(input
), fDevNumOutChans(output
), fCAInputData(NULL
)
149 memset(fInChannel
, 0, sizeof(float*) * MAX_CHANNELS
);
150 memset(fOutChannel
, 0, sizeof(float*) * MAX_CHANNELS
);
152 for (int i
= 0; i
< fDevNumInChans
; i
++) {
153 fInChannel
[i
] = new float[8192];
156 for (int i
= 0; i
< fDevNumOutChans
; i
++) {
157 fOutChannel
[i
] = new float[8192];
161 virtual ~TiPhoneCoreAudioRenderer()
163 for (int i
= 0; i
< fDevNumInChans
; i
++) {
164 delete[] fInChannel
[i
];
167 for (int i
= 0; i
< fDevNumOutChans
; i
++) {
168 delete[] fOutChannel
[i
];
172 for (int i
= 0; i
< fDevNumInChans
; i
++) {
173 free(fCAInputData
->mBuffers
[i
].mData
);
179 int Open(int bufferSize
, int sampleRate
);
187 typedef TiPhoneCoreAudioRenderer
* TiPhoneCoreAudioRendererPtr
;
189 static void PrintStreamDesc(AudioStreamBasicDescription
*inDesc
)
191 printf("- - - - - - - - - - - - - - - - - - - -\n");
192 printf(" Sample Rate:%f\n", inDesc
->mSampleRate
);
193 printf(" Format ID:%.*s\n", (int) sizeof(inDesc
->mFormatID
), (char*)&inDesc
->mFormatID
);
194 printf(" Format Flags:%lX\n", inDesc
->mFormatFlags
);
195 printf(" Bytes per Packet:%ld\n", inDesc
->mBytesPerPacket
);
196 printf(" Frames per Packet:%ld\n", inDesc
->mFramesPerPacket
);
197 printf(" Bytes per Frame:%ld\n", inDesc
->mBytesPerFrame
);
198 printf(" Channels per Frame:%ld\n", inDesc
->mChannelsPerFrame
);
199 printf(" Bits per Channel:%ld\n", inDesc
->mBitsPerChannel
);
200 printf("- - - - - - - - - - - - - - - - - - - -\n");
203 static void printError(OSStatus err
)
206 case kAudioConverterErr_FormatNotSupported
:
207 printf("error code : kAudioConverterErr_FormatNotSupported\n");
209 case kAudioConverterErr_OperationNotSupported
:
210 printf("error code : kAudioConverterErr_OperationNotSupported\n");
212 case kAudioConverterErr_PropertyNotSupported
:
213 printf("error code : kAudioConverterErr_PropertyNotSupported\n");
215 case kAudioConverterErr_InvalidInputSize
:
216 printf("error code : kAudioConverterErr_InvalidInputSize\n");
218 case kAudioConverterErr_InvalidOutputSize
:
219 printf("error code : kAudioConverterErr_InvalidOutputSize\n");
221 case kAudioConverterErr_UnspecifiedError
:
222 printf("error code : kAudioConverterErr_UnspecifiedError\n");
224 case kAudioConverterErr_BadPropertySizeError
:
225 printf("error code : kAudioConverterErr_BadPropertySizeError\n");
227 case kAudioConverterErr_RequiresPacketDescriptionsError
:
228 printf("error code : kAudioConverterErr_RequiresPacketDescriptionsError\n");
230 case kAudioConverterErr_InputSampleRateOutOfRange
:
231 printf("error code : kAudioConverterErr_InputSampleRateOutOfRange\n");
233 case kAudioConverterErr_OutputSampleRateOutOfRange
:
234 printf("error code : kAudioConverterErr_OutputSampleRateOutOfRange\n");
237 printf("error code : unknown\n");
242 OSStatus
TiPhoneCoreAudioRenderer::Render(void *inRefCon
,
243 AudioUnitRenderActionFlags
*ioActionFlags
,
244 const AudioTimeStamp
*inTimeStamp
,
246 UInt32 inNumberFrames
,
247 AudioBufferList
*ioData
)
249 TiPhoneCoreAudioRendererPtr renderer
= (TiPhoneCoreAudioRendererPtr
)inRefCon
;
250 AudioUnitRender(renderer
->fAUHAL
, ioActionFlags
, inTimeStamp
, 1, inNumberFrames
, renderer
->fCAInputData
);
252 float coef
= float(LONG_MAX
);
253 float inv_coef
= 1.f
/float(LONG_MAX
);
255 if (renderer
->fHWNumInChans
== 1) {
257 for (int chan
= 0; chan
< renderer
->fDevNumInChans
; chan
++) {
258 for (int frame
= 0; frame
< inNumberFrames
; frame
++) {
259 renderer
->fInChannel
[chan
][frame
] = float(((int*)renderer
->fCAInputData
->mBuffers
[0].mData
)[frame
]) * inv_coef
;
263 for (int chan
= 0; chan
< renderer
->fDevNumInChans
; chan
++) {
264 for (int frame
= 0; frame
< inNumberFrames
; frame
++) {
265 renderer
->fInChannel
[chan
][frame
] = float(((int*)renderer
->fCAInputData
->mBuffers
[chan
].mData
)[frame
]) * inv_coef
;
270 DSP
.compute((int)inNumberFrames
, renderer
->fInChannel
, renderer
->fOutChannel
);
272 for (int chan
= 0; chan
< renderer
->fDevNumOutChans
; chan
++) {
273 for (int frame
= 0; frame
< inNumberFrames
; frame
++) {
274 ((long*)ioData
->mBuffers
[chan
].mData
)[frame
] = long(renderer
->fOutChannel
[chan
][frame
] * coef
);
281 void TiPhoneCoreAudioRenderer::InterruptionListener(void *inClientData
, UInt32 inInterruption
)
283 TiPhoneCoreAudioRenderer
*obj
= (TiPhoneCoreAudioRenderer
*)inClientData
;
284 printf("Session interrupted! --- %s ---", inInterruption
== kAudioSessionBeginInterruption
? "Begin Interruption" : "End Interruption");
286 if (inInterruption
== kAudioSessionEndInterruption
) {
287 // make sure we are again the active session
288 AudioSessionSetActive(true);
289 AudioOutputUnitStart(obj
->fAUHAL
);
292 if (inInterruption
== kAudioSessionBeginInterruption
) {
293 AudioOutputUnitStop(obj
->fAUHAL
);
297 int TiPhoneCoreAudioRenderer::Open(int bufferSize
, int samplerate
)
302 AudioStreamBasicDescription srcFormat
, dstFormat
;
304 printf("OpenDefault fDevNumInChans = %ld fDevNumOutChans = %ld bufferSize = %ld samplerate = %ld\n", fDevNumInChans
, fDevNumOutChans
, bufferSize
, samplerate
);
306 // Initialize and configure the audio session
307 err1
= AudioSessionInitialize(NULL
, NULL
, InterruptionListener
, this);
309 printf("Couldn't initialize audio session\n");
314 err1
= AudioSessionSetActive(true);
316 printf("Couldn't set audio session active\n");
321 UInt32 audioCategory
= kAudioSessionCategory_PlayAndRecord
;
322 err1
= AudioSessionSetProperty(kAudioSessionProperty_AudioCategory
, sizeof(audioCategory
), &audioCategory
);
324 printf("Couldn't set audio category\n");
329 //err1 = AudioSessionAddPropertyListener(kAudioSessionProperty_AudioRouteChange, propListener, self), "couldn't set property listener");
331 Float64 hwSampleRate
;
332 outSize
= sizeof(hwSampleRate
);
333 err1
= AudioSessionGetProperty(kAudioSessionProperty_CurrentHardwareSampleRate
, &outSize
, &hwSampleRate
);
335 printf("Couldn't get hw sample rate\n");
339 printf("Get hw sample rate %f\n", hwSampleRate
);
342 Float32 hwBufferSize
;
343 outSize
= sizeof(hwBufferSize
);
344 err1
= AudioSessionGetProperty(kAudioSessionProperty_CurrentHardwareIOBufferDuration
, &outSize
, &hwBufferSize
);
346 printf("Couldn't get hw buffer duration\n");
350 printf("Get hw buffer duration %f\n", hwBufferSize
);
353 outSize
= sizeof(fHWNumInChans
);
354 err1
= AudioSessionGetProperty(kAudioSessionProperty_CurrentHardwareInputNumberChannels
, &outSize
, &fHWNumInChans
);
356 printf("Couldn't get hw input channels\n");
360 printf("Get hw input channels %d\n", fHWNumInChans
);
363 outSize
= sizeof(fHWNumOutChans
);
364 err1
= AudioSessionGetProperty(kAudioSessionProperty_CurrentHardwareOutputNumberChannels
, &outSize
, &fHWNumOutChans
);
366 printf("Couldn't get hw output channels\n");
370 printf("Get hw output channels %d\n", fHWNumOutChans
);
373 Float32 preferredBufferSize
= float(bufferSize
) / float(samplerate
);
374 printf("preferredBufferSize %f \n", preferredBufferSize
);
376 err1
= AudioSessionSetProperty(kAudioSessionProperty_PreferredHardwareIOBufferDuration
, sizeof(preferredBufferSize
), &preferredBufferSize
);
378 printf("Couldn't set i/o buffer duration\n");
383 Float64 preferredSamplerate
= float(samplerate
);
384 err1
= AudioSessionSetProperty(kAudioSessionProperty_PreferredHardwareSampleRate
, sizeof(preferredSamplerate
), &preferredSamplerate
);
386 printf("Couldn't set i/o sample rate\n");
392 AudioComponentDescription cd
= {kAudioUnitType_Output
, kAudioUnitSubType_RemoteIO
, kAudioUnitManufacturer_Apple
, 0, 0};
393 AudioComponent HALOutput
= AudioComponentFindNext(NULL
, &cd
);
395 err1
= AudioComponentInstanceNew(HALOutput
, &fAUHAL
);
397 printf("Error calling OpenAComponent\n");
403 err1
= AudioUnitSetProperty(fAUHAL
, kAudioOutputUnitProperty_EnableIO
, kAudioUnitScope_Output
, 0, &enableIO
, sizeof(enableIO
));
405 printf("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output\n");
411 err1
= AudioUnitSetProperty(fAUHAL
, kAudioOutputUnitProperty_EnableIO
, kAudioUnitScope_Input
, 1, &enableIO
, sizeof(enableIO
));
413 printf("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input\n");
419 outSize
= sizeof(maxFPS
);
420 err1
= AudioUnitGetProperty(fAUHAL
, kAudioUnitProperty_MaximumFramesPerSlice
, kAudioUnitScope_Global
, 0, &maxFPS
, &outSize
);
422 printf("Couldn't get kAudioUnitProperty_MaximumFramesPerSlice\n");
426 printf("Get kAudioUnitProperty_MaximumFramesPerSlice %d\n", maxFPS
);
429 err1
= AudioUnitSetProperty(fAUHAL
, kAudioUnitProperty_MaximumFramesPerSlice
, kAudioUnitScope_Global
, 1, (UInt32
*)&bufferSize
, sizeof(UInt32
));
431 printf("Error calling AudioUnitSetProperty - kAudioUnitProperty_MaximumFramesPerSlice\n");
436 err1
= AudioUnitSetProperty(fAUHAL
, kAudioUnitProperty_MaximumFramesPerSlice
, kAudioUnitScope_Global
, 0, (UInt32
*)&bufferSize
, sizeof(UInt32
));
438 printf("Error calling AudioUnitSetProperty - kAudioUnitProperty_MaximumFramesPerSlice\n");
443 err1
= AudioUnitInitialize(fAUHAL
);
445 printf("Cannot initialize AUHAL unit\n");
452 if (fDevNumInChans
> 0) {
453 outSize
= sizeof(AudioStreamBasicDescription
);
454 err1
= AudioUnitGetProperty(fAUHAL
, kAudioUnitProperty_StreamFormat
, kAudioUnitScope_Output
, 1, &srcFormat
, &outSize
);
456 printf("Error calling AudioUnitGetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Output\n");
459 PrintStreamDesc(&srcFormat
);
461 srcFormat
.mFormatID
= kAudioFormatLinearPCM
;
462 srcFormat
.mFormatFlags
= kAudioFormatFlagsCanonical
| kLinearPCMFormatFlagIsNonInterleaved
;
463 srcFormat
.mBytesPerPacket
= sizeof(AudioUnitSampleType
);
464 srcFormat
.mFramesPerPacket
= 1;
465 srcFormat
.mBytesPerFrame
= sizeof(AudioUnitSampleType
);
466 srcFormat
.mChannelsPerFrame
= fDevNumInChans
;
467 srcFormat
.mBitsPerChannel
= 32;
469 PrintStreamDesc(&srcFormat
);
471 err1
= AudioUnitSetProperty(fAUHAL
, kAudioUnitProperty_StreamFormat
, kAudioUnitScope_Output
, 1, &srcFormat
, sizeof(AudioStreamBasicDescription
));
473 printf("Error calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Output\n");
478 if (fDevNumOutChans
> 0) {
479 outSize
= sizeof(AudioStreamBasicDescription
);
480 err1
= AudioUnitGetProperty(fAUHAL
, kAudioUnitProperty_StreamFormat
, kAudioUnitScope_Input
, 0, &dstFormat
, &outSize
);
482 printf("Error calling AudioUnitGetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Input\n");
485 PrintStreamDesc(&dstFormat
);
487 dstFormat
.mFormatID
= kAudioFormatLinearPCM
;
488 dstFormat
.mFormatFlags
= kAudioFormatFlagsCanonical
| kLinearPCMFormatFlagIsNonInterleaved
;
489 dstFormat
.mBytesPerPacket
= sizeof(AudioUnitSampleType
);
490 dstFormat
.mFramesPerPacket
= 1;
491 dstFormat
.mBytesPerFrame
= sizeof(AudioUnitSampleType
);
492 dstFormat
.mChannelsPerFrame
= fDevNumOutChans
;
493 dstFormat
.mBitsPerChannel
= 32;
495 PrintStreamDesc(&dstFormat
);
497 err1
= AudioUnitSetProperty(fAUHAL
, kAudioUnitProperty_StreamFormat
, kAudioUnitScope_Input
, 0, &dstFormat
, sizeof(AudioStreamBasicDescription
));
499 printf("Error calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Input\n");
504 if (fDevNumInChans
> 0 && fDevNumOutChans
== 0) {
505 AURenderCallbackStruct output
;
506 output
.inputProc
= Render
;
507 output
.inputProcRefCon
= this;
508 err1
= AudioUnitSetProperty(fAUHAL
, kAudioOutputUnitProperty_SetInputCallback
, kAudioUnitScope_Global
, 0, &output
, sizeof(output
));
510 printf("Error calling AudioUnitSetProperty - kAudioUnitProperty_SetRenderCallback 1\n");
515 AURenderCallbackStruct output
;
516 output
.inputProc
= Render
;
517 output
.inputProcRefCon
= this;
518 err1
= AudioUnitSetProperty(fAUHAL
, kAudioUnitProperty_SetRenderCallback
, kAudioUnitScope_Input
, 0, &output
, sizeof(output
));
520 printf("Error calling AudioUnitSetProperty - kAudioUnitProperty_SetRenderCallback 0\n");
527 fCAInputData
= (AudioBufferList
*)malloc(sizeof(UInt32
) + fDevNumInChans
* sizeof(AudioBuffer
));
528 fCAInputData
->mNumberBuffers
= fDevNumInChans
;
529 for (int i
= 0; i
< fDevNumInChans
; i
++) {
530 fCAInputData
->mBuffers
[i
].mNumberChannels
= 1;
531 fCAInputData
->mBuffers
[i
].mDataByteSize
= bufferSize
* sizeof(int);
532 fCAInputData
->mBuffers
[i
].mData
= malloc(bufferSize
* sizeof(int));
538 AudioUnitUninitialize(fAUHAL
);
539 AudioComponentInstanceDispose(fAUHAL
);
543 int TiPhoneCoreAudioRenderer::Close()
545 AudioUnitUninitialize(fAUHAL
);
546 AudioComponentInstanceDispose(fAUHAL
);
550 int TiPhoneCoreAudioRenderer::Start()
552 AudioSessionSetActive(true);
553 OSStatus err
= AudioOutputUnitStart(fAUHAL
);
556 printf("Error while opening device : device open error \n");
563 int TiPhoneCoreAudioRenderer::Stop()
565 OSStatus err
= AudioOutputUnitStop(fAUHAL
);
568 printf("Error while closing device : device close error \n");
576 /********************END ARCHITECTURE SECTION (part 2/2)****************/