annotate projects/audio_in_FFT/render.cpp @ 284:7bfb25a2e158 Doxy prerelease

Merge
author Robert Jack <robert.h.jack@gmail.com>
date Tue, 17 May 2016 15:53:24 +0100
parents ac8eb07afcf5
children
rev   line source
robert@269 1 /*
robert@269 2 ____ _____ _ _
robert@269 3 | __ )| ____| | / \
robert@269 4 | _ \| _| | | / _ \
robert@269 5 | |_) | |___| |___ / ___ \
robert@269 6 |____/|_____|_____/_/ \_\.io
robert@269 7
robert@269 8 */
robert@269 9
victor@4 10 /*
victor@4 11 * render.cpp
victor@4 12 *
victor@4 13 * Created on: Oct 24, 2014
victor@4 14 * Author: parallels
victor@4 15 */
victor@4 16
robert@269 17 /**
robert@269 18 \example 4_audio_FFT
robert@269 19
robert@269 20 Fast Fourier Transform
robert@269 21 ----------------------
robert@269 22
robert@269 23 This sketch performs an FFT (Fast Fourier Transform) on incoming audio. It uses
robert@269 24 the NE10 library, included at the top of the file (line 11).
robert@269 25
robert@269 26 Read the documentation on the NE10 library [here](http://projectne10.github.io/Ne10/doc/annotated.html).
robert@269 27
robert@269 28 The variables `timeDomainIn`, `timeDomainOut` and `frequencyDomain` are
robert@269 29 variables of the struct `ne10_fft_cpx_float32_t` [http://projectne10.github.io/Ne10/doc/structne10__fft__cpx__float32__t.html](http://projectne10.github.io/Ne10/doc/structne10__fft__cpx__float32__t.html).
robert@269 30 These are declared at the top of the file (line 21), and memory is allocated
robert@269 31 for them in `setup()` (line 41).
robert@269 32
robert@269 33 In `render()` a `for` loop performs the FFT which is performed on each sample,
robert@269 34 and the resulting output is placed on each channel.
robert@269 35
robert@269 36 */
robert@269 37
robert@269 38
robert@269 39
robert@269 40
robert@269 41
victor@4 42
andrewm@56 43 #include <BeagleRT.h>
victor@4 44 #include <rtdk.h>
victor@4 45 #include <NE10.h> // neon library
victor@4 46 #include <cmath>
victor@4 47
andrewm@5 48 int gFFTSize;
andrewm@5 49 float gFFTScaleFactor = 0;
victor@4 50
victor@4 51 int gReadPointer = 0;
victor@4 52 int gWritePointer = 0;
victor@4 53
victor@4 54 // FFT vars
andrewm@5 55 ne10_fft_cpx_float32_t* timeDomainIn;
andrewm@5 56 ne10_fft_cpx_float32_t* timeDomainOut;
victor@4 57 ne10_fft_cpx_float32_t* frequencyDomain;
victor@4 58 ne10_fft_cfg_float32_t cfg;
victor@4 59
andrewm@56 60 // setup() is called once before the audio rendering starts.
victor@4 61 // Use it to perform any initialisation and allocation which is dependent
victor@4 62 // on the period size or sample rate.
victor@4 63 //
victor@4 64 // userData holds an opaque pointer to a data structure that was passed
victor@4 65 // in from the call to initAudio().
victor@4 66 //
victor@4 67 // Return true on success; returning false halts the program.
victor@4 68
andrewm@56 69 bool setup(BeagleRTContext *context, void *userData)
victor@4 70 {
victor@4 71 // Retrieve a parameter passed in from the initAudio() call
andrewm@5 72 gFFTSize = *(int *)userData;
andrewm@5 73 gFFTScaleFactor = 1.0f / (float)gFFTSize;
victor@4 74
andrewm@5 75 timeDomainIn = (ne10_fft_cpx_float32_t*) NE10_MALLOC (gFFTSize * sizeof (ne10_fft_cpx_float32_t));
andrewm@5 76 timeDomainOut = (ne10_fft_cpx_float32_t*) NE10_MALLOC (gFFTSize * sizeof (ne10_fft_cpx_float32_t));
andrewm@5 77 frequencyDomain = (ne10_fft_cpx_float32_t*) NE10_MALLOC (gFFTSize * sizeof (ne10_fft_cpx_float32_t));
andrewm@5 78 cfg = ne10_fft_alloc_c2c_float32 (gFFTSize);
victor@4 79
andrewm@5 80 memset(timeDomainOut, 0, gFFTSize * sizeof (ne10_fft_cpx_float32_t));
victor@4 81
victor@4 82 return true;
victor@4 83 }
victor@4 84
victor@4 85 // render() is called regularly at the highest priority by the audio engine.
victor@4 86 // Input and output are given from the audio hardware and the other
victor@4 87 // ADCs and DACs (if available). If only audio is available, numMatrixFrames
victor@4 88 // will be 0.
victor@4 89
andrewm@52 90 void render(BeagleRTContext *context, void *userData)
victor@4 91 {
andrewm@52 92 for(unsigned int n = 0; n < context->audioFrames; n++) {
andrewm@52 93 timeDomainIn[gReadPointer].r = (ne10_float32_t) ((context->audioIn[n*context->audioChannels] +
andrewm@52 94 context->audioIn[n*context->audioChannels+1]) * 0.5);
andrewm@5 95 timeDomainIn[gReadPointer].i = 0;
victor@4 96
andrewm@5 97 if(++gReadPointer >= gFFTSize)
andrewm@5 98 {
andrewm@5 99 //FFT
andrewm@5 100 ne10_fft_c2c_1d_float32_neon (frequencyDomain, timeDomainIn, cfg->twiddles, cfg->factors, gFFTSize, 0);
victor@4 101
andrewm@5 102 //Do frequency domain stuff
victor@4 103
andrewm@5 104 //IFFT
andrewm@5 105 ne10_fft_c2c_1d_float32_neon (timeDomainOut, frequencyDomain, cfg->twiddles, cfg->factors, gFFTSize, 1);
victor@4 106
andrewm@5 107 gReadPointer = 0;
andrewm@5 108 gWritePointer = 0;
andrewm@5 109 }
victor@4 110
andrewm@56 111 for(unsigned int channel = 0; channel < context->audioChannels; channel++)
andrewm@52 112 context->audioOut[n * context->audioChannels + channel] = (float) timeDomainOut[gWritePointer].r * gFFTScaleFactor;
andrewm@5 113 gWritePointer++;
victor@4 114 }
victor@4 115 }
victor@4 116
andrewm@56 117 // cleanup() is called once at the end, after the audio has stopped.
andrewm@56 118 // Release any resources that were allocated in setup().
victor@4 119
andrewm@56 120 void cleanup(BeagleRTContext *context, void *userData)
victor@4 121 {
andrewm@5 122 NE10_FREE(timeDomainIn);
andrewm@5 123 NE10_FREE(timeDomainOut);
victor@4 124 NE10_FREE(frequencyDomain);
victor@4 125 NE10_FREE(cfg);
victor@4 126 }