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