annotate projects/samples/render.cpp @ 284:7bfb25a2e158 Doxy prerelease

Merge
author Robert Jack <robert.h.jack@gmail.com>
date Tue, 17 May 2016 15:53:24 +0100
parents ac8eb07afcf5
children
rev   line source
victor@1 1 /*
robert@269 2 ____ _____ _ _
robert@269 3 | __ )| ____| | / \
robert@269 4 | _ \| _| | | / _ \
robert@269 5 | |_) | |___| |___ / ___ \
robert@269 6 |____/|_____|_____/_/ \_\.io
robert@269 7
robert@269 8 */
robert@269 9
robert@269 10 /*
victor@1 11 *
robert@269 12 * Andrew McPherson and Victor Zappi
robert@269 13 * Queen Mary, University of London
victor@1 14 */
victor@1 15
robert@269 16 /**
robert@269 17 \example 4_audio_samples
robert@269 18
robert@269 19 Playback WAV files
robert@269 20 ------------------
robert@269 21
robert@269 22 This sketch shows how to playback audio samples from a buffer.
robert@269 23
robert@269 24 An audio file is loaded into a buffer `SampleData` as `gSampleData`. This is
robert@269 25 accessed with a read pointer that is incremented at audio rate within the render
robert@269 26 function: `out += gSampleData.samples[gReadPtr++]`.
robert@269 27
robert@269 28 Note that the read pointer is stopped from incrementing past the length of the
robert@269 29 `gSampleData`. This is achieved by comparing the read pointer value against the
robert@269 30 sample length which we can access as follows: `gSampleData.sampleLen`.
robert@269 31
robert@269 32 The sample is triggered by keyboard input: (a) starts sample playback, (s)
robert@269 33 stops sample playback. The triggering is treated as a lower priority task than
robert@269 34 the audio. You can see this at the bottom of the render function:
robert@269 35 `Bela_scheduleAuxiliaryTask(gTriggerSamplesTask)`;
robert@269 36
robert@269 37 Edit
robert@269 38
robert@269 39 */
robert@269 40
robert@269 41
victor@1 42
andrewm@56 43 #include <BeagleRT.h>
victor@1 44 #include <cmath>
victor@1 45 #include "SampleData.h"
victor@1 46
victor@1 47 SampleData gSampleData; // User defined structure to get complex data from main
victor@1 48 int gReadPtr; // Position of last read sample from file
victor@1 49
victor@1 50 // Task for handling the update of the frequencies using the matrix
victor@1 51 AuxiliaryTask gTriggerSamplesTask;
victor@1 52
victor@1 53 bool initialise_trigger();
victor@1 54 void trigger_samples();
victor@1 55
andrewm@56 56 // setup() is called once before the audio rendering starts.
victor@1 57 // Use it to perform any initialisation and allocation which is dependent
victor@1 58 // on the period size or sample rate.
victor@1 59 //
victor@1 60 // userData holds an opaque pointer to a data structure that was passed
victor@1 61 // in from the call to initAudio().
victor@1 62 //
victor@1 63 // Return true on success; returning false halts the program.
victor@1 64
andrewm@56 65 bool setup(BeagleRTContext *context, void *userData)
victor@1 66 {
victor@1 67
victor@1 68 // Retrieve a parameter passed in from the initAudio() call
victor@1 69 gSampleData = *(SampleData *)userData;
victor@1 70
victor@1 71 gReadPtr = -1;
victor@1 72
victor@1 73 // Initialise auxiliary tasks
victor@1 74 if(!initialise_trigger())
victor@1 75 return false;
victor@1 76
victor@1 77 return true;
victor@1 78 }
victor@1 79
victor@1 80 // render() is called regularly at the highest priority by the audio engine.
victor@1 81 // Input and output are given from the audio hardware and the other
victor@1 82 // ADCs and DACs (if available). If only audio is available, numMatrixFrames
victor@1 83 // will be 0.
victor@1 84
andrewm@52 85 void render(BeagleRTContext *context, void *userData)
victor@1 86 {
andrewm@56 87 for(unsigned int n = 0; n < context->audioFrames; n++) {
victor@1 88 float out = 0;
victor@1 89
victor@1 90 // If triggered...
victor@1 91 if(gReadPtr != -1)
victor@1 92 out += gSampleData.samples[gReadPtr++]; // ...read each sample...
victor@1 93
victor@1 94 if(gReadPtr >= gSampleData.sampleLen)
victor@1 95 gReadPtr = -1;
victor@1 96
andrewm@56 97 for(unsigned int channel = 0; channel < context->audioChannels; channel++)
andrewm@52 98 context->audioOut[n * context->audioChannels + channel] = out; // ...and put it in both left and right channel
victor@1 99 }
victor@1 100
victor@1 101 // Request that the lower-priority task run at next opportunity
andrewm@52 102 BeagleRT_scheduleAuxiliaryTask(gTriggerSamplesTask);
victor@1 103 }
victor@1 104
victor@1 105 // Initialise the auxiliary task
victor@1 106 // and print info
victor@1 107
victor@1 108 bool initialise_trigger()
victor@1 109 {
andrewm@52 110 if((gTriggerSamplesTask = BeagleRT_createAuxiliaryTask(&trigger_samples, 50, "beaglert-trigger-samples")) == 0)
victor@1 111 return false;
victor@1 112
victor@1 113 rt_printf("Press 'a' to trigger sample, 's' to stop\n");
victor@1 114 rt_printf("Press 'q' to quit\n");
victor@1 115
victor@1 116 return true;
victor@1 117 }
victor@1 118
victor@1 119 // This is a lower-priority call to periodically read keyboard input
victor@1 120 // and trigger samples. By placing it at a lower priority,
victor@1 121 // it has minimal effect on the audio performance but it will take longer to
victor@1 122 // complete if the system is under heavy audio load.
victor@1 123
victor@1 124 void trigger_samples()
victor@1 125 {
victor@1 126 // This is not a real-time task!
victor@1 127 // Cos getchar is a system call, not handled by Xenomai.
victor@1 128 // This task will be automatically down graded.
victor@1 129
victor@1 130 char keyStroke = '.';
victor@1 131
victor@1 132 keyStroke = getchar();
victor@1 133 while(getchar()!='\n'); // to read the first stroke
victor@1 134
victor@1 135 switch (keyStroke)
victor@1 136 {
victor@1 137 case 'a':
victor@1 138 gReadPtr = 0;
victor@1 139 break;
victor@1 140 case 's':
victor@1 141 gReadPtr = -1;
victor@1 142 break;
victor@1 143 case 'q':
victor@1 144 gShouldStop = true;
victor@1 145 break;
victor@1 146 default:
victor@1 147 break;
victor@1 148 }
victor@1 149 }
victor@1 150
victor@1 151
victor@1 152
andrewm@56 153 // cleanup() is called once at the end, after the audio has stopped.
andrewm@56 154 // Release any resources that were allocated in setup().
victor@1 155
andrewm@56 156 void cleanup(BeagleRTContext *context, void *userData)
victor@1 157 {
victor@1 158 delete[] gSampleData.samples;
victor@1 159 }