annotate projects/filter_FIR/render.cpp @ 9:323a4eb9b7c0

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