annotate examples/audio_in_FFT/render.cpp @ 379:24c3a0663d54 prerelease

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