annotate projects/filter_FIR/render.cpp @ 14:06f93bef7dd2

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