mirror of
				https://github.com/mfulz/qmk_firmware.git
				synced 2025-10-31 05:12:33 +01:00 
			
		
		
		
	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
This commit is contained in:
		
							parent
							
								
									2c070163ff
								
							
						
					
					
						commit
						83e1cc241e
					
				| @ -158,4 +158,9 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>. | |||||||
| //#define NO_ACTION_MACRO
 | //#define NO_ACTION_MACRO
 | ||||||
| //#define NO_ACTION_FUNCTION
 | //#define NO_ACTION_FUNCTION
 | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
|  | //#define VIBRATO_ENABLE
 | ||||||
|  | //#define VIBRATO_STRENGTH_ENABLE
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| #endif | #endif | ||||||
|  | |||||||
| @ -11,8 +11,8 @@ | |||||||
| #define LAYER_QWERTY         0 | #define LAYER_QWERTY         0 | ||||||
| #define LAYER_COLEMAK        1 | #define LAYER_COLEMAK        1 | ||||||
| #define LAYER_DVORAK         2 | #define LAYER_DVORAK         2 | ||||||
| #define LAYER_LOWER          3 | #define LAYER_RAISE          3 | ||||||
| #define LAYER_RAISE          4 | #define LAYER_LOWER          4 | ||||||
| #define LAYER_FUNCTION       5 | #define LAYER_FUNCTION       5 | ||||||
| #define LAYER_MOUSE          6 | #define LAYER_MOUSE          6 | ||||||
| #define LAYER_MUSIC          7 | #define LAYER_MUSIC          7 | ||||||
| @ -21,8 +21,8 @@ | |||||||
| #define MACRO_QWERTY         0 | #define MACRO_QWERTY         0 | ||||||
| #define MACRO_COLEMAK        1 | #define MACRO_COLEMAK        1 | ||||||
| #define MACRO_DVORAK         2 | #define MACRO_DVORAK         2 | ||||||
| #define MACRO_LOWER          3 | #define MACRO_RAISE          3 | ||||||
| #define MACRO_RAISE          4 | #define MACRO_LOWER          4 | ||||||
| #define MACRO_FUNCTION       5 | #define MACRO_FUNCTION       5 | ||||||
| #define MACRO_MOUSE          6 | #define MACRO_MOUSE          6 | ||||||
| #define MACRO_TIMBRE_1       7 | #define MACRO_TIMBRE_1       7 | ||||||
| @ -42,8 +42,8 @@ | |||||||
| #define M_QWRTY             M(MACRO_QWERTY) | #define M_QWRTY             M(MACRO_QWERTY) | ||||||
| #define M_COLMK             M(MACRO_COLEMAK) | #define M_COLMK             M(MACRO_COLEMAK) | ||||||
| #define M_DVORK             M(MACRO_DVORAK) | #define M_DVORK             M(MACRO_DVORAK) | ||||||
| #define M_LOWER             M(MACRO_LOWER) |  | ||||||
| #define M_RAISE             M(MACRO_RAISE) | #define M_RAISE             M(MACRO_RAISE) | ||||||
|  | #define M_LOWER             M(MACRO_LOWER) | ||||||
| #define M_FUNCT             M(MACRO_FUNCTION) | #define M_FUNCT             M(MACRO_FUNCTION) | ||||||
| #define M_MOUSE             M(MACRO_MOUSE) | #define M_MOUSE             M(MACRO_MOUSE) | ||||||
| #define TIMBR_1             M(MACRO_TIMBRE_1) | #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  }, |   { 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 */ |  [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,  ________________  }, |   { 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_F13,  KC_F14,  KC_F15,  KC_F16,  _______, _______, _______, _______, _______, _______, _______, _______, _______, KC_INS   }, | ||||||
|   { _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, ________________, KC_HOME  }, |   { _______, KC_F17,  KC_F18,  KC_F19,  KC_F20,  _______, _______, _______, _______, _______, _______, _______, ________________, KC_HOME  }, | ||||||
|   { _______, SC_REDO, _______, _______, _______, _______, _______, _______, _______, _______, _______, ________________, _______, KC_END   }, |   { _______, KC_F21,  KC_F22,  KC_F23,  KC_F24,  _______, _______, _______, _______, _______, _______, ________________, _______, KC_END   }, | ||||||
|   { _______, _______, _______, _______, _______, KC_BSPC, KC_BSPC, _______, _______, _______, _______, _______, _______, _______, _______  }, |   { _______, _______, _______, _______, _______, 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 */ |  [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_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  }, |   { 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,19 +280,6 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) | |||||||
|             } |             } | ||||||
|             break; |             break; | ||||||
| 
 | 
 | ||||||
|         case MACRO_LOWER: |  | ||||||
|             if (record->event.pressed) |  | ||||||
|             { |  | ||||||
|                 layer_on(LAYER_LOWER); |  | ||||||
|                 update_tri_layer(LAYER_LOWER, LAYER_RAISE, LAYER_ADJUST); |  | ||||||
|             } |  | ||||||
|             else |  | ||||||
|             { |  | ||||||
|                 layer_off(LAYER_LOWER); |  | ||||||
|                 update_tri_layer(LAYER_LOWER, LAYER_RAISE, LAYER_ADJUST); |  | ||||||
|             } |  | ||||||
|             break; |  | ||||||
| 
 |  | ||||||
|         case MACRO_RAISE: |         case MACRO_RAISE: | ||||||
|             if (record->event.pressed) |             if (record->event.pressed) | ||||||
|             { |             { | ||||||
| @ -307,6 +293,19 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) | |||||||
|             } |             } | ||||||
|             break; |             break; | ||||||
| 
 | 
 | ||||||
|  |         case MACRO_LOWER: | ||||||
|  |             if (record->event.pressed) | ||||||
|  |             { | ||||||
|  |                 layer_on(LAYER_LOWER); | ||||||
|  |                 update_tri_layer(LAYER_LOWER, LAYER_RAISE, LAYER_ADJUST); | ||||||
|  |             } | ||||||
|  |             else | ||||||
|  |             { | ||||||
|  |                 layer_off(LAYER_LOWER); | ||||||
|  |                 update_tri_layer(LAYER_LOWER, LAYER_RAISE, LAYER_ADJUST); | ||||||
|  |             } | ||||||
|  |             break; | ||||||
|  | 
 | ||||||
|         case MACRO_FUNCTION: |         case MACRO_FUNCTION: | ||||||
|             if (record->event.pressed) |             if (record->event.pressed) | ||||||
|             { |             { | ||||||
| @ -468,36 +467,40 @@ void led_set_user(uint8_t usb_led) | |||||||
| 
 | 
 | ||||||
|     _delay_ms(10); // gets rid of tick
 |     _delay_ms(10); // gets rid of tick
 | ||||||
| 
 | 
 | ||||||
|     if ((usb_led & (1<<USB_LED_CAPS_LOCK)) && !(old_usb_led & (1<<USB_LED_CAPS_LOCK))) | 	if (!is_playing_notes()) | ||||||
|     { | 	{ | ||||||
|             // If CAPS LK LED is turning on...
 | 	    if ((usb_led & (1<<USB_LED_CAPS_LOCK)) && !(old_usb_led & (1<<USB_LED_CAPS_LOCK))) | ||||||
|             PLAY_NOTE_ARRAY(tone_caps_on,  false, LEGATO); | 	    { | ||||||
|     } | 	            // If CAPS LK LED is turning on...
 | ||||||
|     else if (!(usb_led & (1<<USB_LED_CAPS_LOCK)) && (old_usb_led & (1<<USB_LED_CAPS_LOCK))) | 	            PLAY_NOTE_ARRAY(tone_caps_on,  false, LEGATO); | ||||||
|     { | 	    } | ||||||
|             // If CAPS LK LED is turning off...
 | 	    else if (!(usb_led & (1<<USB_LED_CAPS_LOCK)) && (old_usb_led & (1<<USB_LED_CAPS_LOCK))) | ||||||
|             PLAY_NOTE_ARRAY(tone_caps_off, false, LEGATO); | 	    { | ||||||
|     } | 	            // If CAPS LK LED is turning off...
 | ||||||
|     else if ((usb_led & (1<<USB_LED_NUM_LOCK)) && !(old_usb_led & (1<<USB_LED_NUM_LOCK))) | 	            PLAY_NOTE_ARRAY(tone_caps_off, false, LEGATO); | ||||||
|     { | 	    } | ||||||
|             // If NUM LK LED is turning on...
 | 	    else if ((usb_led & (1<<USB_LED_NUM_LOCK)) && !(old_usb_led & (1<<USB_LED_NUM_LOCK))) | ||||||
|             PLAY_NOTE_ARRAY(tone_numlk_on,  false, LEGATO); | 	    { | ||||||
|     } | 	            // If NUM LK LED is turning on...
 | ||||||
|     else if (!(usb_led & (1<<USB_LED_NUM_LOCK)) && (old_usb_led & (1<<USB_LED_NUM_LOCK))) | 	            PLAY_NOTE_ARRAY(tone_numlk_on,  false, LEGATO); | ||||||
|     { | 	    } | ||||||
|             // If NUM LED is turning off...
 | 	    else if (!(usb_led & (1<<USB_LED_NUM_LOCK)) && (old_usb_led & (1<<USB_LED_NUM_LOCK))) | ||||||
|             PLAY_NOTE_ARRAY(tone_numlk_off, false, LEGATO); | 	    { | ||||||
|     } | 	            // If NUM LED is turning off...
 | ||||||
|     else if ((usb_led & (1<<USB_LED_SCROLL_LOCK)) && !(old_usb_led & (1<<USB_LED_SCROLL_LOCK))) | 	            PLAY_NOTE_ARRAY(tone_numlk_off, false, LEGATO); | ||||||
|     { | 	    } | ||||||
|             // If SCROLL LK LED is turning on...
 | 	    else if ((usb_led & (1<<USB_LED_SCROLL_LOCK)) && !(old_usb_led & (1<<USB_LED_SCROLL_LOCK))) | ||||||
|             PLAY_NOTE_ARRAY(tone_scroll_on,  false, LEGATO); | 	    { | ||||||
|     } | 	            // If SCROLL LK LED is turning on...
 | ||||||
|     else if (!(usb_led & (1<<USB_LED_SCROLL_LOCK)) && (old_usb_led & (1<<USB_LED_SCROLL_LOCK))) | 	            PLAY_NOTE_ARRAY(tone_scroll_on,  false, LEGATO); | ||||||
|     { | 	    } | ||||||
|             // If SCROLL LED is turning off...
 | 	    else if (!(usb_led & (1<<USB_LED_SCROLL_LOCK)) && (old_usb_led & (1<<USB_LED_SCROLL_LOCK))) | ||||||
|             PLAY_NOTE_ARRAY(tone_scroll_off, false, LEGATO); | 	    { | ||||||
|     } | 	            // If SCROLL LED is turning off...
 | ||||||
|  | 	            PLAY_NOTE_ARRAY(tone_scroll_off, false, LEGATO); | ||||||
|  | 	    } | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|     old_usb_led = usb_led; |     old_usb_led = usb_led; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -73,7 +73,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>. | |||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| /* disable debug print */ | /* disable debug print */ | ||||||
| //#define NO_DEBUG
 | #define NO_DEBUG | ||||||
| 
 | 
 | ||||||
| /* disable print */ | /* disable print */ | ||||||
| //#define NO_PRINT
 | //#define NO_PRINT
 | ||||||
|  | |||||||
| @ -96,7 +96,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { | |||||||
| 
 | 
 | ||||||
|  [LAYER_QWERTY]       = { /* QWERTY */ |  [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_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_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  }, |   { 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 */ |  [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_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_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  }, |   { KC_LCTL, KC_LGUI, M_FUNCT, KC_LALT, M_RAISE, KC_SPC,  KC_SPC,  M_LOWER, KC_UP,   KC_DOWN, KC_LEFT, KC_RGHT  }, | ||||||
|  }, |  }, | ||||||
|  | |||||||
| @ -4,6 +4,7 @@ EXTRAKEY_ENABLE  = yes # Audio control and System control(+450) | |||||||
| CONSOLE_ENABLE   = yes # Console for debug(+400) | CONSOLE_ENABLE   = yes # Console for debug(+400) | ||||||
| COMMAND_ENABLE   = yes # Commands for debug and configuration | 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 | 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 | MIDI_ENABLE      = no  # MIDI controls | ||||||
| AUDIO_ENABLE     = no  # Audio output on port C6 | AUDIO_ENABLE     = no  # Audio output on port C6 | ||||||
| UNICODE_ENABLE   = no  # Unicode | UNICODE_ENABLE   = no  # Unicode | ||||||
|  | |||||||
| @ -1,6 +1,6 @@ | |||||||
| #include <stdio.h> | #include <stdio.h> | ||||||
| #include <string.h> | #include <string.h> | ||||||
| #include <math.h> | //#include <math.h>
 | ||||||
| #include <avr/pgmspace.h> | #include <avr/pgmspace.h> | ||||||
| #include <avr/interrupt.h> | #include <avr/interrupt.h> | ||||||
| #include <avr/io.h> | #include <avr/io.h> | ||||||
| @ -10,30 +10,28 @@ | |||||||
| 
 | 
 | ||||||
| #include "eeconfig.h" | #include "eeconfig.h" | ||||||
| 
 | 
 | ||||||
| #ifdef VIBRATO_ENABLE |  | ||||||
|     #include "vibrato_lut.h" |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
| #define PI 3.14159265 |  | ||||||
| 
 |  | ||||||
| #define CPU_PRESCALER 8 | #define CPU_PRESCALER 8 | ||||||
| 
 | 
 | ||||||
| #ifdef PWM_AUDIO | // -----------------------------------------------------------------------------
 | ||||||
|     #include "wave.h" | // Timer Abstractions
 | ||||||
|     #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}; | // TIMSK3 - Timer/Counter #3 Interrupt Mask Register
 | ||||||
|     uint16_t place_int = 0; | // Turn on/off 3A interputs, stopping/enabling the ISR calls
 | ||||||
|     bool repeat = true; | #define ENABLE_AUDIO_COUNTER_3_ISR TIMSK3 |= _BV(OCIE3A) | ||||||
| #endif | #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)); | ||||||
|  | 
 | ||||||
|  | // 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 voices = 0; | ||||||
| int voice_place = 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}; | int volumes[8] = {0, 0, 0, 0, 0, 0, 0, 0}; | ||||||
| bool sliding = false; | bool sliding = false; | ||||||
| 
 | 
 | ||||||
| int max = 0xFF; |  | ||||||
| float sum = 0; |  | ||||||
| float place = 0; | float place = 0; | ||||||
| 
 | 
 | ||||||
| uint8_t * sample; | uint8_t * sample; | ||||||
| uint16_t sample_length = 0; | uint16_t sample_length = 0; | ||||||
| // float freq = 0;
 |  | ||||||
| 
 | 
 | ||||||
| bool notes = false; | bool     playing_notes = false; | ||||||
| bool note = false; | bool     playing_note = false; | ||||||
| float note_frequency = 0; | float    note_frequency = 0; | ||||||
| float note_length = 0; | float    note_length = 0; | ||||||
| float note_tempo = TEMPO_DEFAULT; | uint8_t  note_tempo = TEMPO_DEFAULT; | ||||||
| float note_timbre = TIMBRE_DEFAULT; | float    note_timbre = TIMBRE_DEFAULT; | ||||||
| uint16_t note_position = 0; | uint16_t note_position = 0; | ||||||
| float (* notes_pointer)[][2]; | float (* notes_pointer)[][2]; | ||||||
| uint16_t notes_count; | uint16_t notes_count; | ||||||
| bool notes_repeat; | bool     notes_repeat; | ||||||
| float notes_rest; | float    notes_rest; | ||||||
| bool note_resting = false; | bool     note_resting = false; | ||||||
| 
 | 
 | ||||||
| uint8_t current_note = 0; | uint8_t current_note = 0; | ||||||
| uint8_t rest_counter = 0; | uint8_t rest_counter = 0; | ||||||
| @ -77,12 +72,308 @@ float vibrato_rate = 0.125; | |||||||
| 
 | 
 | ||||||
| float polyphony_rate = 0; | float polyphony_rate = 0; | ||||||
| 
 | 
 | ||||||
| bool inited = false; | static bool audio_initialized = false; | ||||||
| 
 | 
 | ||||||
| audio_config_t audio_config; | audio_config_t audio_config; | ||||||
| 
 | 
 | ||||||
| uint16_t envelope_index = 0; | uint16_t envelope_index = 0; | ||||||
| 
 | 
 | ||||||
|  | void audio_init() | ||||||
|  | { | ||||||
|  | 
 | ||||||
|  |     // Check EEPROM
 | ||||||
|  |     if (!eeconfig_is_enabled()) | ||||||
|  |     { | ||||||
|  |         eeconfig_init(); | ||||||
|  |     } | ||||||
|  |     audio_config.raw = eeconfig_read_audio(); | ||||||
|  | 
 | ||||||
|  | 	// 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); | ||||||
|  | 
 | ||||||
|  |     audio_initialized = true; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void stop_all_notes() | ||||||
|  | { | ||||||
|  |     if (!audio_initialized) { | ||||||
|  |         audio_init(); | ||||||
|  |     } | ||||||
|  |     voices = 0; | ||||||
|  | 
 | ||||||
|  |     DISABLE_AUDIO_COUNTER_3_ISR; | ||||||
|  |     DISABLE_AUDIO_COUNTER_3_OUTPUT; | ||||||
|  | 
 | ||||||
|  |     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(); | ||||||
|  |         } | ||||||
|  |         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) { | ||||||
|  |             DISABLE_AUDIO_COUNTER_3_ISR; | ||||||
|  |             DISABLE_AUDIO_COUNTER_3_OUTPUT; | ||||||
|  |             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) | ||||||
|  | { | ||||||
|  | 	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; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 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; | ||||||
|  | 
 | ||||||
|  | 	    if (freq > 0) { | ||||||
|  | 	        frequencies[voices] = freq; | ||||||
|  | 	        volumes[voices] = vol; | ||||||
|  | 	        voices++; | ||||||
|  | 	    } | ||||||
|  | 
 | ||||||
|  |         ENABLE_AUDIO_COUNTER_3_ISR; | ||||||
|  |         ENABLE_AUDIO_COUNTER_3_OUTPUT; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 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; | ||||||
|  | 
 | ||||||
|  |         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; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool is_playing_notes(void) { | ||||||
|  | 	return playing_notes; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void audio_toggle(void) { | void audio_toggle(void) { | ||||||
|     audio_config.enable ^= 1; |     audio_config.enable ^= 1; | ||||||
|     eeconfig_update_audio(audio_config.raw); |     eeconfig_update_audio(audio_config.raw); | ||||||
| @ -99,6 +390,7 @@ void audio_off(void) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #ifdef VIBRATO_ENABLE | #ifdef VIBRATO_ENABLE | ||||||
|  | 
 | ||||||
| // Vibrato rate functions
 | // Vibrato rate functions
 | ||||||
| 
 | 
 | ||||||
| void set_vibrato_rate(float rate) { | void set_vibrato_rate(float rate) { | ||||||
| @ -127,9 +419,9 @@ void decrease_vibrato_strength(float change) { | |||||||
|     vibrato_strength /= change; |     vibrato_strength /= change; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #endif | #endif  /* VIBRATO_STRENGTH_ENABLE */ | ||||||
| 
 | 
 | ||||||
| #endif | #endif /* VIBRATO_ENABLE */ | ||||||
| 
 | 
 | ||||||
| // Polyphony functions
 | // Polyphony functions
 | ||||||
| 
 | 
 | ||||||
| @ -161,433 +453,22 @@ void set_timbre(float timbre) { | |||||||
| 
 | 
 | ||||||
| // Tempo functions
 | // Tempo functions
 | ||||||
| 
 | 
 | ||||||
| void set_tempo(float tempo) { | void set_tempo(uint8_t tempo) { | ||||||
|     note_tempo = tempo; |     note_tempo = tempo; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void decrease_tempo(uint8_t tempo_change) { | void decrease_tempo(uint8_t tempo_change) { | ||||||
|     note_tempo += (float) tempo_change; |     note_tempo += tempo_change; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void increase_tempo(uint8_t tempo_change) { | void increase_tempo(uint8_t tempo_change) { | ||||||
|     if (note_tempo - (float) tempo_change < 10) { |     if (note_tempo - tempo_change < 10) { | ||||||
|         note_tempo = 10; |         note_tempo = 10; | ||||||
|     } else { |     } else { | ||||||
|         note_tempo -= (float) tempo_change; |         note_tempo -= 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
 | // Override these functions in your keymap file to play different tunes on
 | ||||||
| @ -597,11 +478,8 @@ void play_startup_tone() | |||||||
| { | { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| __attribute__ ((weak)) | __attribute__ ((weak)) | ||||||
| void play_goodbye_tone() | void play_goodbye_tone() | ||||||
| { | { | ||||||
| 
 |  | ||||||
| } | } | ||||||
| //------------------------------------------------------------------------------
 | //------------------------------------------------------------------------------
 | ||||||
|  | |||||||
| @ -56,7 +56,7 @@ void increase_polyphony_rate(float change); | |||||||
| void decrease_polyphony_rate(float change); | void decrease_polyphony_rate(float change); | ||||||
| 
 | 
 | ||||||
| void set_timbre(float timbre); | void set_timbre(float timbre); | ||||||
| void set_tempo(float tempo); | void set_tempo(uint8_t tempo); | ||||||
| 
 | 
 | ||||||
| void increase_tempo(uint8_t tempo_change); | void increase_tempo(uint8_t tempo_change); | ||||||
| void decrease_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 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)); | #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)); | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
|  | bool is_playing_notes(void); | ||||||
| void play_goodbye_tone(void); | void play_goodbye_tone(void); | ||||||
| void play_startup_tone(void); | void play_startup_tone(void); | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| #endif | #endif | ||||||
							
								
								
									
										643
									
								
								quantum/audio/audio_pwm.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										643
									
								
								quantum/audio/audio_pwm.c
									
									
									
									
									
										Normal file
									
								
							| @ -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() | ||||||
|  | { | ||||||
|  | } | ||||||
|  | //------------------------------------------------------------------------------
 | ||||||
| @ -1,357 +0,0 @@ | |||||||
| #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 |  | ||||||
| }; |  | ||||||
							
								
								
									
										382
									
								
								quantum/audio/luts.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										382
									
								
								quantum/audio/luts.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,382 @@ | |||||||
|  | #include <avr/io.h> | ||||||
|  | #include <avr/interrupt.h> | ||||||
|  | #include <avr/pgmspace.h> | ||||||
|  | #include "luts.h" | ||||||
|  | 
 | ||||||
|  | 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, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
							
								
								
									
										15
									
								
								quantum/audio/luts.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								quantum/audio/luts.h
									
									
									
									
									
										Normal file
									
								
							| @ -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 */ | ||||||
| @ -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 |  | ||||||
| }; |  | ||||||
| @ -1,6 +1,6 @@ | |||||||
| #include "voices.h" | #include "voices.h" | ||||||
|  | #include "audio.h" | ||||||
| #include "stdlib.h" | #include "stdlib.h" | ||||||
| #include "vibrato_lut.h" |  | ||||||
| 
 | 
 | ||||||
| // these are imported from audio.c
 | // these are imported from audio.c
 | ||||||
| extern uint16_t envelope_index; | extern uint16_t envelope_index; | ||||||
| @ -109,7 +109,7 @@ float voice_envelope(float frequency) { | |||||||
|                 case 0 ... VOICE_VIBRATO_DELAY: |                 case 0 ... VOICE_VIBRATO_DELAY: | ||||||
|                     break; |                     break; | ||||||
|                 default: |                 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; | ||||||
|             } |             } | ||||||
|             break; |             break; | ||||||
| @ -161,3 +161,5 @@ float voice_envelope(float frequency) { | |||||||
| 
 | 
 | ||||||
|     return frequency; |     return frequency; | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | |||||||
| @ -2,8 +2,7 @@ | |||||||
| #include <stdbool.h> | #include <stdbool.h> | ||||||
| #include <avr/io.h> | #include <avr/io.h> | ||||||
| #include <util/delay.h> | #include <util/delay.h> | ||||||
| #include "musical_notes.h" | #include "luts.h" | ||||||
| #include "song_list.h" |  | ||||||
| 
 | 
 | ||||||
| #ifndef VOICES_H | #ifndef VOICES_H | ||||||
| #define VOICES_H | #define VOICES_H | ||||||
|  | |||||||
| @ -24,10 +24,14 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>. | |||||||
| #include "action_macro.h" | #include "action_macro.h" | ||||||
| #include "debug.h" | #include "debug.h" | ||||||
| #include "backlight.h" | #include "backlight.h" | ||||||
| #include "keymap_midi.h" |  | ||||||
| #include "bootloader.h" | #include "bootloader.h" | ||||||
| #include "eeconfig.h" | #include "eeconfig.h" | ||||||
| 
 | 
 | ||||||
|  | #ifdef MIDI_ENABLE | ||||||
|  | 	#include "keymap_midi.h" | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| extern keymap_config_t keymap_config; | extern keymap_config_t keymap_config; | ||||||
| 
 | 
 | ||||||
| #include <stdio.h> | #include <stdio.h> | ||||||
|  | |||||||
| @ -29,6 +29,7 @@ endif | |||||||
| 
 | 
 | ||||||
| ifeq ($(strip $(AUDIO_ENABLE)), yes) | 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/voices.c | ||||||
|  | 	SRC += $(QUANTUM_DIR)/audio/audio.c $(QUANTUM_DIR)/audio/luts.c | ||||||
| endif | endif | ||||||
| 
 | 
 | ||||||
| ifeq ($(strip $(UNICODE_ENABLE)), yes) | ifeq ($(strip $(UNICODE_ENABLE)), yes) | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 IBNobody
						IBNobody