| andrewm@13 | 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  /* | 
| andrewm@13 | 11  * render.cpp | 
| andrewm@13 | 12  * | 
| andrewm@13 | 13  *  Created on: Oct 24, 2014 | 
| andrewm@13 | 14  *      Author: parallels | 
| andrewm@13 | 15  */ | 
| andrewm@13 | 16 | 
| robert@269 | 17 /** | 
| robert@269 | 18 \example 1_basic_audio_passthrough | 
| robert@269 | 19 | 
| robert@269 | 20 Audio passthrough: input to output | 
| robert@269 | 21 ----------------------------------------- | 
| robert@269 | 22 | 
| robert@269 | 23 This sketch demonstrates the simplest possible case of using audio: it passes | 
| robert@269 | 24 audio input straight to audio output. | 
| robert@269 | 25 | 
| robert@269 | 26 Note the nested `for` loop structure. You will see this in all Bela projects. The | 
| robert@269 | 27 first `for` loop cycles through the audio frames, the second through each of the | 
| robert@269 | 28 audio channels (in this case left 0 and right 1). | 
| robert@269 | 29 | 
| robert@269 | 30 | 
| robert@269 | 31 We write samples to the audio output buffer like this: | 
| robert@269 | 32 `context->audioOut[n * context->audioChannels + ch]` where `n` is the current audio | 
| robert@269 | 33 frame and `ch` is the current channel, both provided by the nested for loop structure. | 
| robert@269 | 34 | 
| robert@269 | 35 We can access samples in the audio input buffer in a similar way, like this: | 
| robert@269 | 36 `context->audioIn[n * context->audioChannels + ch]`. | 
| robert@269 | 37 | 
| robert@269 | 38 So a simple audio pass through is achieved by setting output buffer equal to | 
| robert@269 | 39 input buffer: | 
| robert@269 | 40 `context->audioOut[n * context->audioChannels + ch] = context->audioIn[n * context->audioChannels + ch]`. | 
| robert@269 | 41 | 
| robert@269 | 42 | 
| robert@269 | 43 */ | 
| robert@269 | 44 | 
| robert@269 | 45 | 
| robert@269 | 46 | 
| robert@269 | 47 | 
| andrewm@13 | 48 | 
| andrewm@56 | 49 #include <BeagleRT.h> | 
| andrewm@56 | 50 #include <Utilities.h> | 
| andrewm@13 | 51 #include <rtdk.h> | 
| andrewm@13 | 52 | 
| andrewm@56 | 53 // setup() is called once before the audio rendering starts. | 
| andrewm@13 | 54 // Use it to perform any initialisation and allocation which is dependent | 
| andrewm@13 | 55 // on the period size or sample rate. | 
| andrewm@13 | 56 // | 
| andrewm@13 | 57 // userData holds an opaque pointer to a data structure that was passed | 
| andrewm@13 | 58 // in from the call to initAudio(). | 
| andrewm@13 | 59 // | 
| andrewm@13 | 60 // Return true on success; returning false halts the program. | 
| andrewm@13 | 61 | 
| andrewm@56 | 62 bool setup(BeagleRTContext *context, void *userData) | 
| andrewm@13 | 63 { | 
| andrewm@13 | 64 	// Nothing to do here... | 
| andrewm@13 | 65 	return true; | 
| andrewm@13 | 66 } | 
| andrewm@13 | 67 | 
| andrewm@13 | 68 // render() is called regularly at the highest priority by the audio engine. | 
| andrewm@13 | 69 // Input and output are given from the audio hardware and the other | 
| andrewm@13 | 70 // ADCs and DACs (if available). If only audio is available, numMatrixFrames | 
| andrewm@13 | 71 // will be 0. | 
| andrewm@13 | 72 | 
| andrewm@52 | 73 void render(BeagleRTContext *context, void *userData) | 
| andrewm@13 | 74 { | 
| andrewm@13 | 75 	// Simplest possible case: pass inputs through to outputs | 
| andrewm@52 | 76 	for(unsigned int n = 0; n < context->audioFrames; n++) { | 
| giuliomoro@180 | 77 		for(unsigned int ch = 0; ch < context->audioChannels; ch++){ | 
| giuliomoro@180 | 78 			// Two equivalent ways to write this code | 
| giuliomoro@180 | 79 | 
| giuliomoro@180 | 80 			// The long way, using the buffers directly: | 
| giuliomoro@180 | 81 			// context->audioOut[n * context->audioChannels + ch] = | 
| giuliomoro@180 | 82 			// 		context->audioIn[n * context->audioChannels + ch]; | 
| giuliomoro@180 | 83 | 
| giuliomoro@180 | 84 			// Or using the macros: | 
| giuliomoro@180 | 85 			audioWriteFrame(context, n, ch, audioReadFrame(context, n, ch)); | 
| giuliomoro@180 | 86 		} | 
| andrewm@13 | 87 	} | 
| andrewm@13 | 88 | 
| giuliomoro@180 | 89 	// Same with analog channelss | 
| giuliomoro@180 | 90 	for(unsigned int n = 0; n < context->analogFrames; n++) { | 
| giuliomoro@180 | 91 		for(unsigned int ch = 0; ch < context->analogChannels; ch++) { | 
| giuliomoro@180 | 92 			// Two equivalent ways to write this code | 
| giuliomoro@180 | 93 | 
| giuliomoro@180 | 94 			// The long way, using the buffers directly: | 
| giuliomoro@180 | 95 			// context->analogOut[n * context->analogChannels + ch] = context->analogIn[n * context->analogChannels + ch]; | 
| giuliomoro@180 | 96 | 
| giuliomoro@180 | 97 			// Or using the macros: | 
| giuliomoro@180 | 98 			analogWriteFrame(context, n, ch, analogReadFrame(context, n, ch)); | 
| giuliomoro@180 | 99 		} | 
| giuliomoro@180 | 100 	} | 
| andrewm@13 | 101 } | 
| andrewm@13 | 102 | 
| andrewm@56 | 103 // cleanup() is called once at the end, after the audio has stopped. | 
| andrewm@56 | 104 // Release any resources that were allocated in setup(). | 
| andrewm@13 | 105 | 
| andrewm@56 | 106 void cleanup(BeagleRTContext *context, void *userData) | 
| andrewm@13 | 107 { | 
| andrewm@13 | 108 | 
| andrewm@13 | 109 } |