annotate examples/samples/render.cpp @ 372:db2fe4e1b88e prerelease

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