source: orbit/iOS/Orbit/Orbit/AudioGenerator.m @ bdd316c

Servo
Last change on this file since bdd316c was 6db346c, checked in by Steve Castellotti <sc@…>, 8 years ago
  • Scoring fields added
  • Tilt Control widgets added
  • Property mode set to 100644
File size: 24.9 KB
Line 
1//
2//  AudioGenerator.m
3//  orbit
4//
5//  Copyright (c) 2013 Puzzlebox Productions, LLC. All rights reserved.
6//  Originally created by Jonathon Horsman.
7//
8//  This code is released under the GNU Public License (GPL) version 2
9//  For more information please refer to http://www.gnu.org/copyleft/gpl.html
10//
11
12#import "AudioGenerator.h"
13
14
15
16#define SAMPLE_RATE_F 48000.f
17#define SIGNAL_WAVE_FREQUENCY 100.f
18
19
20/**
21 * Half periods in the audio code, in seconds.
22 */
23
24
25
26//#define longHIGH 0.000829649
27//#define longLOW 0.000797027
28//#define shortHIGH 0.000412649
29//#define shortLOW 0.000378351
30
31#define longHIGH 0.00089583333
32#define longLOW 0.00070833333
33#define shortHIGH 0.00045833333
34#define shortLOW 0.0003125
35
36#define USEFUL_BIT_SIZE 29
37
38#define IDLE_TIME_MS 84
39
40
41volatile BOOL g_refreshCtrCode = NO;
42
43//22 = 0.00045833333
44//15 = 0.0003125
45//
46//43 = 0.00089583333
47//34 = 0.00070833333
48//
49//14 = 0.00029166667
50//131 = 0.0027291667
51//16 = 0.00033333333
52//12 = 0.00025
53//3 = 0.0000625
54//18 = 0.000375
55//3998 = 0.083291667
56//4049 = 0.084354167
57
58#define INIT_CODE_DATA_SIZE 202
59
60
61double     g_initCodeTime[INIT_CODE_DATA_SIZE] = {
62   
63    0.00089583333, 0.0003125,
64    0.00089583333, 0.0003125,
65    0.00089583333, 0.00070833333,
66    0.00045833333, 0.0003125,
67    0.00089583333, 0.00070833333,
68    0.00089583333, 0.00070833333,
69    0.00045833333, 0.0003125,
70    0.00089583333, 0.00070833333,
71    0.00089583333, 0.00070833333,
72    0.00089583333, 0.00070833333,
73    0.00045833333, 0.0003125,
74    0.00089583333, 0.00070833333,
75    0.00045833333, 0.0003125,
76    0.00045833333, 0.0003125,
77    0.00089583333, 0.00070833333,
78    0.00089583333, 0.00070833333,
79    0.00045833333, 0.0003125,
80    0.00045833333, 0.0003125,
81    0.00089583333, 0.00070833333,
82    0.00045833333, 0.0003125,
83    0.00045833333, 0.0003125,
84    0.00089583333, 0.00070833333,
85    0.00089583333, 0.00070833333,
86    0.00089583333, 0.00070833333,
87    0.00089583333, 0.00070833333,
88    0.00089583333, 0.00070833333,
89    0.00045833333, 0.0003125,
90    0.00089583333, 0.00070833333,
91    0.00089583333, 0.00070833333,
92    0.00045833333, 0.0003125,
93    0.00089583333, 0.00070833333,
94   
95    0.083291667,
96   
97    0.00089583333, 0.0003125,
98    0.00089583333, 0.0003125,
99    0.00089583333, 0.00070833333,
100    0.00045833333, 0.0003125,
101    0.00089583333, 0.00070833333,
102    0.00089583333, 0.00070833333,
103    0.00045833333, 0.0003125,
104    0.00089583333, 0.00070833333,
105    0.00089583333, 0.00070833333,
106    0.00089583333, 0.00070833333,
107    0.00045833333, 0.0003125,
108    0.00089583333, 0.00070833333,
109    0.00045833333, 0.0003125,
110    0.00045833333, 0.0003125,
111    0.00089583333, 0.00070833333,
112    0.00089583333, 0.00070833333,
113    0.00045833333, 0.0003125,
114    0.00045833333, 0.0003125,
115    0.00089583333, 0.00070833333,
116    0.00045833333, 0.0003125,
117    0.00045833333, 0.0003125,
118    0.00089583333, 0.00070833333,
119    0.00089583333, 0.00070833333,
120    0.00089583333, 0.00070833333,
121    0.00089583333, 0.00070833333,
122    0.00089583333, 0.00070833333,
123    0.00045833333, 0.0003125,
124    0.00089583333, 0.00070833333,
125    0.00089583333, 0.00070833333,
126    0.00045833333, 0.0003125,
127    0.00089583333, 0.00070833333,
128   
129    0.083291667,
130   
131    0.00029166667, 0.0027291667,
132    0.00029166667, 0.0027291667,
133    0.00029166667, 0.00033333333,
134    0.00025, 0.0000625,
135    0.00025, 0.0000625,
136    0.00025, 0.0000625,
137    0.00025, 0.0000625,
138    0.00025, 0.0000625,
139    0.00025, 0.0000625,
140   
141    0.084354167,
142   
143    0.00029166667, 0.0027291667,
144    0.00029166667, 0.0027291667,
145    0.00029166667, 0.00033333333,
146    0.00025, 0.0000625,
147    0.00025, 0.0000625,
148    0.00025, 0.0000625,
149    0.00025, 0.0000625,
150    0.00025, 0.0000625,
151    0.00025, 0.0000625,
152   
153    0.084354167,
154   
155    0.00029166667, 0.0027291667,
156    0.00029166667, 0.0027291667,
157    0.00025, 0.000375,
158    0.00025, 0.000375,
159    0.00025, 0.0000625,
160    0.00025, 0.0000625,
161    0.00025, 0.0000625,
162    0.00025, 0.0000625,
163    0.00025, 0.0000625,
164   
165    0.084354167,
166   
167    0.00029166667, 0.0027291667,
168    0.00029166667, 0.0027291667,
169    0.00025, 0.000375,
170    0.00025, 0.000375,
171    0.00025, 0.0000625,
172    0.00025, 0.0000625,
173    0.00025, 0.0000625,
174    0.00025, 0.0000625,
175    0.00025, 0.0000625,
176   
177    0.084354167
178   
179};
180
181
182BOOL     g_initCodeUD[INIT_CODE_DATA_SIZE] = {
183   
184    YES, NO,
185    YES, NO,
186    YES, NO,
187    YES, NO,
188    YES, NO,
189    YES, NO,
190    YES, NO,
191    YES, NO,
192    YES, NO,
193    YES, NO,
194    YES, NO,
195    YES, NO,
196    YES, NO,
197    YES, NO,
198    YES, NO,
199    YES, NO,
200    YES, NO,
201    YES, NO,
202    YES, NO,
203    YES, NO,
204    YES, NO,
205    YES, NO,
206    YES, NO,
207    YES, NO,
208    YES, NO,
209    YES, NO,
210    YES, NO,
211    YES, NO,
212    YES, NO,
213    YES, NO,
214    YES, NO,
215   
216    NO,
217   
218    YES, NO,
219    YES, NO,
220    YES, NO,
221    YES, NO,
222    YES, NO,
223    YES, NO,
224    YES, NO,
225    YES, NO,
226    YES, NO,
227    YES, NO,
228    YES, NO,
229    YES, NO,
230    YES, NO,
231    YES, NO,
232    YES, NO,
233    YES, NO,
234    YES, NO,
235    YES, NO,
236    YES, NO,
237    YES, NO,
238    YES, NO,
239    YES, NO,
240    YES, NO,
241    YES, NO,
242    YES, NO,
243    YES, NO,
244    YES, NO,
245    YES, NO,
246    YES, NO,
247    YES, NO,
248    YES, NO,
249   
250    NO,
251   
252    YES, NO,
253    YES, NO,
254    YES, NO,
255    YES, NO,
256    YES, NO,
257    YES, NO,
258    YES, NO,
259    YES, NO,
260    YES, NO,
261   
262    NO,
263   
264    YES, NO,
265    YES, NO,
266    YES, NO,
267    YES, NO,
268    YES, NO,
269    YES, NO,
270    YES, NO,
271    YES, NO,
272    YES, NO,
273   
274    NO,
275   
276    YES, NO,
277    YES, NO,
278    YES, NO,
279    YES, NO,
280    YES, NO,
281    YES, NO,
282    YES, NO,
283    YES, NO,
284    YES, NO,
285   
286    NO,
287   
288    YES, NO,
289    YES, NO,
290    YES, NO,
291    YES, NO,
292    YES, NO,
293    YES, NO,
294    YES, NO,
295    YES, NO,
296    YES, NO,
297   
298    NO,
299   
300};
301
302
303@interface AudioGenerator()
304{
305   
306    int         m_initCodeLen[INIT_CODE_DATA_SIZE];
307   
308    AudioUnit   m_audioUnit;
309    Float32     m_sampleRate;
310    BOOL        m_isPlaying;
311    double      m_signalPhaseCur;
312
313   
314    int         waveBit_01_len[2];
315    Float32     *waveBit_01[2];
316   
317    int         ctrWaveMaxLen;
318    int         ctrWaveDataLen;
319    Float32     *ctrWave;
320   
321    int         ctrWaveHeadLen;
322    Float32     *ctrWaveHead;
323   
324    int         ctrWaveReadIdx;
325   
326    int         idleWaveLen;
327    int         idleWaveReadIdx;
328   
329   
330   
331    BOOL        sendInitWave;
332   
333    int         initWaveSendLenIdx;
334    int         initWaveSendLenIdxLenMax;
335    int         initWaveSendLenIdxLenCur;
336   
337    Float32     initWaveCurAngle;
338}
339
340@end
341
342
343@implementation AudioGenerator {
344   
345    float sampleTime;
346    int longHighLength, shortHighLength, longZeroLength, longLowLength, mediumLowLength, shortLowLength, waveBitLength;
347    float *waveLongHigh, *waveShortHigh, *waveLongZero, *waveLongLow, *waveMediumLow, *waveShortLow, *waveBit;
348   
349   
350   
351    int MAX_BUFFER_SIZE;
352
353}
354
355@synthesize yaw, pitch, throttle;
356
357- (id) init
358{
359    self = [super init];
360    if (self) {
361        sampleTime = 1.0f / SAMPLE_RATE_F;
362       
363        [self prepareStaticArrays];
364    }
365    return self;
366}
367
368#pragma mark - ---- interface ----
369
370- (void) playWithThrottle: (int)t yaw: (int)y pitch: (int)p
371{
372    self.yaw = y;
373    self.pitch = p;
374    self.throttle = t;
375   
376    [self audioUnitStart];
377   
378}
379
380
381- (void) stop
382{
383    [self audioUnitStop];
384}
385
386
387#pragma mark - ---- Audio Unit func ----
388
389- (void) audioUnitStart
390{
391
392    if (m_audioUnit == nil) {
393        [self prepareAudioUnit];
394       
395        sendInitWave = YES;
396        initWaveSendLenIdx = 0;
397        initWaveSendLenIdxLenMax = m_initCodeLen[0];
398        initWaveSendLenIdxLenCur = 0;
399        initWaveCurAngle = 0.f;
400    }
401   
402    if (!m_isPlaying) {
403       
404        [self updateCtrCode:NO];
405       
406        OSStatus status = AudioUnitInitialize(m_audioUnit);
407       
408        if (status != noErr) {
409            NSLog(@"AudioUnitInitialize - error");
410        }
411
412       
413        status = AudioOutputUnitStart(m_audioUnit);
414        if (status != noErr) {
415            NSLog(@"AudioOutputUnitStart - error");
416        }
417       
418        m_isPlaying = YES;
419    }
420    else {
421        [self updateCtrCode:YES];
422    }
423
424   
425}
426
427
428- (void) audioUnitStop
429{
430   
431    if (m_isPlaying) {
432        OSStatus status = AudioOutputUnitStop(m_audioUnit);
433        if (status != noErr) {
434            NSLog(@"AudioOutputUnitStop - error");
435        }
436       
437        m_isPlaying = NO;
438    }
439   
440    if (m_audioUnit) {
441        OSStatus status = AudioUnitUninitialize(m_audioUnit);
442        if (status != noErr) {
443            NSLog(@"AudioUnitUninitialize - error");
444        }
445       
446        status = AudioComponentInstanceDispose(m_audioUnit);
447        if (status != noErr) {
448            NSLog(@"AudioComponentInstanceDispose - error");
449        }
450       
451        m_audioUnit = nil;
452    }
453   
454   
455}
456
457
458
459- (void) prepareAudioUnit
460{
461    m_sampleRate = SAMPLE_RATE_F;
462    m_isPlaying = NO;
463    m_signalPhaseCur = 0.0;
464   
465    OSStatus status = noErr;
466   
467    AudioComponentDescription au_cd;
468    au_cd.componentType = kAudioUnitType_Output;
469    au_cd.componentSubType = kAudioUnitSubType_RemoteIO;
470    au_cd.componentManufacturer = kAudioUnitManufacturer_Apple;
471    au_cd.componentFlags = 0;
472    au_cd.componentFlagsMask = 0;
473   
474    AudioComponent component = AudioComponentFindNext(NULL, &au_cd);
475    if (component == NULL) {
476        NSLog(@"AudioComponentFindNext - error");
477    }
478   
479   
480    status = AudioComponentInstanceNew(component, &m_audioUnit);
481    if (status != noErr) {
482        NSLog(@"AudioComponentInstanceNew - error");
483    }
484   
485   
486    AURenderCallbackStruct callbackStruct;
487    callbackStruct.inputProc = renderAudioUnitCallback;
488    callbackStruct.inputProcRefCon = (__bridge void *)(self);
489   
490    status = AudioUnitSetProperty(m_audioUnit,
491                         kAudioUnitProperty_SetRenderCallback,
492                         kAudioUnitScope_Input,
493                         0,
494                         &callbackStruct,
495                         sizeof(AURenderCallbackStruct));
496   
497    if (status != noErr) {
498        NSLog(@"kAudioUnitProperty_SetRenderCallback - error");
499    }
500   
501   
502        AudioStreamBasicDescription streamFormat;
503        streamFormat.mSampleRate         = m_sampleRate;
504        streamFormat.mFormatID           = kAudioFormatLinearPCM;
505        streamFormat.mFormatFlags        = kAudioFormatFlagsNativeFloatPacked | kAudioFormatFlagIsNonInterleaved;
506        streamFormat.mChannelsPerFrame   = 2;
507        streamFormat.mBytesPerPacket     = sizeof(Float32);
508        streamFormat.mBytesPerFrame      = sizeof(Float32);
509        streamFormat.mFramesPerPacket    = 1;
510        streamFormat.mBitsPerChannel     = 8 * sizeof(Float32);
511   
512        status = AudioUnitSetProperty(m_audioUnit,
513                                                 kAudioUnitProperty_StreamFormat,
514                                                 kAudioUnitScope_Input,
515                                                 0,
516                                                 &streamFormat,
517                                                 sizeof(AudioStreamBasicDescription));
518   
519    if (status != noErr) {
520        NSLog(@"kAudioUnitProperty_StreamFormat - error");
521    }
522   
523}
524
525
526OSStatus renderAudioUnitCallback(void*                       inRefCon,
527                                   AudioUnitRenderActionFlags* ioActionFlags,
528                                   const AudioTimeStamp*       inTimeStamp,
529                                   UInt32                      inBusNumber,
530                                   UInt32                      inNumberFrames,
531                                   AudioBufferList*            ioData)
532{
533    AudioGenerator *generator = (__bridge AudioGenerator*)inRefCon;
534   
535    Float32 *ctr_buffer = ioData->mBuffers[0].mData;
536    [generator writeCtrWaveToBuffer:ctr_buffer maxSize:inNumberFrames];
537   
538    Float32 *signal_buffer = ioData->mBuffers[1].mData;
539    [generator writeSignalWaveToBuffer:signal_buffer maxSize:inNumberFrames];
540   
541    return noErr;
542}
543
544
545- (void)writeCtrWaveToBuffer:(Float32*)buffer maxSize:(UInt32)frames
546{
547   
548    for (int i=0; i < frames; ++i) {
549       
550        if (g_refreshCtrCode) {
551            ctrWaveReadIdx = 0;
552            idleWaveReadIdx = 0;
553            g_refreshCtrCode = NO;
554            break;
555        }
556       
557        if (sendInitWave) {
558           
559            double increment = M_PI/(g_initCodeTime[initWaveSendLenIdx] * SAMPLE_RATE_F);
560           
561            if (g_initCodeUD[initWaveSendLenIdx]) {
562                *buffer++ = sinf(initWaveCurAngle);
563                initWaveCurAngle += increment;
564            }
565            else {
566                *buffer++ = 0.0f;
567            }
568           
569            initWaveSendLenIdxLenCur++;
570           
571            if (initWaveSendLenIdxLenCur >= initWaveSendLenIdxLenMax) {
572                initWaveSendLenIdx++;
573               
574                if (initWaveSendLenIdx >= INIT_CODE_DATA_SIZE) {
575                    sendInitWave = NO;
576                    continue;
577                }
578                else {
579                    initWaveSendLenIdxLenMax = m_initCodeLen[initWaveSendLenIdx];
580                    initWaveSendLenIdxLenCur = 0;
581                    initWaveCurAngle = 0.f;
582                }
583               
584               
585            }
586           
587           
588        }
589        else {
590            if (ctrWaveReadIdx < ctrWaveDataLen && idleWaveReadIdx == 0) {
591                *buffer++ = ctrWave[ctrWaveReadIdx++];
592            }
593            else if (ctrWaveReadIdx >= ctrWaveDataLen && idleWaveReadIdx < idleWaveLen)
594            {
595                *buffer++ = 0.0f;
596                idleWaveReadIdx++;
597            }
598            else if (ctrWaveReadIdx >= ctrWaveDataLen && idleWaveReadIdx >= idleWaveLen)
599            {
600                ctrWaveReadIdx = 0;
601                idleWaveReadIdx = 0;
602                *buffer++ = ctrWave[ctrWaveReadIdx++];
603            }
604        }
605       
606       
607    }
608}
609
610- (void)writeSignalWaveToBuffer:(Float32*)buffer maxSize:(UInt32)frames
611{
612    double phase_step = SIGNAL_WAVE_FREQUENCY * 2.0 * M_PI / SAMPLE_RATE_F;
613       
614        for (int i = 0; i < frames; ++i){
615                float wave = sin(m_signalPhaseCur);
616                *buffer++ = wave;
617        m_signalPhaseCur += phase_step;
618       
619        if (m_signalPhaseCur > 2.0 * M_PI) {
620            m_signalPhaseCur -= 2.0 * M_PI;
621        }
622    }
623}
624
625
626
627#pragma mark - ---- Audio Generator func ----
628
629
630
631- (void) prepareStaticArrays
632{
633   
634    waveLongHigh = [self generateHalfSine:true halfPeriod:longHIGH];
635    longHighLength = [self arraySizeWithHalfPeriod:longHIGH];
636    waveLongLow = [self generateHalfSine:false halfPeriod:longLOW];
637    longLowLength = [self arraySizeWithHalfPeriod:longLOW];
638    waveShortHigh = [self generateHalfSine:true halfPeriod:shortHIGH];
639    shortHighLength = [self arraySizeWithHalfPeriod:shortHIGH];
640    waveShortLow = [self generateHalfSine:false halfPeriod:shortLOW];
641    shortLowLength = [self arraySizeWithHalfPeriod:shortLOW];
642   
643    float mediumLow = 0.0005 - sampleTime;
644    waveMediumLow = [self generateHalfSine:false halfPeriod:mediumLow];
645    mediumLowLength = [self arraySizeWithHalfPeriod:mediumLow];
646   
647   
648    longZeroLength = (int)floor((0.002 + 1 / SAMPLE_RATE_F) * SAMPLE_RATE_F);
649    waveLongZero = malloc(longZeroLength);
650   
651    [self generateWaveBit];
652   
653   
654    [self initCodeWaveLen];
655   
656    [self generateCtrWaveHead];
657    [self generateWaveBit_01];
658   
659    [self setupCtrWave];
660}
661
662- (void)initCodeWaveLen
663{
664    //int initCodeDataLen = sizeof(g_initCodeTime) / sizeof(double);
665   
666    for (int i=0; i < INIT_CODE_DATA_SIZE; ++i) {
667        m_initCodeLen[i] = [self arraySizeWithHalfPeriod:g_initCodeTime[i]];
668    }
669   
670    initWaveSendLenIdx = 0;
671    initWaveSendLenIdxLenMax = m_initCodeLen[0];
672    initWaveSendLenIdxLenCur = 0;
673    initWaveCurAngle = 0.f;
674}
675
676- (void)setupCtrWave
677{
678    ctrWaveMaxLen = ctrWaveHeadLen +
679                USEFUL_BIT_SIZE * (waveBit_01_len[0] > waveBit_01_len[1] ? waveBit_01_len[0] : waveBit_01_len[1]) +
680                longHighLength;
681   
682    idleWaveLen = (int)floor(IDLE_TIME_MS * 0.001f * SAMPLE_RATE_F);
683   
684    ctrWave = malloc(sizeof(Float32) * ctrWaveMaxLen);
685   
686    memcpy(ctrWave, ctrWaveHead, sizeof(Float32) * ctrWaveHeadLen);
687   
688    ctrWaveReadIdx = 0;
689    idleWaveReadIdx = 0;
690}
691
692
693
694- (void)generateCtrWaveHead
695{
696    int ctr_longH_len = [self arraySizeWithHalfPeriod:longHIGH];
697    int ctr_shortL_len = [self arraySizeWithHalfPeriod:shortLOW];
698   
699    ctrWaveHeadLen = 2 * ctr_longH_len + 2 * ctr_shortL_len;
700    ctrWaveHead = malloc(sizeof(Float32) * ctrWaveHeadLen);
701   
702    int idx = 0;
703   
704    double increment = M_PI/((longHIGH - sampleTime * 2) * SAMPLE_RATE_F);
705    double angle = 0;
706   
707    for (int i=0; i < ctr_longH_len; ++i) {
708        Float32 value = sinf(angle);
709        ctrWaveHead[idx + ctr_longH_len + ctr_shortL_len] = value;
710        ctrWaveHead[idx++] = value;
711        angle += increment;
712    }
713   
714    memset(ctrWaveHead + idx, 0, sizeof(Float32) * ctr_shortL_len);
715    memset(ctrWaveHead + (idx + ctr_longH_len + ctr_shortL_len), 0, sizeof(Float32) * ctr_shortL_len);
716
717}
718
719- (void) generateWaveBit_01
720{
721    waveBit_01_len[0] = shortHighLength + shortLowLength;
722    waveBit_01_len[1] = longHighLength + longLowLength;
723   
724    waveBit_01[0] = malloc(sizeof(Float32) * waveBit_01_len[0]);
725    waveBit_01[1] = malloc(sizeof(Float32) * waveBit_01_len[1]);
726   
727    int idx = 0;
728    for (int i=0; i < shortHighLength; ++i) {
729        waveBit_01[0][idx++] = waveShortHigh[i];
730    }
731    for (int i=0; i < shortLowLength; ++i) {
732        waveBit_01[0][idx++] = waveShortLow[i];
733    }
734   
735    idx = 0;
736    for (int i=0; i < longHighLength; ++i) {
737        waveBit_01[1][idx++] = waveLongHigh[i];
738    }
739    for (int i=0; i < longLowLength; ++i) {
740        waveBit_01[1][idx++] = waveLongLow[i];
741    }
742   
743}
744
745- (void) generateWaveBit
746{
747    waveBitLength = longHighLength + longLowLength + shortHighLength + shortLowLength;
748    waveBit = malloc(sizeof(waveBit) * waveBitLength);
749    int c = 0;
750    for (int i = 0; i < longHighLength; i++) {
751        waveBit[c++] = waveLongHigh[i];
752    }
753    for (int i = 0; i < longLowLength; i++) {
754        waveBit[c++] = waveLongLow[i];
755    }
756    for (int i = 0; i < shortHighLength; i++) {
757        waveBit[c++] = waveShortHigh[i];
758    }
759    for (int i = 0; i < shortLowLength; i++) {
760        waveBit[c++] = waveShortLow[i];
761    }
762}
763
764
765
766// calculate the checksum for the generated code used to generate the WAV array
767- (int) codeChecksum:(int)code
768{
769    int checksum = 0;
770    for (int i = 0; i < 7; i++) {
771        checksum += (code >> 4*i) & 15;
772    }
773    return 16 - (checksum & 15);
774}
775
776// Generate the code used to create the WAV file based on the given throttle, yaw and pitch.
777// Copied from AudioService.java in the Android app (command2code method)
778// throttle: 0~127, nothing will happen if this value is below 30.
779// yaw: 0~127, normally 78 will keep orbit from rotating.
780// pitch: 0~63, normally 31 will stop the top propeller.
781// channel: 1=Channel A, 0=Channel B 2= Channel C, depend on which channel you want to pair to the orbit. You can fly at most 3 orbit in a same room.
782- (int) generateCode
783{
784    int channel = 1;
785    int code = throttle << 21;
786    code += 1 << 20;
787    code += yaw << 12;
788    code += pitch << 4;
789    code += ((channel >> 1) & 1) << 19;
790    code += (channel & 1) << 11;
791    code += [self codeChecksum:code];
792   
793    return (code << 1) + 1;
794}
795
796- (void)updateCtrCode:(BOOL)refresh
797{
798    int ctr_code = [self generateCode];
799   
800    //1110110111010011001001111101101
801   
802    //ctr_code = 0B00010110111010011001001111101101;
803    //ctr_code = 0x0000FFFF;
804   
805    [self codeToWave:ctr_code];
806   
807    if (refresh) {
808        g_refreshCtrCode = YES;
809    }
810   
811}
812
813- (void)codeToWave:(int)code
814{
815    Float32 *pos = ctrWave + ctrWaveHeadLen;
816   
817    for (int i=USEFUL_BIT_SIZE-1; i >= 0 ; --i) {
818        int bit = (code >> i) & 1;
819        memcpy(pos, waveBit_01[bit], sizeof(Float32) * waveBit_01_len[bit]);
820        pos += waveBit_01_len[bit];
821    }
822   
823    memcpy(pos, waveLongHigh, sizeof(Float32) * longHighLength);
824    pos += longHighLength;
825   
826    ctrWaveDataLen = pos - ctrWave;
827    int lost_len = ctrWaveMaxLen - ctrWaveDataLen;
828   
829    memset(pos, 0, sizeof(Float32) * lost_len);
830}
831
832
833
834
835- (int) writeBytesToBuffer:(Float32 *) buffer maxSize:(UInt32) frames
836{
837    MAX_BUFFER_SIZE = sizeof(buffer) * frames;
838    int position = 0;
839    [self writeWaveToBuffer:buffer        at:&position];
840    [self writeInitialWaveToBuffer:buffer at:&position];
841   
842    return position;
843}
844
845- (void) writeInitialWaveToBuffer:(Float32 *) buffer at: (int *) position
846{
847    [self writeWave123To: buffer at: position];
848    [self writeWave123To: buffer at: position];
849    [self writeWave456To: buffer at: position];
850    [self writeWave456To: buffer at: position];
851    [self writeWave456To: buffer at: position];
852}
853
854- (void) writeWave123To:(Float32 *) buffer at:(int *) position
855{
856    [self writeOriginalTo:buffer at: position];
857    [self writeArray:waveMediumLow to:buffer length:mediumLowLength at:position];
858    for (int i = 0; i < 4; i++) {
859        [self writeShortHShortLTo:buffer at:position];
860    }
861    [self writeArray:waveShortHigh to:buffer length:shortHighLength at:position];
862    [self writeMediumLShortHTo:buffer at:position];
863    [self writePauseInSamplesTo:buffer at:position];
864}
865
866- (void) writeWave456To:(Float32 *) buffer at:(int *) position
867{
868    [self writeOriginalTo:buffer at:position];
869    [self writeArray:waveShortLow to:buffer length:shortLowLength at:position];
870    for (int i = 0; i < 4; i++) {
871        [self writeShortHShortLTo:buffer at:position];
872    }
873    [self writeArray:waveShortHigh to:buffer length:shortHighLength at:position];
874    [self writeMediumLShortHTo:buffer at:position];
875    [self writePauseInSamplesTo:buffer at:position];
876}
877
878
879- (void) writeOriginalTo:(Float32 *) buffer at:(int *) position
880{
881    [self writeLongHLongZeroTo: buffer at: position];
882    [self writeLongHLongZeroTo: buffer at: position];
883    [self writeArray:waveLongHigh to:buffer length:longHighLength at:position];
884    [self writeMediumLShortHTo:buffer at:position];
885}
886
887- (void) writeLongHLongZeroTo:(Float32 *) buffer at:(int *) position
888{
889    [self writeArray:waveLongHigh to:buffer length:longHighLength at:position];
890    [self writeArray:waveLongZero to:buffer length:longZeroLength at:position];
891}
892
893- (void) writeMediumLShortHTo:(Float32 *) buffer at:(int *) position
894{
895    [self writeArray:waveMediumLow to:buffer length:mediumLowLength at:position];
896    [self writeArray:waveShortHigh to:buffer length:shortHighLength at:position];
897}
898
899- (void) writeShortHShortLTo:(Float32 *) buffer at:(int *) position
900{
901    [self writeArray:waveShortHigh to:buffer length:shortHighLength at:position];
902    [self writeArray:waveShortLow to:buffer length:shortLowLength at:position];
903}
904
905- (void) writePauseInSamplesTo:(Float32 *) buffer at:(int *) position
906{
907    int length = (int)floor(0.010 * SAMPLE_RATE_F); // length of pause to insert
908    float arr[length];
909    [self writeArray:arr to:buffer length:length at:position];
910}
911
912- (void) writeArray:(float *) array to:(Float32 *) buffer length: (int)length at:(int *) position
913{
914    for (int i = 0; i < length; i++) {
915        if (*position < MAX_BUFFER_SIZE) buffer[(*position)++] = array[i];
916    }
917}
918
919- (void) writeWaveToBuffer:(Float32 *) buffer at: (int *) position
920{
921    [self halfSineGen: false halfPeriod: longLOW                   toBuffer:buffer at:position];
922    [self halfSineGen: true  halfPeriod: longHIGH - sampleTime * 2 toBuffer:buffer at:position];
923    [self halfSineGen: false halfPeriod: shortLOW + sampleTime * 2 toBuffer:buffer at:position];
924    [self halfSineGen: true  halfPeriod: longHIGH - sampleTime * 2 toBuffer:buffer at:position]; // duplicate?
925    [self halfSineGen: false halfPeriod: shortLOW + sampleTime * 2 toBuffer:buffer at:position]; // duplicate?
926   
927    int code = [self generateCode];
928    for (int i=0; i < 27; i++) {
929        buffer[(*position)++] = waveBit[((code >> (27 - i)) & 1)];
930    }
931    for (int i = 0; i < longHighLength; i++) {
932        buffer[(*position)++] = waveLongHigh[i];
933    }
934   
935}
936
937/**
938 * Generate half sine signal.
939 * Copied from AudioService.java in the AndroidApp
940 * @param upper, means it's the upper half or lower half or sine wave.
941 * @param halfPeriod: half of the period of sine wave, in seconds
942 * @param toBuffer the buffer (float array) to write to
943 * @param position the position in the array to start writing to
944 */
945- (void) halfSineGen:(BOOL)upper halfPeriod: (double)halfPeriod toBuffer:(Float32 *) buffer at:(int *) position
946{
947   
948   // TODO - testing
949   //halfPeriod =true;
950   
951    int sampleCount = [self arraySizeWithHalfPeriod:halfPeriod];
952    double increment = M_PI/(halfPeriod * SAMPLE_RATE_F);
953    double angle = upper ? 0 : M_PI;
954       
955    for (int i = 0; i < sampleCount; i++) {
956        buffer[(*position)++] = sinf(angle);
957        angle += increment;
958    }
959}
960
961- (int) arraySizeWithHalfPeriod: (double)halfPeriod
962{
963    return (int)floor(halfPeriod * SAMPLE_RATE_F);
964}
965
966/**
967 * Generate half sine signal.
968 * Copied from AudioService.java in the AndroidApp
969 * @param upper, means it's the upper half or lower half of sine wave.
970 * @param halfPeriod: half of the period of sine wave, in seconds
971 * @return the length of the array
972 */
973- (float *) generateHalfSine:(BOOL)upper halfPeriod: (double)halfPeriod
974{
975    int sampleCount = [self arraySizeWithHalfPeriod:halfPeriod];
976    Float32 *array = malloc(sizeof(Float32) * sampleCount);
977    double increment = M_PI/(halfPeriod * SAMPLE_RATE_F);
978    double angle = 0;
979   
980    for (int i = 0; i < sampleCount; i++) {
981        if (upper) {
982            array[i] = sinf(angle);
983            angle += increment;
984        }
985        else {
986            array[i] = 0.0f;
987        }
988       
989    }
990    return array;
991}
992
993@end
Note: See TracBrowser for help on using the repository browser.