diff options
Diffstat (limited to 'quantum/audio/audio.c')
-rw-r--r-- | quantum/audio/audio.c | 322 |
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 | ||
107 | void stop_all_notes() | 107 | void 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 | ||
129 | void stop_note(float freq) | 131 | void 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 | ||
184 | ISR(TIMER3_COMPA_vect) | 188 | ISR(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 | ||
313 | void play_note(float freq, int vol) { | 317 | void 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 | ||
378 | bool is_playing_notes(void) { | 384 | bool is_playing_notes(void) { |
379 | return playing_notes; | 385 | return playing_notes; |
380 | } | 386 | } |
381 | 387 | ||
382 | bool is_audio_on(void) { | 388 | bool is_audio_on(void) { |