annotate projects/samples/render.cpp @ 1:24fc8026ae8e

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