summary refs log tree commit diff
path: root/quantum
diff options
context:
space:
mode:
authorJack Humbert <jack.humb@gmail.com>2016-01-23 20:34:05 -0500
committerJack Humbert <jack.humb@gmail.com>2016-01-23 20:34:05 -0500
commit5143c59bdff8e0b8cb896b905ab643ab8293ea47 (patch)
tree7082bac0facec617715d55deddca2b448ad880fa /quantum
parent544a49329cac78206c0d195f2e7bfd39db05507d (diff)
parentc753bfcc144e4158a1e683c2c93b32667dc08388 (diff)
Merge branch 'audio' of https://github.com/jackhumbert/tmk_keyboard into smarkefile
Diffstat (limited to 'quantum')
-rw-r--r--quantum/audio.c362
-rw-r--r--quantum/audio.h (renamed from quantum/beeps.h)7
-rw-r--r--quantum/beeps.c246
-rw-r--r--quantum/keymap_midi.c21
-rw-r--r--quantum/keymap_midi.h2
-rw-r--r--quantum/keymap_unicode.c2
-rw-r--r--quantum/quantum.mk7
-rw-r--r--quantum/wave.h265
8 files changed, 649 insertions, 263 deletions
diff --git a/quantum/audio.c b/quantum/audio.c
new file mode 100644
index 0000000000..3a3a1a4910
--- /dev/null
+++ b/quantum/audio.c
@@ -0,0 +1,362 @@
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#include <avr/pgmspace.h>
+#include <avr/interrupt.h>
+#include <avr/io.h>
+
+#include "audio.h"
+#include "keymap_common.h"
+
+#define PI 3.14159265
+
+// #define PWM_AUDIO
+
+#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
+#endif
+
+void delay_us(int count) {
+  while(count--) {
+    _delay_us(1);
+  }
+}
+
+int voices = 0;
+int voice_place = 0;
+double frequency = 0;
+int volume = 0;
+long position = 0;
+
+double frequencies[8] = {0, 0, 0, 0, 0, 0, 0, 0};
+int volumes[8] = {0, 0, 0, 0, 0, 0, 0, 0};
+bool sliding = false;
+
+int max = 0xFF;
+float sum = 0;
+int value = 128;
+float place = 0;
+float places[8] = {0, 0, 0, 0, 0, 0, 0, 0};
+
+uint16_t place_int = 0;
+bool repeat = true;
+uint8_t * sample;
+uint16_t sample_length = 0;
+
+
+bool notes = false;
+bool note = false;
+float note_frequency = 0;
+float note_length = 0;
+uint16_t note_position = 0;
+float (* notes_pointer)[][2];
+uint8_t notes_length;
+bool notes_repeat;
+uint8_t current_note = 0;
+
+void stop_all_notes() {
+    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(double freq) {
+    #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;
+            }
+        }
+    }
+    voices--;
+    if (voices < 0)
+        voices = 0;
+    if (voices == 0) {
+        #ifdef PWM_AUDIO
+            TIMSK3 &= ~_BV(OCIE3A);
+        #else
+            TIMSK3 &= ~_BV(OCIE3A);
+            TCCR3A &= ~_BV(COM3A1);
+        #endif
+        frequency = 0;
+        volume = 0;
+        note = false;
+    } else {
+        double freq = frequencies[voices - 1];
+        int vol = volumes[voices - 1];
+        double starting_f = frequency;
+        if (frequency < freq) {
+            sliding = true;
+            for (double f = starting_f; f <= freq; f += ((freq - starting_f) / 2000.0)) {
+                frequency = f;
+            }
+            sliding = false;
+        } else if (frequency > freq) {
+            sliding = true;
+            for (double f = starting_f; f >= freq; f -= ((starting_f - freq) / 2000.0)) {
+                frequency = f;
+            }
+            sliding = false;
+        }
+        frequency = freq;
+        volume = vol;
+    }
+}
+
+void init_notes() {
+
+    #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
+}
+
+
+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 (frequency > 0) {
+                // ICR3 = (int)(((double)F_CPU) / frequency); // Set max to the period
+                // OCR3A = (int)(((double)F_CPU) / frequency) >> 1; // Set compare to half the period
+                if (place > 10) {
+                    voice_place = (voice_place + 1) % voices;
+                    place = 0.0;
+                }
+                ICR3 = (int)(((double)F_CPU) / frequencies[voice_place]); // Set max to the period
+                OCR3A = (int)(((double)F_CPU) / frequencies[voice_place]) >> 1; // Set compare to half the period
+                place++;
+            }
+        #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) {
+                ICR3 = (int)(((double)F_CPU) / note_frequency); // Set max to the period
+                OCR3A = (int)(((double)F_CPU) / note_frequency) >> 1; // Set compare to half the period
+            }
+        #endif
+
+
+        note_position++;
+        if (note_position >= note_length) {
+            current_note++;
+            if (current_note >= notes_length) {
+                if (notes_repeat) {
+                    current_note = 0;
+                } else {
+                    #ifdef PWM_AUDIO
+                        TIMSK3 &= ~_BV(OCIE3A);
+                    #else
+                        TIMSK3 &= ~_BV(OCIE3A);
+                        TCCR3A &= ~_BV(COM3A1);
+                    #endif
+                    notes = false;
+                    return;
+                }
+            }
+            #ifdef PWM_AUDIO
+                note_frequency = (*notes_pointer)[current_note][0] / SAMPLE_RATE;
+                note_length = (*notes_pointer)[current_note][1];
+            #else
+                note_frequency = (*notes_pointer)[current_note][0];
+                note_length = (*notes_pointer)[current_note][1] / 4;
+            #endif
+            note_position = 0;
+        }
+
+    }
+
+}
+
+void play_notes(float (*np)[][2], uint8_t n_length, bool n_repeat) {
+    if (note)
+        stop_all_notes();
+    notes = true;
+
+    notes_pointer = np;
+    notes_length = n_length;
+    notes_repeat = n_repeat;
+
+    place = 0;
+    current_note = 0;
+    #ifdef PWM_AUDIO
+        note_frequency = (*notes_pointer)[current_note][0] / SAMPLE_RATE;
+        note_length = (*notes_pointer)[current_note][1];
+    #else
+        note_frequency = (*notes_pointer)[current_note][0];
+        note_length = (*notes_pointer)[current_note][1] / 4;
+    #endif
+    note_position = 0;
+
+
+    #ifdef PWM_AUDIO
+        TIMSK3 |= _BV(OCIE3A);
+    #else
+        TIMSK3 |= _BV(OCIE3A);
+        TCCR3A |= _BV(COM3A1);
+    #endif
+}
+
+void play_sample(uint8_t * s, uint16_t l, bool r) {
+    stop_all_notes();
+    place_int = 0;
+    sample = s;
+    sample_length = l;
+    repeat = r;
+
+    #ifdef PWM_AUDIO
+        TIMSK3 |= _BV(OCIE3A);
+    #else
+    #endif
+}
+
+void play_note(double freq, int vol) {
+    if (notes)
+        stop_all_notes();
+    note = true;
+    #ifdef PWM_AUDIO
+        freq = freq / SAMPLE_RATE;
+    #endif
+    if (freq > 0) {
+        if (frequency != 0) {
+            double starting_f = frequency;
+            if (frequency < freq) {
+                for (double f = starting_f; f <= freq; f += ((freq - starting_f) / 2000.0)) {   
+                    frequency = f;
+                }
+            } else if (frequency > freq) {
+                for (double f = starting_f; f >= freq; f -= ((starting_f - freq) / 2000.0)) {
+                    frequency = f;
+                }
+            }
+        }
+        frequency = freq;
+        volume = vol;
+
+        frequencies[voices] = frequency;
+        volumes[voices] = volume;
+        voices++;
+    }
+
+    #ifdef PWM_AUDIO
+        TIMSK3 |= _BV(OCIE3A);
+    #else
+        TIMSK3 |= _BV(OCIE3A);
+        TCCR3A |= _BV(COM3A1);
+    #endif
+
+}
\ No newline at end of file
diff --git a/quantum/beeps.h b/quantum/audio.h
index 378983c605..99203cea7a 100644
--- a/quantum/beeps.h
+++ b/quantum/audio.h
@@ -3,10 +3,9 @@
 #include <avr/io.h>
 #include <util/delay.h>
 
-void note(int x, float length);
-void beeps();
-void true_note(float x, float y, float length);
+void play_sample(uint8_t * s, uint16_t l, bool r);
 void play_note(double freq, int vol);
 void stop_note(double freq);
 void stop_all_notes();
-void init_notes();
\ No newline at end of file
+void init_notes();
+void play_notes(float (*np)[][2], uint8_t n_length, bool n_repeat);
\ No newline at end of file
diff --git a/quantum/beeps.c b/quantum/beeps.c
deleted file mode 100644
index 8d1f81f210..0000000000
--- a/quantum/beeps.c
+++ /dev/null
@@ -1,246 +0,0 @@
-#include "beeps.h"
-#include <math.h>
-#include <avr/pgmspace.h>
-#include <avr/interrupt.h>
-#include <avr/io.h>
-
-#define PI 3.14159265
-
-void delay_us(int count) {
-  while(count--) {
-    _delay_us(1);
-  }
-}
-
-int voices = 0;
-double frequency = 0;
-int volume = 0;
-int position = 0;
-
-double frequencies[8] = {0, 0, 0, 0, 0, 0, 0, 0};
-int volumes[8] = {0, 0, 0, 0, 0, 0, 0, 0};
-bool sliding = false;
-#define RANGE 1000
-volatile int i=0; //elements of the wave
-
-
-void beeps() {
-    play_notes();
-}
-
-void send_freq(double freq, int vol) {
-    int duty = (((double)F_CPU) / freq);
-    ICR3 = duty; // Set max to the period
-    OCR3A = duty >> (0x10 - vol); // Set compare to half the period
-}
-
-void stop_all_notes() {
-    voices = 0;
-    TCCR3A = 0;
-    TCCR3B = 0;
-    frequency = 0;
-    volume = 0;
-
-    for (int i = 0; i < 8; i++) {
-        frequencies[i] = 0;
-        volumes[i] = 0;
-    }
-}
-
-void stop_note(double freq) {
-    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;
-            }
-        }
-    }
-    voices--;
-    if (voices < 0)
-        voices = 0;
-    if (voices == 0) {
-        TCCR3A = 0;
-        TCCR3B = 0;
-        frequency = 0;
-        volume = 0;
-    } else {
-        double freq = frequencies[voices - 1];
-        int vol = volumes[voices - 1];
-        if (frequency < freq) {
-            sliding = true;
-            for (double f = frequency; f <= freq; f += ((freq - frequency) / 500.0)) {
-                send_freq(f, vol);
-            }
-            sliding = false;
-        } else if (frequency > freq) {
-            sliding = true;
-            for (double f = frequency; f >= freq; f -= ((frequency - freq) / 500.0)) {
-                send_freq(f, vol);
-            }
-            sliding = false;
-        }
-        send_freq(freq, vol);
-        frequency = freq;
-        volume = vol;
-    }
-}
-
-void init_notes() {
-    // TCCR1A = (1 << COM1A1) | (0 << COM1A0) | (1 << WGM11) | (1 << WGM10);
-    // TCCR1B = (1 << COM1B1) | (0 << COM1A0) | (1 << WGM13) | (1 << WGM12) | (0 << CS12) | (0 << CS11) | (1 << CS10);
-
-    // DDRC |= (1<<6); 
-
-    // TCCR3A = (1 << COM3A1) | (0 << COM3A0) | (1 << WGM31) | (0 << WGM30);
-    // TCCR3B = (1 << WGM33) | (1 << WGM32) | (0 << CS32) | (0 << CS31) | (1 << CS30);
-
-    // ICR3 = 0xFFFF; 
-    // OCR3A = (int)((float)wave[i]*ICR3/RANGE); //go to next array element
-
-
-    // cli();
-
-    // /* Enable interrupt on timer2 == 127, with clk/8 prescaler. At 16MHz,
-    //    this gives a timer interrupt at 15625Hz. */
-    // TIMSK3 = (1 << OCIE3A);
-
-    // /* clear/reset timer on match */
-    // // TCCR3A = 1<<WGM31 | 0<<WGM30;  CTC mode, reset on match 
-    // // TCCR3B = 0<<CS32 | 1<<CS31 | 0<<CS30; /* clk, /8 prescaler */
-
-    // TCCR3A = (1 << COM3A1) | (0 << COM3A0) | (1 << WGM31) | (0 << WGM30);
-    // TCCR3B = (0 << WGM33) | (0 << WGM32) | (0 << CS32) | (0 << CS31) | (1 << CS30);
-
-
-    // TCCR1A = (1 << COM1A1) | (0 << COM1A0) | (1 << WGM11) | (0 << WGM10);
-    // TCCR1B = (1 << WGM12) | (0 << CS12) | (0 << CS11) | (1 << CS10);
-    // // SPCR = 0x50;
-    // // SPSR = 0x01;
-    // DDRC |= (1<<6);
-    // // ICR3 = 0xFFFF; 
-    // // OCR3A=80;
-    // PORTC |= (1<<6);
-
-    // sei();
-}
-
-// #define highByte(c) ((c >> 8) & 0x00FF)
-// #define lowByte(c) (c & 0x00FF)
-
-ISR(TIMER3_COMPA_vect) {
-
-    if (ICR3 > 0 && !sliding) {
-        switch (position) {
-            case 0: {
-                int duty = (((double)F_CPU) / (frequency));
-                ICR3 = duty; // Set max to the period
-                OCR3A = duty >> 1; // Set compare to half the period
-                break;
-            }
-            case 1: {
-                int duty = (((double)F_CPU) / (frequency*2));
-                ICR3 = duty; // Set max to the period
-                OCR3A = duty >> 1; // Set compare to half the period
-                break;
-            }
-            case 2: {
-                int duty = (((double)F_CPU) / (frequency*3));
-                ICR3 = duty; // Set max to the period
-                OCR3A = duty >> 1; // Set compare to half the period
-                break;
-            }
-        }
-        position = (position + 1) % 3;
-    }
-//     /* OCR2A has been cleared, per TCCR2A above */
-//     // OCR3A = 127;
-
-//     // pos1 += incr1;
-//     // pos2 += incr2;
-//     // pos3 += incr3;
-
-//     // sample = sinewave[highByte(pos1)] + sinewave[highByte(pos2)] + sinewave[highByte(pos3)];
-
-//     // OCR3A = sample;
-
-
-//     OCR3A=pgm_read_byte(&sinewave[pos1]);
-//     pos1++;
-//     // PORTC &= ~(1<<6);
-
-//     /* buffered, 1x gain, active mode */
-//     // SPDR = highByte(sample) | 0x70;
-//     // while (!(SPSR & (1<<SPIF)));
-
-//     // SPDR = lowByte(sample);
-//     // while (!(SPSR & (1<<SPIF)));
-
-//     // PORTC |= (1<<6);
-}
-
-void play_note(double freq, int vol) {
-
-    if (freq > 0) {
-        DDRC |= (1<<6); 
-
-        TCCR3A = (1 << COM3A1) | (0 << COM3A0) | (1 << WGM31) | (0 << WGM30);
-        TCCR3B = (1 << WGM33) | (1 << WGM32) | (0 << CS32) | (1 << CS31) | (0 << CS30);
-
-        if (frequency != 0) {
-            if (frequency < freq) {
-                for (double f = frequency; f <= freq; f += ((freq - frequency) / 500.0)) {
-                    send_freq(f, vol);
-                }
-            } else if (frequency > freq) {
-                for (double f = frequency; f >= freq; f -= ((frequency - freq) / 500.0)) {
-                    send_freq(f, vol);
-                }
-            }
-        }
-        send_freq(freq, vol);
-        frequency = freq;
-        volume = vol;
-
-        frequencies[voices] = frequency;
-        volumes[voices] = volume;
-        voices++;
-    }
-    // ICR3 = 0xFFFF;
-    // for (int i = 0; i < 10000; i++) {
-    //     OCR3A = round((sin(i*freq)*.5)+.5)*0xFFFF;
-    //     // _delay_us(50);
-    // }
-
-    // TCCR3A = 0;
-    // TCCR3B = 0;
-}
-
-// void note(int x, float length) {
-//     DDRC |= (1<<6);
-// 	int t = (int)(440*pow(2,-x/12.0)); // starting note
-//     for (int y = 0; y < length*1000/t; y++) { // note length
-//         PORTC |= (1<<6);
-//         delay_us(t);
-//         PORTC &= ~(1<<6);
-//         delay_us(t);
-//     }
-// 	PORTC &= ~(1<<6);
-// }
-
-// void true_note(float x, float y, float length) {
-// 	for (uint32_t i = 0; i < length * 50; i++) {
-// 		uint32_t v = (uint32_t) (round(sin(PI*2*i*640000*pow(2, x/12.0))*.5+1 + sin(PI*2*i*640000*pow(2, y/12.0))*.5+1) / 2 * pow(2, 8)); 
-// 		for (int u = 0; u < 8; u++) {
-// 			if (v & (1 << u) && !(PORTC&(1<<6)))
-// 		        PORTC |= (1<<6);
-// 		    else if (PORTC&(1<<6))
-// 	        	PORTC &= ~(1<<6);
-// 		}
-// 	}
-// 	PORTC &= ~(1<<6);
-// }
\ No newline at end of file
diff --git a/quantum/keymap_midi.c b/quantum/keymap_midi.c
index b7eba3ab76..e37ea31039 100644
--- a/quantum/keymap_midi.c
+++ b/quantum/keymap_midi.c
@@ -17,7 +17,6 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 #include "keymap_common.h"
 #include "keymap_midi.h"
-#include <lufa.h>
 
 uint8_t starting_note = 0x0C;
 int offset = 7;
@@ -35,7 +34,7 @@ void action_function(keyrecord_t *record, uint8_t id, uint8_t opt)
     if (record->event.key.col == (MATRIX_COLS - 1) && record->event.key.row == (MATRIX_ROWS - 1)) {
         if (record->event.pressed) {
             starting_note++;
-            play_note(((double)261.6)*pow(2.0, -1.0)*pow(2.0,(starting_note + SCALE[0 + offset])/12.0+(MATRIX_ROWS - 1)), 0xC);
+            play_note(((double)261.626)*pow(2.0, -1.0)*pow(2.0,(starting_note + SCALE[0 + offset])/12.0+(MATRIX_ROWS - 1)), 0xC);
             midi_send_cc(&midi_device, 0, 0x7B, 0);
             midi_send_cc(&midi_device, 1, 0x7B, 0);
             midi_send_cc(&midi_device, 2, 0x7B, 0);
@@ -43,7 +42,7 @@ void action_function(keyrecord_t *record, uint8_t id, uint8_t opt)
             midi_send_cc(&midi_device, 4, 0x7B, 0);
             return;
         } else {
-            stop_note(((double)261.6)*pow(2.0, -1.0)*pow(2.0,(starting_note + SCALE[0 + offset])/12.0+(MATRIX_ROWS - 1)));
+            stop_note(((double)261.626)*pow(2.0, -1.0)*pow(2.0,(starting_note + SCALE[0 + offset])/12.0+(MATRIX_ROWS - 1)));
             stop_all_notes();
             return;
         }
@@ -51,7 +50,7 @@ void action_function(keyrecord_t *record, uint8_t id, uint8_t opt)
     if (record->event.key.col == (MATRIX_COLS - 2) && record->event.key.row == (MATRIX_ROWS - 1)) {
         if (record->event.pressed) {
             starting_note--;
-            play_note(((double)261.6)*pow(2.0, -1.0)*pow(2.0,(starting_note + SCALE[0 + offset])/12.0+(MATRIX_ROWS - 1)), 0xC);
+            play_note(((double)261.626)*pow(2.0, -1.0)*pow(2.0,(starting_note + SCALE[0 + offset])/12.0+(MATRIX_ROWS - 1)), 0xC);
             midi_send_cc(&midi_device, 0, 0x7B, 0);
             midi_send_cc(&midi_device, 1, 0x7B, 0);
             midi_send_cc(&midi_device, 2, 0x7B, 0);
@@ -59,7 +58,7 @@ void action_function(keyrecord_t *record, uint8_t id, uint8_t opt)
             midi_send_cc(&midi_device, 4, 0x7B, 0);
             return;
         } else {
-            stop_note(((double)261.6)*pow(2.0, -1.0)*pow(2.0,(starting_note + SCALE[0 + offset])/12.0+(MATRIX_ROWS - 1)));
+            stop_note(((double)261.626)*pow(2.0, -1.0)*pow(2.0,(starting_note + SCALE[0 + offset])/12.0+(MATRIX_ROWS - 1)));
             stop_all_notes();
             return;
         }
@@ -74,9 +73,9 @@ void action_function(keyrecord_t *record, uint8_t id, uint8_t opt)
         midi_send_cc(&midi_device, 4, 0x7B, 0);
         stop_all_notes();
         for (int i = 0; i <= 7; i++) {
-            play_note(((double)261.6)*pow(2.0, -1.0)*pow(2.0,(starting_note + SCALE[i + offset])/12.0+(MATRIX_ROWS - 1)), 0xC);
+            play_note(((double)261.626)*pow(2.0, -1.0)*pow(2.0,(starting_note + SCALE[i + offset])/12.0+(MATRIX_ROWS - 1)), 0xC);
             _delay_us(80000);
-            stop_note(((double)261.6)*pow(2.0, -1.0)*pow(2.0,(starting_note + SCALE[i + offset])/12.0+(MATRIX_ROWS - 1)));
+            stop_note(((double)261.626)*pow(2.0, -1.0)*pow(2.0,(starting_note + SCALE[i + offset])/12.0+(MATRIX_ROWS - 1)));
             _delay_us(8000);
         }
         return;
@@ -90,9 +89,9 @@ void action_function(keyrecord_t *record, uint8_t id, uint8_t opt)
         midi_send_cc(&midi_device, 4, 0x7B, 0);
         stop_all_notes();
         for (int i = 0; i <= 7; i++) {
-            play_note(((double)261.6)*pow(2.0, -1.0)*pow(2.0,(starting_note + SCALE[i + offset])/12.0+(MATRIX_ROWS - 1)), 0xC);
+            play_note(((double)261.626)*pow(2.0, -1.0)*pow(2.0,(starting_note + SCALE[i + offset])/12.0+(MATRIX_ROWS - 1)), 0xC);
             _delay_us(80000);
-            stop_note(((double)261.6)*pow(2.0, -1.0)*pow(2.0,(starting_note + SCALE[i + offset])/12.0+(MATRIX_ROWS - 1)));
+            stop_note(((double)261.626)*pow(2.0, -1.0)*pow(2.0,(starting_note + SCALE[i + offset])/12.0+(MATRIX_ROWS - 1)));
             _delay_us(8000);
         }
         return;
@@ -101,10 +100,10 @@ void action_function(keyrecord_t *record, uint8_t id, uint8_t opt)
     if (record->event.pressed) {
     	// midi_send_noteon(&midi_device, record->event.key.row, starting_note + SCALE[record->event.key.col], 127);
         midi_send_noteon(&midi_device, 0, (starting_note + SCALE[record->event.key.col + offset])+12*(MATRIX_ROWS - record->event.key.row), 127);
-        play_note(((double)261.6)*pow(2.0, -1.0)*pow(2.0,(starting_note + SCALE[record->event.key.col + offset])/12.0+(MATRIX_ROWS - record->event.key.row)), 0xF);
+        play_note(((double)261.626)*pow(2.0, -1.0)*pow(2.0,(starting_note + SCALE[record->event.key.col + offset])/12.0+(MATRIX_ROWS - record->event.key.row)), 0xF);
     } else {
         // midi_send_noteoff(&midi_device, record->event.key.row, starting_note + SCALE[record->event.key.col], 127);
         midi_send_noteoff(&midi_device, 0, (starting_note + SCALE[record->event.key.col + offset])+12*(MATRIX_ROWS - record->event.key.row), 127);
-        stop_note(((double)261.6)*pow(2.0, -1.0)*pow(2.0,(starting_note + SCALE[record->event.key.col + offset])/12.0+(MATRIX_ROWS - record->event.key.row)));
+        stop_note(((double)261.626)*pow(2.0, -1.0)*pow(2.0,(starting_note + SCALE[record->event.key.col + offset])/12.0+(MATRIX_ROWS - record->event.key.row)));
     }
 }
\ No newline at end of file
diff --git a/quantum/keymap_midi.h b/quantum/keymap_midi.h
index c5917f884e..a89420ce2a 100644
--- a/quantum/keymap_midi.h
+++ b/quantum/keymap_midi.h
@@ -18,6 +18,8 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #ifndef KEYMAP_MIDI_H
 #define KEYMAP_MIDI_H
 
+#include <lufa.h>
+
 #define MIDI 0x6000
 #define MIDI12 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000
 
diff --git a/quantum/keymap_unicode.c b/quantum/keymap_unicode.c
index a9357edec7..a44965e611 100644
--- a/quantum/keymap_unicode.c
+++ b/quantum/keymap_unicode.c
@@ -30,6 +30,8 @@ uint16_t hextokeycode(int hex) {
 void action_function(keyrecord_t *record, uint8_t id, uint8_t opt)
 {
 
+    // For more info on how this works per OS, see here: https://en.wikipedia.org/wiki/Unicode_input#Hexadecimal_code_input
+
     if (record->event.pressed) {
         uint16_t unicode = (opt << 8) | id;
         register_code(KC_LALT);
diff --git a/quantum/quantum.mk b/quantum/quantum.mk
index a2b7d8db56..df72241788 100644
--- a/quantum/quantum.mk
+++ b/quantum/quantum.mk
@@ -24,8 +24,11 @@ ifndef CUSTOM_MATRIX
 endif
 
 ifdef MIDI_ENABLE
-	SRC += $(QUANTUM_DIR)/keymap_midi.c \
-		   $(QUANTUM_DIR)/beeps.c
+	SRC += $(QUANTUM_DIR)/keymap_midi.c
+endif
+
+ifdef AUDIO_ENABLE
+	SRC += $(QUANTUM_DIR)/audio.c
 endif
 
 ifdef UNICODE_ENABLE
diff --git a/quantum/wave.h b/quantum/wave.h
new file mode 100644
index 0000000000..6ebc348519
--- /dev/null
+++ b/quantum/wave.h
@@ -0,0 +1,265 @@
+#include <avr/io.h>
+#include <avr/interrupt.h>
+#include <avr/pgmspace.h>
+
+#define SINE_LENGTH 2048
+
+const uint8_t sinewave[] PROGMEM= //2048 values
+{
+0x80,0x80,0x80,0x81,0x81,0x81,0x82,0x82,
+0x83,0x83,0x83,0x84,0x84,0x85,0x85,0x85,
+0x86,0x86,0x87,0x87,0x87,0x88,0x88,0x88,
+0x89,0x89,0x8a,0x8a,0x8a,0x8b,0x8b,0x8c,
+0x8c,0x8c,0x8d,0x8d,0x8e,0x8e,0x8e,0x8f,
+0x8f,0x8f,0x90,0x90,0x91,0x91,0x91,0x92,
+0x92,0x93,0x93,0x93,0x94,0x94,0x95,0x95,
+0x95,0x96,0x96,0x96,0x97,0x97,0x98,0x98,
+0x98,0x99,0x99,0x9a,0x9a,0x9a,0x9b,0x9b,
+0x9b,0x9c,0x9c,0x9d,0x9d,0x9d,0x9e,0x9e,
+0x9e,0x9f,0x9f,0xa0,0xa0,0xa0,0xa1,0xa1,
+0xa2,0xa2,0xa2,0xa3,0xa3,0xa3,0xa4,0xa4,
+0xa5,0xa5,0xa5,0xa6,0xa6,0xa6,0xa7,0xa7,
+0xa7,0xa8,0xa8,0xa9,0xa9,0xa9,0xaa,0xaa,
+0xaa,0xab,0xab,0xac,0xac,0xac,0xad,0xad,
+0xad,0xae,0xae,0xae,0xaf,0xaf,0xb0,0xb0,
+0xb0,0xb1,0xb1,0xb1,0xb2,0xb2,0xb2,0xb3,
+0xb3,0xb4,0xb4,0xb4,0xb5,0xb5,0xb5,0xb6,
+0xb6,0xb6,0xb7,0xb7,0xb7,0xb8,0xb8,0xb8,
+0xb9,0xb9,0xba,0xba,0xba,0xbb,0xbb,0xbb,
+0xbc,0xbc,0xbc,0xbd,0xbd,0xbd,0xbe,0xbe,
+0xbe,0xbf,0xbf,0xbf,0xc0,0xc0,0xc0,0xc1,
+0xc1,0xc1,0xc2,0xc2,0xc2,0xc3,0xc3,0xc3,
+0xc4,0xc4,0xc4,0xc5,0xc5,0xc5,0xc6,0xc6,
+0xc6,0xc7,0xc7,0xc7,0xc8,0xc8,0xc8,0xc9,
+0xc9,0xc9,0xca,0xca,0xca,0xcb,0xcb,0xcb,
+0xcb,0xcc,0xcc,0xcc,0xcd,0xcd,0xcd,0xce,
+0xce,0xce,0xcf,0xcf,0xcf,0xcf,0xd0,0xd0,
+0xd0,0xd1,0xd1,0xd1,0xd2,0xd2,0xd2,0xd2,
+0xd3,0xd3,0xd3,0xd4,0xd4,0xd4,0xd5,0xd5,
+0xd5,0xd5,0xd6,0xd6,0xd6,0xd7,0xd7,0xd7,
+0xd7,0xd8,0xd8,0xd8,0xd9,0xd9,0xd9,0xd9,
+0xda,0xda,0xda,0xda,0xdb,0xdb,0xdb,0xdc,
+0xdc,0xdc,0xdc,0xdd,0xdd,0xdd,0xdd,0xde,
+0xde,0xde,0xde,0xdf,0xdf,0xdf,0xe0,0xe0,
+0xe0,0xe0,0xe1,0xe1,0xe1,0xe1,0xe2,0xe2,
+0xe2,0xe2,0xe3,0xe3,0xe3,0xe3,0xe4,0xe4,
+0xe4,0xe4,0xe4,0xe5,0xe5,0xe5,0xe5,0xe6,
+0xe6,0xe6,0xe6,0xe7,0xe7,0xe7,0xe7,0xe8,
+0xe8,0xe8,0xe8,0xe8,0xe9,0xe9,0xe9,0xe9,
+0xea,0xea,0xea,0xea,0xea,0xeb,0xeb,0xeb,
+0xeb,0xeb,0xec,0xec,0xec,0xec,0xec,0xed,
+0xed,0xed,0xed,0xed,0xee,0xee,0xee,0xee,
+0xee,0xef,0xef,0xef,0xef,0xef,0xf0,0xf0,
+0xf0,0xf0,0xf0,0xf0,0xf1,0xf1,0xf1,0xf1,
+0xf1,0xf2,0xf2,0xf2,0xf2,0xf2,0xf2,0xf3,
+0xf3,0xf3,0xf3,0xf3,0xf3,0xf4,0xf4,0xf4,
+0xf4,0xf4,0xf4,0xf5,0xf5,0xf5,0xf5,0xf5,
+0xf5,0xf5,0xf6,0xf6,0xf6,0xf6,0xf6,0xf6,
+0xf6,0xf7,0xf7,0xf7,0xf7,0xf7,0xf7,0xf7,
+0xf8,0xf8,0xf8,0xf8,0xf8,0xf8,0xf8,0xf8,
+0xf9,0xf9,0xf9,0xf9,0xf9,0xf9,0xf9,0xf9,
+0xfa,0xfa,0xfa,0xfa,0xfa,0xfa,0xfa,0xfa,
+0xfa,0xfa,0xfb,0xfb,0xfb,0xfb,0xfb,0xfb,
+0xfb,0xfb,0xfb,0xfb,0xfc,0xfc,0xfc,0xfc,
+0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,
+0xfd,0xfd,0xfd,0xfd,0xfd,0xfd,0xfd,0xfd,
+0xfd,0xfd,0xfd,0xfd,0xfd,0xfd,0xfe,0xfe,
+0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,
+0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,
+0xfe,0xfe,0xfe,0xfe,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xfe,0xfe,0xfe,
+0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,
+0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,
+0xfe,0xfe,0xfe,0xfd,0xfd,0xfd,0xfd,0xfd,
+0xfd,0xfd,0xfd,0xfd,0xfd,0xfd,0xfd,0xfd,
+0xfd,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,
+0xfc,0xfc,0xfc,0xfc,0xfc,0xfb,0xfb,0xfb,
+0xfb,0xfb,0xfb,0xfb,0xfb,0xfb,0xfb,0xfa,
+0xfa,0xfa,0xfa,0xfa,0xfa,0xfa,0xfa,0xfa,
+0xfa,0xf9,0xf9,0xf9,0xf9,0xf9,0xf9,0xf9,
+0xf9,0xf8,0xf8,0xf8,0xf8,0xf8,0xf8,0xf8,
+0xf8,0xf7,0xf7,0xf7,0xf7,0xf7,0xf7,0xf7,
+0xf6,0xf6,0xf6,0xf6,0xf6,0xf6,0xf6,0xf5,
+0xf5,0xf5,0xf5,0xf5,0xf5,0xf5,0xf4,0xf4,
+0xf4,0xf4,0xf4,0xf4,0xf3,0xf3,0xf3,0xf3,
+0xf3,0xf3,0xf2,0xf2,0xf2,0xf2,0xf2,0xf2,
+0xf1,0xf1,0xf1,0xf1,0xf1,0xf0,0xf0,0xf0,
+0xf0,0xf0,0xf0,0xef,0xef,0xef,0xef,0xef,
+0xee,0xee,0xee,0xee,0xee,0xed,0xed,0xed,
+0xed,0xed,0xec,0xec,0xec,0xec,0xec,0xeb,
+0xeb,0xeb,0xeb,0xeb,0xea,0xea,0xea,0xea,
+0xea,0xe9,0xe9,0xe9,0xe9,0xe8,0xe8,0xe8,
+0xe8,0xe8,0xe7,0xe7,0xe7,0xe7,0xe6,0xe6,
+0xe6,0xe6,0xe5,0xe5,0xe5,0xe5,0xe4,0xe4,
+0xe4,0xe4,0xe4,0xe3,0xe3,0xe3,0xe3,0xe2,
+0xe2,0xe2,0xe2,0xe1,0xe1,0xe1,0xe1,0xe0,
+0xe0,0xe0,0xe0,0xdf,0xdf,0xdf,0xde,0xde,
+0xde,0xde,0xdd,0xdd,0xdd,0xdd,0xdc,0xdc,
+0xdc,0xdc,0xdb,0xdb,0xdb,0xda,0xda,0xda,
+0xda,0xd9,0xd9,0xd9,0xd9,0xd8,0xd8,0xd8,
+0xd7,0xd7,0xd7,0xd7,0xd6,0xd6,0xd6,0xd5,
+0xd5,0xd5,0xd5,0xd4,0xd4,0xd4,0xd3,0xd3,
+0xd3,0xd2,0xd2,0xd2,0xd2,0xd1,0xd1,0xd1,
+0xd0,0xd0,0xd0,0xcf,0xcf,0xcf,0xcf,0xce,
+0xce,0xce,0xcd,0xcd,0xcd,0xcc,0xcc,0xcc,
+0xcb,0xcb,0xcb,0xcb,0xca,0xca,0xca,0xc9,
+0xc9,0xc9,0xc8,0xc8,0xc8,0xc7,0xc7,0xc7,
+0xc6,0xc6,0xc6,0xc5,0xc5,0xc5,0xc4,0xc4,
+0xc4,0xc3,0xc3,0xc3,0xc2,0xc2,0xc2,0xc1,
+0xc1,0xc1,0xc0,0xc0,0xc0,0xbf,0xbf,0xbf,
+0xbe,0xbe,0xbe,0xbd,0xbd,0xbd,0xbc,0xbc,
+0xbc,0xbb,0xbb,0xbb,0xba,0xba,0xba,0xb9,
+0xb9,0xb8,0xb8,0xb8,0xb7,0xb7,0xb7,0xb6,
+0xb6,0xb6,0xb5,0xb5,0xb5,0xb4,0xb4,0xb4,
+0xb3,0xb3,0xb2,0xb2,0xb2,0xb1,0xb1,0xb1,
+0xb0,0xb0,0xb0,0xaf,0xaf,0xae,0xae,0xae,
+0xad,0xad,0xad,0xac,0xac,0xac,0xab,0xab,
+0xaa,0xaa,0xaa,0xa9,0xa9,0xa9,0xa8,0xa8,
+0xa7,0xa7,0xa7,0xa6,0xa6,0xa6,0xa5,0xa5,
+0xa5,0xa4,0xa4,0xa3,0xa3,0xa3,0xa2,0xa2,
+0xa2,0xa1,0xa1,0xa0,0xa0,0xa0,0x9f,0x9f,
+0x9e,0x9e,0x9e,0x9d,0x9d,0x9d,0x9c,0x9c,
+0x9b,0x9b,0x9b,0x9a,0x9a,0x9a,0x99,0x99,
+0x98,0x98,0x98,0x97,0x97,0x96,0x96,0x96,
+0x95,0x95,0x95,0x94,0x94,0x93,0x93,0x93,
+0x92,0x92,0x91,0x91,0x91,0x90,0x90,0x8f,
+0x8f,0x8f,0x8e,0x8e,0x8e,0x8d,0x8d,0x8c,
+0x8c,0x8c,0x8b,0x8b,0x8a,0x8a,0x8a,0x89,
+0x89,0x88,0x88,0x88,0x87,0x87,0x87,0x86,
+0x86,0x85,0x85,0x85,0x84,0x84,0x83,0x83,
+0x83,0x82,0x82,0x81,0x81,0x81,0x80,0x80,
+0x80,0x7f,0x7f,0x7e,0x7e,0x7e,0x7d,0x7d,
+0x7c,0x7c,0x7c,0x7b,0x7b,0x7a,0x7a,0x7a,
+0x79,0x79,0x78,0x78,0x78,0x77,0x77,0x77,
+0x76,0x76,0x75,0x75,0x75,0x74,0x74,0x73,
+0x73,0x73,0x72,0x72,0x71,0x71,0x71,0x70,
+0x70,0x70,0x6f,0x6f,0x6e,0x6e,0x6e,0x6d,
+0x6d,0x6c,0x6c,0x6c,0x6b,0x6b,0x6a,0x6a,
+0x6a,0x69,0x69,0x69,0x68,0x68,0x67,0x67,
+0x67,0x66,0x66,0x65,0x65,0x65,0x64,0x64,
+0x64,0x63,0x63,0x62,0x62,0x62,0x61,0x61,
+0x61,0x60,0x60,0x5f,0x5f,0x5f,0x5e,0x5e,
+0x5d,0x5d,0x5d,0x5c,0x5c,0x5c,0x5b,0x5b,
+0x5a,0x5a,0x5a,0x59,0x59,0x59,0x58,0x58,
+0x58,0x57,0x57,0x56,0x56,0x56,0x55,0x55,
+0x55,0x54,0x54,0x53,0x53,0x53,0x52,0x52,
+0x52,0x51,0x51,0x51,0x50,0x50,0x4f,0x4f,
+0x4f,0x4e,0x4e,0x4e,0x4d,0x4d,0x4d,0x4c,
+0x4c,0x4b,0x4b,0x4b,0x4a,0x4a,0x4a,0x49,
+0x49,0x49,0x48,0x48,0x48,0x47,0x47,0x47,
+0x46,0x46,0x45,0x45,0x45,0x44,0x44,0x44,
+0x43,0x43,0x43,0x42,0x42,0x42,0x41,0x41,
+0x41,0x40,0x40,0x40,0x3f,0x3f,0x3f,0x3e,
+0x3e,0x3e,0x3d,0x3d,0x3d,0x3c,0x3c,0x3c,
+0x3b,0x3b,0x3b,0x3a,0x3a,0x3a,0x39,0x39,
+0x39,0x38,0x38,0x38,0x37,0x37,0x37,0x36,
+0x36,0x36,0x35,0x35,0x35,0x34,0x34,0x34,
+0x34,0x33,0x33,0x33,0x32,0x32,0x32,0x31,
+0x31,0x31,0x30,0x30,0x30,0x30,0x2f,0x2f,
+0x2f,0x2e,0x2e,0x2e,0x2d,0x2d,0x2d,0x2d,
+0x2c,0x2c,0x2c,0x2b,0x2b,0x2b,0x2a,0x2a,
+0x2a,0x2a,0x29,0x29,0x29,0x28,0x28,0x28,
+0x28,0x27,0x27,0x27,0x26,0x26,0x26,0x26,
+0x25,0x25,0x25,0x25,0x24,0x24,0x24,0x23,
+0x23,0x23,0x23,0x22,0x22,0x22,0x22,0x21,
+0x21,0x21,0x21,0x20,0x20,0x20,0x1f,0x1f,
+0x1f,0x1f,0x1e,0x1e,0x1e,0x1e,0x1d,0x1d,
+0x1d,0x1d,0x1c,0x1c,0x1c,0x1c,0x1b,0x1b,
+0x1b,0x1b,0x1b,0x1a,0x1a,0x1a,0x1a,0x19,
+0x19,0x19,0x19,0x18,0x18,0x18,0x18,0x17,
+0x17,0x17,0x17,0x17,0x16,0x16,0x16,0x16,
+0x15,0x15,0x15,0x15,0x15,0x14,0x14,0x14,
+0x14,0x14,0x13,0x13,0x13,0x13,0x13,0x12,
+0x12,0x12,0x12,0x12,0x11,0x11,0x11,0x11,
+0x11,0x10,0x10,0x10,0x10,0x10,0xf,0xf,
+0xf,0xf,0xf,0xf,0xe,0xe,0xe,0xe,
+0xe,0xd,0xd,0xd,0xd,0xd,0xd,0xc,
+0xc,0xc,0xc,0xc,0xc,0xb,0xb,0xb,
+0xb,0xb,0xb,0xa,0xa,0xa,0xa,0xa,
+0xa,0xa,0x9,0x9,0x9,0x9,0x9,0x9,
+0x9,0x8,0x8,0x8,0x8,0x8,0x8,0x8,
+0x7,0x7,0x7,0x7,0x7,0x7,0x7,0x7,
+0x6,0x6,0x6,0x6,0x6,0x6,0x6,0x6,
+0x5,0x5,0x5,0x5,0x5,0x5,0x5,0x5,
+0x5,0x5,0x4,0x4,0x4,0x4,0x4,0x4,
+0x4,0x4,0x4,0x4,0x3,0x3,0x3,0x3,
+0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,
+0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,
+0x2,0x2,0x2,0x2,0x2,0x2,0x1,0x1,
+0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,
+0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,
+0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,
+0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+0x0,0x0,0x0,0x0,0x0,0x1,0x1,0x1,
+0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,
+0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,
+0x1,0x1,0x1,0x2,0x2,0x2,0x2,0x2,
+0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,
+0x2,0x3,0x3,0x3,0x3,0x3,0x3,0x3,
+0x3,0x3,0x3,0x3,0x3,0x4,0x4,0x4,
+0x4,0x4,0x4,0x4,0x4,0x4,0x4,0x5,
+0x5,0x5,0x5,0x5,0x5,0x5,0x5,0x5,
+0x5,0x6,0x6,0x6,0x6,0x6,0x6,0x6,
+0x6,0x7,0x7,0x7,0x7,0x7,0x7,0x7,
+0x7,0x8,0x8,0x8,0x8,0x8,0x8,0x8,
+0x9,0x9,0x9,0x9,0x9,0x9,0x9,0xa,
+0xa,0xa,0xa,0xa,0xa,0xa,0xb,0xb,
+0xb,0xb,0xb,0xb,0xc,0xc,0xc,0xc,
+0xc,0xc,0xd,0xd,0xd,0xd,0xd,0xd,
+0xe,0xe,0xe,0xe,0xe,0xf,0xf,0xf,
+0xf,0xf,0xf,0x10,0x10,0x10,0x10,0x10,
+0x11,0x11,0x11,0x11,0x11,0x12,0x12,0x12,
+0x12,0x12,0x13,0x13,0x13,0x13,0x13,0x14,
+0x14,0x14,0x14,0x14,0x15,0x15,0x15,0x15,
+0x15,0x16,0x16,0x16,0x16,0x17,0x17,0x17,
+0x17,0x17,0x18,0x18,0x18,0x18,0x19,0x19,
+0x19,0x19,0x1a,0x1a,0x1a,0x1a,0x1b,0x1b,
+0x1b,0x1b,0x1b,0x1c,0x1c,0x1c,0x1c,0x1d,
+0x1d,0x1d,0x1d,0x1e,0x1e,0x1e,0x1e,0x1f,
+0x1f,0x1f,0x1f,0x20,0x20,0x20,0x21,0x21,
+0x21,0x21,0x22,0x22,0x22,0x22,0x23,0x23,
+0x23,0x23,0x24,0x24,0x24,0x25,0x25,0x25,
+0x25,0x26,0x26,0x26,0x26,0x27,0x27,0x27,
+0x28,0x28,0x28,0x28,0x29,0x29,0x29,0x2a,
+0x2a,0x2a,0x2a,0x2b,0x2b,0x2b,0x2c,0x2c,
+0x2c,0x2d,0x2d,0x2d,0x2d,0x2e,0x2e,0x2e,
+0x2f,0x2f,0x2f,0x30,0x30,0x30,0x30,0x31,
+0x31,0x31,0x32,0x32,0x32,0x33,0x33,0x33,
+0x34,0x34,0x34,0x34,0x35,0x35,0x35,0x36,
+0x36,0x36,0x37,0x37,0x37,0x38,0x38,0x38,
+0x39,0x39,0x39,0x3a,0x3a,0x3a,0x3b,0x3b,
+0x3b,0x3c,0x3c,0x3c,0x3d,0x3d,0x3d,0x3e,
+0x3e,0x3e,0x3f,0x3f,0x3f,0x40,0x40,0x40,
+0x41,0x41,0x41,0x42,0x42,0x42,0x43,0x43,
+0x43,0x44,0x44,0x44,0x45,0x45,0x45,0x46,
+0x46,0x47,0x47,0x47,0x48,0x48,0x48,0x49,
+0x49,0x49,0x4a,0x4a,0x4a,0x4b,0x4b,0x4b,
+0x4c,0x4c,0x4d,0x4d,0x4d,0x4e,0x4e,0x4e,
+0x4f,0x4f,0x4f,0x50,0x50,0x51,0x51,0x51,
+0x52,0x52,0x52,0x53,0x53,0x53,0x54,0x54,
+0x55,0x55,0x55,0x56,0x56,0x56,0x57,0x57,
+0x58,0x58,0x58,0x59,0x59,0x59,0x5a,0x5a,
+0x5a,0x5b,0x5b,0x5c,0x5c,0x5c,0x5d,0x5d,
+0x5d,0x5e,0x5e,0x5f,0x5f,0x5f,0x60,0x60,
+0x61,0x61,0x61,0x62,0x62,0x62,0x63,0x63,
+0x64,0x64,0x64,0x65,0x65,0x65,0x66,0x66,
+0x67,0x67,0x67,0x68,0x68,0x69,0x69,0x69,
+0x6a,0x6a,0x6a,0x6b,0x6b,0x6c,0x6c,0x6c,
+0x6d,0x6d,0x6e,0x6e,0x6e,0x6f,0x6f,0x70,
+0x70,0x70,0x71,0x71,0x71,0x72,0x72,0x73,
+0x73,0x73,0x74,0x74,0x75,0x75,0x75,0x76,
+0x76,0x77,0x77,0x77,0x78,0x78,0x78,0x79,
+0x79,0x7a,0x7a,0x7a,0x7b,0x7b,0x7c,0x7c,
+0x7c,0x7d,0x7d,0x7e,0x7e,0x7e,0x7f,0x7f
+};
\ No newline at end of file