summaryrefslogtreecommitdiff
path: root/museduino/museduino.ino
diff options
context:
space:
mode:
Diffstat (limited to 'museduino/museduino.ino')
-rw-r--r--museduino/museduino.ino272
1 files changed, 272 insertions, 0 deletions
diff --git a/museduino/museduino.ino b/museduino/museduino.ino
new file mode 100644
index 0000000..b20e4ab
--- /dev/null
+++ b/museduino/museduino.ino
@@ -0,0 +1,272 @@
1
2/*********************
3
4EIG-2006 - Projet Arduino
5
6Museduino
7
8TRAN-GIRARD Pacien
9NICOLE RĂ©mi
10
11**********************/
12
13
14/***** Parameters *****/
15
16// FHT options
17#define FHT_N 256
18#define SCALE 256
19
20#define WINDOW 1
21#define REORDER 1
22
23#define LOG_OUT 0
24#define LIN_OUT 0
25#define LIN_OUT8 1
26
27#define OCTAVE 0
28#define OCT_NORM 0
29
30// Data aquisition options
31#define USE_FAST_AQUISITION 0
32#define PRESCALE_FACTOR 256
33#define DUMMY_SAMPLES 1
34#define WAIT_CYCLES 0
35
36// Data bins
37#define BINS 128 // FHT_N /2
38#define OCTAVES 8 // log2(FHT_N)
39
40// Note matching options
41#define IGNORE_FIRST_BINS 2
42#define AMPLITUDE_THRESHOLD 10
43
44// MIDI output
45#define MIDI_INSTRUMENT 103
46#define MIDI_VOLUME 120
47#define MIDI_RESET_PIN 4
48
49
50/***** System setup *****/
51
52#include <FHT.h>
53#include <SoftwareSerial.h>
54
55SoftwareSerial shieldSerial(2, 3); // RX, TX
56
57void setup_midi_shield() {
58 // setup soft serial link for MIDI control
59 shieldSerial.begin(31250);
60
61 // reset the VS1053
62 pinMode(MIDI_RESET_PIN, OUTPUT);
63
64 digitalWrite(MIDI_RESET_PIN, LOW);
65 delay(100);
66
67 digitalWrite(MIDI_RESET_PIN, HIGH);
68 delay(100);
69
70 // set volume and instrument
71 talkMIDI(0xB0, 0x07, MIDI_VOLUME);
72 talkMIDI(0xC0, MIDI_INSTRUMENT, 0);
73}
74
75void setup_serial_link() {
76 Serial.begin(115200);
77}
78
79void setup_adc() {
80 #if USE_FAST_AQUISITION == 1
81 ADCSRA = 0xe5; // set the adc to free running mode
82 ADMUX = 0x40; // use adc0
83 DIDR0 = 0x01; // turn off the digital input for adc0
84 #endif
85}
86
87void setup() {
88 setup_serial_link();
89 setup_midi_shield();
90 setup_adc();
91}
92
93
94/***** Data transforms *****/
95
96void run_fht() {
97 #if WINDOW == 1
98 fht_window();
99 #endif
100
101 #if REORDER == 1
102 fht_reorder();
103 #endif
104
105 fht_run();
106}
107
108void mag_fht() {
109 #if LOG_OUT == 1
110 fht_mag_log();
111 #elif LIN_OUT == 1
112 fht_mag_lin();
113 #elif LIN_OUT8 == 1
114 fht_mag_lin8();
115 #endif
116}
117
118int find_max_index() {
119 #if LOG_OUT == 1
120 uint8_t* data = fht_log_out;
121 uint8_t m = 0;
122 #elif LIN_OUT == 1
123 uint16_t* data = fht_lin_out;
124 uint16_t m = 0;
125 #elif LIN_OUT8 == 1
126 uint8_t* data = fht_lin_out8;
127 uint8_t m = 0;
128 #endif
129
130 int k = 0;
131 for (int i = IGNORE_FIRST_BINS; i < BINS; i++) {
132 if (data[i] > m && data[i] >= AMPLITUDE_THRESHOLD) {
133 m = data[i];
134 k = i;
135 }
136 }
137 return k;
138}
139
140int find_midi_note(float freq) {
141 float delta = 3.4028235E+38; // max float value
142 int note = 0;
143 for (int i = 0; i < 120; i++) { // exec time must be constant
144 float new_delta = abs(calc_midi_note_freq(i) - freq);
145 if (new_delta < delta) {
146 delta = new_delta;
147 note = i;
148 }
149 }
150 return note;
151}
152
153float calc_bin_frequency(int k) {
154 #if DUMMY_SAMPLES == 0
155 return (float(k) - 0.0616541) / 0.0287293;
156 #elif DUMMY_SAMPLES == 1
157 return (float(k) - 0.00827068) / 0.0573534;
158 #endif
159}
160
161float calc_midi_note_freq(int midi_note) {
162 return 8.1757989156 * pow(2, float(midi_note)/12);
163}
164
165
166/***** I/O wrappers *****/
167
168void talkMIDI(byte cmd, byte data1, byte data2) {
169 shieldSerial.write(cmd);
170 shieldSerial.write(data1);
171
172 // Some commands only have one data byte.
173 // All cmds less than 0xBn have 2 data bytes.
174 // (sort of: http://253.ccarh.org/handout/midiprotocol/)
175 if( (cmd & 0xF0) <= 0xB0)
176 shieldSerial.write(data2);
177}
178
179void noteOn(byte channel, byte note, byte attack_velocity) {
180 talkMIDI((0x90 | channel), note, attack_velocity);
181}
182
183void noteOff(byte channel, byte note, byte release_velocity) {
184 talkMIDI((0x80 | channel), note, release_velocity);
185}
186
187void aquire_data() {
188 noInterrupts();
189
190 #if USE_FAST_AQUISITION == 1
191
192 for (int i = 0; i < FHT_N; i++) {
193 while(!(ADCSRA & 0x10)); // wait for adc to be ready
194 ADCSRA = 0xf5; // restart adc
195 byte m = ADCL; // fetch adc data
196 byte j = ADCH;
197 int k = (j << 8) | m; // form into an int
198 k -= 0x0200; // form into a signed int
199 k <<= 6; // form into a 16b signed int
200 fht_input[i] = k * PRESCALE_FACTOR; // put real data into bin
201 }
202
203 #else
204
205 for (int i = 0; i < FHT_N; i++) {
206 for (int s = -1; s < DUMMY_SAMPLES; s++) {
207 fht_input[i] = analogRead(A0) * PRESCALE_FACTOR;
208 }
209 }
210
211 #endif
212
213 interrupts();
214}
215
216void send_fht_output(int max_index, float fund_freq, int midi_note) {
217 #if LOG_OUT == 1
218 uint8_t* data = fht_log_out;
219 #elif LIN_OUT == 1
220 uint16_t* data = fht_lin_out;
221 #elif LIN_OUT8 == 1
222 uint8_t* data = fht_lin_out8;
223 #endif
224
225 Serial.print("{");
226 Serial.print("\"spectrum\":[");
227 for (int i = 0; i < BINS; i++) {
228 if (i != 0) Serial.print(",");
229 Serial.print(data[i]);
230 }
231 Serial.print("],");
232
233 Serial.print("\"fundamental_bin\":");
234 Serial.print(max_index);
235 Serial.print(",");
236
237 Serial.print("\"fundamental_freq\":");
238 Serial.print(fund_freq);
239 Serial.print(",");
240
241 Serial.print("\"midi_note\":");
242 Serial.print(midi_note);
243
244 Serial.print("}\n");
245}
246
247
248/***** Main program *****/
249
250void loop() {
251 int note = 0;
252
253 while (1) {
254 aquire_data();
255
256 run_fht();