victor@1: /* victor@1: * render.cpp victor@1: * victor@1: * Created on: Oct 24, 2014 victor@1: * Author: Andrew McPherson and Victor Zappi victor@1: */ victor@1: victor@1: victor@1: #include "../../include/render.h" victor@1: #include "../../include/RTAudio.h" // to schedule lower prio parallel process victor@1: #include victor@1: #include victor@1: #include victor@1: #include "SampleData.h" victor@1: victor@1: SampleData gSampleData; // User defined structure to get complex data from main victor@1: int gReadPtr; // Position of last read sample from file victor@1: int gNumChannels; victor@1: victor@1: // Task for handling the update of the frequencies using the matrix victor@1: AuxiliaryTask gTriggerSamplesTask; victor@1: victor@1: bool initialise_trigger(); victor@1: void trigger_samples(); victor@1: victor@1: // initialise_render() is called once before the audio rendering starts. victor@1: // Use it to perform any initialisation and allocation which is dependent victor@1: // on the period size or sample rate. victor@1: // victor@1: // userData holds an opaque pointer to a data structure that was passed victor@1: // in from the call to initAudio(). victor@1: // victor@1: // Return true on success; returning false halts the program. victor@1: victor@1: bool initialise_render(int numChannels, int numMatrixFramesPerPeriod, victor@1: int numAudioFramesPerPeriod, float matrixSampleRate, victor@1: float audioSampleRate, void *userData) victor@1: { victor@1: victor@1: // Retrieve a parameter passed in from the initAudio() call victor@1: gSampleData = *(SampleData *)userData; victor@1: victor@1: gReadPtr = -1; victor@1: gNumChannels = numChannels; victor@1: victor@1: // Initialise auxiliary tasks victor@1: if(!initialise_trigger()) victor@1: return false; victor@1: victor@1: return true; victor@1: } victor@1: victor@1: // render() is called regularly at the highest priority by the audio engine. victor@1: // Input and output are given from the audio hardware and the other victor@1: // ADCs and DACs (if available). If only audio is available, numMatrixFrames victor@1: // will be 0. victor@1: victor@1: void render(int numMatrixFrames, int numAudioFrames, float *audioIn, float *audioOut, victor@1: uint16_t *matrixIn, uint16_t *matrixOut) victor@1: { victor@1: for(int n = 0; n < numAudioFrames; n++) { victor@1: float out = 0; victor@1: victor@1: // If triggered... victor@1: if(gReadPtr != -1) victor@1: out += gSampleData.samples[gReadPtr++]; // ...read each sample... victor@1: victor@1: if(gReadPtr >= gSampleData.sampleLen) victor@1: gReadPtr = -1; victor@1: victor@1: for(int channel = 0; channel < gNumChannels; channel++) victor@1: audioOut[n * gNumChannels + channel] = out; // ...and put it in both left and right channel victor@1: } victor@1: victor@1: // Request that the lower-priority task run at next opportunity victor@1: scheduleAuxiliaryTask(gTriggerSamplesTask); victor@1: } victor@1: victor@1: // Initialise the auxiliary task victor@1: // and print info victor@1: victor@1: bool initialise_trigger() victor@1: { victor@1: if((gTriggerSamplesTask = createAuxiliaryTaskLoop(&trigger_samples, 50, "beaglert-trigger-samples")) == 0) victor@1: return false; victor@1: victor@1: rt_printf("Press 'a' to trigger sample, 's' to stop\n"); victor@1: rt_printf("Press 'q' to quit\n"); victor@1: victor@1: return true; victor@1: } victor@1: victor@1: // This is a lower-priority call to periodically read keyboard input victor@1: // and trigger samples. By placing it at a lower priority, victor@1: // it has minimal effect on the audio performance but it will take longer to victor@1: // complete if the system is under heavy audio load. victor@1: victor@1: void trigger_samples() victor@1: { victor@1: // This is not a real-time task! victor@1: // Cos getchar is a system call, not handled by Xenomai. victor@1: // This task will be automatically down graded. victor@1: victor@1: char keyStroke = '.'; victor@1: victor@1: keyStroke = getchar(); victor@1: while(getchar()!='\n'); // to read the first stroke victor@1: victor@1: switch (keyStroke) victor@1: { victor@1: case 'a': victor@1: gReadPtr = 0; victor@1: break; victor@1: case 's': victor@1: gReadPtr = -1; victor@1: break; victor@1: case 'q': victor@1: gShouldStop = true; victor@1: break; victor@1: default: victor@1: break; victor@1: } victor@1: } victor@1: victor@1: victor@1: victor@1: // cleanup_render() is called once at the end, after the audio has stopped. victor@1: // Release any resources that were allocated in initialise_render(). victor@1: victor@1: void cleanup_render() victor@1: { victor@1: delete[] gSampleData.samples; victor@1: }