annotate projects/filter_FIR/render.cpp @ 39:638bc1ae2500 staging

Improved readibility of the DIGITAL code in the PRU, using register names instead of aliases and expanding some of the macros, removing unused macros. Binaries were not modified
author Giulio Moro <giuliomoro@yahoo.it>
date Wed, 13 May 2015 12:18:10 +0100
parents 06f93bef7dd2
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 }