Created
April 9, 2018 14:37
-
-
Save lithium/373815a5e71f9eae17f049fb10e417ab to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include "tables.h" | |
| #include <MIDI.h> | |
| MIDI_CREATE_DEFAULT_INSTANCE(); | |
| #define FS 20000.0 // sample rate in hz | |
| #define ledPin 13 | |
| class SynthVoice { | |
| private: | |
| volatile unsigned int phase; | |
| volatile unsigned int tuning_word; | |
| volatile unsigned char level; | |
| volatile unsigned int frequency; | |
| volatile const char *wave; | |
| public: | |
| SynthVoice() { | |
| this->phase = 0; | |
| this->tuning_word = 1000; | |
| this->level = 255; | |
| this->frequency = 500; | |
| this->wave = (const char *)SinTable; | |
| } | |
| void setFrequency(float f) | |
| { | |
| this->frequency = f / (FS/65535.0); | |
| } | |
| void setNote(unsigned char MIDInote) | |
| { | |
| this->frequency = pgm_read_word(PITCHS + MIDInote); | |
| this->tuning_word = this->frequency + (int)((this->frequency >> 6) / 128); | |
| } | |
| void setWave(char *wave) | |
| { | |
| this->wave = wave; | |
| } | |
| signed char nextSample() | |
| { | |
| return ((signed char)pgm_read_byte(this->wave + ((unsigned char *)&(this->phase += this->tuning_word))[1]) * this->level) >> 8; | |
| } | |
| }; | |
| SynthVoice *voices[4]; | |
| void HandleNoteOn(byte channel, byte pitch, byte velocity) | |
| { | |
| // Do something here with your data! | |
| voices[0]->setNote(pitch); | |
| } | |
| void HandleCC(byte channel, byte pitch, byte velocity) | |
| { | |
| // Do something here with your data! | |
| } | |
| void HandleNoteOff(byte channel, byte pitch, byte velocity) | |
| { | |
| // Do something here with your data! | |
| } | |
| void setup() { | |
| pinMode(ledPin, OUTPUT); | |
| voices[0] = new SynthVoice(); | |
| voices[0]->setNote(60); | |
| voices[1] = new SynthVoice(); | |
| voices[1]->setNote(63); | |
| voices[2] = new SynthVoice(); | |
| voices[2]->setNote(67); | |
| voices[2] = new SynthVoice(); | |
| voices[2]->setNote(70); | |
| //setup audio interrupt on TIMER1 | |
| TCCR1A = 0x00; | |
| TCCR1B = 0x09; | |
| TCCR1C = 0x00; | |
| OCR1A = 16000000.0 / FS; // sample rate | |
| TIMSK1 |= (1<<OCIE1A); | |
| sei(); | |
| //8-bit audio pwm | |
| TCCR2A = 0xB3; | |
| TCCR2B = 0x01; | |
| OCR2A = OCR2B = 127; | |
| DDRB |= 1<<3; | |
| DDRD |= 1<<3; | |
| //midi handlers | |
| MIDI.begin(MIDI_CHANNEL_OMNI); | |
| MIDI.setHandleNoteOn(HandleNoteOn); | |
| MIDI.setHandleControlChange(HandleCC); | |
| MIDI.setHandleNoteOff(HandleNoteOff); | |
| } | |
| void loop() { | |
| MIDI.read(); | |
| } | |
| SIGNAL(TIMER1_COMPA_vect) | |
| { | |
| OCR2A = OCR2B = 127 + ( | |
| ( | |
| voices[0]->nextSample() | |
| +voices[1]->nextSample() | |
| +voices[2]->nextSample() | |
| +voices[3]->nextSample() | |
| ) >> 2 | |
| ); | |
| } | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment