/*
-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:
#include <string.h>
#include "stm32l0xx.h"
-#include "klavirko.h"\r
-\r
+#include "klavirko.h"
+
uint16_t tuning = DEFAULT_TUNING;
int8_t transp = 0;
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_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_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];
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);
__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 * */
- // 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 |
- MIDI_EN;\r
+ MIDI_EN;
// GPIO alternate function:
UART_PORT->UART_AF_REG = (UART_PORT->UART_AF_REG & ~ UART_AF_MASK) | UART_AF_SET;
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;
- 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 * */
-\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 * */
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);
- // 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(LPUART1_IRQn);\r
-\r
- for(;;)\r
- {\r
+ NVIC_EnableIRQ(LPUART1_IRQn);
+
+ for(;;)
+ {
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 */
- 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;
- 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
- 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
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)
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;
}
- while (temp_transp < -6)
+ while (temp_transp < (MAX_TRANSP-12))
{
temp_tuning >>= 1;
temp_transp += 12;
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)
{
/*
-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:
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 TUNING_SHIFT 2
+#define TUNING_SHIFT 2
+#define N_FACTORS (N_NOTES + MAX_TRANSP - MIN_TRANSP) // 97 + 12 + 12 = 121
#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
#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