1 /************************************************************************
2
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 *************************************************************************/
8
9 /*******************BEGIN ARCHITECTURE SECTION (part 1/2)****************/
10
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.
19
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.
24
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/>.
27
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.
32
33 ************************************************************************
34 ************************************************************************/
35
36 /* link with */
37 #include <math.h>
38 /* link with */
39 #include <stdlib.h>
40 #include <stdio.h>
41 #include <string.h>
42 #include <limits.h>
43 #include <math.h>
44 #include <errno.h>
45 #include <time.h>
46 #include <sys/ioctl.h>
47 #include <unistd.h>
48 #include <fcntl.h>
49 #include <pwd.h>
50 #include <sys/types.h>
51 #include <assert.h>
52 #include <pthread.h>
53 #include <sys/wait.h>
54
55 #include <list>
56 #include <vector>
57 #include <iostream>
58 #include <fstream>
59 #include <stack>
60 #include <list>
61 #include <map>
62 #include <libgen.h>
63
64 #include <AudioToolbox/AudioConverter.h>
65 #include <AudioToolbox/AudioServices.h>
66 #include <AudioUnit/AudioUnit.h>
67
68 using namespace std;
69
70 /******************************************************************************
71 *******************************************************************************
72
73 VECTOR INTRINSICS
74
75 *******************************************************************************
76 *******************************************************************************/
77
78 <<includeIntrinsic>>
79
80 /******************************************************************************
81 *******************************************************************************
82
83 USER INTERFACE
84
85 *******************************************************************************
86 *******************************************************************************/
87
88 #include "CocoaUI.h"
89 #include "audio/dsp.h"
90 #include "misc.h"
91
92 /********************END ARCHITECTURE SECTION (part 1/2)****************/
93
94 /**************************BEGIN USER SECTION **************************/
95
96 <<includeclass>>
97
98 /***************************END USER SECTION ***************************/
99
100 /*******************BEGIN ARCHITECTURE SECTION (part 2/2)***************/
101
102 mydsp DSP;
103
104 /******************************************************************************
105 *******************************************************************************
106
107 COREAUDIO INTERFACE
108
109 *******************************************************************************
110 *******************************************************************************/
111
112 #define MAX_CHANNELS 256
113 #define OPEN_ERR -1
114 #define NO_ERR 0
115
116 class TiPhoneCoreAudioRenderer
117 {
118
119 private:
120
121 AudioUnit fAUHAL;
122
123 int fDevNumInChans;
124 int fDevNumOutChans;
125
126 int fHWNumInChans;
127 int fHWNumOutChans;
128
129 AudioBufferList* fCAInputData;
130
131 float* fInChannel[MAX_CHANNELS];
132 float* fOutChannel[MAX_CHANNELS];
133
134 static OSStatus Render(void *inRefCon,
135 AudioUnitRenderActionFlags *ioActionFlags,
136 const AudioTimeStamp *inTimeStamp,
137 UInt32 inBusNumber,
138 UInt32 inNumberFrames,
139 AudioBufferList *ioData);
140
141 static void InterruptionListener(void *inClientData, UInt32 inInterruption);
142
143 public:
144
TiPhoneCoreAudioRenderer(int input,int output)145 TiPhoneCoreAudioRenderer(int input, int output)
146 :fDevNumInChans(input), fDevNumOutChans(output), fCAInputData(NULL)
147 {
148 memset(fInChannel, 0, sizeof(float*) * MAX_CHANNELS);
149 memset(fOutChannel, 0, sizeof(float*) * MAX_CHANNELS);
150
151 for (int i = 0; i < fDevNumInChans; i++) {
152 fInChannel[i] = new float[8192];
153 }
154
155 for (int i = 0; i < fDevNumOutChans; i++) {
156 fOutChannel[i] = new float[8192];
157 }
158 }
159
~TiPhoneCoreAudioRenderer()160 virtual ~TiPhoneCoreAudioRenderer()
161 {
162 for (int i = 0; i < fDevNumInChans; i++) {
163 delete[] fInChannel[i];
164 }
165
166 for (int i = 0; i < fDevNumOutChans; i++) {
167 delete[] fOutChannel[i];
168 }
169
170 if (fCAInputData) {
171 for (int i = 0; i < fDevNumInChans; i++) {
172 free(fCAInputData->mBuffers[i].mData);
173 }
174 free(fCAInputData);
175 }
176 }
177
178 int Open(int bufferSize, int sampleRate);
179 int Close();
180
181 int Start();
182 int Stop();
183
184 };
185
186 typedef TiPhoneCoreAudioRenderer * TiPhoneCoreAudioRendererPtr;
187
PrintStreamDesc(AudioStreamBasicDescription * inDesc)188 static void PrintStreamDesc(AudioStreamBasicDescription *inDesc)
189 {
190 printf("- - - - - - - - - - - - - - - - - - - -\n");
191 printf(" Sample Rate:%f\n", inDesc->mSampleRate);
192 printf(" Format ID:%.*s\n", (int) sizeof(inDesc->mFormatID), (char*)&inDesc->mFormatID);
193 printf(" Format Flags:%lX\n", inDesc->mFormatFlags);
194 printf(" Bytes per Packet:%ld\n", inDesc->mBytesPerPacket);
195 printf(" Frames per Packet:%ld\n", inDesc->mFramesPerPacket);
196 printf(" Bytes per Frame:%ld\n", inDesc->mBytesPerFrame);
197 printf(" Channels per Frame:%ld\n", inDesc->mChannelsPerFrame);
198 printf(" Bits per Channel:%ld\n", inDesc->mBitsPerChannel);
199 printf("- - - - - - - - - - - - - - - - - - - -\n");
200 }
201
printError(OSStatus err)202 static void printError(OSStatus err)
203 {
204 switch (err) {
205 case kAudioConverterErr_FormatNotSupported:
206 printf("error code : kAudioConverterErr_FormatNotSupported\n");
207 break;
208 case kAudioConverterErr_OperationNotSupported:
209 printf("error code : kAudioConverterErr_OperationNotSupported\n");
210 break;
211 case kAudioConverterErr_PropertyNotSupported:
212 printf("error code : kAudioConverterErr_PropertyNotSupported\n");
213 break;
214 case kAudioConverterErr_InvalidInputSize:
215 printf("error code : kAudioConverterErr_InvalidInputSize\n");
216 break;
217 case kAudioConverterErr_InvalidOutputSize:
218 printf("error code : kAudioConverterErr_InvalidOutputSize\n");
219 break;
220 case kAudioConverterErr_UnspecifiedError:
221 printf("error code : kAudioConverterErr_UnspecifiedError\n");
222 break;
223 case kAudioConverterErr_BadPropertySizeError:
224 printf("error code : kAudioConverterErr_BadPropertySizeError\n");
225 break;
226 case kAudioConverterErr_RequiresPacketDescriptionsError:
227 printf("error code : kAudioConverterErr_RequiresPacketDescriptionsError\n");
228 break;
229 case kAudioConverterErr_InputSampleRateOutOfRange:
230 printf("error code : kAudioConverterErr_InputSampleRateOutOfRange\n");
231 break;
232 case kAudioConverterErr_OutputSampleRateOutOfRange:
233 printf("error code : kAudioConverterErr_OutputSampleRateOutOfRange\n");
234 break;
235 default:
236 printf("error code : unknown\n");
237 break;
238 }
239 }
240
Render(void * inRefCon,AudioUnitRenderActionFlags * ioActionFlags,const AudioTimeStamp * inTimeStamp,UInt32,UInt32 inNumberFrames,AudioBufferList * ioData)241 OSStatus TiPhoneCoreAudioRenderer::Render(void *inRefCon,
242 AudioUnitRenderActionFlags *ioActionFlags,
243 const AudioTimeStamp *inTimeStamp,
244 UInt32,
245 UInt32 inNumberFrames,
246 AudioBufferList *ioData)
247 {
248 TiPhoneCoreAudioRendererPtr renderer = (TiPhoneCoreAudioRendererPtr)inRefCon;
249 AudioUnitRender(renderer->fAUHAL, ioActionFlags, inTimeStamp, 1, inNumberFrames, renderer->fCAInputData);
250
251 float coef = float(LONG_MAX);
252 float inv_coef = 1.f/float(LONG_MAX);
253
254 if (renderer->fHWNumInChans == 1) {
255 // Mono ==> stereo
256 for (int chan = 0; chan < renderer->fDevNumInChans; chan++) {
257 for (int frame = 0; frame < inNumberFrames; frame++) {
258 renderer->fInChannel[chan][frame] = float(((int*)renderer->fCAInputData->mBuffers[0].mData)[frame]) * inv_coef;
259 }
260 }
261 } else {
262 for (int chan = 0; chan < renderer->fDevNumInChans; chan++) {
263 for (int frame = 0; frame < inNumberFrames; frame++) {
264 renderer->fInChannel[chan][frame] = float(((int*)renderer->fCAInputData->mBuffers[chan].mData)[frame]) * inv_coef;
265 }
266 }
267 }
268
269 DSP.compute((int)inNumberFrames, renderer->fInChannel, renderer->fOutChannel);
270
271 for (int chan = 0; chan < renderer->fDevNumOutChans; chan++) {
272 for (int frame = 0; frame < inNumberFrames; frame++) {
273 ((long*)ioData->mBuffers[chan].mData)[frame] = long(renderer->fOutChannel[chan][frame] * coef);
274 }
275 }
276
277 return 0;
278 }
279
InterruptionListener(void * inClientData,UInt32 inInterruption)280 void TiPhoneCoreAudioRenderer::InterruptionListener(void *inClientData, UInt32 inInterruption)
281 {
282 TiPhoneCoreAudioRenderer *obj = (TiPhoneCoreAudioRenderer*)inClientData;
283 printf("Session interrupted! --- %s ---", inInterruption == kAudioSessionBeginInterruption ? "Begin Interruption" : "End Interruption");
284
285 if (inInterruption == kAudioSessionEndInterruption) {
286 // make sure we are again the active session
287 AudioSessionSetActive(true);
288 AudioOutputUnitStart(obj->fAUHAL);
289 }
290
291 if (inInterruption == kAudioSessionBeginInterruption) {
292 AudioOutputUnitStop(obj->fAUHAL);
293 }
294 }
295
Open(int bufferSize,int samplerate)296 int TiPhoneCoreAudioRenderer::Open(int bufferSize, int samplerate)
297 {
298 OSStatus err1;
299 UInt32 outSize;
300 UInt32 enableIO;
301 AudioStreamBasicDescription srcFormat, dstFormat;
302
303 printf("OpenDefault fDevNumInChans = %ld fDevNumOutChans = %ld bufferSize = %ld samplerate = %ld\n", fDevNumInChans, fDevNumOutChans, bufferSize, samplerate);
304
305 // Initialize and configure the audio session
306 err1 = AudioSessionInitialize(NULL, NULL, InterruptionListener, this);
307 if (err1 != noErr) {
308 printf("Couldn't initialize audio session\n");
309 printError(err1);
310 return OPEN_ERR;
311 }
312
313 err1 = AudioSessionSetActive(true);
314 if (err1 != noErr) {
315 printf("Couldn't set audio session active\n");
316 printError(err1);
317 return OPEN_ERR;
318 }
319
320 UInt32 audioCategory = kAudioSessionCategory_PlayAndRecord;
321 err1 = AudioSessionSetProperty(kAudioSessionProperty_AudioCategory, sizeof(audioCategory), &audioCategory);
322 if (err1 != noErr) {
323 printf("Couldn't set audio category\n");
324 printError(err1);
325 return OPEN_ERR;
326 }
327
328 //err1 = AudioSessionAddPropertyListener(kAudioSessionProperty_AudioRouteChange, propListener, self), "couldn't set property listener");
329
330 Float64 hwSampleRate;
331 outSize = sizeof(hwSampleRate);
332 err1 = AudioSessionGetProperty(kAudioSessionProperty_CurrentHardwareSampleRate, &outSize, &hwSampleRate);
333 if (err1 != noErr) {
334 printf("Couldn't get hw sample rate\n");
335 printError(err1);
336 return OPEN_ERR;
337 } else {
338 printf("Get hw sample rate %f\n", hwSampleRate);
339 }
340
341 Float32 hwBufferSize;
342 outSize = sizeof(hwBufferSize);
343 err1 = AudioSessionGetProperty(kAudioSessionProperty_CurrentHardwareIOBufferDuration, &outSize, &hwBufferSize);
344 if (err1 != noErr) {
345 printf("Couldn't get hw buffer duration\n");
346 printError(err1);
347 return OPEN_ERR;
348 } else {
349 printf("Get hw buffer duration %f\n", hwBufferSize);
350 }
351
352 outSize = sizeof(fHWNumInChans);
353 err1 = AudioSessionGetProperty(kAudioSessionProperty_CurrentHardwareInputNumberChannels, &outSize, &fHWNumInChans);
354 if (err1 != noErr) {
355 printf("Couldn't get hw input channels\n");
356 printError(err1);
357 return OPEN_ERR;
358 } else {
359 printf("Get hw input channels %d\n", fHWNumInChans);
360 }
361
362 outSize = sizeof(fHWNumOutChans);
363 err1 = AudioSessionGetProperty(kAudioSessionProperty_CurrentHardwareOutputNumberChannels, &outSize, &fHWNumOutChans);
364 if (err1 != noErr) {
365 printf("Couldn't get hw output channels\n");
366 printError(err1);
367 return OPEN_ERR;
368 } else {
369 printf("Get hw output channels %d\n", fHWNumOutChans);
370 }
371
372 Float32 preferredBufferSize = float(bufferSize) / float(samplerate);
373 printf("preferredBufferSize %f \n", preferredBufferSize);
374
375 err1 = AudioSessionSetProperty(kAudioSessionProperty_PreferredHardwareIOBufferDuration, sizeof(preferredBufferSize), &preferredBufferSize);
376 if (err1 != noErr) {
377 printf("Couldn't set i/o buffer duration\n");
378 printError(err1);
379 return OPEN_ERR;
380 }
381
382 Float64 preferredSamplerate = float(samplerate);
383 err1 = AudioSessionSetProperty(kAudioSessionProperty_PreferredHardwareSampleRate, sizeof(preferredSamplerate), &preferredSamplerate);
384 if (err1 != noErr) {
385 printf("Couldn't set i/o sample rate\n");
386 printError(err1);
387 return OPEN_ERR;
388 }
389
390 // AUHAL
391 AudioComponentDescription cd = {kAudioUnitType_Output, kAudioUnitSubType_RemoteIO, kAudioUnitManufacturer_Apple, 0, 0};
392 AudioComponent HALOutput = AudioComponentFindNext(NULL, &cd);
393
394 err1 = AudioComponentInstanceNew(HALOutput, &fAUHAL);
395 if (err1 != noErr) {
396 printf("Error calling OpenAComponent\n");
397 printError(err1);
398 goto error;
399 }
400
401 enableIO = 1;
402 err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, 0, &enableIO, sizeof(enableIO));
403 if (err1 != noErr) {
404 printf("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output\n");
405 printError(err1);
406 goto error;
407 }
408
409 enableIO = 1;
410 err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, 1, &enableIO, sizeof(enableIO));
411 if (err1 != noErr) {
412 printf("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input\n");
413 printError(err1);
414 goto error;
415 }
416
417 UInt32 maxFPS;
418 outSize = sizeof(maxFPS);
419 err1 = AudioUnitGetProperty(fAUHAL, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0, &maxFPS, &outSize);
420 if (err1 != noErr) {
421 printf("Couldn't get kAudioUnitProperty_MaximumFramesPerSlice\n");
422 printError(err1);
423 goto error;
424 } else {
425 printf("Get kAudioUnitProperty_MaximumFramesPerSlice %d\n", maxFPS);
426 }
427
428 err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 1, (UInt32*)&bufferSize, sizeof(UInt32));
429 if (err1 != noErr) {
430 printf("Error calling AudioUnitSetProperty - kAudioUnitProperty_MaximumFramesPerSlice\n");
431 printError(err1);
432 goto error;
433 }
434
435 err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0, (UInt32*)&bufferSize, sizeof(UInt32));
436 if (err1 != noErr) {
437 printf("Error calling AudioUnitSetProperty - kAudioUnitProperty_MaximumFramesPerSlice\n");
438 printError(err1);
439 goto error;
440 }
441
442 err1 = AudioUnitInitialize(fAUHAL);
443 if (err1 != noErr) {
444 printf("Cannot initialize AUHAL unit\n");
445 printError(err1);
446 goto error;
447 }
448
449 // Setting format
450
451 if (fDevNumInChans > 0) {
452 outSize = sizeof(AudioStreamBasicDescription);
453 err1 = AudioUnitGetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &srcFormat, &outSize);
454 if (err1 != noErr) {
455 printf("Error calling AudioUnitGetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Output\n");
456 printError(err1);
457 }
458 PrintStreamDesc(&srcFormat);
459
460 srcFormat.mFormatID = kAudioFormatLinearPCM;
461 srcFormat.mFormatFlags = kAudioFormatFlagsCanonical | kLinearPCMFormatFlagIsNonInterleaved;
462 srcFormat.mBytesPerPacket = sizeof(AudioUnitSampleType);
463 srcFormat.mFramesPerPacket = 1;
464 srcFormat.mBytesPerFrame = sizeof(AudioUnitSampleType);
465 srcFormat.mChannelsPerFrame = fDevNumInChans;
466 srcFormat.mBitsPerChannel = 32;
467
468 PrintStreamDesc(&srcFormat);
469
470 err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &srcFormat, sizeof(AudioStreamBasicDescription));
471 if (err1 != noErr) {
472 printf("Error calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Output\n");
473 printError(err1);
474 }
475 }
476
477 if (fDevNumOutChans > 0) {
478 outSize = sizeof(AudioStreamBasicDescription);
479 err1 = AudioUnitGetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &dstFormat, &outSize);
480 if (err1 != noErr) {
481 printf("Error calling AudioUnitGetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Input\n");
482 printError(err1);
483 }
484 PrintStreamDesc(&dstFormat);
485
486 dstFormat.mFormatID = kAudioFormatLinearPCM;
487 dstFormat.mFormatFlags = kAudioFormatFlagsCanonical | kLinearPCMFormatFlagIsNonInterleaved;
488 dstFormat.mBytesPerPacket = sizeof(AudioUnitSampleType);
489 dstFormat.mFramesPerPacket = 1;
490 dstFormat.mBytesPerFrame = sizeof(AudioUnitSampleType);
491 dstFormat.mChannelsPerFrame = fDevNumOutChans;
492 dstFormat.mBitsPerChannel = 32;
493
494 PrintStreamDesc(&dstFormat);
495
496 err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &dstFormat, sizeof(AudioStreamBasicDescription));
497 if (err1 != noErr) {
498 printf("Error calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Input\n");
499 printError(err1);
500 }
501 }
502
503 if (fDevNumInChans > 0 && fDevNumOutChans == 0) {
504 AURenderCallbackStruct output;
505 output.inputProc = Render;
506 output.inputProcRefCon = this;
507 err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_SetInputCallback, kAudioUnitScope_Global, 0, &output, sizeof(output));
508 if (err1 != noErr) {
509 printf("Error calling AudioUnitSetProperty - kAudioUnitProperty_SetRenderCallback 1\n");
510 printError(err1);
511 goto error;
512 }
513 } else {
514 AURenderCallbackStruct output;
515 output.inputProc = Render;
516 output.inputProcRefCon = this;
517 err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &output, sizeof(output));
518 if (err1 != noErr) {
519 printf("Error calling AudioUnitSetProperty - kAudioUnitProperty_SetRenderCallback 0\n");
520 printError(err1);
521 goto error;
522 }
523 }
524
525 // Prepare buffers
526 fCAInputData = (AudioBufferList*)malloc(sizeof(UInt32) + fDevNumInChans * sizeof(AudioBuffer));
527 fCAInputData->mNumberBuffers = fDevNumInChans;
528 for (int i = 0; i < fDevNumInChans; i++) {
529 fCAInputData->mBuffers[i].mNumberChannels = 1;
530 fCAInputData->mBuffers[i].mDataByteSize = bufferSize * sizeof(int);
531 fCAInputData->mBuffers[i].mData = malloc(bufferSize * sizeof(int));
532 }
533
534 return NO_ERR;
535
536 error:
537 AudioUnitUninitialize(fAUHAL);
538 AudioComponentInstanceDispose(fAUHAL);
539 return OPEN_ERR;
540 }
541
Close()542 int TiPhoneCoreAudioRenderer::Close()
543 {
544 AudioUnitUninitialize(fAUHAL);
545 AudioComponentInstanceDispose(fAUHAL);
546 return NO_ERR;
547 }
548
Start()549 int TiPhoneCoreAudioRenderer::Start()
550 {
551 AudioSessionSetActive(true);
552 OSStatus err = AudioOutputUnitStart(fAUHAL);
553
554 if (err != noErr) {
555 printf("Error while opening device : device open error \n");
556 return OPEN_ERR;
557 } else {
558 return NO_ERR;
559 }
560 }
561
Stop()562 int TiPhoneCoreAudioRenderer::Stop()
563 {
564 OSStatus err = AudioOutputUnitStop(fAUHAL);
565
566 if (err != noErr) {
567 printf("Error while closing device : device close error \n");
568 return OPEN_ERR;
569 } else {
570 return NO_ERR;
571 }
572 }
573
574
575 /********************END ARCHITECTURE SECTION (part 2/2)****************/
576
577
578