source: orbit/iOS/Orbit/Orbit/AudioGenerator.m @ 37ca4e8

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