| robert@372 | 1 /* | 
| robert@372 | 2  ____  _____ _        _ | 
| robert@372 | 3 | __ )| ____| |      / \ | 
| robert@372 | 4 |  _ \|  _| | |     / _ \ | 
| robert@372 | 5 | |_) | |___| |___ / ___ \ | 
| robert@372 | 6 |____/|_____|_____/_/   \_\.io | 
| robert@372 | 7 | 
| robert@372 | 8  */ | 
| robert@372 | 9 | 
| andrewm@0 | 10 /* | 
| andrewm@0 | 11  * render.cpp | 
| andrewm@0 | 12  * | 
| andrewm@0 | 13  *  Created on: Oct 24, 2014 | 
| andrewm@0 | 14  *      Author: parallels | 
| andrewm@0 | 15  */ | 
| andrewm@0 | 16 | 
| robert@372 | 17 /** | 
| robert@372 | 18 \example 1_basic_helloworld | 
| robert@372 | 19 | 
| robert@372 | 20 Producing your first bleep! | 
| robert@372 | 21 --------------------------- | 
| robert@372 | 22 | 
| robert@372 | 23 This sketch is the hello world of embedded interactive audio. Better known as bleep, it | 
| robert@372 | 24 produces a sine tone. | 
| robert@372 | 25 | 
| robert@372 | 26 The frequency of the sine tone is determined by a global variable, `gFrequency` | 
| robert@372 | 27 (line 12). The sine tone is produced by incrementing the phase of a sin function | 
| robert@372 | 28 on every audio frame. | 
| robert@372 | 29 | 
| robert@372 | 30 In render() you'll see a nested for loop structure. You'll see this in all Bela projects. | 
| robert@372 | 31 The first for loop cycles through 'audioFrames', the second through 'audioChannels' (in this case left 0 and right 1). | 
| robert@372 | 32 It is good to familiarise yourself with this structure as it's fundamental to producing sound with the system. | 
| robert@372 | 33 */ | 
| andrewm@0 | 34 | 
| giuliomoro@301 | 35 #include <Bela.h> | 
| andrewm@0 | 36 #include <cmath> | 
| andrewm@0 | 37 | 
| andrewm@56 | 38 float gFrequency = 440.0; | 
| andrewm@0 | 39 float gPhase; | 
| andrewm@0 | 40 float gInverseSampleRate; | 
| andrewm@0 | 41 | 
| andrewm@56 | 42 // setup() is called once before the audio rendering starts. | 
| andrewm@0 | 43 // Use it to perform any initialisation and allocation which is dependent | 
| andrewm@0 | 44 // on the period size or sample rate. | 
| andrewm@0 | 45 // | 
| andrewm@0 | 46 // userData holds an opaque pointer to a data structure that was passed | 
| andrewm@0 | 47 // in from the call to initAudio(). | 
| andrewm@0 | 48 // | 
| andrewm@0 | 49 // Return true on success; returning false halts the program. | 
| andrewm@0 | 50 | 
| giuliomoro@301 | 51 bool setup(BelaContext *context, void *userData) | 
| andrewm@0 | 52 { | 
| andrewm@0 | 53 	// Retrieve a parameter passed in from the initAudio() call | 
| andrewm@56 | 54 	if(userData != 0) | 
| andrewm@56 | 55 		gFrequency = *(float *)userData; | 
| andrewm@0 | 56 | 
| andrewm@45 | 57 	gInverseSampleRate = 1.0 / context->audioSampleRate; | 
| andrewm@0 | 58 	gPhase = 0.0; | 
| andrewm@0 | 59 | 
| andrewm@0 | 60 	return true; | 
| andrewm@0 | 61 } | 
| andrewm@0 | 62 | 
| andrewm@0 | 63 // render() is called regularly at the highest priority by the audio engine. | 
| andrewm@0 | 64 // Input and output are given from the audio hardware and the other | 
| andrewm@0 | 65 // ADCs and DACs (if available). If only audio is available, numMatrixFrames | 
| andrewm@0 | 66 // will be 0. | 
| andrewm@0 | 67 | 
| giuliomoro@301 | 68 void render(BelaContext *context, void *userData) | 
| andrewm@0 | 69 { | 
| andrewm@45 | 70 	for(unsigned int n = 0; n < context->audioFrames; n++) { | 
| andrewm@0 | 71 		float out = 0.8f * sinf(gPhase); | 
| andrewm@0 | 72 		gPhase += 2.0 * M_PI * gFrequency * gInverseSampleRate; | 
| andrewm@0 | 73 		if(gPhase > 2.0 * M_PI) | 
| andrewm@0 | 74 			gPhase -= 2.0 * M_PI; | 
| andrewm@0 | 75 | 
| giuliomoro@180 | 76 		for(unsigned int channel = 0; channel < context->audioChannels; channel++) { | 
| giuliomoro@180 | 77 			// Two equivalent ways to write this code | 
| giuliomoro@180 | 78 | 
| giuliomoro@180 | 79 			// The long way, using the buffers directly: | 
| giuliomoro@180 | 80 			// context->audioOut[n * context->audioChannels + channel] = out; | 
| giuliomoro@180 | 81 | 
| giuliomoro@180 | 82 			// Or using the macros: | 
| andrewm@308 | 83 			audioWrite(context, n, channel, out); | 
| giuliomoro@180 | 84 		} | 
| andrewm@0 | 85 	} | 
| andrewm@0 | 86 } | 
| andrewm@0 | 87 | 
| andrewm@56 | 88 // cleanup() is called once at the end, after the audio has stopped. | 
| andrewm@56 | 89 // Release any resources that were allocated in setup(). | 
| andrewm@0 | 90 | 
| giuliomoro@301 | 91 void cleanup(BelaContext *context, void *userData) | 
| andrewm@0 | 92 { | 
| andrewm@0 | 93 | 
| andrewm@0 | 94 } |