Skip to content

Instantly share code, notes, and snippets.

@lithium
Created April 9, 2018 14:37
Show Gist options
  • Select an option

  • Save lithium/373815a5e71f9eae17f049fb10e417ab to your computer and use it in GitHub Desktop.

Select an option

Save lithium/373815a5e71f9eae17f049fb10e417ab to your computer and use it in GitHub Desktop.
#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