]> bicyclesonthemoon.info Git - klavirko/main/commitdiff
updated handling of tuning and transposition, new limits main
authorb <rowerynaksiezycu@gmail.com>
Sun, 29 Dec 2024 01:25:05 +0000 (02:25 +0100)
committerb <rowerynaksiezycu@gmail.com>
Sun, 29 Dec 2024 01:25:05 +0000 (02:25 +0100)
src/klavirko.c
src/klavirko.h

index eac5e5fd4021fd0b2ae697f78fe8e0dfdd16e4dd..defe8a845f7b55f529404f47d8865a90a64f51b1 100644 (file)
@@ -1,5 +1,5 @@
 /*
 /*
-Copyright 2021, 2022 Balthasar Szczepański
+Copyright 2021, 2022, 2024 Balthasar Szczepański
 
 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
 
 
 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
 
@@ -12,8 +12,8 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 
 #include <string.h>
 #include "stm32l0xx.h"
 
 #include <string.h>
 #include "stm32l0xx.h"
-#include "klavirko.h"\r
-\r
+#include "klavirko.h"
+
          uint16_t      tuning = DEFAULT_TUNING;
          int8_t        transp = 0;
 
          uint16_t      tuning = DEFAULT_TUNING;
          int8_t        transp = 0;
 
@@ -24,36 +24,37 @@ volatile uint32_t      synth_R = DEFAULT_R;
 volatile uint32_t      synth_RD= DEFAULT_RD;
 volatile uint32_t      synth_0 = 0; // this is a hack, I need an addressable 32 bit variable == 0, as these parameters are accessed by pointers.
 
 volatile uint32_t      synth_RD= DEFAULT_RD;
 volatile uint32_t      synth_0 = 0; // this is a hack, I need an addressable 32 bit variable == 0, as these parameters are accessed by pointers.
 
-volatile uint32_t      synth_counter  [N_CHANNELS] = {[0 ... (N_CHANNELS-1)] = 0};  // pitch frequency generator counter\r
-volatile uint32_t      synth_pitch    [N_CHANNELS] = {[0 ... (N_CHANNELS-1)] = 0};  // pitch frequency setting\r
-volatile uint32_t      synth_envelope [N_CHANNELS] = {[0 ... (N_CHANNELS-1)] = 0};  // ADSR; current amplitude\r
-volatile int_fast8_t   synth_key      [N_CHANNELS] = {[0 ... (N_CHANNELS-1)] = -1}; // key assigned to this note\r
-volatile uint32_t      synth_active   [N_CHANNELS] = {[0 ... (N_CHANNELS-1)] = 0};  // bool, continue playing or fadeout?\r
-volatile uint32_t      synth_state    [N_CHANNELS] = {[0 ... (N_CHANNELS-1)] = ENVL_0}; // current ADSR phase\r
-volatile uint32_t      synth_envl_add [N_CHANNELS] = {[0 ... (N_CHANNELS-1)] = (uint32_t)(&synth_0)}; // current ADSR increment ramp\r
-volatile uint32_t      synth_envl_sub [N_CHANNELS] = {[0 ... (N_CHANNELS-1)] = (uint32_t)(&synth_0)}; // current ADSR decrement ramp\r
-volatile uint32_t      synth_envl_goal[N_CHANNELS] = {[0 ... (N_CHANNELS-1)] = (uint32_t)(&synth_0)}; // current ADSR decrement limit\r
-volatile int_fast8_t   synth_prev     [N_CHANNELS] = SYNTH_PREV_INIT; // previous channel in the list\r
-volatile int_fast8_t   synth_next     [N_CHANNELS] = SYNTH_NEXT_INIT; // next channel in the list\r
-volatile int_fast8_t   synth_first                 = 0;               // first channel in the list\r
-volatile int_fast8_t   synth_last                  = N_CHANNELS-1;    // last channel in the list\r
-\r
-volatile uint8_t       scan_count  = SCAN_DIV;    // counter for keyboard scan timing\r
-volatile uint8_t       scan_flag   = 0;           // trigger for next keyboard scan\r
-         uint16_t      scan_octave = 0;           // which octave to check on keyboard now\r
-         uint16_t      scan_notes  = 0;           // note states read from the currently checked octave\r
-         uint16_t      scan_pedal  = KEYB_IN_PEDAL; // pedal state read together with notes\r
-         uint_fast8_t  scan_index  = 0;           // note in current octave to be checked\r
-         uint_fast8_t  free_channel= 0;\r
-volatile uint8_t       envl_index  = 0;\r
+volatile uint32_t      synth_counter  [N_CHANNELS] = {[0 ... (N_CHANNELS-1)] = 0};  // pitch frequency generator counter
+volatile uint32_t      synth_pitch    [N_CHANNELS] = {[0 ... (N_CHANNELS-1)] = 0};  // pitch frequency setting
+volatile uint32_t      synth_envelope [N_CHANNELS] = {[0 ... (N_CHANNELS-1)] = 0};  // ADSR; current amplitude
+volatile int_fast8_t   synth_key      [N_CHANNELS] = {[0 ... (N_CHANNELS-1)] = -1}; // key assigned to this note
+volatile uint32_t      synth_active   [N_CHANNELS] = {[0 ... (N_CHANNELS-1)] = 0};  // bool, continue playing or fadeout?
+volatile uint32_t      synth_state    [N_CHANNELS] = {[0 ... (N_CHANNELS-1)] = ENVL_0}; // current ADSR phase
+volatile uint32_t      synth_envl_add [N_CHANNELS] = {[0 ... (N_CHANNELS-1)] = (uint32_t)(&synth_0)}; // current ADSR increment ramp
+volatile uint32_t      synth_envl_sub [N_CHANNELS] = {[0 ... (N_CHANNELS-1)] = (uint32_t)(&synth_0)}; // current ADSR decrement ramp
+volatile uint32_t      synth_envl_goal[N_CHANNELS] = {[0 ... (N_CHANNELS-1)] = (uint32_t)(&synth_0)}; // current ADSR decrement limit
+volatile int_fast8_t   synth_prev     [N_CHANNELS] = SYNTH_PREV_INIT; // previous channel in the list
+volatile int_fast8_t   synth_next     [N_CHANNELS] = SYNTH_NEXT_INIT; // next channel in the list
+volatile int_fast8_t   synth_first                 = 0;               // first channel in the list
+volatile int_fast8_t   synth_last                  = N_CHANNELS-1;    // last channel in the list
+
+volatile uint8_t       scan_count  = SCAN_DIV;    // counter for keyboard scan timing
+volatile uint8_t       scan_flag   = 0;           // trigger for next keyboard scan
+         uint16_t      scan_octave = 0;           // which octave to check on keyboard now
+         uint16_t      scan_notes  = 0;           // note states read from the currently checked octave
+         uint16_t      scan_pedal  = KEYB_IN_PEDAL; // pedal state read together with notes
+         uint_fast8_t  scan_index  = 0;           // note in current octave to be checked
+         uint_fast8_t  free_channel= 0;
+volatile uint8_t       envl_index  = 0;
 
          uint16_t      CH_PEDAL      = 0;
 
          uint16_t      CH_PEDAL      = 0;
-         uint16_t      CH_PEDAL_WAIT = 0;\r
+         uint16_t      CH_PEDAL_WAIT = 0;
          uint8_t       CH_ACTIVE [2*N_NOTES] = {[0 ... (2*N_NOTES-1)] = 0};
          uint8_t       CH_ACTIVE [2*N_NOTES] = {[0 ... (2*N_NOTES-1)] = 0};
-         uint8_t       CH_WAIT_ON[  N_NOTES] = {[0 ...    N_NOTES-1 ] = 0};\r
-         int_fast8_t   CH_INDEX  [2*N_NOTES] = {[0 ... (2*N_NOTES-1)] = -1};\r
-volatile uint32_t      PITCH     [  N_NOTES]; //must be set by set_tuning();\r
-\r
+         uint8_t       CH_WAIT_ON[  N_NOTES] = {[0 ...    N_NOTES-1 ] = 0};
+         int_fast8_t   CH_INDEX  [2*N_NOTES] = {[0 ... (2*N_NOTES-1)] = -1};
+volatile uint32_t      PITCH     [  N_NOTES]; //must be set by set_tuning();
+const    uint32_t      FACTOR    [N_FACTORS] = TUNING_FACTORS;
+
 volatile int8_t        SAMPLE [N_SAMPLE] = DEFAULT_SAMPLE;
 
 volatile uint8_t       buffer_in [N_BUFFER_IN];
 volatile int8_t        SAMPLE [N_SAMPLE] = DEFAULT_SAMPLE;
 
 volatile uint8_t       buffer_in [N_BUFFER_IN];
@@ -89,8 +90,8 @@ volatile uint8_t       midi_buffer_out_rd = 0;
          uint8_t       midi_pedal      = 0;
          uint8_t       midi_pedal_en   = 0xff;
 volatile uint8_t       midi_status_out = MIDI_NOP;
          uint8_t       midi_pedal      = 0;
          uint8_t       midi_pedal_en   = 0xff;
 volatile uint8_t       midi_status_out = MIDI_NOP;
-\r
-\r
+
+
                 void set_tuning(uint16_t f, int8_t t);
 __STATIC_INLINE void handle_midi_in(void);
                 void handle_midi_out(void);
                 void set_tuning(uint16_t f, int8_t t);
 __STATIC_INLINE void handle_midi_in(void);
                 void handle_midi_out(void);
@@ -102,40 +103,40 @@ __STATIC_INLINE void midi_note_off (const uint8_t note);
 __STATIC_INLINE void midi_pedal_on (void);
 __STATIC_INLINE void midi_pedal_off (void);
 
 __STATIC_INLINE void midi_pedal_on (void);
 __STATIC_INLINE void midi_pedal_off (void);
 
-int main(void)\r
-{\r
-//     uint_fast16_t i;\r
-\r
-       /* * SET UP TIMING * */\r
-\r
-       // power range:\r
-       RCC->APB1ENR |= RCC_APB1ENR_PWREN; // enable power control module\r
-       PWR->CR = (PWR->CR & ~PWR_CR_VOS) | PWR_CR_VOS_0; // set PWR range 1 (high speed)\r
-\r
-       // external 8MHz from ST link:\r
-       RCC->CR |=\r
-                       RCC_CR_HSEBYP | // external clock, bypass oscillator\r
-                       RCC_CR_HSEON;   // enable highspeed external clock\r
-       while(!(RCC->CR | RCC_CR_HSERDY)); // wait for external clock ready\r
-\r
-       // PLL to get 32MHz:\r
-       RCC->CFGR |=\r
-                       RCC_CFGR_PLLSRC |  // HSE is input of PLL\r
-                       PLL_MUL | PLL_DIV;  // PLL ratio (see #define)\r
-       RCC->CR |= RCC_CR_PLLON; // enable PLL\r
-       while(!(RCC->CR | RCC_CR_PLLRDY)); // wait for PLL ready\r
-       RCC->CFGR |= RCC_CFGR_SW_PLL; // set PLL as SYSCLK\r
-\r
+int main(void)
+{
+//     uint_fast16_t i;
+
+       /* * SET UP TIMING * */
+
+       // power range:
+       RCC->APB1ENR |= RCC_APB1ENR_PWREN; // enable power control module
+       PWR->CR = (PWR->CR & ~PWR_CR_VOS) | PWR_CR_VOS_0; // set PWR range 1 (high speed)
+
+       // external 8MHz from ST link:
+       RCC->CR |=
+                       RCC_CR_HSEBYP | // external clock, bypass oscillator
+                       RCC_CR_HSEON;   // enable highspeed external clock
+       while(!(RCC->CR | RCC_CR_HSERDY)); // wait for external clock ready
+
+       // PLL to get 32MHz:
+       RCC->CFGR |=
+                       RCC_CFGR_PLLSRC |  // HSE is input of PLL
+                       PLL_MUL | PLL_DIV;  // PLL ratio (see #define)
+       RCC->CR |= RCC_CR_PLLON; // enable PLL
+       while(!(RCC->CR | RCC_CR_PLLRDY)); // wait for PLL ready
+       RCC->CFGR |= RCC_CFGR_SW_PLL; // set PLL as SYSCLK
+
        /* * SET UP GPIO * */
 
        /* * SET UP GPIO * */
 
-       // GPIO enable:\r
-       RCC->IOPENR |=\r
-                       DEBUG_EN |\r
-                       KEYB_OUT_EN |\r
+       // GPIO enable:
+       RCC->IOPENR |=
+                       DEBUG_EN |
+                       KEYB_OUT_EN |
                        KEYB_IN_EN |
                        DAC_EN |
                        UART_EN |
                        KEYB_IN_EN |
                        DAC_EN |
                        UART_EN |
-                       MIDI_EN;\r
+                       MIDI_EN;
 
        // GPIO alternate function:
        UART_PORT->UART_AF_REG = (UART_PORT->UART_AF_REG & ~ UART_AF_MASK) | UART_AF_SET;
 
        // GPIO alternate function:
        UART_PORT->UART_AF_REG = (UART_PORT->UART_AF_REG & ~ UART_AF_MASK) | UART_AF_SET;
@@ -153,29 +154,29 @@ int main(void)
        GPIOH->MODER = (GPIOH->MODER & ~ UNUSED_H_MASK) | UNUSED_H_MODE;
        GPIOH->BSRR = UNUSED_H_BSRR;
 
        GPIOH->MODER = (GPIOH->MODER & ~ UNUSED_H_MASK) | UNUSED_H_MODE;
        GPIOH->BSRR = UNUSED_H_BSRR;
 
-       // GPIO mode:\r
-       DEBUG_PORT->MODER = (DEBUG_PORT->MODER & ~DEBUG_MODE_MASK) | DEBUG_MODE_SET;\r
-       KEYB_OUT_PORT->MODER = (KEYB_OUT_PORT->MODER & ~KEYB_OUT_MODE_MASK) | KEYB_OUT_MODE_SET;\r
+       // GPIO mode:
+       DEBUG_PORT->MODER = (DEBUG_PORT->MODER & ~DEBUG_MODE_MASK) | DEBUG_MODE_SET;
+       KEYB_OUT_PORT->MODER = (KEYB_OUT_PORT->MODER & ~KEYB_OUT_MODE_MASK) | KEYB_OUT_MODE_SET;
        KEYB_IN_PORT->MODER = (KEYB_IN_PORT->MODER & ~KEYB_IN_MODE_MASK) | KEYB_IN_MODE_SET;
        KEYB_IN_PORT->PUPDR = (KEYB_IN_PORT->PUPDR & ~KEYB_IN_MODE_MASK) | KEYB_IN_PULLUP;
        UART_PORT->MODER = (UART_PORT->MODER & ~UART_MODE_MASK) | UART_MODE_SET;
        MIDI_PORT->MODER = (MIDI_PORT->MODER & ~MIDI_MODE_MASK) | MIDI_MODE_SET;
        KEYB_IN_PORT->MODER = (KEYB_IN_PORT->MODER & ~KEYB_IN_MODE_MASK) | KEYB_IN_MODE_SET;
        KEYB_IN_PORT->PUPDR = (KEYB_IN_PORT->PUPDR & ~KEYB_IN_MODE_MASK) | KEYB_IN_PULLUP;
        UART_PORT->MODER = (UART_PORT->MODER & ~UART_MODE_MASK) | UART_MODE_SET;
        MIDI_PORT->MODER = (MIDI_PORT->MODER & ~MIDI_MODE_MASK) | MIDI_MODE_SET;
-       DAC_PORT->MODER = (DAC_PORT->MODER & ~DAC_MODE_MASK) | DAC_MODE_SET;\r
-\r
+       DAC_PORT->MODER = (DAC_PORT->MODER & ~DAC_MODE_MASK) | DAC_MODE_SET;
+
        /* * SET UP TIMER & DAC * */
        /* * SET UP TIMER & DAC * */
-\r
-       RCC->APB1ENR |=\r
-                       RCC_APB1ENR_DACEN | // enable DAC\r
-                       RCC_APB1ENR_TIM6EN; // enable timer 6\r
-\r
-       TIM6->CR1 |= TIM_CR1_URS;   // counter overflow is only event source\r
-       TIM6->CR2 |= TIM_CR2_MMS_1; // sync. for DAC\r
-       TIM6->DIER |= TIM_DIER_UIE; // enable update interrupt\r
-       TIM6->ARR = SAMP_DIV-1;     // set divide value (see #define)\r
-\r
-       DAC->CR |=\r
-                       DAC_CR_TEN1 | // sync. to timer\r
-                       DAC_CR_EN1;   // start DAC\r
+
+       RCC->APB1ENR |=
+                       RCC_APB1ENR_DACEN | // enable DAC
+                       RCC_APB1ENR_TIM6EN; // enable timer 6
+
+       TIM6->CR1 |= TIM_CR1_URS;   // counter overflow is only event source
+       TIM6->CR2 |= TIM_CR2_MMS_1; // sync. for DAC
+       TIM6->DIER |= TIM_DIER_UIE; // enable update interrupt
+       TIM6->ARR = SAMP_DIV-1;     // set divide value (see #define)
+
+       DAC->CR |=
+                       DAC_CR_TEN1 | // sync. to timer
+                       DAC_CR_EN1;   // start DAC
        TIM6->CR1 |= TIM_CR1_CEN; // start timer
 
        /* * SET UP UARTS * */
        TIM6->CR1 |= TIM_CR1_CEN; // start timer
 
        /* * SET UP UARTS * */
@@ -201,52 +202,42 @@ int main(void)
                USART_CR1_RXNEIE| //enable interrupt on receive
                USART_CR1_TE| //enable transmitter
                USART_CR1_RE| //enable receiver
                USART_CR1_RXNEIE| //enable interrupt on receive
                USART_CR1_TE| //enable transmitter
                USART_CR1_RE| //enable receiver
-               USART_CR1_UE; //enable LPUART\r
+               USART_CR1_UE; //enable LPUART
 
 
-       /* * DEFAULT SYNTH PARAMETERS * */\r
+       /* * DEFAULT SYNTH PARAMETERS * */
 
        set_tuning(DEFAULT_TUNING, 0);
 
        set_tuning(DEFAULT_TUNING, 0);
-       // all other parameters are pre-initialized\r
+       // all other parameters are pre-initialized
+
+       /* * OK, START RUNNING! * */
 
 
-       /* * OK, START RUNNING! * */\r
-\r
        NVIC_EnableIRQ(TIM6_DAC_IRQn);
        NVIC_EnableIRQ(USART1_IRQn);
        NVIC_EnableIRQ(TIM6_DAC_IRQn);
        NVIC_EnableIRQ(USART1_IRQn);
-       NVIC_EnableIRQ(LPUART1_IRQn);\r
-\r
-       for(;;)\r
-       {\r
+       NVIC_EnableIRQ(LPUART1_IRQn);
+
+       for(;;)
+       {
                handle_midi_in();
                handle_keyboard();
                handle_serial();
                handle_midi_in();
                handle_keyboard();
                handle_serial();
-               handle_midi_out();\r
-       }\r
-}\r
-\r
+               handle_midi_out();
+       }
+}
+
 void set_tuning(
        uint16_t f, /* tuning frequency, in 0.1Hz, < MAX_TUNING */
 void set_tuning(
        uint16_t f, /* tuning frequency, in 0.1Hz, < MAX_TUNING */
-       int8_t t    /* transposition in semitones, -6 to 6 */
-)\r
-{\r
-       int_fast8_t  i;\r
-       uint_fast8_t j;\r
-       uint32_t factor[12] = TUNING_FACTORS;
+       int8_t t    /* transposition in semitones, -12 to 12 */
+)
+{
+       uint_fast8_t i, j;
        
        tuning = f;
        
        tuning = f;
-       transp = t;\r
+       transp = t;
        
        
-       for (j=0; j<(6-t); ++j)
+       for (i=0, j=t-MIN_TRANSP; i<N_NOTES; ++i, ++j)
        {
        {
-               factor[j] >>= 1; // shift down to use in next octave
-       }\r
-       for (i=N_NOTES-1; i>=0; --i)\r
-       {\r
-               if (j==12) // reached next octave already
-                       j=0;
                // calculate particular pitch using precalculated factors
                // calculate particular pitch using precalculated factors
-               PITCH[i] = (((uint32_t)f) * factor[j]) >> TUNING_SHIFT;\r
-               factor[j] >>= 1; // shift down to use in next octave\r
-               ++j;\r
+               PITCH[i] = (((uint32_t)f) * FACTOR[j]) >> TUNING_SHIFT;
        }
        
        // apply new tuning to already played notes
        }
        
        // apply new tuning to already played notes
@@ -256,7 +247,7 @@ void set_tuning(
                        synth_pitch[i] = PITCH[synth_key[i] - N_NOTES];
                else if (synth_key[i] >= 0) // regular key
                        synth_pitch[i] = PITCH[synth_key[i]];
                        synth_pitch[i] = PITCH[synth_key[i] - N_NOTES];
                else if (synth_key[i] >= 0) // regular key
                        synth_pitch[i] = PITCH[synth_key[i]];
-       }\r
+       }
 }
 
 __STATIC_INLINE void handle_midi_in(void)
 }
 
 __STATIC_INLINE void handle_midi_in(void)
@@ -829,12 +820,12 @@ __STATIC_INLINE void handle_serial(void)
                case CMD_SET_TUNING:
                        temp_tuning = *((uint16_t*)cmd_buffer);
                        temp_transp = *((int8_t*)(cmd_buffer+2));
                case CMD_SET_TUNING:
                        temp_tuning = *((uint16_t*)cmd_buffer);
                        temp_transp = *((int8_t*)(cmd_buffer+2));
-                       while (temp_transp > 6)
+                       while (temp_transp > MAX_TRANSP)
                        {
                                temp_tuning <<= 1;
                                temp_transp -= 12;
                        }
                        {
                                temp_tuning <<= 1;
                                temp_transp -= 12;
                        }
-                       while (temp_transp < -6)
+                       while (temp_transp < (MAX_TRANSP-12))
                        {
                                temp_tuning >>= 1;
                                temp_transp += 12;
                        {
                                temp_tuning >>= 1;
                                temp_transp += 12;
@@ -1062,7 +1053,7 @@ __STATIC_INLINE void midi_note_on (const uint8_t note)
        midi_send_byte(note + MIDI_NOTE_MIN);
        midi_send_byte(MIDI_THRESHOLD);
        handle_midi_out();
        midi_send_byte(note + MIDI_NOTE_MIN);
        midi_send_byte(MIDI_THRESHOLD);
        handle_midi_out();
-}\r
+}
 
 __STATIC_INLINE void midi_note_off (const uint8_t note)
 {
 
 __STATIC_INLINE void midi_note_off (const uint8_t note)
 {
index 2e3aa485fbe7882eee22257f3168bcd03ff8329b..daeffca6aba146d02dd117a072862588409c9b1a 100644 (file)
@@ -1,5 +1,5 @@
 /*
 /*
-Copyright 2021, 2022 Balthasar Szczepański
+Copyright 2021, 2022, 2024 Balthasar Szczepański
 
 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
 
 
 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
 
@@ -45,23 +45,135 @@ the tuning factor multiplied by tuning frequency (in 0.1Hz) and shifted right by
 and it is incremented with the sampling frequency, then the counter should overflow with a frequency
 corresponding to a particular note in the topmost octave
  */
 and it is incremented with the sampling frequency, then the counter should overflow with a frequency
 corresponding to a particular note in the topmost octave
  */
-#define MAX_TUNING     8257 // MAX_TUNING * TUNING_FACTORS[0] < 0xffffffff
+#define MAX_TRANSP       12
+#define MIN_TRANSP     (-12)
+#define MAX_TUNING     5839 // MAX_TUNING * TUNING_FACTORS[0] < 0xffffffff
 #define DEFAULT_TUNING 4400
 #define DEFAULT_TUNING 4400
-#define TUNING_SHIFT   2
+#define TUNING_SHIFT      2
+#define N_FACTORS (N_NOTES + MAX_TRANSP - MIN_TRANSP) // 97 + 12 + 12 = 121
 #define TUNING_FACTORS \
 { \
 #define TUNING_FACTORS \
 { \
-       520074, /* F#8*/ \
-       490884, /* F8 */ \
-       463333, /* E8 */ \
-       437328, /* D#8*/ \
-       412783, /* D8 */ \
-       389615, /* C#8*/ \
-       367748, /* C8 */ \
-       347108, /* H7 */ \
-       327626, /* A#7*/ \
-       309238, /* A7 */ \
-       291881, /* G#7*/ \
-       275499  /* G7 */ \
+          718, /* C -1   8.175798915643707 -> 8.172872993681166 Hz */ \
+          760, /* C#-1   8.661957218027252 -> 8.650951915317112 Hz */ \
+          806, /* D -1   9.177023997418988 -> 9.174562162823147 Hz */ \
+          854, /* D#-1   9.722718241315029 -> 9.720938073264229 Hz */ \
+          904, /* E -1  10.30086115352718 -> 10.29007964664035 Hz */ \
+          958, /* F -1  10.91338223228137 -> 10.90475254588657 Hz */ \
+         1015, /* F#-1  11.56232570973857 -> 11.55357393953535 Hz */ \
+         1076, /* G -1  12.24985737442966 -> 12.24792665905423 Hz */ \
+         1140, /* G#-1  12.97827179937329 -> 12.97642787297567 Hz */ \
+         1207, /* A -1  13.75             -> 13.73907758129968 Hz */ \
+         1279, /* A#-1  14.56761754744031 -> 14.5586414469613  Hz */ \
+         1355, /* H -1  15.43385316425388 -> 15.42373663849301 Hz */ \
+         1436, /* C 0   16.35159783128741 -> 16.34574598736233 Hz */ \
+         1521, /* C#0   17.3239144360545  -> 17.31328666210175 Hz */ \
+         1612, /* D 0   18.35404799483798 -> 18.34912432564629 Hz */ \
+         1708, /* D#0   19.44543648263006 -> 19.44187614652846 Hz */ \
+         1809, /* E 0   20.60172230705437 -> 20.59154212474823 Hz */ \
+         1917, /* F 0   21.82676446456275 -> 21.82088792324066 Hz */ \
+         2031, /* F#0   23.12465141947715  ->23.11853071053823 Hz */ \
+         2152, /* G 0   24.49971474885933 -> 24.49585331810845 Hz */ \
+         2280, /* G#0   25.95654359874657 -> 25.95285574595134 Hz */ \
+         2415, /* A 0   27.5              -> 27.48953799406688 Hz */ \
+         2559, /* A#0   29.13523509488062 -> 29.12866572539012 Hz */ \
+         2711, /* H 0   30.86770632850775 -> 30.85885610845354 Hz */ \
+         2873, /* C 1   32.70319566257483 -> 32.70287480619218 Hz */ \
+         3043, /* C#1   34.64782887210901 -> 34.63795615567101 Hz */ \
+         3224, /* D 1   36.70809598967594 -> 36.69824865129259 Hz */ \
+         3416, /* D#1   38.89087296526012 -> 38.88375229305692 Hz */ \
+         3619, /* E 1   41.20344461410875 -> 41.19446708096398 Hz */ \
+         3835, /* F 1   43.65352892912549 -> 43.65315867794884 Hz */ \
+         4063, /* F#1   46.2493028389543  -> 46.24844425254398 Hz */ \
+         4304, /* G 1   48.99942949771867 -> 48.9917066362169  Hz */ \
+         4560, /* G#1   51.91308719749314 -> 51.90571149190267 Hz */ \
+         4831, /* A 1   55                -> 54.99045881960127 Hz */ \
+         5119, /* A#1   58.27047018976124 -> 58.26871428224776 Hz */ \
+         5423, /* H 1   61.7354126570155  -> 61.7290950483746  Hz */ \
+         5746, /* C 2   65.40639132514966 -> 65.40574961238437 Hz */ \
+         6087, /* C#2   69.29565774421802 -> 69.28729514280955 Hz */ \
+         6449, /* D 2   73.41619197935188 -> 73.4078801340527  Hz */ \
+         6833, /* D#2   77.78174593052023 -> 77.77888741758134 Hz */ \
+         7239, /* E 2   82.40688922821749 -> 82.40031699339549 Hz */ \
+         7670, /* F 2   87.30705785825097 -> 87.30631735589769 Hz */ \
+         8126, /* F#2   92.4986056779086  -> 92.49688850508797 Hz */ \
+         8609, /* G 2   97.99885899543733 -> 97.99479610390134 Hz */ \
+         9121, /* G#2  103.8261743949863 -> 103.8228058152729 Hz */ \
+         9663, /* A 2  110               -> 109.9923004706701 Hz */ \
+        10238, /* A#2  116.5409403795225 -> 116.5374285644955 Hz */ \
+        10847, /* H 2  123.4708253140311 -> 123.4695729282167 Hz */ \
+        11492, /* C 3  130.8127826502993 -> 130.8114992247687 Hz */ \
+        12175, /* C#3  138.591315488436  -> 138.5859731170866 Hz */ \
+        12899, /* D 3  146.8323839587038 -> 146.8271430995729 Hz */ \
+        13666, /* D#3  155.5634918610405 -> 155.5577748351627 Hz */ \
+        14479, /* E 3  164.8137784564349 -> 164.8120168182585 Hz */ \
+        15340, /* F 3  174.614115716502  -> 174.6126347117954 Hz */ \
+        16252, /* F#3  184.9972113558172 -> 184.9937770101759 Hz */ \
+        17218, /* G 3  195.9977179908746 -> 195.9895922078027 Hz */ \
+        18242, /* G#3  207.6523487899726 -> 207.6456116305457 Hz */ \
+        19327, /* A 3  220               -> 219.9959837728076 Hz */ \
+        20476, /* A#3  233.0818807590449 -> 233.074857128991  Hz */ \
+        21694, /* H 3  246.9416506280621 -> 246.9391458564334 Hz */ \
+        22984, /* C 4  261.6255653005986 -> 261.6229984495375 Hz */ \
+        24350, /* C#4  277.1826309768721 -> 277.1719462341733 Hz */ \
+        25798, /* D 4  293.6647679174076 -> 293.6542861991459 Hz */ \
+        27333, /* D#4  311.1269837220809 -> 311.1269325017929 Hz */ \
+        28958, /* E 4  329.6275569128699 -> 329.624033636517  Hz */ \
+        30680, /* F 4  349.2282314330039 -> 349.2252694235908 Hz */ \
+        32504, /* F#4  369.9944227116344 -> 369.9875540203519 Hz */ \
+        34437, /* G 4  391.9954359817492 -> 391.9905672470729 Hz */ \
+        36485, /* G#4  415.3046975799452 -> 415.302606092559  Hz */ \
+        38654, /* A 4  440               -> 439.9919675456153 Hz */ \
+        40953, /* A#4  466.1637615180898 -> 466.1610970894496 Hz */ \
+        43388, /* H 4  493.8833012561242 -> 493.8782917128669 Hz */ \
+        45968, /* C 5  523.2511306011972 -> 523.245996899075  Hz */ \
+        48701, /* C#5  554.3652619537442 -> 554.355275299814  Hz */ \
+        51597, /* D 5  587.3295358348153 -> 587.3199552297592 Hz */ \
+        54666, /* D#5  622.2539674441618 -> 622.2538650035858 Hz */ \
+        57916, /* E 5  659.2551138257397 -> 659.2480672730341 Hz */ \
+        61360, /* F 5  698.4564628660079 -> 698.4505388471815 Hz */ \
+        65009, /* F#5  739.9888454232688 -> 739.9864908721712 Hz */ \
+        68874, /* G 5  783.9908719634984 -> 783.9811344941457 Hz */ \
+        72970, /* G#5  830.6093951598904 -> 830.6052121851179 Hz */ \
+        77309, /* A 5  880               -> 879.9953179226982 Hz */ \
+        81906, /* A#5  932.3275230361796 -> 932.3221941788992 Hz */ \
+        86776, /* H 5  987.7666025122485 -> 987.7565834257338 Hz */ \
+        91936, /* C 6 1046.502261202394 -> 1046.49199379815  Hz */ \
+        97403, /* C#6 1108.730523907488 -> 1108.721933431096 Hz */ \
+       103195, /* D 6 1174.659071669631 -> 1174.651293290986 Hz */ \
+       109332, /* D#6 1244.507934888324 -> 1244.507730007172 Hz */ \
+       115833, /* E 6 1318.510227651479 -> 1318.507517377536 Hz */ \
+       122721, /* F 6 1396.912925732016 -> 1396.912460525831 Hz */ \
+       130018, /* F#6 1479.977690846538 -> 1479.972981744342 Hz */ \
+       137749, /* G 6 1567.981743926997 -> 1567.973651819759 Hz */ \
+       145940, /* G#6 1661.218790319781 -> 1661.210424370236 Hz */ \
+       154618, /* A 6 1760              -> 1759.990635845396 Hz */ \
+       163812, /* A#6 1864.655046072361 -> 1864.644388357798 Hz */ \
+       173553, /* H 6 1975.533205024496 -> 1975.524549682935 Hz */ \
+       183873, /* C 7 2093.004522404789 -> 2092.995370427767 Hz */ \
+       194807, /* C#7 2217.461047814978 -> 2217.455249693659 Hz */ \
+       206391, /* D 7 2349.31814333926  -> 2349.313969413439 Hz */ \
+       218664, /* D#7 2489.015869776647 -> 2489.015460014343 Hz */ \
+       231666, /* E 7 2637.020455302961 -> 2637.015034755071 Hz */ \
+       245442, /* F 7 2793.82585146403  -> 2793.824921051661 Hz */ \
+       260036, /* F#7 2959.955381693075 -> 2959.945963488685 Hz */ \
+       275499, /* G 7 3135.963487853996 -> 3135.958686470985 Hz */ \
+       291881, /* G#7 3322.43758063956  -> 3322.432231571939 Hz */ \
+       309237, /* A 7 3520              -> 3519.99265452226  Hz */ \
+       327625, /* A#7 3729.310092144721 -> 3729.300159547064 Hz */ \
+       347107, /* H 7 3951.066410048992 -> 3951.060482197338 Hz */ \
+       367747, /* C 8 4186.009044809578 -> 4186.002123687002 Hz */ \
+       389615, /* C#8 4434.922095629955 -> 4434.921882218785 Hz */ \
+       412782, /* D 8 4698.636286678519 -> 4698.627938826879 Hz */ \
+       437328, /* D#8 4978.031739553295 -> 4978.030920028687 Hz */ \
+       463332, /* E 8 5274.040910605921 -> 5274.030069510142 Hz */ \
+       490884, /* F 8 5587.65170292806  -> 5587.649842103322 Hz */ \
+       520073, /* F#8 5919.91076338615  -> 5919.903309808838 Hz */ \
+       550998, /* G 8 6271.926975707992 -> 6271.917372941971 Hz */ \
+       583762, /* G#8 6644.875161279119 -> 6644.864463143878 Hz */ \
+       618475, /* A 8 7040              -> 7039.996691875987 Hz */ \
+       655251, /* A#8 7458.620184289442 -> 7458.611701925595 Hz */ \
+       694215, /* H 8 7902.132820097983 -> 7902.132347226143 Hz */ \
+       735495  /* C 9 8372.018089619156 -> 8372.015630205473 Hz */ \
 }
 
 // cos(2pi * i / 256), 8 bit
 }
 
 // cos(2pi * i / 256), 8 bit
@@ -272,7 +384,7 @@ corresponding to a particular note in the topmost octave
 #define MIDI_THRESHOLD 0x40
 #define MIDI_DATA      0x7F
 #define MIDI_NOTE_MIN    12 // C0
 #define MIDI_THRESHOLD 0x40
 #define MIDI_DATA      0x7F
 #define MIDI_NOTE_MIN    12 // C0
-#define MIDI_NOTE_MAX   108
+#define MIDI_NOTE_MAX   108 // C8
 
 #define ACTION_NOP       0
 #define ACTION_NOTE_ON   1
 
 #define ACTION_NOP       0
 #define ACTION_NOTE_ON   1