diff options
author | Roman Zolotarev <hi@romanzolotarev.com> | 2016-04-26 16:23:10 +0800 |
---|---|---|
committer | Roman Zolotarev <hi@romanzolotarev.com> | 2016-04-26 16:23:10 +0800 |
commit | 28f0b64e31b8c30a842dfd356421356cf0513177 (patch) | |
tree | e5a76f4a2fb747c3599de1e297f46e4dc6fd4f0e /quantum/audio | |
parent | fa2eedb7bd906634b8c500ba0d91638e63eaafed (diff) | |
parent | bf56838fe99aafd37559d560e47b707a83c87588 (diff) |
Merge branch 'master' of https://github.com/jackhumbert/qmk_firmware
Diffstat (limited to 'quantum/audio')
-rw-r--r-- | quantum/audio/audio.c | 607 | ||||
-rw-r--r-- | quantum/audio/audio.h | 89 | ||||
-rw-r--r-- | quantum/audio/frequency_lut.h | 357 | ||||
-rw-r--r-- | quantum/audio/musical_notes.h | 217 | ||||
-rw-r--r-- | quantum/audio/song_list.h | 117 | ||||
-rw-r--r-- | quantum/audio/vibrato_lut.h | 28 | ||||
-rw-r--r-- | quantum/audio/voices.c | 163 | ||||
-rw-r--r-- | quantum/audio/voices.h | 32 | ||||
-rw-r--r-- | quantum/audio/wave.h | 265 |
9 files changed, 1875 insertions, 0 deletions
diff --git a/quantum/audio/audio.c b/quantum/audio/audio.c new file mode 100644 index 0000000000..e85370d958 --- /dev/null +++ b/quantum/audio/audio.c @@ -0,0 +1,607 @@ +#include <stdio.h> +#include <string.h> +#include <math.h> +#include <avr/pgmspace.h> +#include <avr/interrupt.h> +#include <avr/io.h> +#include "print.h" +#include "audio.h" +#include "keymap_common.h" + +#include "eeconfig.h" + +#ifdef VIBRATO_ENABLE + #include "vibrato_lut.h" +#endif + +#define PI 3.14159265 + +#define CPU_PRESCALER 8 + +#ifdef PWM_AUDIO + #include "wave.h" + #define SAMPLE_DIVIDER 39 + #define SAMPLE_RATE (2000000.0/SAMPLE_DIVIDER/2048) + // Resistor value of 1/ (2 * PI * 10nF * (2000000 hertz / SAMPLE_DIVIDER / 10)) for 10nF cap + + float places[8] = {0, 0, 0, 0, 0, 0, 0, 0}; + uint16_t place_int = 0; + bool repeat = true; +#endif + +void delay_us(int count) { + while(count--) { + _delay_us(1); + } +} + +int voices = 0; +int voice_place = 0; +float frequency = 0; +int volume = 0; +long position = 0; + +float frequencies[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +int volumes[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +bool sliding = false; + +int max = 0xFF; +float sum = 0; +float place = 0; + +uint8_t * sample; +uint16_t sample_length = 0; +// float freq = 0; + +bool notes = false; +bool note = false; +float note_frequency = 0; +float note_length = 0; +float note_tempo = TEMPO_DEFAULT; +float note_timbre = TIMBRE_DEFAULT; +uint16_t note_position = 0; +float (* notes_pointer)[][2]; +uint16_t notes_count; +bool notes_repeat; +float notes_rest; +bool note_resting = false; + +uint8_t current_note = 0; +uint8_t rest_counter = 0; + +#ifdef VIBRATO_ENABLE +float vibrato_counter = 0; +float vibrato_strength = .5; +float vibrato_rate = 0.125; +#endif + +float polyphony_rate = 0; + +bool inited = false; + +audio_config_t audio_config; + +uint16_t envelope_index = 0; + +void audio_toggle(void) { + audio_config.enable ^= 1; + eeconfig_update_audio(audio_config.raw); +} + +void audio_on(void) { + audio_config.enable = 1; + eeconfig_update_audio(audio_config.raw); +} + +void audio_off(void) { + audio_config.enable = 0; + eeconfig_update_audio(audio_config.raw); +} + +#ifdef VIBRATO_ENABLE +// Vibrato rate functions + +void set_vibrato_rate(float rate) { + vibrato_rate = rate; +} + +void increase_vibrato_rate(float change) { + vibrato_rate *= change; +} + +void decrease_vibrato_rate(float change) { + vibrato_rate /= change; +} + +#ifdef VIBRATO_STRENGTH_ENABLE + +void set_vibrato_strength(float strength) { + vibrato_strength = strength; +} + +void increase_vibrato_strength(float change) { + vibrato_strength *= change; +} + +void decrease_vibrato_strength(float change) { + vibrato_strength /= change; +} + +#endif + +#endif + +// Polyphony functions + +void set_polyphony_rate(float rate) { + polyphony_rate = rate; +} + +void enable_polyphony() { + polyphony_rate = 5; +} + +void disable_polyphony() { + polyphony_rate = 0; +} + +void increase_polyphony_rate(float change) { + polyphony_rate *= change; +} + +void decrease_polyphony_rate(float change) { + polyphony_rate /= change; +} + +// Timbre function + +void set_timbre(float timbre) { + note_timbre = timbre; +} + +// Tempo functions + +void set_tempo(float tempo) { + note_tempo = tempo; +} + +void decrease_tempo(uint8_t tempo_change) { + note_tempo += (float) tempo_change; +} + +void increase_tempo(uint8_t tempo_change) { + if (note_tempo - (float) tempo_change < 10) { + note_tempo = 10; + } else { + note_tempo -= (float) tempo_change; + } +} + +void audio_init() { + + /* check signature */ + if (!eeconfig_is_enabled()) { + eeconfig_init(); + } + audio_config.raw = eeconfig_read_audio(); + + #ifdef PWM_AUDIO + PLLFRQ = _BV(PDIV2); + PLLCSR = _BV(PLLE); + while(!(PLLCSR & _BV(PLOCK))); + PLLFRQ |= _BV(PLLTM0); /* PCK 48MHz */ + + /* Init a fast PWM on Timer4 */ + TCCR4A = _BV(COM4A0) | _BV(PWM4A); /* Clear OC4A on Compare Match */ + TCCR4B = _BV(CS40); /* No prescaling => f = PCK/256 = 187500Hz */ + OCR4A = 0; + + /* Enable the OC4A output */ + DDRC |= _BV(PORTC6); + + TIMSK3 &= ~_BV(OCIE3A); // Turn off 3A interputs + + TCCR3A = 0x0; // Options not needed + TCCR3B = _BV(CS31) | _BV(CS30) | _BV(WGM32); // 64th prescaling and CTC + OCR3A = SAMPLE_DIVIDER - 1; // Correct count/compare, related to sample playback + #else + DDRC |= _BV(PORTC6); + + TIMSK3 &= ~_BV(OCIE3A); // Turn off 3A interputs + + TCCR3A = (0 << COM3A1) | (0 << COM3A0) | (1 << WGM31) | (0 << WGM30); + TCCR3B = (1 << WGM33) | (1 << WGM32) | (0 << CS32) | (1 << CS31) | (0 << CS30); + #endif + + inited = true; +} + +void stop_all_notes() { + if (!inited) { + audio_init(); + } + voices = 0; + #ifdef PWM_AUDIO + TIMSK3 &= ~_BV(OCIE3A); + #else + TIMSK3 &= ~_BV(OCIE3A); + TCCR3A &= ~_BV(COM3A1); + #endif + notes = false; + note = false; + frequency = 0; + volume = 0; + + for (int i = 0; i < 8; i++) { + frequencies[i] = 0; + volumes[i] = 0; + } +} + +void stop_note(float freq) { + if (note) { + if (!inited) { + audio_init(); + } + #ifdef PWM_AUDIO + freq = freq / SAMPLE_RATE; + #endif + for (int i = 7; i >= 0; i--) { + if (frequencies[i] == freq) { + frequencies[i] = 0; + volumes[i] = 0; + for (int j = i; (j < 7); j++) { + frequencies[j] = frequencies[j+1]; + frequencies[j+1] = 0; + volumes[j] = volumes[j+1]; + volumes[j+1] = 0; + } + break; + } + } + voices--; + if (voices < 0) + voices = 0; + if (voice_place >= voices) { + voice_place = 0; + } + if (voices == 0) { + #ifdef PWM_AUDIO + TIMSK3 &= ~_BV(OCIE3A); + #else + TIMSK3 &= ~_BV(OCIE3A); + TCCR3A &= ~_BV(COM3A1); + #endif + frequency = 0; + volume = 0; + note = false; + } + } +} + +#ifdef VIBRATO_ENABLE + +float mod(float a, int b) +{ + float r = fmod(a, b); + return r < 0 ? r + b : r; +} + +float vibrato(float average_freq) { + #ifdef VIBRATO_STRENGTH_ENABLE + float vibrated_freq = average_freq * pow(VIBRATO_LUT[(int)vibrato_counter], vibrato_strength); + #else + float vibrated_freq = average_freq * VIBRATO_LUT[(int)vibrato_counter]; + #endif + vibrato_counter = mod((vibrato_counter + vibrato_rate * (1.0 + 440.0/average_freq)), VIBRATO_LUT_LENGTH); + return vibrated_freq; +} + +#endif + +ISR(TIMER3_COMPA_vect) { + if (note) { + #ifdef PWM_AUDIO + if (voices == 1) { + // SINE + OCR4A = pgm_read_byte(&sinewave[(uint16_t)place]) >> 2; + + // SQUARE + // if (((int)place) >= 1024){ + // OCR4A = 0xFF >> 2; + // } else { + // OCR4A = 0x00; + // } + + // SAWTOOTH + // OCR4A = (int)place / 4; + + // TRIANGLE + // if (((int)place) >= 1024) { + // OCR4A = (int)place / 2; + // } else { + // OCR4A = 2048 - (int)place / 2; + // } + + place += frequency; + + if (place >= SINE_LENGTH) + place -= SINE_LENGTH; + + } else { + int sum = 0; + for (int i = 0; i < voices; i++) { + // SINE + sum += pgm_read_byte(&sinewave[(uint16_t)places[i]]) >> 2; + + // SQUARE + // if (((int)places[i]) >= 1024){ + // sum += 0xFF >> 2; + // } else { + // sum += 0x00; + // } + + places[i] += frequencies[i]; + + if (places[i] >= SINE_LENGTH) + places[i] -= SINE_LENGTH; + } + OCR4A = sum; + } + #else + if (voices > 0) { + float freq; + if (polyphony_rate > 0) { + if (voices > 1) { + voice_place %= voices; + if (place++ > (frequencies[voice_place] / polyphony_rate / CPU_PRESCALER)) { + voice_place = (voice_place + 1) % voices; + place = 0.0; + } + } + #ifdef VIBRATO_ENABLE + if (vibrato_strength > 0) { + freq = vibrato(frequencies[voice_place]); + } else { + #else + { + #endif + freq = frequencies[voice_place]; + } + } else { + if (frequency != 0 && frequency < frequencies[voices - 1] && frequency < frequencies[voices - 1] * pow(2, -440/frequencies[voices - 1]/12/2)) { + frequency = frequency * pow(2, 440/frequency/12/2); + } else if (frequency != 0 && frequency > frequencies[voices - 1] && frequency > frequencies[voices - 1] * pow(2, 440/frequencies[voices - 1]/12/2)) { + frequency = frequency * pow(2, -440/frequency/12/2); + } else { + frequency = frequencies[voices - 1]; + } + + + #ifdef VIBRATO_ENABLE + if (vibrato_strength > 0) { + freq = vibrato(frequency); + } else { + #else + { + #endif + freq = frequency; + } + } + + if (envelope_index < 65535) { + envelope_index++; + } + freq = voice_envelope(freq); + + if (freq < 30.517578125) + freq = 30.52; + ICR3 = (int)(((double)F_CPU) / (freq * CPU_PRESCALER)); // Set max to the period + OCR3A = (int)((((double)F_CPU) / (freq * CPU_PRESCALER)) * note_timbre); // Set compare to half the period + } + #endif + } + + // SAMPLE + // OCR4A = pgm_read_byte(&sample[(uint16_t)place_int]); + + // place_int++; + + // if (place_int >= sample_length) + // if (repeat) + // place_int -= sample_length; + // else + // TIMSK3 &= ~_BV(OCIE3A); + + + if (notes) { + #ifdef PWM_AUDIO + OCR4A = pgm_read_byte(&sinewave[(uint16_t)place]) >> 0; + + place += note_frequency; + if (place >= SINE_LENGTH) + place -= SINE_LENGTH; + #else + if (note_frequency > 0) { + float freq; + + #ifdef VIBRATO_ENABLE + if (vibrato_strength > 0) { + freq = vibrato(note_frequency); + } else { + #else + { + #endif + freq = note_frequency; + } + + if (envelope_index < 65535) { + envelope_index++; + } + freq = voice_envelope(freq); + + ICR3 = (int)(((double)F_CPU) / (freq * CPU_PRESCALER)); // Set max to the period + OCR3A = (int)((((double)F_CPU) / (freq * CPU_PRESCALER)) * note_timbre); // Set compare to half the period + } else { + ICR3 = 0; + OCR3A = 0; + } + #endif + + + note_position++; + bool end_of_note = false; + if (ICR3 > 0) + end_of_note = (note_position >= (note_length / ICR3 * 0xFFFF)); + else + end_of_note = (note_position >= (note_length * 0x7FF)); + if (end_of_note) { + current_note++; + if (current_note >= notes_count) { + if (notes_repeat) { + current_note = 0; + } else { + #ifdef PWM_AUDIO + TIMSK3 &= ~_BV(OCIE3A); + #else + TIMSK3 &= ~_BV(OCIE3A); + TCCR3A &= ~_BV(COM3A1); + #endif + notes = false; + return; + } + } + if (!note_resting && (notes_rest > 0)) { + note_resting = true; + note_frequency = 0; + note_length = notes_rest; + current_note--; + } else { + note_resting = false; + #ifdef PWM_AUDIO + note_frequency = (*notes_pointer)[current_note][0] / SAMPLE_RATE; + note_length = (*notes_pointer)[current_note][1] * (note_tempo / 100); + #else + envelope_index = 0; + note_frequency = (*notes_pointer)[current_note][0]; + note_length = ((*notes_pointer)[current_note][1] / 4) * (note_tempo / 100); + #endif + } + note_position = 0; + } + + } + + if (!audio_config.enable) { + notes = false; + note = false; + } +} + +void play_note(float freq, int vol) { + + if (!inited) { + audio_init(); + } + +if (audio_config.enable && voices < 8) { + TIMSK3 &= ~_BV(OCIE3A); + // Cancel notes if notes are playing + if (notes) + stop_all_notes(); + note = true; + envelope_index = 0; + #ifdef PWM_AUDIO + freq = freq / SAMPLE_RATE; + #endif + if (freq > 0) { + frequencies[voices] = freq; + volumes[voices] = vol; + voices++; + } + + #ifdef PWM_AUDIO + TIMSK3 |= _BV(OCIE3A); + #else + TIMSK3 |= _BV(OCIE3A); + TCCR3A |= _BV(COM3A1); + #endif +} + +} + +void play_notes(float (*np)[][2], uint16_t n_count, bool n_repeat, float n_rest) { + + if (!inited) { + audio_init(); + } + +if (audio_config.enable) { + TIMSK3 &= ~_BV(OCIE3A); + // Cancel note if a note is playing + if (note) + stop_all_notes(); + notes = true; + + notes_pointer = np; + notes_count = n_count; + notes_repeat = n_repeat; + notes_rest = n_rest; + + place = 0; + current_note = 0; + #ifdef PWM_AUDIO + note_frequency = (*notes_pointer)[current_note][0] / SAMPLE_RATE; + note_length = (*notes_pointer)[current_note][1] * (note_tempo / 100); + #else + note_frequency = (*notes_pointer)[current_note][0]; + note_length = ((*notes_pointer)[current_note][1] / 4) * (note_tempo / 100); + #endif + note_position = 0; + + + #ifdef PWM_AUDIO + TIMSK3 |= _BV(OCIE3A); + #else + TIMSK3 |= _BV(OCIE3A); + TCCR3A |= _BV(COM3A1); + #endif +} + +} + +#ifdef PWM_AUDIO +void play_sample(uint8_t * s, uint16_t l, bool r) { + if (!inited) { + audio_init(); + } + + if (audio_config.enable) { + TIMSK3 &= ~_BV(OCIE3A); + stop_all_notes(); + place_int = 0; + sample = s; + sample_length = l; + repeat = r; + + TIMSK3 |= _BV(OCIE3A); + } +} +#endif + +//------------------------------------------------------------------------------ +// Override these functions in your keymap file to play different tunes on +// startup and bootloader jump +__attribute__ ((weak)) +void play_startup_tone() +{ +} + + + +__attribute__ ((weak)) +void play_goodbye_tone() +{ + +} +//------------------------------------------------------------------------------ diff --git a/quantum/audio/audio.h b/quantum/audio/audio.h new file mode 100644 index 0000000000..89769507e1 --- /dev/null +++ b/quantum/audio/audio.h @@ -0,0 +1,89 @@ +#include <stdint.h> +#include <stdbool.h> +#include <avr/io.h> +#include <util/delay.h> +#include "musical_notes.h" +#include "song_list.h" +#include "voices.h" + +#ifndef AUDIO_H +#define AUDIO_H + +// Largely untested PWM audio mode (doesn't sound as good) +// #define PWM_AUDIO + +// #define VIBRATO_ENABLE + +// Enable vibrato strength/amplitude - slows down ISR too much +// #define VIBRATO_STRENGTH_ENABLE + +typedef union { + uint8_t raw; + struct { + bool enable :1; + uint8_t level :7; + }; +} audio_config_t; + +void audio_toggle(void); +void audio_on(void); +void audio_off(void); + +// Vibrato rate functions + +#ifdef VIBRATO_ENABLE + +void set_vibrato_rate(float rate); +void increase_vibrato_rate(float change); +void decrease_vibrato_rate(float change); + +#ifdef VIBRATO_STRENGTH_ENABLE + +void set_vibrato_strength(float strength); +void increase_vibrato_strength(float change); +void decrease_vibrato_strength(float change); + +#endif + +#endif + +// Polyphony functions + +void set_polyphony_rate(float rate); +void enable_polyphony(void); +void disable_polyphony(void); +void increase_polyphony_rate(float change); +void decrease_polyphony_rate(float change); + +void set_timbre(float timbre); +void set_tempo(float tempo); + +void increase_tempo(uint8_t tempo_change); +void decrease_tempo(uint8_t tempo_change); + +void audio_init(void); + +#ifdef PWM_AUDIO +void play_sample(uint8_t * s, uint16_t l, bool r); +#endif +void play_note(float freq, int vol); +void stop_note(float freq); +void stop_all_notes(void); +void play_notes(float (*np)[][2], uint16_t n_count, bool n_repeat, float n_rest); + +#define SCALE (int []){ 0 + (12*0), 2 + (12*0), 4 + (12*0), 5 + (12*0), 7 + (12*0), 9 + (12*0), 11 + (12*0), \ + 0 + (12*1), 2 + (12*1), 4 + (12*1), 5 + (12*1), 7 + (12*1), 9 + (12*1), 11 + (12*1), \ + 0 + (12*2), 2 + (12*2), 4 + (12*2), 5 + (12*2), 7 + (12*2), 9 + (12*2), 11 + (12*2), \ + 0 + (12*3), 2 + (12*3), 4 + (12*3), 5 + (12*3), 7 + (12*3), 9 + (12*3), 11 + (12*3), \ + 0 + (12*4), 2 + (12*4), 4 + (12*4), 5 + (12*4), 7 + (12*4), 9 + (12*4), 11 + (12*4), } + +// These macros are used to allow play_notes to play an array of indeterminate +// length. This works around the limitation of C's sizeof operation on pointers. +// The global float array for the song must be used here. +#define NOTE_ARRAY_SIZE(x) ((int16_t)(sizeof(x) / (sizeof(x[0])))) +#define PLAY_NOTE_ARRAY(note_array, note_repeat, note_rest_style) play_notes(¬e_array, NOTE_ARRAY_SIZE((note_array)), (note_repeat), (note_rest_style)); + +void play_goodbye_tone(void); +void play_startup_tone(void); + +#endif
\ No newline at end of file diff --git a/quantum/audio/frequency_lut.h b/quantum/audio/frequency_lut.h new file mode 100644 index 0000000000..e62da5be4e --- /dev/null +++ b/quantum/audio/frequency_lut.h @@ -0,0 +1,357 @@ +#include <avr/io.h> +#include <avr/interrupt.h> +#include <avr/pgmspace.h> + +#define FREQUENCY_LUT_LENGTH 349 + +const uint16_t FREQUENCY_LUT[FREQUENCY_LUT_LENGTH] = { +0x8E0B, +0x8C02, +0x8A00, +0x8805, +0x8612, +0x8426, +0x8241, +0x8063, +0x7E8C, +0x7CBB, +0x7AF2, +0x792E, +0x7772, +0x75BB, +0x740B, +0x7261, +0x70BD, +0x6F20, +0x6D88, +0x6BF6, +0x6A69, +0x68E3, +0x6762, +0x65E6, +0x6470, +0x6300, +0x6194, +0x602E, +0x5ECD, +0x5D71, +0x5C1A, +0x5AC8, +0x597B, +0x5833, +0x56EF, +0x55B0, +0x5475, +0x533F, +0x520E, +0x50E1, +0x4FB8, +0x4E93, +0x4D73, +0x4C57, +0x4B3E, +0x4A2A, +0x491A, +0x480E, +0x4705, +0x4601, +0x4500, +0x4402, +0x4309, +0x4213, +0x4120, +0x4031, +0x3F46, +0x3E5D, +0x3D79, +0x3C97, +0x3BB9, +0x3ADD, +0x3A05, +0x3930, +0x385E, +0x3790, +0x36C4, +0x35FB, +0x3534, +0x3471, +0x33B1, +0x32F3, +0x3238, +0x3180, +0x30CA, +0x3017, +0x2F66, +0x2EB8, +0x2E0D, +0x2D64, +0x2CBD, +0x2C19, +0x2B77, +0x2AD8, +0x2A3A, +0x299F, +0x2907, +0x2870, +0x27DC, +0x2749, +0x26B9, +0x262B, +0x259F, +0x2515, +0x248D, +0x2407, +0x2382, +0x2300, +0x2280, +0x2201, +0x2184, +0x2109, +0x2090, +0x2018, +0x1FA3, +0x1F2E, +0x1EBC, +0x1E4B, +0x1DDC, +0x1D6E, +0x1D02, +0x1C98, +0x1C2F, +0x1BC8, +0x1B62, +0x1AFD, +0x1A9A, +0x1A38, +0x19D8, +0x1979, +0x191C, +0x18C0, +0x1865, +0x180B, +0x17B3, +0x175C, +0x1706, +0x16B2, +0x165E, +0x160C, +0x15BB, +0x156C, +0x151D, +0x14CF, +0x1483, +0x1438, +0x13EE, +0x13A4, +0x135C, +0x1315, +0x12CF, +0x128A, +0x1246, +0x1203, +0x11C1, +0x1180, +0x1140, +0x1100, +0x10C2, +0x1084, +0x1048, +0x100C, +0xFD1, +0xF97, +0xF5E, +0xF25, +0xEEE, +0xEB7, +0xE81, +0xE4C, +0xE17, +0xDE4, +0xDB1, +0xD7E, +0xD4D, +0xD1C, +0xCEC, +0xCBC, +0xC8E, +0xC60, +0xC32, +0xC05, +0xBD9, +0xBAE, +0xB83, +0xB59, +0xB2F, +0xB06, +0xADD, +0xAB6, +0xA8E, +0xA67, +0xA41, +0xA1C, +0x9F7, +0x9D2, +0x9AE, +0x98A, +0x967, +0x945, +0x923, +0x901, +0x8E0, +0x8C0, +0x8A0, +0x880, +0x861, +0x842, +0x824, +0x806, +0x7E8, +0x7CB, +0x7AF, +0x792, +0x777, +0x75B, +0x740, +0x726, +0x70B, +0x6F2, +0x6D8, +0x6BF, +0x6A6, +0x68E, +0x676, +0x65E, +0x647, +0x630, +0x619, +0x602, +0x5EC, +0x5D7, +0x5C1, +0x5AC, +0x597, +0x583, +0x56E, +0x55B, +0x547, +0x533, +0x520, +0x50E, +0x4FB, +0x4E9, +0x4D7, +0x4C5, +0x4B3, +0x4A2, +0x491, +0x480, +0x470, +0x460, +0x450, +0x440, +0x430, +0x421, +0x412, +0x403, +0x3F4, +0x3E5, +0x3D7, +0x3C9, +0x3BB, +0x3AD, +0x3A0, +0x393, +0x385, +0x379, +0x36C, +0x35F, +0x353, +0x347, +0x33B, +0x32F, +0x323, +0x318, +0x30C, +0x301, +0x2F6, +0x2EB, +0x2E0, +0x2D6, +0x2CB, +0x2C1, +0x2B7, +0x2AD, +0x2A3, +0x299, +0x290, +0x287, +0x27D, +0x274, +0x26B, +0x262, +0x259, +0x251, +0x248, +0x240, +0x238, +0x230, +0x228, +0x220, +0x218, +0x210, +0x209, +0x201, +0x1FA, +0x1F2, +0x1EB, +0x1E4, +0x1DD, +0x1D6, +0x1D0, +0x1C9, +0x1C2, +0x1BC, +0x1B6, +0x1AF, +0x1A9, +0x1A3, +0x19D, +0x197, +0x191, +0x18C, +0x186, +0x180, +0x17B, +0x175, +0x170, +0x16B, +0x165, +0x160, +0x15B, +0x156, +0x151, +0x14C, +0x148, +0x143, +0x13E, +0x13A, +0x135, +0x131, +0x12C, +0x128, +0x124, +0x120, +0x11C, +0x118, +0x114, +0x110, +0x10C, +0x108, +0x104, +0x100, +0xFD, +0xF9, +0xF5, +0xF2, +0xEE +};
\ No newline at end of file diff --git a/quantum/audio/musical_notes.h b/quantum/audio/musical_notes.h new file mode 100644 index 0000000000..b08d16a6fa --- /dev/null +++ b/quantum/audio/musical_notes.h @@ -0,0 +1,217 @@ +#ifndef MUSICAL_NOTES_H +#define MUSICAL_NOTES_H + +// Tempo Placeholder +#define TEMPO_DEFAULT 100 + + +#define SONG(notes...) { notes } + + +// Note Types +#define MUSICAL_NOTE(note, duration) {(NOTE##note), duration} +#define WHOLE_NOTE(note) MUSICAL_NOTE(note, 64) +#define HALF_NOTE(note) MUSICAL_NOTE(note, 32) +#define QUARTER_NOTE(note) MUSICAL_NOTE(note, 16) +#define EIGHTH_NOTE(note) MUSICAL_NOTE(note, 8) +#define SIXTEENTH_NOTE(note) MUSICAL_NOTE(note, 4) + +#define WHOLE_DOT_NOTE(note) MUSICAL_NOTE(note, 64+32) +#define HALF_DOT_NOTE(note) MUSICAL_NOTE(note, 32+16) +#define QUARTER_DOT_NOTE(note) MUSICAL_NOTE(note, 16+8) +#define EIGHTH_DOT_NOTE(note) MUSICAL_NOTE(note, 8+4) +#define SIXTEENTH_DOT_NOTE(note) MUSICAL_NOTE(note, 4+2) + +// Note Type Shortcuts +#define M__NOTE(note, duration) MUSICAL_NOTE(note, duration) +#define W__NOTE(n) WHOLE_NOTE(n) +#define H__NOTE(n) HALF_NOTE(n) +#define Q__NOTE(n) QUARTER_NOTE(n) +#define E__NOTE(n) EIGHTH_NOTE(n) +#define S__NOTE(n) SIXTEENTH_NOTE(n) +#define WD_NOTE(n) WHOLE_DOT_NOTE(n) +#define HD_NOTE(n) HALF_DOT_NOTE(n) +#define QD_NOTE(n) QUARTER_DOT_NOTE(n) +#define ED_NOTE(n) EIGHTH_DOT_NOTE(n) +#define SD_NOTE(n) SIXTEENTH_DOT_NOTE(n) + +// Note Styles +// Staccato makes sure there is a rest between each note. Think: TA TA TA +// Legato makes notes flow together. Think: TAAA +#define STACCATO 0.01 +#define LEGATO 0 + +// Note Timbre +// Changes how the notes sound +#define TIMBRE_12 0.125 +#define TIMBRE_25 0.250 +#define TIMBRE_50 0.500 +#define TIMBRE_75 0.750 +#define TIMBRE_DEFAULT TIMBRE_50 + + +// Notes - # = Octave + +#define NOTE_REST 0.00 + +/* These notes are currently bugged +#define NOTE_C0 16.35 +#define NOTE_CS0 17.32 +#define NOTE_D0 18.35 +#define NOTE_DS0 19.45 +#define NOTE_E0 20.60 +#define NOTE_F0 21.83 +#define NOTE_FS0 23.12 +#define NOTE_G0 24.50 +#define NOTE_GS0 25.96 +#define NOTE_A0 27.50 +#define NOTE_AS0 29.14 +#define NOTE_B0 30.87 +#define NOTE_C1 32.70 +#define NOTE_CS1 34.65 +#define NOTE_D1 36.71 +#define NOTE_DS1 38.89 +#define NOTE_E1 41.20 +#define NOTE_F1 43.65 +#define NOTE_FS1 46.25 +#define NOTE_G1 49.00 +#define NOTE_GS1 51.91 +#define NOTE_A1 55.00 +#define NOTE_AS1 58.27 +*/ + +#define NOTE_B1 61.74 +#define NOTE_C2 65.41 +#define NOTE_CS2 69.30 +#define NOTE_D2 73.42 +#define NOTE_DS2 77.78 +#define NOTE_E2 82.41 +#define NOTE_F2 87.31 +#define NOTE_FS2 92.50 +#define NOTE_G2 98.00 +#define NOTE_GS2 103.83 +#define NOTE_A2 110.00 +#define NOTE_AS2 116.54 +#define NOTE_B2 123.47 +#define NOTE_C3 130.81 +#define NOTE_CS3 138.59 +#define NOTE_D3 146.83 +#define NOTE_DS3 155.56 +#define NOTE_E3 164.81 +#define NOTE_F3 174.61 +#define NOTE_FS3 185.00 +#define NOTE_G3 196.00 +#define NOTE_GS3 207.65 +#define NOTE_A3 220.00 +#define NOTE_AS3 233.08 +#define NOTE_B3 246.94 +#define NOTE_C4 261.63 +#define NOTE_CS4 277.18 +#define NOTE_D4 293.66 +#define NOTE_DS4 311.13 +#define NOTE_E4 329.63 +#define NOTE_F4 349.23 +#define NOTE_FS4 369.99 +#define NOTE_G4 392.00 +#define NOTE_GS4 415.30 +#define NOTE_A4 440.00 +#define NOTE_AS4 466.16 +#define NOTE_B4 493.88 +#define NOTE_C5 523.25 +#define NOTE_CS5 554.37 +#define NOTE_D5 587.33 +#define NOTE_DS5 622.25 +#define NOTE_E5 659.26 +#define NOTE_F5 698.46 +#define NOTE_FS5 739.99 +#define NOTE_G5 783.99 +#define NOTE_GS5 830.61 +#define NOTE_A5 880.00 +#define NOTE_AS5 932.33 +#define NOTE_B5 987.77 +#define NOTE_C6 1046.50 +#define NOTE_CS6 1108.73 +#define NOTE_D6 1174.66 +#define NOTE_DS6 1244.51 +#define NOTE_E6 1318.51 +#define NOTE_F6 1396.91 +#define NOTE_FS6 1479.98 +#define NOTE_G6 1567.98 +#define NOTE_GS6 1661.22 +#define NOTE_A6 1760.00 +#define NOTE_AS6 1864.66 +#define NOTE_B6 1975.53 +#define NOTE_C7 2093.00 +#define NOTE_CS7 2217.46 +#define NOTE_D7 2349.32 +#define NOTE_DS7 2489.02 +#define NOTE_E7 2637.02 +#define NOTE_F7 2793.83 +#define NOTE_FS7 2959.96 +#define NOTE_G7 3135.96 +#define NOTE_GS7 3322.44 +#define NOTE_A7 3520.00 +#define NOTE_AS7 3729.31 +#define NOTE_B7 3951.07 +#define NOTE_C8 4186.01 |