robert@533
|
1 /*
|
robert@533
|
2 ____ _____ _ _
|
robert@533
|
3 | __ )| ____| | / \
|
robert@533
|
4 | _ \| _| | | / _ \
|
robert@533
|
5 | |_) | |___| |___ / ___ \
|
robert@533
|
6 |____/|_____|_____/_/ \_\
|
robert@533
|
7
|
robert@533
|
8 The platform for ultra-low latency audio and sensor processing
|
robert@533
|
9
|
robert@533
|
10 http://bela.io
|
robert@533
|
11
|
robert@533
|
12 A project of the Augmented Instruments Laboratory within the
|
robert@533
|
13 Centre for Digital Music at Queen Mary University of London.
|
robert@533
|
14 http://www.eecs.qmul.ac.uk/~andrewm
|
robert@533
|
15
|
robert@533
|
16 (c) 2016 Augmented Instruments Laboratory: Andrew McPherson,
|
robert@533
|
17 Astrid Bin, Liam Donovan, Christian Heinrichs, Robert Jack,
|
robert@533
|
18 Giulio Moro, Laurel Pardue, Victor Zappi. All rights reserved.
|
robert@533
|
19
|
robert@533
|
20 The Bela software is distributed under the GNU Lesser General Public License
|
robert@533
|
21 (LGPL 3.0), available here: https://www.gnu.org/licenses/lgpl-3.0.txt
|
robert@533
|
22 */
|
robert@533
|
23
|
robert@533
|
24 #include <Bela.h>
|
robert@533
|
25 #include <cmath>
|
robert@533
|
26
|
robert@533
|
27 float gFrequency = 4.0;
|
robert@533
|
28 float gPhase;
|
robert@533
|
29 float gInverseSampleRate;
|
robert@533
|
30
|
robert@533
|
31 bool setup(BelaContext *context, void *userData)
|
robert@533
|
32 {
|
robert@545
|
33 // Check that we have the same number of inputs and outputs.
|
robert@545
|
34 if(context->audioInChannels != context->audioOutChannels ||
|
robert@545
|
35 context->analogInChannels != context-> analogOutChannels){
|
robert@545
|
36 printf("Error: for this project, you need the same number of input and output channels.\n");
|
robert@545
|
37 return false;
|
robert@545
|
38 }
|
robert@533
|
39
|
robert@533
|
40 gInverseSampleRate = 1.0 / context->audioSampleRate;
|
robert@533
|
41 gPhase = 0.0;
|
robert@533
|
42
|
robert@533
|
43 return true;
|
robert@533
|
44 }
|
robert@533
|
45
|
robert@533
|
46 void render(BelaContext *context, void *userData)
|
robert@533
|
47 {
|
robert@533
|
48 // Nested for loops for audio channels
|
robert@533
|
49 for(unsigned int n = 0; n < context->audioFrames; n++) {
|
giuliomoro@538
|
50
|
robert@533
|
51 // Generate a sinewave with frequency set by gFrequency
|
robert@533
|
52 // and amplitude from -0.5 to 0.5
|
robert@533
|
53 float lfo = sinf(gPhase) * 0.5;
|
robert@533
|
54 // Keep track and wrap the phase of the sinewave
|
robert@533
|
55 gPhase += 2.0 * M_PI * gFrequency * gInverseSampleRate;
|
robert@533
|
56 if(gPhase > 2.0 * M_PI)
|
robert@533
|
57 gPhase -= 2.0 * M_PI;
|
robert@533
|
58
|
robert@545
|
59 for(unsigned int channel = 0; channel < context->audioOutChannels; channel++) {
|
giuliomoro@538
|
60 // Read the audio input and half the amplitude
|
giuliomoro@538
|
61 float input = audioRead(context, n, channel) * 0.5;
|
robert@533
|
62 // Write to audio output the audio input multiplied by the sinewave
|
robert@533
|
63 audioWrite(context, n, channel, (input*lfo));
|
robert@533
|
64 }
|
robert@533
|
65 }
|
robert@533
|
66
|
robert@533
|
67 // Nested for loops for analog channels
|
robert@533
|
68 for(unsigned int n = 0; n < context->analogFrames; n++) {
|
robert@545
|
69 for(unsigned int ch = 0; ch < context->analogOutChannels; ch++) {
|
robert@533
|
70 // Read analog channel 0 and map the range from 0-1 to 0.25-20
|
robert@533
|
71 // use this to set the value of gFrequency
|
robert@533
|
72 gFrequency = map(analogRead(context, n, 0), 0.0, 1.0, 0.25, 20.0);
|
robert@533
|
73 }
|
robert@533
|
74 }
|
robert@533
|
75
|
robert@533
|
76 }
|
robert@533
|
77
|
robert@533
|
78 void cleanup(BelaContext *context, void *userData)
|
robert@533
|
79 {
|
robert@533
|
80
|
robert@533
|
81 }
|
robert@533
|
82
|
robert@533
|
83
|
robert@533
|
84 /**
|
robert@533
|
85 \example tremolo/render.cpp
|
robert@533
|
86
|
robert@533
|
87 A simple tremolo effect
|
robert@533
|
88 -----------------------
|
robert@533
|
89
|
robert@533
|
90 This sketch demonstrates how to make a simple tremolo effect with one potiometer to
|
robert@533
|
91 control the rate of the effect. A tremolo effect is a simple type of amplitude modulation
|
robert@533
|
92 where the amplitude of one signal is continuous modulated by the amplitude of another.
|
robert@534
|
93 This is achieved by multiplying two signals together.
|
robert@533
|
94
|
robert@533
|
95 In this example we want to create a tremolo effect like that you would find in a guitar
|
robert@533
|
96 effects box so our first signal will be our audio input into which we could plug a guitar
|
robert@533
|
97 or external sound source. This will be our 'carrier' signal.
|
robert@533
|
98
|
robert@533
|
99 The second signal that we will use, the 'modulator', will be a low freqeuncy oscillator (LFO),
|
robert@533
|
100 in this case a sinetone which we will generate in the same way as the 01-Basic/sinetone example.
|
robert@533
|
101 The frequency of this sinetone is determined by a global variable, `gFrequency`. Again, the
|
robert@533
|
102 sinetone is produced by incrementing the phase of a sine function on every audio frame.
|
robert@533
|
103
|
robert@533
|
104 In `render()` you'll see two nested for loop structures, one for audio and the other for the
|
robert@534
|
105 analogs. You should be pretty familiar with this structure by now. In the first of these loops
|
robert@533
|
106 we deal with all the audio -- in the second with reading the analog input channels. We read the
|
robert@533
|
107 value of analog input 0 and map it to an appropriate range for controlling the frequency
|
robert@533
|
108 of the sine tone.
|
robert@533
|
109
|
robert@533
|
110 The lfo is then mulitplied together with the audio input and sent to the audio output.
|
robert@534
|
111
|
robert@534
|
112 Hardware
|
robert@534
|
113 -----------------------
|
robert@534
|
114 - connect a 10K pot to 3.3V and GND on its 1st and 3rd pins.
|
robert@534
|
115 - connect the 2nd middle pin of the pot to analogIn 0.
|
robert@534
|
116
|
robert@533
|
117 */
|