robert@464: /*
robert@464:  ____  _____ _        _    
robert@464: | __ )| ____| |      / \   
robert@464: |  _ \|  _| | |     / _ \  
robert@464: | |_) | |___| |___ / ___ \ 
robert@464: |____/|_____|_____/_/   \_\
robert@464: 
robert@464: The platform for ultra-low latency audio and sensor processing
robert@464: 
robert@464: http://bela.io
robert@464: 
robert@464: A project of the Augmented Instruments Laboratory within the
robert@464: Centre for Digital Music at Queen Mary University of London.
robert@464: http://www.eecs.qmul.ac.uk/~andrewm
robert@464: 
robert@464: (c) 2016 Augmented Instruments Laboratory: Andrew McPherson,
robert@464:   Astrid Bin, Liam Donovan, Christian Heinrichs, Robert Jack,
robert@464:   Giulio Moro, Laurel Pardue, Victor Zappi. All rights reserved.
robert@464: 
robert@464: The Bela software is distributed under the GNU Lesser General Public License
robert@464: (LGPL 3.0), available here: https://www.gnu.org/licenses/lgpl-3.0.txt
robert@464: */
robert@464: 
robert@464: 
robert@464: #include <Bela.h>
robert@464: #include <cmath>
robert@464: #include <Scope.h>
robert@464: 
robert@464: Scope scope;
robert@464: 
robert@464: float gInverseSampleRate;
robert@464: float gPhase;
robert@464: 
robert@464: bool setup(BelaContext *context, void *userData)
robert@464: {
robert@464: 
robert@464:     // setup the scope with 3 channels at the audio sample rate
robert@464: 	scope.setup(3, context->audioSampleRate);
robert@464: 	
robert@464: 	gInverseSampleRate = 1.0 / context->audioSampleRate;
robert@464: 	gPhase = 0.0;
robert@464: 
robert@464: 	return true;
robert@464: }
robert@464: 
robert@464: void render(BelaContext *context, void *userData)
robert@464: {
robert@464: 
robert@464: 	for(unsigned int n = 0; n < context->audioFrames; n++) {
robert@464: 	    
robert@464: 	    // read analogIn channels 0 and 1
robert@464: 	    float in1 = analogRead(context, n, 0);
robert@464: 	    float in2 = analogRead(context, n, 1);
robert@464: 	    
robert@464: 	    // map in1 to amplitude and in2 to frequency
robert@464: 	    float amplitude = in1 * 0.8f;
robert@464: 	    float frequency = map(in2, 0, 1, 100, 1000);
robert@464: 	    
robert@464: 	    // generate a sine wave with the amplitude and frequency 
robert@464: 	    float out = amplitude * sinf(gPhase);
robert@464: 	    gPhase += 2.0 * M_PI * frequency * gInverseSampleRate;
robert@464: 		if(gPhase > 2.0 * M_PI)
robert@464: 			gPhase -= 2.0 * M_PI;
robert@464: 	    
robert@464: 	    // log the sine wave and sensor values on the scope
robert@464: 	    scope.log(out, in1, in2);
robert@464: 	    
robert@464: 	    // pass the sine wave to the audio outputs
robert@464: 	    for(unsigned int channel = 0; channel < context->audioChannels; channel++)
robert@464: 			context->audioOut[n * context->audioChannels + channel] = out;
robert@464: 
robert@464: 	}
robert@464: }
robert@464: 
robert@464: void cleanup(BelaContext *context, void *userData)
robert@464: {
robert@464: 
robert@464: }
robert@464: 
robert@464: 
robert@464: /**
robert@500: \example scope-analog/render.cpp
robert@464: 
robert@464: Connecting potentiometers
robert@464: -------------------------
robert@464: 
robert@464: This example reads from analogue inputs 0 and 1 via `analogReadFrame()` and 
robert@464: generates a sine wave with amplitude and frequency determined by their values. 
robert@464: It's best to connect a 10K potentiometer to each of these analog inputs. Far 
robert@464: left and far right pins of the pot go to 3.3V and GND, the middle should be 
robert@464: connected to the analog in pins.
robert@464: 
robert@464: The sine wave is then plotted on the oscilloscope. Click the Open Scope button to 
robert@464: view the results. As you turn the potentiometers you will see the amplitude and 
robert@464: frequency of the sine wave change.
robert@464: 
robert@464: This project also shows as example of `map()` which allows you to re-scale a number 
robert@464: from one range to another. Note that `map()` does not constrain your variable 
robert@464: within the upper and lower limits. If you want to do this use the `constrain()`
robert@464: function.
robert@464: */