diff options
Diffstat (limited to 'quantum/audio')
| -rw-r--r-- | quantum/audio/audio.c | 334 | ||||
| -rw-r--r-- | quantum/audio/audio.h | 17 | ||||
| -rw-r--r-- | quantum/audio/audio_pwm.c | 15 | ||||
| -rw-r--r-- | quantum/audio/luts.c | 16 | ||||
| -rw-r--r-- | quantum/audio/luts.h | 18 | ||||
| -rw-r--r-- | quantum/audio/musical_notes.h | 18 | ||||
| -rw-r--r-- | quantum/audio/song_list.h | 42 | ||||
| -rw-r--r-- | quantum/audio/voices.c | 137 | ||||
| -rw-r--r-- | quantum/audio/voices.h | 21 | ||||
| -rw-r--r-- | quantum/audio/wave.h | 18 |
10 files changed, 474 insertions, 162 deletions
diff --git a/quantum/audio/audio.c b/quantum/audio/audio.c index ead5fbf3e..597073611 100644 --- a/quantum/audio/audio.c +++ b/quantum/audio/audio.c | |||
| @@ -1,3 +1,18 @@ | |||
| 1 | /* Copyright 2016 Jack Humbert | ||
| 2 | * | ||
| 3 | * This program is free software: you can redistribute it and/or modify | ||
| 4 | * it under the terms of the GNU General Public License as published by | ||
| 5 | * the Free Software Foundation, either version 2 of the License, or | ||
| 6 | * (at your option) any later version. | ||
| 7 | * | ||
| 8 | * This program is distributed in the hope that it will be useful, | ||
| 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 11 | * GNU General Public License for more details. | ||
| 12 | * | ||
| 13 | * You should have received a copy of the GNU General Public License | ||
| 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 15 | */ | ||
| 1 | #include <stdio.h> | 16 | #include <stdio.h> |
| 2 | #include <string.h> | 17 | #include <string.h> |
| 3 | //#include <math.h> | 18 | //#include <math.h> |
| @@ -77,6 +92,7 @@ static bool audio_initialized = false; | |||
| 77 | audio_config_t audio_config; | 92 | audio_config_t audio_config; |
| 78 | 93 | ||
| 79 | uint16_t envelope_index = 0; | 94 | uint16_t envelope_index = 0; |
| 95 | bool glissando = true; | ||
| 80 | 96 | ||
| 81 | void audio_init() | 97 | void audio_init() |
| 82 | { | 98 | { |
| @@ -88,15 +104,15 @@ void audio_init() | |||
| 88 | } | 104 | } |
| 89 | audio_config.raw = eeconfig_read_audio(); | 105 | audio_config.raw = eeconfig_read_audio(); |
| 90 | 106 | ||
| 91 | // Set port PC6 (OC3A and /OC4A) as output | 107 | // Set port PC6 (OC3A and /OC4A) as output |
| 92 | DDRC |= _BV(PORTC6); | 108 | DDRC |= _BV(PORTC6); |
| 93 | 109 | ||
| 94 | DISABLE_AUDIO_COUNTER_3_ISR; | 110 | DISABLE_AUDIO_COUNTER_3_ISR; |
| 95 | 111 | ||
| 96 | // TCCR3A / TCCR3B: Timer/Counter #3 Control Registers | 112 | // TCCR3A / TCCR3B: Timer/Counter #3 Control Registers |
| 97 | // Compare Output Mode (COM3An) = 0b00 = Normal port operation, OC3A disconnected from PC6 | 113 | // Compare Output Mode (COM3An) = 0b00 = Normal port operation, OC3A disconnected from PC6 |
| 98 | // Waveform Generation Mode (WGM3n) = 0b1110 = Fast PWM Mode 14 (Period = ICR3, Duty Cycle = OCR3A) | 114 | // Waveform Generation Mode (WGM3n) = 0b1110 = Fast PWM Mode 14 (Period = ICR3, Duty Cycle = OCR3A) |
| 99 | // Clock Select (CS3n) = 0b010 = Clock / 8 | 115 | // Clock Select (CS3n) = 0b010 = Clock / 8 |
| 100 | TCCR3A = (0 << COM3A1) | (0 << COM3A0) | (1 << WGM31) | (0 << WGM30); | 116 | TCCR3A = (0 << COM3A1) | (0 << COM3A0) | (1 << WGM31) | (0 << WGM30); |
| 101 | TCCR3B = (1 << WGM33) | (1 << WGM32) | (0 << CS32) | (1 << CS31) | (0 << CS30); | 117 | TCCR3B = (1 << WGM33) | (1 << WGM32) | (0 << CS32) | (1 << CS31) | (0 << CS30); |
| 102 | 118 | ||
| @@ -105,6 +121,8 @@ void audio_init() | |||
| 105 | 121 | ||
| 106 | void stop_all_notes() | 122 | void stop_all_notes() |
| 107 | { | 123 | { |
| 124 | dprintf("audio stop all notes"); | ||
| 125 | |||
| 108 | if (!audio_initialized) { | 126 | if (!audio_initialized) { |
| 109 | audio_init(); | 127 | audio_init(); |
| 110 | } | 128 | } |
| @@ -127,6 +145,8 @@ void stop_all_notes() | |||
| 127 | 145 | ||
| 128 | void stop_note(float freq) | 146 | void stop_note(float freq) |
| 129 | { | 147 | { |
| 148 | dprintf("audio stop note freq=%d", (int)freq); | ||
| 149 | |||
| 130 | if (playing_note) { | 150 | if (playing_note) { |
| 131 | if (!audio_initialized) { | 151 | if (!audio_initialized) { |
| 132 | audio_init(); | 152 | audio_init(); |
| @@ -182,155 +202,161 @@ float vibrato(float average_freq) { | |||
| 182 | 202 | ||
| 183 | ISR(TIMER3_COMPA_vect) | 203 | ISR(TIMER3_COMPA_vect) |
| 184 | { | 204 | { |
| 185 | float freq; | 205 | float freq; |
| 186 | 206 | ||
| 187 | if (playing_note) { | 207 | if (playing_note) { |
| 188 | if (voices > 0) { | 208 | if (voices > 0) { |
| 189 | if (polyphony_rate > 0) { | 209 | if (polyphony_rate > 0) { |
| 190 | if (voices > 1) { | 210 | if (voices > 1) { |
| 191 | voice_place %= voices; | 211 | voice_place %= voices; |
| 192 | if (place++ > (frequencies[voice_place] / polyphony_rate / CPU_PRESCALER)) { | 212 | if (place++ > (frequencies[voice_place] / polyphony_rate / CPU_PRESCALER)) { |
| 193 | voice_place = (voice_place + 1) % voices; | 213 | voice_place = (voice_place + 1) % voices; |
| 194 | place = 0.0; | 214 | place = 0.0; |
| 195 | } | 215 | } |
| 196 | } | 216 | } |
| 197 | 217 | ||
| 198 | #ifdef VIBRATO_ENABLE | 218 | #ifdef VIBRATO_ENABLE |
| 199 | if (vibrato_strength > 0) { | 219 | if (vibrato_strength > 0) { |
| 200 | freq = vibrato(frequencies[voice_place]); | 220 | freq = vibrato(frequencies[voice_place]); |
| 201 | } else { | 221 | } else { |
| 202 | freq = frequencies[voice_place]; | 222 | freq = frequencies[voice_place]; |
| 203 | } | 223 | } |
| 204 | #else | 224 | #else |
| 205 | freq = frequencies[voice_place]; | 225 | freq = frequencies[voice_place]; |
| 206 | #endif | 226 | #endif |
| 207 | } else { | 227 | } else { |
| 208 | if (frequency != 0 && frequency < frequencies[voices - 1] && frequency < frequencies[voices - 1] * pow(2, -440/frequencies[voices - 1]/12/2)) { | 228 | if (glissando) { |
| 209 | frequency = frequency * pow(2, 440/frequency/12/2); | 229 | if (frequency != 0 && frequency < frequencies[voices - 1] && frequency < frequencies[voices - 1] * pow(2, -440/frequencies[voices - 1]/12/2)) { |
| 210 | } else if (frequency != 0 && frequency > frequencies[voices - 1] && frequency > frequencies[voices - 1] * pow(2, 440/frequencies[voices - 1]/12/2)) { | 230 | frequency = frequency * pow(2, 440/frequency/12/2); |
| 211 | frequency = frequency * pow(2, -440/frequency/12/2); | 231 | } else if (frequency != 0 && frequency > frequencies[voices - 1] && frequency > frequencies[voices - 1] * pow(2, 440/frequencies[voices - 1]/12/2)) { |
| 212 | } else { | 232 | frequency = frequency * pow(2, -440/frequency/12/2); |
| 213 | frequency = frequencies[voices - 1]; | 233 | } else { |
| 214 | } | 234 | frequency = frequencies[voices - 1]; |
| 215 | 235 | } | |
| 216 | #ifdef VIBRATO_ENABLE | 236 | } else { |
| 217 | if (vibrato_strength > 0) { | 237 | frequency = frequencies[voices - 1]; |
| 218 | freq = vibrato(frequency); | 238 | } |
| 219 | } else { | 239 | |
| 220 | freq = frequency; | 240 | #ifdef VIBRATO_ENABLE |
| 221 | } | 241 | if (vibrato_strength > 0) { |
| 222 | #else | 242 | freq = vibrato(frequency); |
| 223 | freq = frequency; | 243 | } else { |
| 224 | #endif | 244 | freq = frequency; |
| 225 | } | 245 | } |
| 226 | 246 | #else | |
| 227 | if (envelope_index < 65535) { | 247 | freq = frequency; |
| 228 | envelope_index++; | 248 | #endif |
| 229 | } | 249 | } |
| 230 | 250 | ||
| 231 | freq = voice_envelope(freq); | 251 | if (envelope_index < 65535) { |
| 232 | 252 | envelope_index++; | |
| 233 | if (freq < 30.517578125) { | 253 | } |
| 234 | freq = 30.52; | 254 | |
| 235 | } | 255 | freq = voice_envelope(freq); |
| 236 | 256 | ||
| 237 | TIMER_3_PERIOD = (uint16_t)(((float)F_CPU) / (freq * CPU_PRESCALER)); | 257 | if (freq < 30.517578125) { |
| 238 | TIMER_3_DUTY_CYCLE = (uint16_t)((((float)F_CPU) / (freq * CPU_PRESCALER)) * note_timbre); | 258 | freq = 30.52; |
| 239 | } | 259 | } |
| 240 | } | 260 | |
| 241 | 261 | TIMER_3_PERIOD = (uint16_t)(((float)F_CPU) / (freq * CPU_PRESCALER)); | |
| 242 | if (playing_notes) { | 262 | TIMER_3_DUTY_CYCLE = (uint16_t)((((float)F_CPU) / (freq * CPU_PRESCALER)) * note_timbre); |
| 243 | if (note_frequency > 0) { | 263 | } |
| 244 | #ifdef VIBRATO_ENABLE | 264 | } |
| 245 | if (vibrato_strength > 0) { | 265 | |
| 246 | freq = vibrato(note_frequency); | 266 | if (playing_notes) { |
| 247 | } else { | 267 | if (note_frequency > 0) { |
| 248 | freq = note_frequency; | 268 | #ifdef VIBRATO_ENABLE |
| 249 | } | 269 | if (vibrato_strength > 0) { |
| 250 | #else | 270 | freq = vibrato(note_frequency); |
| 251 | freq = note_frequency; | 271 | } else { |
| 252 | #endif | 272 | freq = note_frequency; |
| 253 | 273 | } | |
| 254 | if (envelope_index < 65535) { | 274 | #else |
| 255 | envelope_index++; | 275 | freq = note_frequency; |
| 256 | } | 276 | #endif |
| 257 | freq = voice_envelope(freq); | 277 | |
| 258 | 278 | if (envelope_index < 65535) { | |
| 259 | TIMER_3_PERIOD = (uint16_t)(((float)F_CPU) / (freq * CPU_PRESCALER)); | 279 | envelope_index++; |
| 260 | TIMER_3_DUTY_CYCLE = (uint16_t)((((float)F_CPU) / (freq * CPU_PRESCALER)) * note_timbre); | 280 | } |
| 261 | } else { | 281 | freq = voice_envelope(freq); |
| 262 | TIMER_3_PERIOD = 0; | 282 | |
| 263 | TIMER_3_DUTY_CYCLE = 0; | 283 | TIMER_3_PERIOD = (uint16_t)(((float)F_CPU) / (freq * CPU_PRESCALER)); |
| 264 | } | 284 | TIMER_3_DUTY_CYCLE = (uint16_t)((((float)F_CPU) / (freq * CPU_PRESCALER)) * note_timbre); |
| 265 | 285 | } else { | |
| 266 | note_position++; | 286 | TIMER_3_PERIOD = 0; |
| 267 | bool end_of_note = false; | 287 | TIMER_3_DUTY_CYCLE = 0; |
| 268 | if (TIMER_3_PERIOD > 0) { | 288 | } |
| 269 | end_of_note = (note_position >= (note_length / TIMER_3_PERIOD * 0xFFFF)); | 289 | |
| 270 | } else { | 290 | note_position++; |
| 271 | end_of_note = (note_position >= (note_length * 0x7FF)); | 291 | bool end_of_note = false; |
| 272 | } | 292 | if (TIMER_3_PERIOD > 0) { |
| 273 | 293 | end_of_note = (note_position >= (note_length / TIMER_3_PERIOD * 0xFFFF)); | |
| 274 | if (end_of_note) { | 294 | } else { |
| 275 | current_note++; | 295 | end_of_note = (note_position >= (note_length * 0x7FF)); |
| 276 | if (current_note >= notes_count) { | 296 | } |
| 277 | if (notes_repeat) { | 297 | |
| 278 | current_note = 0; | 298 | if (end_of_note) { |
| 279 | } else { | 299 | current_note++; |
| 280 | DISABLE_AUDIO_COUNTER_3_ISR; | 300 | if (current_note >= notes_count) { |
| 281 | DISABLE_AUDIO_COUNTER_3_OUTPUT; | 301 | if (notes_repeat) { |
| 282 | playing_notes = false; | 302 | current_note = 0; |
| 283 | return; | 303 | } else { |
| 284 | } | 304 | DISABLE_AUDIO_COUNTER_3_ISR; |
| 285 | } | 305 | DISABLE_AUDIO_COUNTER_3_OUTPUT; |
| 286 | if (!note_resting && (notes_rest > 0)) { | 306 | playing_notes = false; |
| 287 | note_resting = true; | 307 | return; |
| 288 | note_frequency = 0; | 308 | } |
| 289 | note_length = notes_rest; | 309 | } |
| 290 | current_note--; | 310 | if (!note_resting && (notes_rest > 0)) { |
| 291 | } else { | 311 | note_resting = true; |
| 292 | note_resting = false; | 312 | note_frequency = 0; |
| 293 | envelope_index = 0; | 313 | note_length = notes_rest; |
| 294 | note_frequency = (*notes_pointer)[current_note][0]; | 314 | current_note--; |
| 295 | note_length = ((*notes_pointer)[current_note][1] / 4) * (((float)note_tempo) / 100); | 315 | } else { |
| 296 | } | 316 | note_resting = false; |
| 297 | 317 | envelope_index = 0; | |
| 298 | note_position = 0; | 318 | note_frequency = (*notes_pointer)[current_note][0]; |
| 299 | } | 319 | note_length = ((*notes_pointer)[current_note][1] / 4) * (((float)note_tempo) / 100); |
| 300 | } | 320 | } |
| 301 | 321 | ||
| 302 | if (!audio_config.enable) { | 322 | note_position = 0; |
| 303 | playing_notes = false; | 323 | } |
| 304 | playing_note = false; | 324 | } |
| 305 | } | 325 | |
| 326 | if (!audio_config.enable) { | ||
| 327 | playing_notes = false; | ||
| 328 | playing_note = false; | ||
| 329 | } | ||
| 306 | } | 330 | } |
| 307 | 331 | ||
| 308 | void play_note(float freq, int vol) { | 332 | void play_note(float freq, int vol) { |
| 309 | 333 | ||
| 334 | dprintf("audio play note freq=%d vol=%d", (int)freq, vol); | ||
| 335 | |||
| 310 | if (!audio_initialized) { | 336 | if (!audio_initialized) { |
| 311 | audio_init(); | 337 | audio_init(); |
| 312 | } | 338 | } |
| 313 | 339 | ||
| 314 | if (audio_config.enable && voices < 8) { | 340 | if (audio_config.enable && voices < 8) { |
| 315 | DISABLE_AUDIO_COUNTER_3_ISR; | 341 | DISABLE_AUDIO_COUNTER_3_ISR; |
| 316 | 342 | ||
| 317 | // Cancel notes if notes are playing | 343 | // Cancel notes if notes are playing |
| 318 | if (playing_notes) | 344 | if (playing_notes) |
| 319 | stop_all_notes(); | 345 | stop_all_notes(); |
| 320 | 346 | ||
| 321 | playing_note = true; | 347 | playing_note = true; |
| 322 | 348 | ||
| 323 | envelope_index = 0; | 349 | envelope_index = 0; |
| 324 | 350 | ||
| 325 | if (freq > 0) { | 351 | if (freq > 0) { |
| 326 | frequencies[voices] = freq; | 352 | frequencies[voices] = freq; |
| 327 | volumes[voices] = vol; | 353 | volumes[voices] = vol; |
| 328 | voices++; | 354 | voices++; |
| 329 | } | 355 | } |
| 330 | 356 | ||
| 331 | ENABLE_AUDIO_COUNTER_3_ISR; | 357 | ENABLE_AUDIO_COUNTER_3_ISR; |
| 332 | ENABLE_AUDIO_COUNTER_3_OUTPUT; | 358 | ENABLE_AUDIO_COUNTER_3_OUTPUT; |
| 333 | } | 359 | } |
| 334 | 360 | ||
| 335 | } | 361 | } |
| 336 | 362 | ||
| @@ -341,37 +367,37 @@ void play_notes(float (*np)[][2], uint16_t n_count, bool n_repeat, float n_rest) | |||
| 341 | audio_init(); | 367 | audio_init(); |
| 342 | } | 368 | } |
| 343 | 369 | ||
| 344 | if (audio_config.enable) { | 370 | if (audio_config.enable) { |
| 345 | 371 | ||
| 346 | DISABLE_AUDIO_COUNTER_3_ISR; | 372 | DISABLE_AUDIO_COUNTER_3_ISR; |
| 347 | 373 | ||
| 348 | // Cancel note if a note is playing | 374 | // Cancel note if a note is playing |
| 349 | if (playing_note) | 375 | if (playing_note) |
| 350 | stop_all_notes(); | 376 | stop_all_notes(); |
| 351 | 377 | ||
| 352 | playing_notes = true; | 378 | playing_notes = true; |
| 353 | 379 | ||
| 354 | notes_pointer = np; | 380 | notes_pointer = np; |
| 355 | notes_count = n_count; | 381 | notes_count = n_count; |
| 356 | notes_repeat = n_repeat; | 382 | notes_repeat = n_repeat; |
| 357 | notes_rest = n_rest; | 383 | notes_rest = n_rest; |
| 358 | 384 | ||
| 359 | place = 0; | 385 | place = 0; |
| 360 | current_note = 0; | 386 | current_note = 0; |
| 361 | 387 | ||
| 362 | note_frequency = (*notes_pointer)[current_note][0]; | 388 | note_frequency = (*notes_pointer)[current_note][0]; |
| 363 | note_length = ((*notes_pointer)[current_note][1] / 4) * (((float)note_tempo) / 100); | 389 | note_length = ((*notes_pointer)[current_note][1] / 4) * (((float)note_tempo) / 100); |
| 364 | note_position = 0; | 390 | note_position = 0; |
| 365 | 391 | ||
| 366 | 392 | ||
| 367 | ENABLE_AUDIO_COUNTER_3_ISR; | 393 | ENABLE_AUDIO_COUNTER_3_ISR; |
| 368 | ENABLE_AUDIO_COUNTER_3_OUTPUT; | 394 | ENABLE_AUDIO_COUNTER_3_OUTPUT; |
| 369 | } | 395 | } |
| 370 | 396 | ||
| 371 | } | 397 | } |
| 372 | 398 | ||
| 373 | bool is_playing_notes(void) { | 399 | bool is_playing_notes(void) { |
| 374 | return playing_notes; | 400 | return playing_notes; |
| 375 | } | 401 | } |
| 376 | 402 | ||
| 377 | bool is_audio_on(void) { | 403 | bool is_audio_on(void) { |
diff --git a/quantum/audio/audio.h b/quantum/audio/audio.h index 47f326ea0..27fdc2ab6 100644 --- a/quantum/audio/audio.h +++ b/quantum/audio/audio.h | |||
| @@ -1,3 +1,18 @@ | |||
| 1 | /* Copyright 2016 Jack Humbert | ||
| 2 | * | ||
| 3 | * This program is free software: you can redistribute it and/or modify | ||
| 4 | * it under the terms of the GNU General Public License as published by | ||
| 5 | * the Free Software Foundation, either version 2 of the License, or | ||
| 6 | * (at your option) any later version. | ||
| 7 | * | ||
| 8 | * This program is distributed in the hope that it will be useful, | ||
| 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 11 | * GNU General Public License for more details. | ||
| 12 | * | ||
| 13 | * You should have received a copy of the GNU General Public License | ||
| 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 15 | */ | ||
| 1 | #ifndef AUDIO_H | 16 | #ifndef AUDIO_H |
| 2 | #define AUDIO_H | 17 | #define AUDIO_H |
| 3 | 18 | ||
| @@ -88,4 +103,4 @@ void play_notes(float (*np)[][2], uint16_t n_count, bool n_repeat, float n_rest) | |||
| 88 | 103 | ||
| 89 | bool is_playing_notes(void); | 104 | bool is_playing_notes(void); |
| 90 | 105 | ||
| 91 | #endif \ No newline at end of file | 106 | #endif |
diff --git a/quantum/audio/audio_pwm.c b/quantum/audio/audio_pwm.c index f820eec1b..ded86edee 100644 --- a/quantum/audio/audio_pwm.c +++ b/quantum/audio/audio_pwm.c | |||
| @@ -1,3 +1,18 @@ | |||
| 1 | /* Copyright 2016 Jack Humbert | ||
| 2 | * | ||
| 3 | * This program is free software: you can redistribute it and/or modify | ||
| 4 | * it under the terms of the GNU General Public License as published by | ||
| 5 | * the Free Software Foundation, either version 2 of the License, or | ||
| 6 | * (at your option) any later version. | ||
| 7 | * | ||
| 8 | * This program is distributed in the hope that it will be useful, | ||
| 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 11 | * GNU General Public License for more details. | ||
| 12 | * | ||
| 13 | * You should have received a copy of the GNU General Public License | ||
| 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 15 | */ | ||
| 1 | #include <stdio.h> | 16 | #include <stdio.h> |
| 2 | #include <string.h> | 17 | #include <string.h> |
| 3 | //#include <math.h> | 18 | //#include <math.h> |
diff --git a/quantum/audio/luts.c b/quantum/audio/luts.c index 9f3de9a05..57f2d5924 100644 --- a/quantum/audio/luts.c +++ b/quantum/audio/luts.c | |||
| @@ -1,3 +1,19 @@ | |||
| 1 | /* Copyright 2016 IBNobody | ||
| 2 | * | ||
| 3 | * This program is free software: you can redistribute it and/or modify | ||
| 4 | * it under the terms of the GNU General Public License as published by | ||
| 5 | * the Free Software Foundation, either version 2 of the License, or | ||
| 6 | * (at your option) any later version. | ||
| 7 | * | ||
| 8 | * This program is distributed in the hope that it will be useful, | ||
| 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 11 | * GNU General Public License for more details. | ||
| 12 | * | ||
| 13 | * You should have received a copy of the GNU General Public License | ||
| 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 15 | */ | ||
| 16 | |||
| 1 | #include <avr/io.h> | 17 | #include <avr/io.h> |
| 2 | #include <avr/interrupt.h> | 18 | #include <avr/interrupt.h> |
| 3 | #include <avr/pgmspace.h> | 19 | #include <avr/pgmspace.h> |
diff --git a/quantum/audio/luts.h b/quantum/audio/luts.h index 7df3078a7..155e34e88 100644 --- a/quantum/audio/luts.h +++ b/quantum/audio/luts.h | |||
| @@ -1,3 +1,19 @@ | |||
| 1 | /* Copyright 2016 IBNobody | ||
| 2 | * | ||
| 3 | * This program is free software: you can redistribute it and/or modify | ||
| 4 | * it under the terms of the GNU General Public License as published by | ||
| 5 | * the Free Software Foundation, either version 2 of the License, or | ||
| 6 | * (at your option) any later version. | ||
| 7 | * | ||
| 8 | * This program is distributed in the hope that it will be useful, | ||
| 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 11 | * GNU General Public License for more details. | ||
| 12 | * | ||
| 13 | * You should have received a copy of the GNU General Public License | ||
| 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 15 | */ | ||
| 16 | |||
| 1 | #include <avr/io.h> | 17 | #include <avr/io.h> |
| 2 | #include <avr/interrupt.h> | 18 | #include <avr/interrupt.h> |
| 3 | #include <avr/pgmspace.h> | 19 | #include <avr/pgmspace.h> |
| @@ -12,4 +28,4 @@ | |||
| 12 | extern const float vibrato_lut[VIBRATO_LUT_LENGTH]; | 28 | extern const float vibrato_lut[VIBRATO_LUT_LENGTH]; |
| 13 | extern const uint16_t frequency_lut[FREQUENCY_LUT_LENGTH]; | 29 | extern const uint16_t frequency_lut[FREQUENCY_LUT_LENGTH]; |
| 14 | 30 | ||
| 15 | #endif /* LUTS_H */ \ No newline at end of file | 31 | #endif /* LUTS_H */ |
diff --git a/quantum/audio/musical_notes.h b/quantum/audio/musical_notes.h index b08d16a6f..a3aaa2f19 100644 --- a/quantum/audio/musical_notes.h +++ b/quantum/audio/musical_notes.h | |||
| @@ -1,3 +1,19 @@ | |||
| 1 | /* Copyright 2016 Jack Humbert | ||
| 2 | * | ||
| 3 | * This program is free software: you can redistribute it and/or modify | ||
| 4 | * it under the terms of the GNU General Public License as published by | ||
| 5 | * the Free Software Foundation, either version 2 of the License, or | ||
| 6 | * (at your option) any later version. | ||
| 7 | * | ||
| 8 | * This program is distributed in the hope that it will be useful, | ||
| 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 11 | * GNU General Public License for more details. | ||
| 12 | * | ||
| 13 | * You should have received a copy of the GNU General Public License | ||
| 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 15 | */ | ||
| 16 | |||
| 1 | #ifndef MUSICAL_NOTES_H | 17 | #ifndef MUSICAL_NOTES_H |
| 2 | #define MUSICAL_NOTES_H | 18 | #define MUSICAL_NOTES_H |
| 3 | 19 | ||
| @@ -214,4 +230,4 @@ | |||
| 214 | #define NOTE_BF8 NOTE_AS8 | 230 | #define NOTE_BF8 NOTE_AS8 |
| 215 | 231 | ||
| 216 | 232 | ||
| 217 | #endif \ No newline at end of file | 233 | #endif |
diff --git a/quantum/audio/song_list.h b/quantum/audio/song_list.h index 623f24f32..db2d1a94c 100644 --- a/quantum/audio/song_list.h +++ b/quantum/audio/song_list.h | |||
| @@ -1,3 +1,18 @@ | |||
| 1 | /* Copyright 2016 Jack Humbert | ||
| 2 | * | ||
| 3 | * This program is free software: you can redistribute it and/or modify | ||
| 4 | * it under the terms of the GNU General Public License as published by | ||
| 5 | * the Free Software Foundation, either version 2 of the License, or | ||
| 6 | * (at your option) any later version. | ||
| 7 | * | ||
| 8 | * This program is distributed in the hope that it will be useful, | ||
| 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 11 | * GNU General Public License for more details. | ||
| 12 | * | ||
| 13 | * You should have received a copy of the GNU General Public License | ||
| 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 15 | */ | ||
| 1 | #include "musical_notes.h" | 16 | #include "musical_notes.h" |
| 2 | 17 | ||
| 3 | #ifndef SONG_LIST_H | 18 | #ifndef SONG_LIST_H |
| @@ -134,4 +149,31 @@ | |||
| 134 | E__NOTE(_E6), \ | 149 | E__NOTE(_E6), \ |
| 135 | S__NOTE(_B5), | 150 | S__NOTE(_B5), |
| 136 | 151 | ||
| 152 | #define COIN_SOUND \ | ||
| 153 | E__NOTE(_A5 ), \ | ||
| 154 | HD_NOTE(_E6 ), | ||
| 155 | |||
| 156 | #define ONE_UP_SOUND \ | ||
| 157 | Q__NOTE(_E6 ), \ | ||
| 158 | Q__NOTE(_G6 ), \ | ||
| 159 | Q__NOTE(_E7 ), \ | ||
| 160 | Q__NOTE(_C7 ), \ | ||
| 161 | Q__NOTE(_D7 ), \ | ||
| 162 | Q__NOTE(_G7 ), | ||
| 163 | |||
| 164 | #define SONIC_RING \ | ||
| 165 | E__NOTE(_E6), \ | ||
| 166 | E__NOTE(_G6), \ | ||
| 167 | HD_NOTE(_C7), | ||
| 168 | |||
| 169 | #define ZELDA_PUZZLE \ | ||
| 170 | Q__NOTE(_G5), \ | ||
| 171 | Q__NOTE(_FS5), \ | ||
| 172 | Q__NOTE(_DS5), \ | ||
| 173 | Q__NOTE(_A4), \ | ||
| 174 | Q__NOTE(_GS4), \ | ||
| 175 | Q__NOTE(_E5), \ | ||
| 176 | Q__NOTE(_GS5), \ | ||
| 177 | HD_NOTE(_C6), | ||
| 178 | |||
| 137 | #endif | 179 | #endif |
diff --git a/quantum/audio/voices.c b/quantum/audio/voices.c index 6d4172a06..54ebd423b 100644 --- a/quantum/audio/voices.c +++ b/quantum/audio/voices.c | |||
| @@ -1,3 +1,18 @@ | |||
| 1 | /* Copyright 2016 Jack Humbert | ||
| 2 | * | ||
| 3 | * This program is free software: you can redistribute it and/or modify | ||
| 4 | * it under the terms of the GNU General Public License as published by | ||
| 5 | * the Free Software Foundation, either version 2 of the License, or | ||
| 6 | * (at your option) any later version. | ||
| 7 | * | ||
| 8 | * This program is distributed in the hope that it will be useful, | ||
| 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 11 | * GNU General Public License for more details. | ||
| 12 | * | ||
| 13 | * You should have received a copy of the GNU General Public License | ||
| 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 15 | */ | ||
| 1 | #include "voices.h" | 16 | #include "voices.h" |
| 2 | #include "audio.h" | 17 | #include "audio.h" |
| 3 | #include "stdlib.h" | 18 | #include "stdlib.h" |
| @@ -6,6 +21,7 @@ | |||
| 6 | extern uint16_t envelope_index; | 21 | extern uint16_t envelope_index; |
| 7 | extern float note_timbre; | 22 | extern float note_timbre; |
| 8 | extern float polyphony_rate; | 23 | extern float polyphony_rate; |
| 24 | extern bool glissando; | ||
| 9 | 25 | ||
| 10 | voice_type voice = default_voice; | 26 | voice_type voice = default_voice; |
| 11 | 27 | ||
| @@ -18,20 +34,132 @@ void voice_iterate() { | |||
| 18 | } | 34 | } |
| 19 | 35 | ||
| 20 | void voice_deiterate() { | 36 | void voice_deiterate() { |
| 21 | voice = (voice - 1) % number_of_voices; | 37 | voice = (voice - 1 + number_of_voices) % number_of_voices; |
| 22 | } | 38 | } |
| 23 | 39 | ||
| 24 | float voice_envelope(float frequency) { | 40 | float voice_envelope(float frequency) { |
| 25 | // envelope_index ranges from 0 to 0xFFFF, which is preserved at 880.0 Hz | 41 | // envelope_index ranges from 0 to 0xFFFF, which is preserved at 880.0 Hz |
| 42 | __attribute__ ((unused)) | ||
| 26 | uint16_t compensated_index = (uint16_t)((float)envelope_index * (880.0 / frequency)); | 43 | uint16_t compensated_index = (uint16_t)((float)envelope_index * (880.0 / frequency)); |
| 27 | 44 | ||
| 28 | switch (voice) { | 45 | switch (voice) { |
| 29 | case default_voice: | 46 | case default_voice: |
| 47 | glissando = true; | ||
| 30 | note_timbre = TIMBRE_50; | 48 | note_timbre = TIMBRE_50; |
| 31 | polyphony_rate = 0; | 49 | polyphony_rate = 0; |
| 32 | break; | 50 | break; |
| 33 | 51 | ||
| 52 | #ifdef AUDIO_VOICES | ||
| 53 | |||
| 54 | case something: | ||
| 55 | glissando = false; | ||
| 56 | polyphony_rate = 0; | ||
| 57 | switch (compensated_index) { | ||
| 58 | case 0 ... 9: | ||
| 59 | note_timbre = TIMBRE_12; | ||
| 60 | break; | ||
| 61 | |||
| 62 | case 10 ... 19: | ||
| 63 | note_timbre = TIMBRE_25; | ||
| 64 | break; | ||
| 65 | |||
| 66 | case 20 ... 200: | ||
| 67 | note_timbre = .125 + .125; | ||
| 68 | break; | ||
| 69 | |||
| 70 | default: | ||
| 71 | note_timbre = .125; | ||
| 72 | break; | ||
| 73 | } | ||
| 74 | break; | ||
| 75 | |||
| 76 | case drums: | ||
| 77 | glissando = false; | ||
| 78 | polyphony_rate = 0; | ||
| 79 | // switch (compensated_index) { | ||
| 80 | // case 0 ... 10: | ||
| 81 | // note_timbre = 0.5; | ||
| 82 | // break; | ||
| 83 | // case 11 ... 20: | ||
| 84 | // note_timbre = 0.5 * (21 - compensated_index) / 10; | ||
| 85 | // break; | ||
| 86 | // default: | ||
| 87 | // note_timbre = 0; | ||
| 88 | // break; | ||
| 89 | // } | ||
| 90 | // frequency = (rand() % (int)(frequency * 1.2 - frequency)) + (frequency * 0.8); | ||
| 91 | |||
| 92 | if (frequency < 80.0) { | ||
| 93 | |||
| 94 | } else if (frequency < 160.0) { | ||
| 95 | |||
| 96 | // Bass drum: 60 - 100 Hz | ||
| 97 | frequency = (rand() % (int)(40)) + 60; | ||
| 98 | switch (envelope_index) { | ||
| 99 | case 0 ... 10: | ||
| 100 | note_timbre = 0.5; | ||
| 101 | break; | ||
| 102 | case 11 ... 20: | ||
| 103 | note_timbre = 0.5 * (21 - envelope_index) / 10; | ||
| 104 | break; | ||
| 105 | default: | ||
| 106 | note_timbre = 0; | ||
| 107 | break; | ||
| 108 | } | ||
| 109 | |||
| 110 | } else if (frequency < 320.0) { | ||
| 111 | |||
| 112 | |||
| 113 | // Snare drum: 1 - 2 KHz | ||
| 114 | frequency = (rand() % (int)(1000)) + 1000; | ||
| 115 | switch (envelope_index) { | ||
| 116 | case 0 ... 5: | ||
| 117 | note_timbre = 0.5; | ||
| 118 | break; | ||
| 119 | case 6 ... 20: | ||
| 120 | note_timbre = 0.5 * (21 - envelope_index) / 15; | ||
| 121 | break; | ||
| 122 | default: | ||
| 123 | note_timbre = 0; | ||
| 124 | break; | ||
| 125 | } | ||
| 126 | |||
| 127 | } else if (frequency < 640.0) { | ||
| 128 | |||
| 129 | // Closed Hi-hat: 3 - 5 KHz | ||
| 130 | frequency = (rand() % (int)(2000)) + 3000; | ||
| 131 | switch (envelope_index) { | ||
| 132 | case 0 ... 15: | ||
| 133 | note_timbre = 0.5; | ||
| 134 | break; | ||
| 135 | case 16 ... 20: | ||
| 136 | note_timbre = 0.5 * (21 - envelope_index) / 5; | ||
| 137 | break; | ||
| 138 | default: | ||
| 139 | note_timbre = 0; | ||
| 140 | break; | ||
| 141 | } | ||
| 142 | |||
| 143 | } else if (frequency < 1280.0) { | ||
| 144 | |||
| 145 | // Open Hi-hat: 3 - 5 KHz | ||
| 146 | frequency = (rand() % (int)(2000)) + 3000; | ||
| 147 | switch (envelope_index) { | ||
| 148 | case 0 ... 35: | ||
| 149 | note_timbre = 0.5; | ||
| 150 | break; | ||
| 151 | case 36 ... 50: | ||
| 152 | note_timbre = 0.5 * (51 - envelope_index) / 15; | ||
| 153 | break; | ||
| 154 | default: | ||
| 155 | note_timbre = 0; | ||
| 156 | break; | ||
| 157 | } | ||
| 158 | |||
| 159 | } | ||
| 160 | break; | ||
| 34 | case butts_fader: | 161 | case butts_fader: |
| 162 | glissando = true; | ||
| 35 | polyphony_rate = 0; | 163 | polyphony_rate = 0; |
| 36 | switch (compensated_index) { | 164 | switch (compensated_index) { |
| 37 | case 0 ... 9: | 165 | case 0 ... 9: |
| @@ -79,6 +207,7 @@ float voice_envelope(float frequency) { | |||
| 79 | 207 | ||
| 80 | case duty_osc: | 208 | case duty_osc: |
| 81 | // This slows the loop down a substantial amount, so higher notes may freeze | 209 | // This slows the loop down a substantial amount, so higher notes may freeze |
| 210 | glissando = true; | ||
| 82 | polyphony_rate = 0; | 211 | polyphony_rate = 0; |
| 83 | switch (compensated_index) { | 212 | switch (compensated_index) { |
| 84 | default: | 213 | default: |
| @@ -93,6 +222,7 @@ float voice_envelope(float frequency) { | |||
| 93 | break; | 222 | break; |
| 94 | 223 | ||
| 95 | case duty_octave_down: | 224 | case duty_octave_down: |
| 225 | glissando = true; | ||
| 96 | polyphony_rate = 0; | 226 | polyphony_rate = 0; |
| 97 | note_timbre = (envelope_index % 2) * .125 + .375 * 2; | 227 | note_timbre = (envelope_index % 2) * .125 + .375 * 2; |
| 98 | if ((envelope_index % 4) == 0) | 228 | if ((envelope_index % 4) == 0) |
| @@ -101,6 +231,7 @@ float voice_envelope(float frequency) { | |||
| 101 | note_timbre = 0; | 231 | note_timbre = 0; |
| 102 | break; | 232 | break; |
| 103 | case delayed_vibrato: | 233 | case delayed_vibrato: |
| 234 | glissando = true; | ||
| 104 | polyphony_rate = 0; | 235 | polyphony_rate = 0; |
| 105 | note_timbre = TIMBRE_50; | 236 | note_timbre = TIMBRE_50; |
| 106 | #define VOICE_VIBRATO_DELAY 150 | 237 | #define VOICE_VIBRATO_DELAY 150 |
| @@ -155,11 +286,11 @@ float voice_envelope(float frequency) { | |||
| 155 | // note_timbre = 0.25; | 286 | // note_timbre = 0.25; |
| 156 | // break; | 287 | // break; |
| 157 | 288 | ||
| 289 | #endif | ||
| 290 | |||
| 158 | default: | 291 | default: |
| 159 | break; | 292 | break; |
| 160 | } | 293 | } |
| 161 | 294 | ||
| 162 | return frequency; | 295 | return frequency; |
| 163 | } | 296 | } |
| 164 | |||
| 165 | |||
diff --git a/quantum/audio/voices.h b/quantum/audio/voices.h index b2495b23b..9403a6b5e 100644 --- a/quantum/audio/voices.h +++ b/quantum/audio/voices.h | |||
| @@ -1,3 +1,18 @@ | |||
| 1 | /* Copyright 2016 Jack Humbert | ||
| 2 | * | ||
| 3 | * This program is free software: you can redistribute it and/or modify | ||
| 4 | * it under the terms of the GNU General Public License as published by | ||
| 5 | * the Free Software Foundation, either version 2 of the License, or | ||
| 6 | * (at your option) any later version. | ||
| 7 | * | ||
| 8 | * This program is distributed in the hope that it will be useful, | ||
| 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 11 | * GNU General Public License for more details. | ||
| 12 | * | ||
| 13 | * You should have received a copy of the GNU General Public License | ||
| 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 15 | */ | ||
| 1 | #include <stdint.h> | 16 | #include <stdint.h> |
| 2 | #include <stdbool.h> | 17 | #include <stdbool.h> |
| 3 | #include <avr/io.h> | 18 | #include <avr/io.h> |
| @@ -11,6 +26,9 @@ float voice_envelope(float frequency); | |||
| 11 | 26 | ||
| 12 | typedef enum { | 27 | typedef enum { |
| 13 | default_voice, | 28 | default_voice, |
| 29 | #ifdef AUDIO_VOICES | ||
| 30 | something, | ||
| 31 | drums, | ||
| 14 | butts_fader, | 32 | butts_fader, |
| 15 | octave_crunch, | 33 | octave_crunch, |
| 16 | duty_osc, | 34 | duty_osc, |
| @@ -21,6 +39,7 @@ typedef enum { | |||
| 21 | // duty_fourth_down, | 39 | // duty_fourth_down, |
| 22 | // duty_third_down, | 40 | // duty_third_down, |
| 23 | // duty_fifth_third_down, | 41 | // duty_fifth_third_down, |
| 42 | #endif | ||
| 24 | number_of_voices // important that this is last | 43 | number_of_voices // important that this is last |
| 25 | } voice_type; | 44 | } voice_type; |
| 26 | 45 | ||
| @@ -28,4 +47,4 @@ void set_voice(voice_type v); | |||
| 28 | void voice_iterate(void); | 47 | void voice_iterate(void); |
| 29 | void voice_deiterate(void); | 48 | void voice_deiterate(void); |
| 30 | 49 | ||
| 31 | #endif \ No newline at end of file | 50 | #endif |
diff --git a/quantum/audio/wave.h b/quantum/audio/wave.h index 6ebc34851..f15615dd1 100644 --- a/quantum/audio/wave.h +++ b/quantum/audio/wave.h | |||
| @@ -1,3 +1,19 @@ | |||
| 1 | /* Copyright 2016 Jack Humbert | ||
| 2 | * | ||
| 3 | * This program is free software: you can redistribute it and/or modify | ||
| 4 | * it under the terms of the GNU General Public License as published by | ||
| 5 | * the Free Software Foundation, either version 2 of the License, or | ||
| 6 | * (at your option) any later version. | ||
| 7 | * | ||
| 8 | * This program is distributed in the hope that it will be useful, | ||
| 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 11 | * GNU General Public License for more details. | ||
| 12 | * | ||
| 13 | * You should have received a copy of the GNU General Public License | ||
| 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 15 | */ | ||
| 16 | |||
| 1 | #include <avr/io.h> | 17 | #include <avr/io.h> |
| 2 | #include <avr/interrupt.h> | 18 | #include <avr/interrupt.h> |
| 3 | #include <avr/pgmspace.h> | 19 | #include <avr/pgmspace.h> |
| @@ -262,4 +278,4 @@ const uint8_t sinewave[] PROGMEM= //2048 values | |||
| 262 | 0x76,0x77,0x77,0x77,0x78,0x78,0x78,0x79, | 278 | 0x76,0x77,0x77,0x77,0x78,0x78,0x78,0x79, |
| 263 | 0x79,0x7a,0x7a,0x7a,0x7b,0x7b,0x7c,0x7c, | 279 | 0x79,0x7a,0x7a,0x7a,0x7b,0x7b,0x7c,0x7c, |
| 264 | 0x7c,0x7d,0x7d,0x7e,0x7e,0x7e,0x7f,0x7f | 280 | 0x7c,0x7d,0x7d,0x7e,0x7e,0x7e,0x7f,0x7f |
| 265 | }; \ No newline at end of file | 281 | }; |
