Mercurial > hg > beaglert
comparison projects/audio_in_FFT/render.cpp @ 5:09f03ac40fcc
API improvements and cleanups. Now all common audio command-line options can be parsed automatically.
author | andrewm |
---|---|
date | Sat, 08 Nov 2014 16:16:55 +0100 |
parents | f34c63568523 |
children | 06f93bef7dd2 |
comparison
equal
deleted
inserted
replaced
4:f34c63568523 | 5:09f03ac40fcc |
---|---|
9 #include "../../include/render.h" | 9 #include "../../include/render.h" |
10 #include <rtdk.h> | 10 #include <rtdk.h> |
11 #include <NE10.h> // neon library | 11 #include <NE10.h> // neon library |
12 #include <cmath> | 12 #include <cmath> |
13 | 13 |
14 int gFftSize; | 14 int gFFTSize; |
15 float gFFTScaleFactor = 0; | |
15 int gNumChannels; | 16 int gNumChannels; |
16 | 17 |
17 int gReadPointer = 0; | 18 int gReadPointer = 0; |
18 int gWritePointer = 0; | 19 int gWritePointer = 0; |
19 | 20 |
20 // FFT vars | 21 // FFT vars |
21 ne10_fft_cpx_float32_t* timeDomain; | 22 ne10_fft_cpx_float32_t* timeDomainIn; |
23 ne10_fft_cpx_float32_t* timeDomainOut; | |
22 ne10_fft_cpx_float32_t* frequencyDomain; | 24 ne10_fft_cpx_float32_t* frequencyDomain; |
23 ne10_fft_cfg_float32_t cfg; | 25 ne10_fft_cfg_float32_t cfg; |
24 | 26 |
25 // initialise_render() is called once before the audio rendering starts. | 27 // initialise_render() is called once before the audio rendering starts. |
26 // Use it to perform any initialisation and allocation which is dependent | 28 // Use it to perform any initialisation and allocation which is dependent |
34 bool initialise_render(int numChannels, int numMatrixFramesPerPeriod, | 36 bool initialise_render(int numChannels, int numMatrixFramesPerPeriod, |
35 int numAudioFramesPerPeriod, float matrixSampleRate, | 37 int numAudioFramesPerPeriod, float matrixSampleRate, |
36 float audioSampleRate, void *userData) | 38 float audioSampleRate, void *userData) |
37 { | 39 { |
38 // Retrieve a parameter passed in from the initAudio() call | 40 // Retrieve a parameter passed in from the initAudio() call |
39 gFftSize = *(int *)userData; | 41 gFFTSize = *(int *)userData; |
42 gFFTScaleFactor = 1.0f / (float)gFFTSize; | |
40 gNumChannels = numChannels; | 43 gNumChannels = numChannels; |
41 | 44 |
42 //memset(outSamples, gFftSize, 0.0); // set all to 0 | 45 timeDomainIn = (ne10_fft_cpx_float32_t*) NE10_MALLOC (gFFTSize * sizeof (ne10_fft_cpx_float32_t)); |
46 timeDomainOut = (ne10_fft_cpx_float32_t*) NE10_MALLOC (gFFTSize * sizeof (ne10_fft_cpx_float32_t)); | |
47 frequencyDomain = (ne10_fft_cpx_float32_t*) NE10_MALLOC (gFFTSize * sizeof (ne10_fft_cpx_float32_t)); | |
48 cfg = ne10_fft_alloc_c2c_float32 (gFFTSize); | |
43 | 49 |
44 timeDomain = (ne10_fft_cpx_float32_t*) NE10_MALLOC (gFftSize * sizeof (ne10_fft_cpx_float32_t)); | 50 memset(timeDomainOut, 0, gFFTSize * sizeof (ne10_fft_cpx_float32_t)); |
45 frequencyDomain = (ne10_fft_cpx_float32_t*) NE10_MALLOC (gFftSize * sizeof (ne10_fft_cpx_float32_t)); | |
46 cfg = ne10_fft_alloc_c2c_float32 (gFftSize); | |
47 | 51 |
48 return true; | 52 return true; |
49 } | 53 } |
50 | 54 |
51 // render() is called regularly at the highest priority by the audio engine. | 55 // render() is called regularly at the highest priority by the audio engine. |
55 | 59 |
56 void render(int numMatrixFrames, int numAudioFrames, float *audioIn, float *audioOut, | 60 void render(int numMatrixFrames, int numAudioFrames, float *audioIn, float *audioOut, |
57 uint16_t *matrixIn, uint16_t *matrixOut) | 61 uint16_t *matrixIn, uint16_t *matrixOut) |
58 { | 62 { |
59 for(int n = 0; n < numAudioFrames; n++) { | 63 for(int n = 0; n < numAudioFrames; n++) { |
60 timeDomain[gReadPointer].r = (ne10_float32_t) ((audioIn[n*gNumChannels] + audioIn[n*gNumChannels+1])/2); | 64 timeDomainIn[gReadPointer].r = (ne10_float32_t) ((audioIn[n*gNumChannels] + audioIn[n*gNumChannels+1]) * 0.5); |
61 timeDomain[gReadPointer].i = 0; | 65 timeDomainIn[gReadPointer].i = 0; |
62 gReadPointer++; | |
63 } | |
64 | 66 |
65 if(gReadPointer>=gFftSize) | 67 if(++gReadPointer >= gFFTSize) |
66 { | 68 { |
67 //FFT | 69 //FFT |
68 ne10_fft_c2c_1d_float32_neon (frequencyDomain, timeDomain, cfg->twiddles, cfg->factors, gFftSize, 0); | 70 ne10_fft_c2c_1d_float32_neon (frequencyDomain, timeDomainIn, cfg->twiddles, cfg->factors, gFFTSize, 0); |
69 | 71 |
70 //Do frequency domain stuff | 72 //Do frequency domain stuff |
71 | 73 |
72 //IFFT | 74 //IFFT |
73 ne10_fft_c2c_1d_float32_neon (timeDomain, frequencyDomain, cfg->twiddles, cfg->factors, gFftSize, 1); | 75 ne10_fft_c2c_1d_float32_neon (timeDomainOut, frequencyDomain, cfg->twiddles, cfg->factors, gFFTSize, 1); |
74 | 76 |
75 gReadPointer = 0; | 77 gReadPointer = 0; |
76 gWritePointer = 0; | 78 gWritePointer = 0; |
77 } | 79 } |
78 | 80 |
79 for(int n = 0; n < numAudioFrames; n++) { | |
80 for(int channel = 0; channel < gNumChannels; channel++) | 81 for(int channel = 0; channel < gNumChannels; channel++) |
81 audioOut[n * gNumChannels + channel] = (float) timeDomain[gWritePointer++].r/gFftSize; | 82 audioOut[n * gNumChannels + channel] = (float) timeDomainOut[gWritePointer].r * gFFTScaleFactor; |
83 gWritePointer++; | |
82 } | 84 } |
83 } | 85 } |
84 | 86 |
85 // cleanup_render() is called once at the end, after the audio has stopped. | 87 // cleanup_render() is called once at the end, after the audio has stopped. |
86 // Release any resources that were allocated in initialise_render(). | 88 // Release any resources that were allocated in initialise_render(). |
87 | 89 |
88 void cleanup_render() | 90 void cleanup_render() |
89 { | 91 { |
90 NE10_FREE(timeDomain); | 92 NE10_FREE(timeDomainIn); |
93 NE10_FREE(timeDomainOut); | |
91 NE10_FREE(frequencyDomain); | 94 NE10_FREE(frequencyDomain); |
92 NE10_FREE(cfg); | 95 NE10_FREE(cfg); |
93 } | 96 } |