robert@372: /* robert@372: ____ _____ _ _ robert@372: | __ )| ____| | / \ robert@372: | _ \| _| | | / _ \ robert@372: | |_) | |___| |___ / ___ \ robert@372: |____/|_____|_____/_/ \_\.io robert@372: robert@372: */ robert@372: andrewm@57: /* andrewm@57: * render.cpp andrewm@57: * andrewm@57: * Created on: Oct 24, 2014 andrewm@57: * Author: parallels andrewm@57: */ andrewm@57: robert@372: /** robert@372: \example 3_analog_input robert@372: robert@372: Connecting potentiometers robert@372: ------------------------- robert@372: robert@372: This sketch produces a sine tone, the frequency and amplitude of which are robert@372: affected by data received on the analog pins. Before looping through each audio robert@372: frame, we declare a value for the frequency and amplitude of our sine tone robert@372: (line 55); we adjust these values by taking in data from analog sensors robert@372: (for example potentiometers) with `analogRead()`. robert@372: robert@372: - connect a 10K pot to 3.3V and GND on its 1st and 3rd pins. robert@372: - connect the 2nd middle pin of the pot to analogIn 0. robert@372: - connect another 10K pot in the same way but with the middle pin connected to analogIn 1. robert@372: robert@372: The important thing to notice is that audio is sampled twice as often as analog robert@372: data. The audio sampling rate is 44.1kHz (44100 frames per second) and the robert@372: analog sampling rate is 22.05kHz (22050 frames per second). On line 62 you might robert@372: notice that we are processing the analog data and updating frequency and robert@372: amplitude only on every second audio sample, since the analog sampling rate is robert@372: half that of the audio. robert@372: robert@372: Note that the pin numbers are stored in the variables `gAnalogInputFrequency` and robert@372: `gAnalogInputAmplitude`. These are declared in the main.cpp file; if you look in robert@372: that file you will see that they have the values of 0 and 1. Bear in mind that robert@372: these are analog input pins which is a specific header! robert@372: */ andrewm@57: giuliomoro@301: #include andrewm@57: #include andrewm@57: #include andrewm@57: andrewm@57: float gPhase; andrewm@57: float gInverseSampleRate; andrewm@57: int gAudioFramesPerAnalogFrame; andrewm@57: andrewm@57: // These settings are carried over from main.cpp andrewm@57: // Setting global variables is an alternative approach andrewm@57: // to passing a structure to userData in setup() andrewm@57: andrewm@57: extern int gSensorInputFrequency; andrewm@57: extern int gSensorInputAmplitude; andrewm@57: andrewm@57: // setup() is called once before the audio rendering starts. andrewm@57: // Use it to perform any initialisation and allocation which is dependent andrewm@57: // on the period size or sample rate. andrewm@57: // andrewm@57: // userData holds an opaque pointer to a data structure that was passed andrewm@57: // in from the call to initAudio(). andrewm@57: // andrewm@57: // Return true on success; returning false halts the program. andrewm@57: giuliomoro@301: bool setup(BelaContext *context, void *userData) andrewm@57: { andrewm@57: if(context->analogFrames == 0 || context->analogFrames > context->audioFrames) { andrewm@57: rt_printf("Error: this example needs analog enabled, with 4 or 8 channels\n"); andrewm@57: return false; andrewm@57: } andrewm@57: andrewm@57: gAudioFramesPerAnalogFrame = context->audioFrames / context->analogFrames; andrewm@57: gInverseSampleRate = 1.0 / context->audioSampleRate; andrewm@57: gPhase = 0.0; andrewm@57: andrewm@57: return true; andrewm@57: } andrewm@57: andrewm@57: // render() is called regularly at the highest priority by the audio engine. andrewm@57: // Input and output are given from the audio hardware and the other andrewm@57: // ADCs and DACs (if available). If only audio is available, numMatrixFrames andrewm@57: // will be 0. andrewm@57: giuliomoro@301: void render(BelaContext *context, void *userData) andrewm@57: { andrewm@57: float frequency = 440.0; andrewm@57: float amplitude = 0.8; andrewm@57: andrewm@57: // There are twice as many audio frames as matrix frames since audio sample rate andrewm@57: // is twice as high andrewm@57: andrewm@57: for(unsigned int n = 0; n < context->audioFrames; n++) { andrewm@57: if(!(n % gAudioFramesPerAnalogFrame)) { andrewm@57: // Even audio samples: update frequency and amplitude from the matrix andrewm@308: frequency = map(analogRead(context, n/gAudioFramesPerAnalogFrame, gSensorInputFrequency), 0, 1, 100, 1000); andrewm@308: amplitude = analogRead(context, n/gAudioFramesPerAnalogFrame, gSensorInputAmplitude); andrewm@57: } andrewm@57: andrewm@57: float out = amplitude * sinf(gPhase); andrewm@57: andrewm@57: for(unsigned int channel = 0; channel < context->audioChannels; channel++) andrewm@57: context->audioOut[n * context->audioChannels + channel] = out; andrewm@57: andrewm@57: gPhase += 2.0 * M_PI * frequency * gInverseSampleRate; andrewm@57: if(gPhase > 2.0 * M_PI) andrewm@57: gPhase -= 2.0 * M_PI; andrewm@57: } andrewm@57: } andrewm@57: andrewm@57: // cleanup() is called once at the end, after the audio has stopped. andrewm@57: // Release any resources that were allocated in setup(). andrewm@57: giuliomoro@301: void cleanup(BelaContext *context, void *userData) andrewm@57: { andrewm@57: andrewm@57: }