~ruther/qmk_firmware

83e1cc241e3aabd69f6cdcd2581477d4b85bb8d3 — IBNobody 9 years ago 2c07016
Clarified audio.c (#302)

* Updated personal layouts

* tweaked personal

* Nightly - Audio Cleanup

Refactored the LUTs. Abstracted some of the registers out of audio to
use more functional names. Split audio into audio and audio_pwm. WIP

* nightly - collapsed code

* Added check for note playing to LEDs
M keyboard/atomic/keymaps/pvc/config.h => keyboard/atomic/keymaps/pvc/config.h +5 -0
@@ 158,4 158,9 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
//#define NO_ACTION_MACRO
//#define NO_ACTION_FUNCTION


//#define VIBRATO_ENABLE
//#define VIBRATO_STRENGTH_ENABLE


#endif

M keyboard/atomic/keymaps/pvc/keymap.c => keyboard/atomic/keymaps/pvc/keymap.c +55 -52
@@ 11,8 11,8 @@
#define LAYER_QWERTY         0
#define LAYER_COLEMAK        1
#define LAYER_DVORAK         2
#define LAYER_LOWER          3
#define LAYER_RAISE          4
#define LAYER_RAISE          3
#define LAYER_LOWER          4
#define LAYER_FUNCTION       5
#define LAYER_MOUSE          6
#define LAYER_MUSIC          7


@@ 21,8 21,8 @@
#define MACRO_QWERTY         0
#define MACRO_COLEMAK        1
#define MACRO_DVORAK         2
#define MACRO_LOWER          3
#define MACRO_RAISE          4
#define MACRO_RAISE          3
#define MACRO_LOWER          4
#define MACRO_FUNCTION       5
#define MACRO_MOUSE          6
#define MACRO_TIMBRE_1       7


@@ 42,8 42,8 @@
#define M_QWRTY             M(MACRO_QWERTY)
#define M_COLMK             M(MACRO_COLEMAK)
#define M_DVORK             M(MACRO_DVORAK)
#define M_LOWER             M(MACRO_LOWER)
#define M_RAISE             M(MACRO_RAISE)
#define M_LOWER             M(MACRO_LOWER)
#define M_FUNCT             M(MACRO_FUNCTION)
#define M_MOUSE             M(MACRO_MOUSE)
#define TIMBR_1             M(MACRO_TIMBRE_1)


@@ 148,23 148,22 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
  { KC_LCTL, KC_LGUI, M_FUNCT, KC_LALT, M_RAISE, KC_SPC,  KC_SPC,  M_LOWER, KC_RALT, KC_RGUI, KC_MENU, KC_RCTL, KC_LEFT, KC_DOWN, KC_RGHT  },
 },

 [LAYER_RAISE]        = { /* RAISED */
  { KC_TILD, KC_PSCR, KC_PAUS, KC_F3,   KC_F4,   KC_F5,   KC_F6,   KC_F7,   KC_F8,   KC_F9,   KC_F10,  KC_F11,  KC_F12,  ________________  },
  { _______, KC_F1,   KC_F2,   KC_F3,   KC_F4,   _______, _______, _______, _______, _______, _______, _______, _______, _______, KC_INS   },
  { _______, KC_F5,   KC_F6,   KC_F7,   KC_F8,   _______, _______, _______, _______, _______, _______, _______, ________________, KC_HOME  },
  { _______, KC_F9,   KC_F10,  KC_F11,  KC_F12,  _______, _______, _______, _______, _______, _______, ________________, _______, KC_END   },
  { _______, _______, _______, _______, _______, ________________, _______, _______, _______, _______, _______, _______, _______, _______  },
 },

 [LAYER_LOWER]        = { /* LOWERED */
  { KC_GRV,  KC_F1,   KC_F2,   KC_F3,   KC_F4,   KC_F5,   KC_F6,   KC_F7,   KC_F8,   KC_F9,   KC_F10,  KC_F11,  KC_F12,  ________________  },
  { _______, _______, _______, _______, SC_CCLS, _______, _______, _______, _______, _______, _______, _______, _______, _______, KC_INS   },
  { _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, ________________, KC_HOME  },
  { _______, SC_REDO, _______, _______, _______, _______, _______, _______, _______, _______, _______, ________________, _______, KC_END   },
  { _______, KC_F13,  KC_F14,  KC_F15,  KC_F16,  _______, _______, _______, _______, _______, _______, _______, _______, _______, KC_INS   },
  { _______, KC_F17,  KC_F18,  KC_F19,  KC_F20,  _______, _______, _______, _______, _______, _______, _______, ________________, KC_HOME  },
  { _______, KC_F21,  KC_F22,  KC_F23,  KC_F24,  _______, _______, _______, _______, _______, _______, ________________, _______, KC_END   },
  { _______, _______, _______, _______, _______, KC_BSPC, KC_BSPC, _______, _______, _______, _______, _______, _______, _______, _______  },
 },

 [LAYER_RAISE]        = { /* RAISED */
  { KC_TILD, KC_F1,   KC_F2,   KC_F3,   KC_F4,   KC_F5,   KC_F6,   KC_F7,   KC_F8,   KC_F9,   KC_F10,  KC_F11,  KC_F12,  ________________  },
  { _______, _______, _______, _______, SC_ACLS, _______, _______, _______, _______, _______, _______, _______, _______, _______, KC_INS   },
  { _______, SC_SELA, SC_SAVE, _______, _______, _______, _______, _______, _______, _______, _______, _______, ________________, KC_HOME  },
  { _______, SC_UNDO, SC_CUT,  SC_COPY, SC_PSTE, _______, _______, _______, _______, _______, _______, ________________, _______, KC_END   },
  { _______, _______, _______, _______, _______, ________________, _______, _______, _______, _______, _______, _______, _______, _______  },
 },

 [LAYER_FUNCTION]     = { /* FUNCTION */
  { KC_NLCK, KC_F1,   KC_F2,   KC_F3,   KC_F4,   KC_F5,   KC_F6,   KC_F7,   KC_F8,   KC_F9,   KC_F10,  KC_F11,  KC_F12,  ________________  },
  { KC_SLCK, KC_F13,  KC_F14,  KC_F15,  KC_F16,  KC_F17,  KC_F18,  KC_F19,  KC_F20,  KC_F21,  KC_F22,  KC_F23,  KC_F24,  _______, KC_PAUS  },


@@ 281,28 280,28 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
            }
            break;

        case MACRO_LOWER:
        case MACRO_RAISE:
            if (record->event.pressed)
            {
                layer_on(LAYER_LOWER);
                layer_on(LAYER_RAISE);
                update_tri_layer(LAYER_LOWER, LAYER_RAISE, LAYER_ADJUST);
            }
            else
            {
                layer_off(LAYER_LOWER);
                layer_off(LAYER_RAISE);
                update_tri_layer(LAYER_LOWER, LAYER_RAISE, LAYER_ADJUST);
            }
            break;

        case MACRO_RAISE:
        case MACRO_LOWER:
            if (record->event.pressed)
            {
                layer_on(LAYER_RAISE);
                layer_on(LAYER_LOWER);
                update_tri_layer(LAYER_LOWER, LAYER_RAISE, LAYER_ADJUST);
            }
            else
            {
                layer_off(LAYER_RAISE);
                layer_off(LAYER_LOWER);
                update_tri_layer(LAYER_LOWER, LAYER_RAISE, LAYER_ADJUST);
            }
            break;


@@ 468,36 467,40 @@ void led_set_user(uint8_t usb_led)

    _delay_ms(10); // gets rid of tick

    if ((usb_led & (1<<USB_LED_CAPS_LOCK)) && !(old_usb_led & (1<<USB_LED_CAPS_LOCK)))
    {
            // If CAPS LK LED is turning on...
            PLAY_NOTE_ARRAY(tone_caps_on,  false, LEGATO);
    }
    else if (!(usb_led & (1<<USB_LED_CAPS_LOCK)) && (old_usb_led & (1<<USB_LED_CAPS_LOCK)))
    {
            // If CAPS LK LED is turning off...
            PLAY_NOTE_ARRAY(tone_caps_off, false, LEGATO);
    }
    else if ((usb_led & (1<<USB_LED_NUM_LOCK)) && !(old_usb_led & (1<<USB_LED_NUM_LOCK)))
    {
            // If NUM LK LED is turning on...
            PLAY_NOTE_ARRAY(tone_numlk_on,  false, LEGATO);
    }
    else if (!(usb_led & (1<<USB_LED_NUM_LOCK)) && (old_usb_led & (1<<USB_LED_NUM_LOCK)))
    {
            // If NUM LED is turning off...
            PLAY_NOTE_ARRAY(tone_numlk_off, false, LEGATO);
    }
    else if ((usb_led & (1<<USB_LED_SCROLL_LOCK)) && !(old_usb_led & (1<<USB_LED_SCROLL_LOCK)))
    {
            // If SCROLL LK LED is turning on...
            PLAY_NOTE_ARRAY(tone_scroll_on,  false, LEGATO);
    }
    else if (!(usb_led & (1<<USB_LED_SCROLL_LOCK)) && (old_usb_led & (1<<USB_LED_SCROLL_LOCK)))
    {
            // If SCROLL LED is turning off...
            PLAY_NOTE_ARRAY(tone_scroll_off, false, LEGATO);
    }
	if (!is_playing_notes())
	{
	    if ((usb_led & (1<<USB_LED_CAPS_LOCK)) && !(old_usb_led & (1<<USB_LED_CAPS_LOCK)))
	    {
	            // If CAPS LK LED is turning on...
	            PLAY_NOTE_ARRAY(tone_caps_on,  false, LEGATO);
	    }
	    else if (!(usb_led & (1<<USB_LED_CAPS_LOCK)) && (old_usb_led & (1<<USB_LED_CAPS_LOCK)))
	    {
	            // If CAPS LK LED is turning off...
	            PLAY_NOTE_ARRAY(tone_caps_off, false, LEGATO);
	    }
	    else if ((usb_led & (1<<USB_LED_NUM_LOCK)) && !(old_usb_led & (1<<USB_LED_NUM_LOCK)))
	    {
	            // If NUM LK LED is turning on...
	            PLAY_NOTE_ARRAY(tone_numlk_on,  false, LEGATO);
	    }
	    else if (!(usb_led & (1<<USB_LED_NUM_LOCK)) && (old_usb_led & (1<<USB_LED_NUM_LOCK)))
	    {
	            // If NUM LED is turning off...
	            PLAY_NOTE_ARRAY(tone_numlk_off, false, LEGATO);
	    }
	    else if ((usb_led & (1<<USB_LED_SCROLL_LOCK)) && !(old_usb_led & (1<<USB_LED_SCROLL_LOCK)))
	    {
	            // If SCROLL LK LED is turning on...
	            PLAY_NOTE_ARRAY(tone_scroll_on,  false, LEGATO);
	    }
	    else if (!(usb_led & (1<<USB_LED_SCROLL_LOCK)) && (old_usb_led & (1<<USB_LED_SCROLL_LOCK)))
	    {
	            // If SCROLL LED is turning off...
	            PLAY_NOTE_ARRAY(tone_scroll_off, false, LEGATO);
	    }
	}

    old_usb_led = usb_led;
}


M keyboard/planck/keymaps/pvc/config.h => keyboard/planck/keymaps/pvc/config.h +1 -1
@@ 73,7 73,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

/* disable debug print */
//#define NO_DEBUG
#define NO_DEBUG

/* disable print */
//#define NO_PRINT

M keyboard/planck/keymaps/pvc/keymap.c => keyboard/planck/keymaps/pvc/keymap.c +2 -2
@@ 96,7 96,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {

 [LAYER_QWERTY]       = { /* QWERTY */
  { KC_TAB,  KC_Q,    KC_W,    KC_E,    KC_R,    KC_T,    KC_Y,    KC_U,    KC_I,    KC_O,    KC_P,    KC_BSPC   },
  { KC_BSPC, KC_A,    KC_S,    KC_D,    KC_F,    KC_G,    KC_H,    KC_J,    KC_K,    KC_L,    KC_SCLN, KC_QUOT  },
  { KC_ESC,  KC_A,    KC_S,    KC_D,    KC_F,    KC_G,    KC_H,    KC_J,    KC_K,    KC_L,    KC_SCLN, KC_QUOT  },
  { KC_LSFT, KC_Z,    KC_X,    KC_C,    KC_V,    KC_B,    KC_N,    KC_M,    KC_COMM, KC_DOT,  KC_SLSH, KC_ENT   },
  { KC_LCTL, KC_LGUI, M_FUNCT, KC_LALT, M_RAISE, KC_SPC,  KC_SPC,  M_LOWER, KC_UP,   KC_DOWN, KC_LEFT, KC_RGHT  },
 },


@@ 115,7 115,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {

 [LAYER_COLEMAK]      = { /* COLEMAK */
  { KC_TAB,  KC_Q,    KC_W,    KC_F,    KC_P,    KC_G,    KC_J,    KC_L,    KC_U,    KC_Y,    KC_SCLN, KC_ESC   },
  { KC_ESC,  KC_A,    KC_R,    KC_S,    KC_T,    KC_D,    KC_H,    KC_N,    KC_E,    KC_I,    KC_O,    KC_QUOT  },
  { KC_BSPC, KC_A,    KC_R,    KC_S,    KC_T,    KC_D,    KC_H,    KC_N,    KC_E,    KC_I,    KC_O,    KC_QUOT  },
  { KC_LSFT, KC_Z,    KC_X,    KC_C,    KC_V,    KC_B,    KC_K,    KC_M,    KC_COMM, KC_DOT,  KC_SLSH, KC_ENT   },
  { KC_LCTL, KC_LGUI, M_FUNCT, KC_LALT, M_RAISE, KC_SPC,  KC_SPC,  M_LOWER, KC_UP,   KC_DOWN, KC_LEFT, KC_RGHT  },
 },

M keyboard/planck/keymaps/pvc/makefile.mk => keyboard/planck/keymaps/pvc/makefile.mk +2 -1
@@ 4,6 4,7 @@ EXTRAKEY_ENABLE  = yes # Audio control and System control(+450)
CONSOLE_ENABLE   = yes # Console for debug(+400)
COMMAND_ENABLE   = yes # Commands for debug and configuration
NKRO_ENABLE      = yes # Nkey Rollover - if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
BACKLIGHT_ENABLE = no  # Enable keyboard backlight functionality
MIDI_ENABLE      = no  # MIDI controls
AUDIO_ENABLE     = no  # Audio output on port C6
UNICODE_ENABLE   = no  # Unicode


@@ 13,4 14,4 @@ RGBLIGHT_ENABLE  = no  # Enable WS2812 RGB underlight.  Do not enable this with 
# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
SLEEP_LED_ENABLE = no  # Breathing sleep LED during USB suspend

CONFIG_H = keymaps/$(KEYMAP)/config.h
CONFIG_H = keymaps/$(KEYMAP)/config.h
\ No newline at end of file

M quantum/audio/audio.c => quantum/audio/audio.c +322 -444
@@ 1,6 1,6 @@
#include <stdio.h>
#include <string.h>
#include <math.h>
//#include <math.h>
#include <avr/pgmspace.h>
#include <avr/interrupt.h>
#include <avr/io.h>


@@ 10,30 10,28 @@

#include "eeconfig.h"

#ifdef VIBRATO_ENABLE
    #include "vibrato_lut.h"
#endif
#define CPU_PRESCALER 8

#define PI 3.14159265
// -----------------------------------------------------------------------------
// Timer Abstractions
// -----------------------------------------------------------------------------

#define CPU_PRESCALER 8
// TIMSK3 - Timer/Counter #3 Interrupt Mask Register
// Turn on/off 3A interputs, stopping/enabling the ISR calls
#define ENABLE_AUDIO_COUNTER_3_ISR TIMSK3 |= _BV(OCIE3A)
#define DISABLE_AUDIO_COUNTER_3_ISR TIMSK3 &= ~_BV(OCIE3A)

#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
// TCCR3A: Timer/Counter #3 Control Register
// Compare Output Mode (COM3An) = 0b00 = Normal port operation, OC3A disconnected from PC6
#define ENABLE_AUDIO_COUNTER_3_OUTPUT TCCR3A |= _BV(COM3A1);
#define DISABLE_AUDIO_COUNTER_3_OUTPUT TCCR3A &= ~(_BV(COM3A1) | _BV(COM3A0));

    float places[8] = {0, 0, 0, 0, 0, 0, 0, 0};
    uint16_t place_int = 0;
    bool repeat = true;
#endif
// Fast PWM Mode Controls
#define TIMER_3_PERIOD     ICR3
#define TIMER_3_DUTY_CYCLE OCR3A

// -----------------------------------------------------------------------------

void delay_us(int count) {
  while(count--) {
    _delay_us(1);
  }
}

int voices = 0;
int voice_place = 0;


@@ 45,26 43,23 @@ 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;

bool     playing_notes = false;
bool     playing_note = false;
float    note_frequency = 0;
float    note_length = 0;
uint8_t  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;
bool     notes_repeat;
float    notes_rest;
bool     note_resting = false;

uint8_t current_note = 0;
uint8_t rest_counter = 0;


@@ 77,175 72,65 @@ float vibrato_rate = 0.125;

float polyphony_rate = 0;

bool inited = false;
static bool audio_initialized = 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() {
void audio_init()
{

    /* check signature */
    if (!eeconfig_is_enabled()) {
    // Check EEPROM
    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 */
	// Set port PC6 (OC3A and /OC4A) as output
    DDRC |= _BV(PORTC6);

        /* 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;
    DISABLE_AUDIO_COUNTER_3_ISR;

        /* Enable the OC4A output */
        DDRC |= _BV(PORTC6);
	// TCCR3A / TCCR3B: Timer/Counter #3 Control Registers
	// Compare Output Mode (COM3An) = 0b00 = Normal port operation, OC3A disconnected from PC6
	// Waveform Generation Mode (WGM3n) = 0b1110 = Fast PWM Mode 14 (Period = ICR3, Duty Cycle = OCR3A)
	// Clock Select (CS3n) = 0b010 = Clock / 8
    TCCR3A = (0 << COM3A1) | (0 << COM3A0) | (1 << WGM31) | (0 << WGM30);
    TCCR3B = (1 << WGM33)  | (1 << WGM32)  | (0 << CS32)  | (1 << CS31) | (0 << CS30);

        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;
    audio_initialized = true;
}

void stop_all_notes() {
    if (!inited) {
void stop_all_notes()
{
    if (!audio_initialized) {
        audio_init();
    }
    voices = 0;
    #ifdef PWM_AUDIO
        TIMSK3 &= ~_BV(OCIE3A);
    #else
        TIMSK3 &= ~_BV(OCIE3A);
        TCCR3A &= ~_BV(COM3A1);
    #endif
    notes = false;
    note = false;

    DISABLE_AUDIO_COUNTER_3_ISR;
    DISABLE_AUDIO_COUNTER_3_OUTPUT;

    playing_notes = false;
    playing_note = false;
    frequency = 0;
    volume = 0;

    for (int i = 0; i < 8; i++) {
    for (uint8_t i = 0; i < 8; i++)
    {
        frequencies[i] = 0;
        volumes[i] = 0;
    }
}

void stop_note(float freq) {
    if (note) {
        if (!inited) {
void stop_note(float freq)
{
    if (playing_note) {
        if (!audio_initialized) {
            audio_init();
        }
        #ifdef PWM_AUDIO
            freq = freq / SAMPLE_RATE;
        #endif
        for (int i = 7; i >= 0; i--) {
            if (frequencies[i] == freq) {
                frequencies[i] = 0;


@@ 266,15 151,11 @@ void stop_note(float freq) {
            voice_place = 0;
        }
        if (voices == 0) {
            #ifdef PWM_AUDIO
                TIMSK3 &= ~_BV(OCIE3A);
            #else
                TIMSK3 &= ~_BV(OCIE3A);
                TCCR3A &= ~_BV(COM3A1);
            #endif
            DISABLE_AUDIO_COUNTER_3_ISR;
            DISABLE_AUDIO_COUNTER_3_OUTPUT;
            frequency = 0;
            volume = 0;
            note = false;
            playing_note = false;
        }
    }
}


@@ 289,9 170,9 @@ float mod(float a, int b)

float vibrato(float average_freq) {
    #ifdef VIBRATO_STRENGTH_ENABLE
        float vibrated_freq = average_freq * pow(VIBRATO_LUT[(int)vibrato_counter], vibrato_strength);
        float vibrated_freq = average_freq * pow(vibrato_lut[(int)vibrato_counter], vibrato_strength);
    #else
        float vibrated_freq = average_freq * VIBRATO_LUT[(int)vibrato_counter];
        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;


@@ 299,295 180,295 @@ float vibrato(float average_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;
                    } 
                }
ISR(TIMER3_COMPA_vect)
{
	float freq;

	if (playing_note) {
		if (voices > 0) {
			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 {
						freq = frequencies[voice_place];
					}
				#else
					freq = frequencies[voice_place];
				#endif
			} 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 {
						freq = frequency;
					}
				#else
					freq = frequency;
				#endif
			}

			if (envelope_index < 65535) {
				envelope_index++;
			}

			freq = voice_envelope(freq);

			if (freq < 30.517578125) {
				freq = 30.52;
			}

			TIMER_3_PERIOD = (uint16_t)(((float)F_CPU) / (freq * CPU_PRESCALER));
			TIMER_3_DUTY_CYCLE = (uint16_t)((((float)F_CPU) / (freq * CPU_PRESCALER)) * note_timbre);
		}
	}

	if (playing_notes) {
		if (note_frequency > 0) {
			#ifdef VIBRATO_ENABLE
				if (vibrato_strength > 0) {
					freq = vibrato(note_frequency);
				} else {
					freq = note_frequency;
				}
			#else
					freq = note_frequency;
			#endif

			if (envelope_index < 65535) {
				envelope_index++;
			}
			freq = voice_envelope(freq);

			TIMER_3_PERIOD = (uint16_t)(((float)F_CPU) / (freq * CPU_PRESCALER));
			TIMER_3_DUTY_CYCLE = (uint16_t)((((float)F_CPU) / (freq * CPU_PRESCALER)) * note_timbre);
		} else {
			TIMER_3_PERIOD = 0;
			TIMER_3_DUTY_CYCLE = 0;
		}

		note_position++;
		bool end_of_note = false;
		if (TIMER_3_PERIOD > 0) {
			end_of_note = (note_position >= (note_length / TIMER_3_PERIOD * 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 {
					DISABLE_AUDIO_COUNTER_3_ISR;
					DISABLE_AUDIO_COUNTER_3_OUTPUT;
					playing_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;
				envelope_index = 0;
				note_frequency = (*notes_pointer)[current_note][0];
				note_length = ((*notes_pointer)[current_note][1] / 4) * (((float)note_tempo) / 100);
			}

			note_position = 0;
		}
	}

	if (!audio_config.enable) {
		playing_notes = false;
		playing_note = false;
	}
}

                if (envelope_index < 65535) {
                    envelope_index++;
                }
                freq = voice_envelope(freq);
void play_note(float freq, int vol) {

                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
    if (!audio_initialized) {
        audio_init();
    }

    // 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 (audio_config.enable && voices < 8) {
	    DISABLE_AUDIO_COUNTER_3_ISR;

                if (envelope_index < 65535) {
                    envelope_index++;
                }
                freq = voice_envelope(freq);
	    // Cancel notes if notes are playing
	    if (playing_notes)
	        stop_all_notes();

                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;
        }
	    playing_note = true;

    }
	    envelope_index = 0;

	    if (freq > 0) {
	        frequencies[voices] = freq;
	        volumes[voices] = vol;
	        voices++;
	    }

        ENABLE_AUDIO_COUNTER_3_ISR;
        ENABLE_AUDIO_COUNTER_3_OUTPUT;
	}

    if (!audio_config.enable) {
        notes = false;
        note = false;
    }
}

void play_note(float freq, int vol) {
void play_notes(float (*np)[][2], uint16_t n_count, bool n_repeat, float n_rest)
{

    if (!inited) {
    if (!audio_initialized) {
        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++;
    }
	if (audio_config.enable) {

	    DISABLE_AUDIO_COUNTER_3_ISR;

		// Cancel note if a note is playing
	    if (playing_note)
	        stop_all_notes();

	    playing_notes = true;

	    notes_pointer = np;
	    notes_count = n_count;
	    notes_repeat = n_repeat;
	    notes_rest = n_rest;

	    place = 0;
	    current_note = 0;

        note_frequency = (*notes_pointer)[current_note][0];
        note_length = ((*notes_pointer)[current_note][1] / 4) * (((float)note_tempo) / 100);
	    note_position = 0;


        ENABLE_AUDIO_COUNTER_3_ISR;
        ENABLE_AUDIO_COUNTER_3_OUTPUT;
	}

    #ifdef PWM_AUDIO
        TIMSK3 |= _BV(OCIE3A);
    #else
        TIMSK3 |= _BV(OCIE3A);
        TCCR3A |= _BV(COM3A1);
    #endif
}

bool is_playing_notes(void) {
	return playing_notes;
}

void play_notes(float (*np)[][2], uint16_t n_count, bool n_repeat, float n_rest) {
void audio_toggle(void) {
    audio_config.enable ^= 1;
    eeconfig_update_audio(audio_config.raw);
}

    if (!inited) {
        audio_init();
    }
void audio_on(void) {
    audio_config.enable = 1;
    eeconfig_update_audio(audio_config.raw);
}

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;
void audio_off(void) {
    audio_config.enable = 0;
    eeconfig_update_audio(audio_config.raw);
}

#ifdef VIBRATO_ENABLE

    #ifdef PWM_AUDIO
        TIMSK3 |= _BV(OCIE3A);
    #else
        TIMSK3 |= _BV(OCIE3A);
        TCCR3A |= _BV(COM3A1);
    #endif
// Vibrato rate functions

void set_vibrato_rate(float rate) {
    vibrato_rate = rate;
}

void increase_vibrato_rate(float change) {
    vibrato_rate *= change;
}

#ifdef PWM_AUDIO
void play_sample(uint8_t * s, uint16_t l, bool r) {
    if (!inited) {
        audio_init();
    }
void decrease_vibrato_rate(float change) {
    vibrato_rate /= change;
}

    if (audio_config.enable) {
        TIMSK3 &= ~_BV(OCIE3A);
        stop_all_notes();
        place_int = 0;
        sample = s;
        sample_length = l;
        repeat = r;
#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  /* VIBRATO_STRENGTH_ENABLE */

#endif /* VIBRATO_ENABLE */

        TIMSK3 |= _BV(OCIE3A);
// 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(uint8_t tempo) {
    note_tempo = tempo;
}

void decrease_tempo(uint8_t tempo_change) {
    note_tempo += tempo_change;
}

void increase_tempo(uint8_t tempo_change) {
    if (note_tempo - tempo_change < 10) {
        note_tempo = 10;
    } else {
        note_tempo -= tempo_change;
    }
}
#endif


//------------------------------------------------------------------------------
// Override these functions in your keymap file to play different tunes on


@@ 597,11 478,8 @@ void play_startup_tone()
{
}



__attribute__ ((weak))
void play_goodbye_tone()
{

}
//------------------------------------------------------------------------------

M quantum/audio/audio.h => quantum/audio/audio.h +5 -1
@@ 56,7 56,7 @@ void increase_polyphony_rate(float change);
void decrease_polyphony_rate(float change);

void set_timbre(float timbre);
void set_tempo(float tempo);
void set_tempo(uint8_t tempo);

void increase_tempo(uint8_t tempo_change);
void decrease_tempo(uint8_t tempo_change);


@@ 83,7 83,11 @@ void play_notes(float (*np)[][2], uint16_t n_count, bool n_repeat, float n_rest)
#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(&note_array, NOTE_ARRAY_SIZE((note_array)), (note_repeat), (note_rest_style));


bool is_playing_notes(void);
void play_goodbye_tone(void);
void play_startup_tone(void);



#endif
\ No newline at end of file

A quantum/audio/audio_pwm.c => quantum/audio/audio_pwm.c +643 -0
@@ 0,0 1,643 @@
#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"

#define PI 3.14159265

#define CPU_PRESCALER 8


// Timer Abstractions

// TIMSK3 - Timer/Counter #3 Interrupt Mask Register
// Turn on/off 3A interputs, stopping/enabling the ISR calls
#define ENABLE_AUDIO_COUNTER_3_ISR TIMSK3 |= _BV(OCIE3A)
#define DISABLE_AUDIO_COUNTER_3_ISR TIMSK3 &= ~_BV(OCIE3A)


// TCCR3A: Timer/Counter #3 Control Register
// Compare Output Mode (COM3An) = 0b00 = Normal port operation, OC3A disconnected from PC6
#define ENABLE_AUDIO_COUNTER_3_OUTPUT TCCR3A |= _BV(COM3A1);
#define DISABLE_AUDIO_COUNTER_3_OUTPUT TCCR3A &= ~(_BV(COM3A1) | _BV(COM3A0));


#define NOTE_PERIOD ICR3
#define NOTE_DUTY_CYCLE OCR3A


#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;

float place = 0;

uint8_t * sample;
uint16_t sample_length = 0;
// float freq = 0;

bool     playing_notes = false;
bool     playing_note = false;
float    note_frequency = 0;
float    note_length = 0;
uint8_t  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;

static bool audio_initialized = false;

audio_config_t audio_config;

uint16_t envelope_index = 0;

void audio_init() {

    // Check EEPROM
    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);

        DISABLE_AUDIO_COUNTER_3_ISR; // 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

    	// Set port PC6 (OC3A and /OC4A) as output
        DDRC |= _BV(PORTC6);

        DISABLE_AUDIO_COUNTER_3_ISR;

		// TCCR3A / TCCR3B: Timer/Counter #3 Control Registers
		// Compare Output Mode (COM3An) = 0b00 = Normal port operation, OC3A disconnected from PC6
		// Waveform Generation Mode (WGM3n) = 0b1110 = Fast PWM Mode 14 (Period = ICR3, Duty Cycle = OCR3A)
		// Clock Select (CS3n) = 0b010 = Clock / 8
        TCCR3A = (0 << COM3A1) | (0 << COM3A0) | (1 << WGM31) | (0 << WGM30);
        TCCR3B = (1 << WGM33)  | (1 << WGM32)  | (0 << CS32)  | (1 << CS31) | (0 << CS30);

    #endif

    audio_initialized = true;
}

void stop_all_notes() {
    if (!audio_initialized) {
        audio_init();
    }
    voices = 0;
    #ifdef PWM_AUDIO
	    DISABLE_AUDIO_COUNTER_3_ISR;
    #else
        DISABLE_AUDIO_COUNTER_3_ISR;
        DISABLE_AUDIO_COUNTER_3_OUTPUT;
    #endif

    playing_notes = false;
    playing_note = false;
    frequency = 0;
    volume = 0;

    for (uint8_t i = 0; i < 8; i++)
    {
        frequencies[i] = 0;
        volumes[i] = 0;
    }
}

void stop_note(float freq)
{
    if (playing_note) {
        if (!audio_initialized) {
            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
                DISABLE_AUDIO_COUNTER_3_ISR;
            #else
                DISABLE_AUDIO_COUNTER_3_ISR;
                DISABLE_AUDIO_COUNTER_3_OUTPUT;
            #endif
            frequency = 0;
            volume = 0;
            playing_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 (playing_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;
                NOTE_PERIOD = (int)(((double)F_CPU) / (freq * CPU_PRESCALER)); // Set max to the period
                NOTE_DUTY_CYCLE = (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
    //         DISABLE_AUDIO_COUNTER_3_ISR;


    if (playing_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);

                NOTE_PERIOD = (int)(((double)F_CPU) / (freq * CPU_PRESCALER)); // Set max to the period
                NOTE_DUTY_CYCLE = (int)((((double)F_CPU) / (freq * CPU_PRESCALER)) * note_timbre); // Set compare to half the period
            } else {
                NOTE_PERIOD = 0;
                NOTE_DUTY_CYCLE = 0;
            }
        #endif


        note_position++;
        bool end_of_note = false;
        if (NOTE_PERIOD > 0)
            end_of_note = (note_position >= (note_length / NOTE_PERIOD * 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
                        DISABLE_AUDIO_COUNTER_3_ISR;
                    #else
                        DISABLE_AUDIO_COUNTER_3_ISR;
                        DISABLE_AUDIO_COUNTER_3_OUTPUT;
                    #endif
                    playing_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] * (((float)note_tempo) / 100);
                #else
                    envelope_index = 0;
                    note_frequency = (*notes_pointer)[current_note][0];
                    note_length = ((*notes_pointer)[current_note][1] / 4) * (((float)note_tempo) / 100);
                #endif
            }
            note_position = 0;
        }

    }

    if (!audio_config.enable) {
        playing_notes = false;
        playing_note = false;
    }
}

void play_note(float freq, int vol) {

    if (!audio_initialized) {
        audio_init();
    }

	if (audio_config.enable && voices < 8) {
	    DISABLE_AUDIO_COUNTER_3_ISR;

	    // Cancel notes if notes are playing
	    if (playing_notes)
	        stop_all_notes();

	    playing_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
	        ENABLE_AUDIO_COUNTER_3_ISR;
	    #else
	        ENABLE_AUDIO_COUNTER_3_ISR;
	        ENABLE_AUDIO_COUNTER_3_OUTPUT;
	    #endif
	}

}

void play_notes(float (*np)[][2], uint16_t n_count, bool n_repeat, float n_rest)
{

    if (!audio_initialized) {
        audio_init();
    }

	if (audio_config.enable) {

	    DISABLE_AUDIO_COUNTER_3_ISR;

		// Cancel note if a note is playing
	    if (playing_note)
	        stop_all_notes();

	    playing_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] * (((float)note_tempo) / 100);
	    #else
	        note_frequency = (*notes_pointer)[current_note][0];
	        note_length = ((*notes_pointer)[current_note][1] / 4) * (((float)note_tempo) / 100);
	    #endif
	    note_position = 0;


	    #ifdef PWM_AUDIO
	        ENABLE_AUDIO_COUNTER_3_ISR;
	    #else
	        ENABLE_AUDIO_COUNTER_3_ISR;
	        ENABLE_AUDIO_COUNTER_3_OUTPUT;
	    #endif
	}

}

#ifdef PWM_AUDIO
void play_sample(uint8_t * s, uint16_t l, bool r) {
    if (!audio_initialized) {
        audio_init();
    }

    if (audio_config.enable) {
        DISABLE_AUDIO_COUNTER_3_ISR;
        stop_all_notes();
        place_int = 0;
        sample = s;
        sample_length = l;
        repeat = r;

        ENABLE_AUDIO_COUNTER_3_ISR;
    }
}
#endif


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  /* VIBRATO_STRENGTH_ENABLE */

#endif /* VIBRATO_ENABLE */

// 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(uint8_t tempo) {
    note_tempo = tempo;
}

void decrease_tempo(uint8_t tempo_change) {
    note_tempo += tempo_change;
}

void increase_tempo(uint8_t tempo_change) {
    if (note_tempo - tempo_change < 10) {
        note_tempo = 10;
    } else {
        note_tempo -= tempo_change;
    }
}


//------------------------------------------------------------------------------
// 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()
{
}
//------------------------------------------------------------------------------

R quantum/audio/frequency_lut.h => quantum/audio/luts.c +377 -352
@@ 1,357 1,382 @@
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include "luts.h"

#define FREQUENCY_LUT_LENGTH 349
const float vibrato_lut[VIBRATO_LUT_LENGTH] =
{
	1.0022336811487,
	1.0042529943610,
	1.0058584256028,
	1.0068905285205,
	1.0072464122237,
	1.0068905285205,
	1.0058584256028,
	1.0042529943610,
	1.0022336811487,
	1.0000000000000,
	0.9977712970630,
	0.9957650169978,
	0.9941756956510,
	0.9931566259436,
	0.9928057204913,
	0.9931566259436,
	0.9941756956510,
	0.9957650169978,
	0.9977712970630,
	1.0000000000000,
};

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,
};

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

A quantum/audio/luts.h => quantum/audio/luts.h +15 -0
@@ 0,0 1,15 @@
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>

#ifndef LUTS_H
#define LUTS_H

#define VIBRATO_LUT_LENGTH 20

#define FREQUENCY_LUT_LENGTH 349

extern const float vibrato_lut[VIBRATO_LUT_LENGTH];
extern const uint16_t frequency_lut[FREQUENCY_LUT_LENGTH];

#endif /* LUTS_H */
\ No newline at end of file

D quantum/audio/vibrato_lut.h => quantum/audio/vibrato_lut.h +0 -28
@@ 1,28 0,0 @@
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>

#define VIBRATO_LUT_LENGTH 20

const float VIBRATO_LUT[VIBRATO_LUT_LENGTH] = { \
1.00223368114872,
1.00425299436105,
1.00585842560279,
1.00689052852052,
1.0072464122237,
1.00689052852052,
1.00585842560279,
1.00425299436105,
1.00223368114872,
1,
0.99777129706302,
0.99576501699778,
0.994175695650927,
0.993156625943589,
0.992805720491269,
0.993156625943589,
0.994175695650927,
0.99576501699778,
0.99777129706302,
1
};
\ No newline at end of file

M quantum/audio/voices.c => quantum/audio/voices.c +5 -3
@@ 1,6 1,6 @@
#include "voices.h"
#include "audio.h"
#include "stdlib.h"
#include "vibrato_lut.h"

// these are imported from audio.c
extern uint16_t envelope_index;


@@ 109,7 109,7 @@ float voice_envelope(float frequency) {
                case 0 ... VOICE_VIBRATO_DELAY:
                    break;
                default:
                    frequency = frequency * VIBRATO_LUT[(int)fmod((((float)compensated_index - (VOICE_VIBRATO_DELAY + 1))/1000*VOICE_VIBRATO_SPEED), VIBRATO_LUT_LENGTH)];
                    frequency = frequency * vibrato_lut[(int)fmod((((float)compensated_index - (VOICE_VIBRATO_DELAY + 1))/1000*VOICE_VIBRATO_SPEED), VIBRATO_LUT_LENGTH)];
                    break;
            }
            break;


@@ 160,4 160,6 @@ float voice_envelope(float frequency) {
    }

    return frequency;
}
\ No newline at end of file
}



M quantum/audio/voices.h => quantum/audio/voices.h +1 -2
@@ 2,8 2,7 @@
#include <stdbool.h>
#include <avr/io.h>
#include <util/delay.h>
#include "musical_notes.h"
#include "song_list.h"
#include "luts.h"

#ifndef VOICES_H
#define VOICES_H

M quantum/keymap_common.c => quantum/keymap_common.c +5 -1
@@ 24,10 24,14 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
#include "action_macro.h"
#include "debug.h"
#include "backlight.h"
#include "keymap_midi.h"
#include "bootloader.h"
#include "eeconfig.h"

#ifdef MIDI_ENABLE
	#include "keymap_midi.h"
#endif


extern keymap_config_t keymap_config;

#include <stdio.h>

M quantum/quantum.mk => quantum/quantum.mk +1 -0
@@ 29,6 29,7 @@ endif

ifeq ($(strip $(AUDIO_ENABLE)), yes)
	SRC += $(QUANTUM_DIR)/audio/audio.c $(QUANTUM_DIR)/audio/voices.c
	SRC += $(QUANTUM_DIR)/audio/audio.c $(QUANTUM_DIR)/audio/luts.c
endif

ifeq ($(strip $(UNICODE_ENABLE)), yes)