diff options
Diffstat (limited to 'quantum/audio.c')
| -rw-r--r-- | quantum/audio.c | 146 |
1 files changed, 101 insertions, 45 deletions
diff --git a/quantum/audio.c b/quantum/audio.c index 50e5505fe..5edcccdbe 100644 --- a/quantum/audio.c +++ b/quantum/audio.c | |||
| @@ -8,6 +8,8 @@ | |||
| 8 | #include "audio.h" | 8 | #include "audio.h" |
| 9 | #include "keymap_common.h" | 9 | #include "keymap_common.h" |
| 10 | 10 | ||
| 11 | #include "eeconfig.h" | ||
| 12 | |||
| 11 | #define PI 3.14159265 | 13 | #define PI 3.14159265 |
| 12 | 14 | ||
| 13 | // #define PWM_AUDIO | 15 | // #define PWM_AUDIO |
| @@ -30,6 +32,8 @@ int voice_place = 0; | |||
| 30 | double frequency = 0; | 32 | double frequency = 0; |
| 31 | int volume = 0; | 33 | int volume = 0; |
| 32 | long position = 0; | 34 | long position = 0; |
| 35 | int duty_place = 1; | ||
| 36 | int duty_counter = 0; | ||
| 33 | 37 | ||
| 34 | double frequencies[8] = {0, 0, 0, 0, 0, 0, 0, 0}; | 38 | double frequencies[8] = {0, 0, 0, 0, 0, 0, 0, 0}; |
| 35 | int volumes[8] = {0, 0, 0, 0, 0, 0, 0, 0}; | 39 | int volumes[8] = {0, 0, 0, 0, 0, 0, 0, 0}; |
| @@ -57,6 +61,25 @@ uint8_t notes_length; | |||
| 57 | bool notes_repeat; | 61 | bool notes_repeat; |
| 58 | uint8_t current_note = 0; | 62 | uint8_t current_note = 0; |
| 59 | 63 | ||
| 64 | audio_config_t audio_config; | ||
| 65 | |||
| 66 | |||
| 67 | void audio_toggle(void) { | ||
| 68 | audio_config.enable ^= 1; | ||
| 69 | eeconfig_write_audio(audio_config.raw); | ||
| 70 | } | ||
| 71 | |||
| 72 | void audio_on(void) { | ||
| 73 | audio_config.enable = 1; | ||
| 74 | eeconfig_write_audio(audio_config.raw); | ||
| 75 | } | ||
| 76 | |||
| 77 | void audio_off(void) { | ||
| 78 | audio_config.enable = 0; | ||
| 79 | eeconfig_write_audio(audio_config.raw); | ||
| 80 | } | ||
| 81 | |||
| 82 | |||
| 60 | void stop_all_notes() { | 83 | void stop_all_notes() { |
| 61 | voices = 0; | 84 | voices = 0; |
| 62 | #ifdef PWM_AUDIO | 85 | #ifdef PWM_AUDIO |
| @@ -77,58 +100,66 @@ void stop_all_notes() { | |||
| 77 | } | 100 | } |
| 78 | 101 | ||
| 79 | void stop_note(double freq) { | 102 | void stop_note(double freq) { |
| 80 | #ifdef PWM_AUDIO | 103 | if (note) { |
| 81 | freq = freq / SAMPLE_RATE; | ||
| 82 | #endif | ||
| 83 | for (int i = 7; i >= 0; i--) { | ||
| 84 | if (frequencies[i] == freq) { | ||
| 85 | frequencies[i] = 0; | ||
| 86 | volumes[i] = 0; | ||
| 87 | for (int j = i; (j < 7); j++) { | ||
| 88 | frequencies[j] = frequencies[j+1]; | ||
| 89 | frequencies[j+1] = 0; | ||
| 90 | volumes[j] = volumes[j+1]; | ||
| 91 | volumes[j+1] = 0; | ||
| 92 | } | ||
| 93 | } | ||
| 94 | } | ||
| 95 | voices--; | ||
| 96 | if (voices < 0) | ||
| 97 | voices = 0; | ||
| 98 | if (voices == 0) { | ||
| 99 | #ifdef PWM_AUDIO | 104 | #ifdef PWM_AUDIO |
| 100 | TIMSK3 &= ~_BV(OCIE3A); | 105 | freq = freq / SAMPLE_RATE; |
| 101 | #else | ||
| 102 | TIMSK3 &= ~_BV(OCIE3A); | ||
| 103 | TCCR3A &= ~_BV(COM3A1); | ||
| 104 | #endif | 106 | #endif |
| 105 | frequency = 0; | 107 | for (int i = 7; i >= 0; i--) { |
| 106 | volume = 0; | 108 | if (frequencies[i] == freq) { |
| 107 | note = false; | 109 | frequencies[i] = 0; |
| 108 | } else { | 110 | volumes[i] = 0; |
| 109 | double freq = frequencies[voices - 1]; | 111 | for (int j = i; (j < 7); j++) { |
| 110 | int vol = volumes[voices - 1]; | 112 | frequencies[j] = frequencies[j+1]; |
| 111 | double starting_f = frequency; | 113 | frequencies[j+1] = 0; |
| 112 | if (frequency < freq) { | 114 | volumes[j] = volumes[j+1]; |
| 113 | sliding = true; | 115 | volumes[j+1] = 0; |
| 114 | for (double f = starting_f; f <= freq; f += ((freq - starting_f) / 2000.0)) { | 116 | } |
| 115 | frequency = f; | ||
| 116 | } | 117 | } |
| 117 | sliding = false; | 118 | } |
| 118 | } else if (frequency > freq) { | 119 | voices--; |
| 119 | sliding = true; | 120 | if (voices < 0) |
| 120 | for (double f = starting_f; f >= freq; f -= ((starting_f - freq) / 2000.0)) { | 121 | voices = 0; |
| 121 | frequency = f; | 122 | if (voices == 0) { |
| 123 | #ifdef PWM_AUDIO | ||
| 124 | TIMSK3 &= ~_BV(OCIE3A); | ||
| 125 | #else | ||
| 126 | TIMSK3 &= ~_BV(OCIE3A); | ||
| 127 | TCCR3A &= ~_BV(COM3A1); | ||
| 128 | #endif | ||
| 129 | frequency = 0; | ||
| 130 | volume = 0; | ||
| 131 | note = false; | ||
| 132 | } else { | ||
| 133 | double freq = frequencies[voices - 1]; | ||
| 134 | int vol = volumes[voices - 1]; | ||
| 135 | double starting_f = frequency; | ||
| 136 | if (frequency < freq) { | ||
| 137 | sliding = true; | ||
| 138 | for (double f = starting_f; f <= freq; f += ((freq - starting_f) / 2000.0)) { | ||
| 139 | frequency = f; | ||
| 140 | } | ||
| 141 | sliding = false; | ||
| 142 | } else if (frequency > freq) { | ||
| 143 | sliding = true; | ||
| 144 | for (double f = starting_f; f >= freq; f -= ((starting_f - freq) / 2000.0)) { | ||
| 145 | frequency = f; | ||
| 146 | } | ||
| 147 | sliding = false; | ||
| 122 | } | 148 | } |
| 123 | sliding = false; | 149 | frequency = freq; |
| 150 | volume = vol; | ||
| 124 | } | 151 | } |
| 125 | frequency = freq; | ||
| 126 | volume = vol; | ||
| 127 | } | 152 | } |
| 128 | } | 153 | } |
| 129 | 154 | ||
| 130 | void init_notes() { | 155 | void init_notes() { |
| 131 | 156 | ||
| 157 | /* check signature */ | ||
| 158 | if (!eeconfig_is_enabled()) { | ||
| 159 | eeconfig_init(); | ||
| 160 | } | ||
| 161 | audio_config.raw = eeconfig_read_audio(); | ||
| 162 | |||
| 132 | #ifdef PWM_AUDIO | 163 | #ifdef PWM_AUDIO |
| 133 | PLLFRQ = _BV(PDIV2); | 164 | PLLFRQ = _BV(PDIV2); |
| 134 | PLLCSR = _BV(PLLE); | 165 | PLLCSR = _BV(PLLE); |
| @@ -160,7 +191,6 @@ void init_notes() { | |||
| 160 | 191 | ||
| 161 | 192 | ||
| 162 | ISR(TIMER3_COMPA_vect) { | 193 | ISR(TIMER3_COMPA_vect) { |
| 163 | |||
| 164 | if (note) { | 194 | if (note) { |
| 165 | #ifdef PWM_AUDIO | 195 | #ifdef PWM_AUDIO |
| 166 | if (voices == 1) { | 196 | if (voices == 1) { |
| @@ -213,13 +243,19 @@ ISR(TIMER3_COMPA_vect) { | |||
| 213 | if (frequency > 0) { | 243 | if (frequency > 0) { |
| 214 | // ICR3 = (int)(((double)F_CPU) / frequency); // Set max to the period | 244 | // ICR3 = (int)(((double)F_CPU) / frequency); // Set max to the period |
| 215 | // OCR3A = (int)(((double)F_CPU) / frequency) >> 1; // Set compare to half the period | 245 | // OCR3A = (int)(((double)F_CPU) / frequency) >> 1; // Set compare to half the period |
| 216 | if (place > 10) { | 246 | voice_place %= voices; |
| 247 | if (place > (frequencies[voice_place] / 500)) { | ||
| 217 | voice_place = (voice_place + 1) % voices; | 248 | voice_place = (voice_place + 1) % voices; |
| 218 | place = 0.0; | 249 | place = 0.0; |
| 219 | } | 250 | } |
| 220 | ICR3 = (int)(((double)F_CPU) / frequencies[voice_place]); // Set max to the period | 251 | ICR3 = (int)(((double)F_CPU) / frequencies[voice_place]); // Set max to the period |
| 221 | OCR3A = (int)(((double)F_CPU) / frequencies[voice_place]) >> 1; // Set compare to half the period | 252 | OCR3A = (int)(((double)F_CPU) / frequencies[voice_place]) >> 1 * duty_place; // Set compare to half the period |
| 222 | place++; | 253 | place++; |
| 254 | // if (duty_counter > (frequencies[voice_place] / 500)) { | ||
| 255 | // duty_place = (duty_place % 3) + 1; | ||
| 256 | // duty_counter = 0; | ||
| 257 | // } | ||
| 258 | // duty_counter++; | ||
| 223 | } | 259 | } |
| 224 | #endif | 260 | #endif |
| 225 | } | 261 | } |
| @@ -288,9 +324,16 @@ ISR(TIMER3_COMPA_vect) { | |||
| 288 | 324 | ||
| 289 | } | 325 | } |
| 290 | 326 | ||
| 327 | if (!audio_config.enable) { | ||
| 328 | notes = false; | ||
| 329 | note = false; | ||
| 330 | } | ||
| 291 | } | 331 | } |
| 292 | 332 | ||
| 293 | void play_notes(float (*np)[][2], uint8_t n_length, bool n_repeat) { | 333 | void play_notes(float (*np)[][2], uint8_t n_length, bool n_repeat) { |
| 334 | |||
| 335 | if (audio_config.enable) { | ||
| 336 | |||
| 294 | if (note) | 337 | if (note) |
| 295 | stop_all_notes(); | 338 | stop_all_notes(); |
| 296 | notes = true; | 339 | notes = true; |
| @@ -319,7 +362,12 @@ void play_notes(float (*np)[][2], uint8_t n_length, bool n_repeat) { | |||
| 319 | #endif | 362 | #endif |
| 320 | } | 363 | } |
| 321 | 364 | ||
| 365 | } | ||
| 366 | |||
| 322 | void play_sample(uint8_t * s, uint16_t l, bool r) { | 367 | void play_sample(uint8_t * s, uint16_t l, bool r) { |
| 368 | |||
| 369 | if (audio_config.enable) { | ||
| 370 | |||
| 323 | stop_all_notes(); | 371 | stop_all_notes(); |
| 324 | place_int = 0; | 372 | place_int = 0; |
| 325 | sample = s; | 373 | sample = s; |
| @@ -330,9 +378,15 @@ void play_sample(uint8_t * s, uint16_t l, bool r) { | |||
| 330 | TIMSK3 |= _BV(OCIE3A); | 378 | TIMSK3 |= _BV(OCIE3A); |
| 331 | #else | 379 | #else |
| 332 | #endif | 380 | #endif |
| 381 | |||
| 382 | } | ||
| 383 | |||
| 333 | } | 384 | } |
| 334 | 385 | ||
| 335 | void play_note(double freq, int vol) { | 386 | void play_note(double freq, int vol) { |
| 387 | |||
| 388 | if (audio_config.enable && voices < 8) { | ||
| 389 | |||
| 336 | if (notes) | 390 | if (notes) |
| 337 | stop_all_notes(); | 391 | stop_all_notes(); |
| 338 | note = true; | 392 | note = true; |
| @@ -367,4 +421,6 @@ void play_note(double freq, int vol) { | |||
| 367 | TCCR3A |= _BV(COM3A1); | 421 | TCCR3A |= _BV(COM3A1); |
| 368 | #endif | 422 | #endif |
| 369 | 423 | ||
| 424 | } | ||
| 425 | |||
| 370 | } \ No newline at end of file | 426 | } \ No newline at end of file |
