aboutsummaryrefslogtreecommitdiff
path: root/quantum/audio/audio.c
diff options
context:
space:
mode:
Diffstat (limited to 'quantum/audio/audio.c')
-rw-r--r--quantum/audio/audio.c322
1 files changed, 164 insertions, 158 deletions
diff --git a/quantum/audio/audio.c b/quantum/audio/audio.c
index 2a315fd16..e1e81fd2b 100644
--- a/quantum/audio/audio.c
+++ b/quantum/audio/audio.c
@@ -89,15 +89,15 @@ void audio_init()
89 } 89 }
90 audio_config.raw = eeconfig_read_audio(); 90 audio_config.raw = eeconfig_read_audio();
91 91
92 // Set port PC6 (OC3A and /OC4A) as output 92 // Set port PC6 (OC3A and /OC4A) as output
93 DDRC |= _BV(PORTC6); 93 DDRC |= _BV(PORTC6);
94 94
95 DISABLE_AUDIO_COUNTER_3_ISR; 95 DISABLE_AUDIO_COUNTER_3_ISR;
96 96
97 // TCCR3A / TCCR3B: Timer/Counter #3 Control Registers 97 // TCCR3A / TCCR3B: Timer/Counter #3 Control Registers
98 // Compare Output Mode (COM3An) = 0b00 = Normal port operation, OC3A disconnected from PC6 98 // Compare Output Mode (COM3An) = 0b00 = Normal port operation, OC3A disconnected from PC6
99 // Waveform Generation Mode (WGM3n) = 0b1110 = Fast PWM Mode 14 (Period = ICR3, Duty Cycle = OCR3A) 99 // Waveform Generation Mode (WGM3n) = 0b1110 = Fast PWM Mode 14 (Period = ICR3, Duty Cycle = OCR3A)
100 // Clock Select (CS3n) = 0b010 = Clock / 8 100 // Clock Select (CS3n) = 0b010 = Clock / 8
101 TCCR3A = (0 << COM3A1) | (0 << COM3A0) | (1 << WGM31) | (0 << WGM30); 101 TCCR3A = (0 << COM3A1) | (0 << COM3A0) | (1 << WGM31) | (0 << WGM30);
102 TCCR3B = (1 << WGM33) | (1 << WGM32) | (0 << CS32) | (1 << CS31) | (0 << CS30); 102 TCCR3B = (1 << WGM33) | (1 << WGM32) | (0 << CS32) | (1 << CS31) | (0 << CS30);
103 103
@@ -106,6 +106,8 @@ void audio_init()
106 106
107void stop_all_notes() 107void stop_all_notes()
108{ 108{
109 dprintf("audio stop all notes");
110
109 if (!audio_initialized) { 111 if (!audio_initialized) {
110 audio_init(); 112 audio_init();
111 } 113 }
@@ -128,6 +130,8 @@ void stop_all_notes()
128 130
129void stop_note(float freq) 131void stop_note(float freq)
130{ 132{
133 dprintf("audio stop note freq=%d", (int)freq);
134
131 if (playing_note) { 135 if (playing_note) {
132 if (!audio_initialized) { 136 if (!audio_initialized) {
133 audio_init(); 137 audio_init();
@@ -183,159 +187,161 @@ float vibrato(float average_freq) {
183 187
184ISR(TIMER3_COMPA_vect) 188ISR(TIMER3_COMPA_vect)
185{ 189{
186 float freq; 190 float freq;
187 191
188 if (playing_note) { 192 if (playing_note) {
189 if (voices > 0) { 193 if (voices > 0) {
190 if (polyphony_rate > 0) { 194 if (polyphony_rate > 0) {
191 if (voices > 1) { 195 if (voices > 1) {
192 voice_place %= voices; 196 voice_place %= voices;
193 if (place++ > (frequencies[voice_place] / polyphony_rate / CPU_PRESCALER)) { 197 if (place++ > (frequencies[voice_place] / polyphony_rate / CPU_PRESCALER)) {
194 voice_place = (voice_place + 1) % voices; 198 voice_place = (voice_place + 1) % voices;
195 place = 0.0; 199 place = 0.0;
196 } 200 }
197 } 201 }
198 202
199 #ifdef VIBRATO_ENABLE 203 #ifdef VIBRATO_ENABLE
200 if (vibrato_strength > 0) { 204 if (vibrato_strength > 0) {
201 freq = vibrato(frequencies[voice_place]); 205 freq = vibrato(frequencies[voice_place]);
202 } else { 206 } else {
203 freq = frequencies[voice_place]; 207 freq = frequencies[voice_place];
204 } 208 }
205 #else 209 #else
206 freq = frequencies[voice_place]; 210 freq = frequencies[voice_place];
207 #endif 211 #endif
208 } else { 212 } else {
209 if (glissando) { 213 if (glissando) {
210 if (frequency != 0 && frequency < frequencies[voices - 1] && frequency < frequencies[voices - 1] * pow(2, -440/frequencies[voices - 1]/12/2)) { 214 if (frequency != 0 && frequency < frequencies[voices - 1] && frequency < frequencies[voices - 1] * pow(2, -440/frequencies[voices - 1]/12/2)) {
211 frequency = frequency * pow(2, 440/frequency/12/2); 215 frequency = frequency * pow(2, 440/frequency/12/2);
212 } else if (frequency != 0 && frequency > frequencies[voices - 1] && frequency > frequencies[voices - 1] * pow(2, 440/frequencies[voices - 1]/12/2)) { 216 } else if (frequency != 0 && frequency > frequencies[voices - 1] && frequency > frequencies[voices - 1] * pow(2, 440/frequencies[voices - 1]/12/2)) {
213 frequency = frequency * pow(2, -440/frequency/12/2); 217 frequency = frequency * pow(2, -440/frequency/12/2);
214 } else { 218 } else {
215 frequency = frequencies[voices - 1]; 219 frequency = frequencies[voices - 1];
216 } 220 }
217 } else { 221 } else {
218 frequency = frequencies[voices - 1]; 222 frequency = frequencies[voices - 1];
219 } 223 }
220 224
221 #ifdef VIBRATO_ENABLE 225 #ifdef VIBRATO_ENABLE
222 if (vibrato_strength > 0) { 226 if (vibrato_strength > 0) {
223 freq = vibrato(frequency); 227 freq = vibrato(frequency);
224 } else { 228 } else {
225 freq = frequency; 229 freq = frequency;
226 } 230 }
227 #else 231 #else
228 freq = frequency; 232 freq = frequency;
229 #endif 233 #endif
230 } 234 }
231 235
232 if (envelope_index < 65535) { 236 if (envelope_index < 65535) {
233 envelope_index++; 237 envelope_index++;
234 } 238 }
235 239
236 freq = voice_envelope(freq); 240 freq = voice_envelope(freq);
237 241
238 if (freq < 30.517578125) { 242 if (freq < 30.517578125) {
239 freq = 30.52; 243 freq = 30.52;
240 } 244 }
241 245
242 TIMER_3_PERIOD = (uint16_t)(((float)F_CPU) / (freq * CPU_PRESCALER)); 246 TIMER_3_PERIOD = (uint16_t)(((float)F_CPU) / (freq * CPU_PRESCALER));
243 TIMER_3_DUTY_CYCLE = (uint16_t)((((float)F_CPU) / (freq * CPU_PRESCALER)) * note_timbre); 247 TIMER_3_DUTY_CYCLE = (uint16_t)((((float)F_CPU) / (freq * CPU_PRESCALER)) * note_timbre);
244 } 248 }
245 } 249 }
246 250
247 if (playing_notes) { 251 if (playing_notes) {
248 if (note_frequency > 0) { 252 if (note_frequency > 0) {
249 #ifdef VIBRATO_ENABLE 253 #ifdef VIBRATO_ENABLE
250 if (vibrato_strength > 0) { 254 if (vibrato_strength > 0) {
251 freq = vibrato(note_frequency); 255 freq = vibrato(note_frequency);
252 } else { 256 } else {
253 freq = note_frequency; 257 freq = note_frequency;
254 } 258 }
255 #else 259 #else
256 freq = note_frequency; 260 freq = note_frequency;
257 #endif 261 #endif
258 262
259 if (envelope_index < 65535) { 263 if (envelope_index < 65535) {
260 envelope_index++; 264 envelope_index++;
261 } 265 }
262 freq = voice_envelope(freq); 266 freq = voice_envelope(freq);
263 267
264 TIMER_3_PERIOD = (uint16_t)(((float)F_CPU) / (freq * CPU_PRESCALER)); 268 TIMER_3_PERIOD = (uint16_t)(((float)F_CPU) / (freq * CPU_PRESCALER));
265 TIMER_3_DUTY_CYCLE = (uint16_t)((((float)F_CPU) / (freq * CPU_PRESCALER)) * note_timbre); 269 TIMER_3_DUTY_CYCLE = (uint16_t)((((float)F_CPU) / (freq * CPU_PRESCALER)) * note_timbre);
266 } else { 270 } else {
267 TIMER_3_PERIOD = 0; 271 TIMER_3_PERIOD = 0;
268 TIMER_3_DUTY_CYCLE = 0; 272 TIMER_3_DUTY_CYCLE = 0;
269 } 273 }
270 274
271 note_position++; 275 note_position++;
272 bool end_of_note = false; 276 bool end_of_note = false;
273 if (TIMER_3_PERIOD > 0) { 277 if (TIMER_3_PERIOD > 0) {
274 end_of_note = (note_position >= (note_length / TIMER_3_PERIOD * 0xFFFF)); 278 end_of_note = (note_position >= (note_length / TIMER_3_PERIOD * 0xFFFF));
275 } else { 279 } else {
276 end_of_note = (note_position >= (note_length * 0x7FF)); 280 end_of_note = (note_position >= (note_length * 0x7FF));
277 } 281 }
278 282
279 if (end_of_note) { 283 if (end_of_note) {
280 current_note++; 284 current_note++;
281 if (current_note >= notes_count) { 285 if (current_note >= notes_count) {
282 if (notes_repeat) { 286 if (notes_repeat) {
283 current_note = 0; 287 current_note = 0;
284 } else { 288 } else {
285 DISABLE_AUDIO_COUNTER_3_ISR; 289 DISABLE_AUDIO_COUNTER_3_ISR;
286 DISABLE_AUDIO_COUNTER_3_OUTPUT; 290 DISABLE_AUDIO_COUNTER_3_OUTPUT;
287 playing_notes = false; 291 playing_notes = false;
288 return; 292 return;
289 } 293 }
290 } 294 }
291 if (!note_resting && (notes_rest > 0)) { 295 if (!note_resting && (notes_rest > 0)) {
292 note_resting = true; 296 note_resting = true;
293 note_frequency = 0; 297 note_frequency = 0;
294 note_length = notes_rest; 298 note_length = notes_rest;
295 current_note--; 299 current_note--;
296 } else { 300 } else {
297 note_resting = false; 301 note_resting = false;
298 envelope_index = 0; 302 envelope_index = 0;
299 note_frequency = (*notes_pointer)[current_note][0]; 303 note_frequency = (*notes_pointer)[current_note][0];
300 note_length = ((*notes_pointer)[current_note][1] / 4) * (((float)note_tempo) / 100); 304 note_length = ((*notes_pointer)[current_note][1] / 4) * (((float)note_tempo) / 100);
301 } 305 }
302 306
303 note_position = 0; 307 note_position = 0;
304 } 308 }
305 } 309 }
306 310
307 if (!audio_config.enable) { 311 if (!audio_config.enable) {
308 playing_notes = false; 312 playing_notes = false;
309 playing_note = false; 313 playing_note = false;
310 } 314 }
311} 315}
312 316
313void play_note(float freq, int vol) { 317void play_note(float freq, int vol) {
314 318
319 dprintf("audio play note freq=%d vol=%d", (int)freq, vol);
320
315 if (!audio_initialized) { 321 if (!audio_initialized) {
316 audio_init(); 322 audio_init();
317 } 323 }
318 324
319 if (audio_config.enable && voices < 8) { 325 if (audio_config.enable && voices < 8) {
320 DISABLE_AUDIO_COUNTER_3_ISR; 326 DISABLE_AUDIO_COUNTER_3_ISR;
321 327
322 // Cancel notes if notes are playing 328 // Cancel notes if notes are playing
323 if (playing_notes) 329 if (playing_notes)
324 stop_all_notes(); 330 stop_all_notes();
325 331
326 playing_note = true; 332 playing_note = true;
327 333
328 envelope_index = 0; 334 envelope_index = 0;
329 335
330 if (freq > 0) { 336 if (freq > 0) {
331 frequencies[voices] = freq; 337 frequencies[voices] = freq;
332 volumes[voices] = vol; 338 volumes[voices] = vol;
333 voices++; 339 voices++;
334 } 340 }
335 341
336 ENABLE_AUDIO_COUNTER_3_ISR; 342 ENABLE_AUDIO_COUNTER_3_ISR;
337 ENABLE_AUDIO_COUNTER_3_OUTPUT; 343 ENABLE_AUDIO_COUNTER_3_OUTPUT;
338 } 344 }
339 345
340} 346}
341 347
@@ -346,37 +352,37 @@ void play_notes(float (*np)[][2], uint16_t n_count, bool n_repeat, float n_rest)
346 audio_init(); 352 audio_init();
347 } 353 }
348 354
349 if (audio_config.enable) { 355 if (audio_config.enable) {
350 356
351 DISABLE_AUDIO_COUNTER_3_ISR; 357 DISABLE_AUDIO_COUNTER_3_ISR;
352 358
353 // Cancel note if a note is playing 359 // Cancel note if a note is playing
354 if (playing_note) 360 if (playing_note)
355 stop_all_notes(); 361 stop_all_notes();
356 362
357 playing_notes = true; 363 playing_notes = true;
358 364
359 notes_pointer = np; 365 notes_pointer = np;
360 notes_count = n_count; 366 notes_count = n_count;
361 notes_repeat = n_repeat; 367 notes_repeat = n_repeat;
362 notes_rest = n_rest; 368 notes_rest = n_rest;
363 369
364 place = 0; 370 place = 0;
365 current_note = 0; 371 current_note = 0;
366 372
367 note_frequency = (*notes_pointer)[current_note][0]; 373 note_frequency = (*notes_pointer)[current_note][0];
368 note_length = ((*notes_pointer)[current_note][1] / 4) * (((float)note_tempo) / 100); 374 note_length = ((*notes_pointer)[current_note][1] / 4) * (((float)note_tempo) / 100);
369 note_position = 0; 375 note_position = 0;
370 376
371 377
372 ENABLE_AUDIO_COUNTER_3_ISR; 378 ENABLE_AUDIO_COUNTER_3_ISR;
373 ENABLE_AUDIO_COUNTER_3_OUTPUT; 379 ENABLE_AUDIO_COUNTER_3_OUTPUT;
374 } 380 }
375 381
376} 382}
377 383
378bool is_playing_notes(void) { 384bool is_playing_notes(void) {
379 return playing_notes; 385 return playing_notes;
380} 386}
381 387
382bool is_audio_on(void) { 388bool is_audio_on(void) {