robert@464
|
1 /*
|
robert@464
|
2 ____ _____ _ _
|
robert@464
|
3 | __ )| ____| | / \
|
robert@464
|
4 | _ \| _| | | / _ \
|
robert@464
|
5 | |_) | |___| |___ / ___ \
|
robert@464
|
6 |____/|_____|_____/_/ \_\
|
robert@464
|
7
|
robert@464
|
8 The platform for ultra-low latency audio and sensor processing
|
robert@464
|
9
|
robert@464
|
10 http://bela.io
|
robert@464
|
11
|
robert@464
|
12 A project of the Augmented Instruments Laboratory within the
|
robert@464
|
13 Centre for Digital Music at Queen Mary University of London.
|
robert@464
|
14 http://www.eecs.qmul.ac.uk/~andrewm
|
robert@464
|
15
|
robert@464
|
16 (c) 2016 Augmented Instruments Laboratory: Andrew McPherson,
|
robert@464
|
17 Astrid Bin, Liam Donovan, Christian Heinrichs, Robert Jack,
|
robert@464
|
18 Giulio Moro, Laurel Pardue, Victor Zappi. All rights reserved.
|
robert@464
|
19
|
robert@464
|
20 The Bela software is distributed under the GNU Lesser General Public License
|
robert@464
|
21 (LGPL 3.0), available here: https://www.gnu.org/licenses/lgpl-3.0.txt
|
robert@464
|
22 */
|
robert@464
|
23
|
robert@464
|
24
|
robert@464
|
25 #include <Bela.h>
|
robert@464
|
26 #include <cmath>
|
robert@464
|
27
|
robert@464
|
28 float gPhase;
|
robert@464
|
29 float gInverseSampleRate;
|
robert@464
|
30 int gAudioFramesPerAnalogFrame;
|
robert@464
|
31
|
robert@542
|
32 // Set the analog channels to read from
|
robert@542
|
33 int gSensorInputFrequency = 0;
|
robert@542
|
34 int gSensorInputAmplitude = 1;
|
robert@464
|
35
|
robert@464
|
36 bool setup(BelaContext *context, void *userData)
|
robert@464
|
37 {
|
robert@542
|
38
|
robert@542
|
39 // Check if analog channels are enabled
|
robert@464
|
40 if(context->analogFrames == 0 || context->analogFrames > context->audioFrames) {
|
robert@464
|
41 rt_printf("Error: this example needs analog enabled, with 4 or 8 channels\n");
|
robert@464
|
42 return false;
|
robert@464
|
43 }
|
robert@464
|
44
|
robert@542
|
45 // Check that we have the same number of inputs and outputs.
|
robert@542
|
46 if(context->audioInChannels != context->audioOutChannels ||
|
robert@542
|
47 context->analogInChannels != context-> analogOutChannels){
|
robert@542
|
48 printf("Error: for this project, you need the same number of input and output channels.\n");
|
robert@542
|
49 return false;
|
robert@542
|
50 }
|
robert@542
|
51
|
robert@542
|
52 // Useful calculations
|
robert@464
|
53 gAudioFramesPerAnalogFrame = context->audioFrames / context->analogFrames;
|
robert@464
|
54 gInverseSampleRate = 1.0 / context->audioSampleRate;
|
robert@464
|
55 gPhase = 0.0;
|
robert@464
|
56
|
robert@464
|
57 return true;
|
robert@464
|
58 }
|
robert@464
|
59
|
robert@464
|
60 void render(BelaContext *context, void *userData)
|
robert@464
|
61 {
|
robert@464
|
62 float frequency = 440.0;
|
robert@464
|
63 float amplitude = 0.8;
|
robert@464
|
64
|
robert@464
|
65 // There are twice as many audio frames as matrix frames since audio sample rate
|
robert@464
|
66 // is twice as high
|
robert@464
|
67
|
robert@464
|
68 for(unsigned int n = 0; n < context->audioFrames; n++) {
|
robert@464
|
69 if(!(n % gAudioFramesPerAnalogFrame)) {
|
robert@542
|
70 // On even audio samples: read analog inputs and update frequency and amplitude
|
robert@464
|
71 frequency = map(analogRead(context, n/gAudioFramesPerAnalogFrame, gSensorInputFrequency), 0, 1, 100, 1000);
|
robert@464
|
72 amplitude = analogRead(context, n/gAudioFramesPerAnalogFrame, gSensorInputAmplitude);
|
robert@464
|
73 }
|
robert@464
|
74
|
robert@464
|
75 float out = amplitude * sinf(gPhase);
|
robert@464
|
76
|
robert@542
|
77 for(unsigned int channel = 0; channel < context->audioOutChannels; channel++) {
|
robert@542
|
78 audioWrite(context, n, channel, out);
|
robert@542
|
79 }
|
robert@464
|
80
|
robert@542
|
81 // Update and wrap phase of sine tone
|
robert@464
|
82 gPhase += 2.0 * M_PI * frequency * gInverseSampleRate;
|
robert@464
|
83 if(gPhase > 2.0 * M_PI)
|
robert@464
|
84 gPhase -= 2.0 * M_PI;
|
robert@464
|
85 }
|
robert@464
|
86 }
|
robert@464
|
87
|
robert@464
|
88 void cleanup(BelaContext *context, void *userData)
|
robert@464
|
89 {
|
robert@464
|
90
|
robert@464
|
91 }
|
robert@464
|
92
|
robert@464
|
93
|
robert@464
|
94 /**
|
robert@500
|
95 \example analog-input/render.cpp
|
robert@464
|
96
|
robert@464
|
97 Connecting potentiometers
|
robert@464
|
98 -------------------------
|
robert@464
|
99
|
robert@464
|
100 This sketch produces a sine tone, the frequency and amplitude of which are
|
robert@542
|
101 modulated by data received on the analog input pins. Before looping through each audio
|
robert@542
|
102 frame, we declare a value for the `frequency` and `amplitude` of our sine tone;
|
robert@542
|
103 we adjust these values by taking in data from analog sensors (for example potentiometers)
|
robert@542
|
104 with `analogRead()`.
|
robert@464
|
105
|
robert@464
|
106 - connect a 10K pot to 3.3V and GND on its 1st and 3rd pins.
|
robert@464
|
107 - connect the 2nd middle pin of the pot to analogIn 0.
|
robert@464
|
108 - connect another 10K pot in the same way but with the middle pin connected to analogIn 1.
|
robert@464
|
109
|
robert@464
|
110 The important thing to notice is that audio is sampled twice as often as analog
|
robert@464
|
111 data. The audio sampling rate is 44.1kHz (44100 frames per second) and the
|
robert@524
|
112 analog sampling rate is 22.05kHz (22050 frames per second). Notice that we are
|
robert@524
|
113 processing the analog data and updating frequency and amplitude only on every
|
robert@524
|
114 second audio sample, since the analog sampling rate is half that of the audio.
|
robert@524
|
115
|
robert@524
|
116 ````
|
robert@524
|
117 if(!(n % gAudioFramesPerAnalogFrame)) {
|
robert@524
|
118 // Even audio samples: update frequency and amplitude from the matrix
|
robert@524
|
119 frequency = map(analogRead(context, n/gAudioFramesPerAnalogFrame, gSensorInputFrequency), 0, 1, 100, 1000);
|
robert@524
|
120 amplitude = analogRead(context, n/gAudioFramesPerAnalogFrame, gSensorInputAmplitude);
|
robert@524
|
121 }
|
robert@524
|
122 ````
|
robert@464
|
123
|
robert@464
|
124 */
|