annotate examples/filter_FIR/render.cpp @ 372:db2fe4e1b88e prerelease

Doxygen content added to each example render.cpp. References to AnalogReadFrame etc. removed from doxygen content.
author Robert Jack <robert.h.jack@gmail.com>
date Thu, 09 Jun 2016 18:16:05 +0100
parents 421a69d42943
children 3bed6b09223c
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@2 10 /*
victor@2 11 * render.cpp
victor@2 12 *
victor@2 13 * Created on: Oct 24, 2014
victor@2 14 * Author: Andrew McPherson and Victor Zappi
victor@2 15 */
victor@2 16
robert@372 17 /**
robert@372 18 \example 4_filter_FIR
robert@372 19
robert@372 20 Finite Impulse Response Filter
robert@372 21 ------------------------------
robert@372 22
robert@372 23 This is an example of a finite impulse response filter implementation.
robert@372 24 */
victor@2 25
giuliomoro@301 26 #include <Bela.h>
victor@2 27 #include <cmath>
victor@2 28 #include <NE10.h> // neon library
victor@2 29 #include "SampleData.h"
victor@2 30 #include "FIRfilter.h"
victor@2 31
victor@2 32 SampleData gSampleData; // User defined structure to get complex data from main
victor@2 33 int gReadPtr; // Position of last read sample from file
victor@2 34
victor@2 35 // filter vars
victor@2 36 ne10_fir_instance_f32_t gFIRfilter;
victor@2 37 ne10_float32_t *gFIRfilterIn;
victor@2 38 ne10_float32_t *gFIRfilterOut;
victor@2 39 ne10_uint32_t blockSize;
victor@2 40 ne10_float32_t *gFIRfilterState;
victor@2 41
giuliomoro@301 42 void initialise_filter(BelaContext *context);
victor@2 43
victor@2 44 // Task for handling the update of the frequencies using the matrix
victor@2 45 AuxiliaryTask gTriggerSamplesTask;
victor@2 46
victor@2 47 bool initialise_trigger();
victor@2 48 void trigger_samples();
victor@2 49
andrewm@56 50 // setup() is called once before the audio rendering starts.
victor@2 51 // Use it to perform any initialisation and allocation which is dependent
victor@2 52 // on the period size or sample rate.
victor@2 53 //
victor@2 54 // userData holds an opaque pointer to a data structure that was passed
victor@2 55 // in from the call to initAudio().
victor@2 56 //
victor@2 57 // Return true on success; returning false halts the program.
victor@2 58
giuliomoro@301 59 bool setup(BelaContext *context, void *userData)
victor@2 60 {
victor@2 61
victor@2 62 // Retrieve a parameter passed in from the initAudio() call
victor@2 63 gSampleData = *(SampleData *)userData;
victor@2 64
victor@2 65 gReadPtr = -1;
victor@2 66
andrewm@52 67 initialise_filter(context);
victor@2 68
victor@2 69 // Initialise auxiliary tasks
victor@2 70 if(!initialise_trigger())
victor@2 71 return false;
victor@2 72
victor@2 73 return true;
victor@2 74 }
victor@2 75
victor@2 76 // render() is called regularly at the highest priority by the audio engine.
victor@2 77 // Input and output are given from the audio hardware and the other
victor@2 78 // ADCs and DACs (if available). If only audio is available, numMatrixFrames
victor@2 79 // will be 0.
victor@2 80
giuliomoro@301 81 void render(BelaContext *context, void *userData)
victor@2 82 {
andrewm@52 83 for(unsigned int n = 0; n < context->audioFrames; n++) {
victor@2 84 float in = 0;
victor@2 85
victor@2 86 // If triggered...
victor@2 87 if(gReadPtr != -1)
victor@2 88 in += gSampleData.samples[gReadPtr++]; // ...read each sample...
victor@2 89
victor@2 90 if(gReadPtr >= gSampleData.sampleLen)
victor@2 91 gReadPtr = -1;
victor@2 92
victor@2 93 gFIRfilterIn[n] = in;
victor@2 94 }
victor@2 95
victor@2 96 ne10_fir_float_neon(&gFIRfilter, gFIRfilterIn, gFIRfilterOut, blockSize);
victor@2 97
andrewm@52 98 for(unsigned int n = 0; n < context->audioFrames; n++) {
andrewm@52 99 for(unsigned int channel = 0; channel < context->audioChannels; channel++)
andrewm@52 100 context->audioOut[n * context->audioChannels + channel] = gFIRfilterOut[n]; // ...and put it in both left and right channel
victor@2 101 }
victor@2 102
victor@2 103
victor@2 104 // Request that the lower-priority task run at next opportunity
giuliomoro@301 105 Bela_scheduleAuxiliaryTask(gTriggerSamplesTask);
victor@2 106 }
victor@2 107
victor@2 108 // Initialise NE10 data structures to define FIR filter
victor@2 109
giuliomoro@301 110 void initialise_filter(BelaContext *context)
victor@2 111 {
andrewm@52 112 blockSize = context->audioFrames;
victor@2 113 gFIRfilterState = (ne10_float32_t *) NE10_MALLOC ((FILTER_TAP_NUM+blockSize-1) * sizeof (ne10_float32_t));
victor@2 114 gFIRfilterIn = (ne10_float32_t *) NE10_MALLOC (blockSize * sizeof (ne10_float32_t));
victor@2 115 gFIRfilterOut = (ne10_float32_t *) NE10_MALLOC (blockSize * sizeof (ne10_float32_t));
victor@2 116 ne10_fir_init_float(&gFIRfilter, FILTER_TAP_NUM, filterTaps, gFIRfilterState, blockSize);
victor@2 117 }
victor@2 118
victor@2 119
victor@2 120 // Initialise the auxiliary task
victor@2 121 // and print info
victor@2 122
victor@2 123 bool initialise_trigger()
victor@2 124 {
andrewm@303 125 if((gTriggerSamplesTask = Bela_createAuxiliaryTask(&trigger_samples, 50, "bela-trigger-samples")) == 0)
victor@2 126 return false;
victor@2 127
victor@2 128 rt_printf("Press 'a' to trigger sample, 's' to stop\n");
victor@2 129 rt_printf("Press 'q' to quit\n");
victor@2 130
victor@2 131 return true;
victor@2 132 }
victor@2 133
victor@2 134 // This is a lower-priority call to periodically read keyboard input
victor@2 135 // and trigger samples. By placing it at a lower priority,
victor@2 136 // it has minimal effect on the audio performance but it will take longer to
victor@2 137 // complete if the system is under heavy audio load.
victor@2 138
victor@2 139 void trigger_samples()
victor@2 140 {
victor@2 141 // This is not a real-time task!
victor@2 142 // Cos getchar is a system call, not handled by Xenomai.
victor@2 143 // This task will be automatically down graded.
victor@2 144
victor@2 145 char keyStroke = '.';
victor@2 146
victor@2 147 keyStroke = getchar();
victor@2 148 while(getchar()!='\n'); // to read the first stroke
victor@2 149
victor@2 150 switch (keyStroke)
victor@2 151 {
victor@2 152 case 'a':
victor@2 153 gReadPtr = 0;
victor@2 154 break;
victor@2 155 case 's':
victor@2 156 gReadPtr = -1;
victor@2 157 break;
victor@2 158 case 'q':
victor@2 159 gShouldStop = true;
victor@2 160 break;
victor@2 161 default:
victor@2 162 break;
victor@2 163 }
victor@2 164 }
victor@2 165
victor@2 166
victor@2 167
andrewm@56 168 // cleanup() is called once at the end, after the audio has stopped.
andrewm@56 169 // Release any resources that were allocated in setup().
victor@2 170
giuliomoro@301 171 void cleanup(BelaContext *context, void *userData)
victor@2 172 {
victor@2 173 delete[] gSampleData.samples;
victor@2 174
victor@2 175 NE10_FREE(gFIRfilterState);
victor@2 176 NE10_FREE(gFIRfilterIn);
victor@2 177 NE10_FREE(gFIRfilterOut);
victor@2 178 }