annotate projects/filter_FIR/render.cpp @ 55:41d24dba6b74 newapi

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