annotate projects/filter_FIR/render.cpp @ 12:a6beeba3a648

Initial support for higher matrix sample rates by reducing the number of channels. Input not tested yet, and not all examples updated to new format.
author andrewm
date Thu, 22 Jan 2015 19:00:22 +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 }