Created
May 6, 2017 22:02
-
-
Save LeoAdamek/2adc26d593a3de9257b63c17643ab016 to your computer and use it in GitHub Desktop.
Polyphonic Synth
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 <Audio.h> | |
#include <MIDI.h> | |
typedef struct { | |
AudioSynthWaveformSine osc; | |
byte note; | |
float freq; | |
float amp; | |
AudioConnection w_lft; | |
AudioConnection w_rgt; | |
} Voice; | |
AudioOutputAnalog uselessOutput; | |
AudioOutputUSB audioRet; | |
AudioMixer4 mixA, mixB, mixC; | |
Voice* voices; | |
unsigned char activeVoices, i; | |
void setup() { | |
AudioMemory(32); | |
activeVoices = 0x00; | |
voices = (Voice*)malloc(6 * sizeof(Voice)); | |
// Connect the first 3 voices to mixA | |
AudioConnection v0mA(voices[0].osc, 0, mixA, 0); | |
AudioConnection v1mA(voices[1].osc, 0, mixA, 1); | |
AudioConnection v2mA(voices[2].osc, 0, mixA, 2); | |
// Connect the last 3 voices to mixB | |
AudioConnection v3mB(voices[3].osc, 0, mixB, 0); | |
AudioConnection v4mB(voices[4].osc, 0, mixB, 1); | |
AudioConnection v5mB(voices[5].osc, 0, mixB, 2); | |
// Connect mix A and B to mix C | |
AudioConnection mAmC(mixA, 0, mixC, 0); | |
AudioConnection mBmC(mixB, 0, mixC, 1); | |
// Connect mix C to Output L and R | |
AudioConnection mCoL(mixC, 0, audioRet, 0); | |
AudioConnection mCoR(mixC, 0, audioRet, 1); | |
// Serial will be used for debugging messages. | |
Serial.begin(9600); | |
// Callbacks for note handling. | |
usbMIDI.setHandleNoteOff(OnNoteOff); | |
usbMIDI.setHandleNoteOn(OnNoteOn); | |
Serial.println("Teensynth (teensy-unth) v0 @ " __FILE__); | |
} | |
void loop() { | |
// Continuously read and handle MIDI messages. | |
usbMIDI.read(); | |
} | |
void OnNoteOn(byte channel, byte note, byte vel) { | |
for(i = 0; i < 6; i++) { | |
// Serial.printf("i = %d \t v = %01x \t a = %01x\n", i, (1<<i), (activeVoices & (1<<i))); | |
if ( (activeVoices & (1<<i)) == 0) { | |
//Serial.printf("Voice %0d on.\n", i); | |
activeVoices |= (1<<i); | |
voices[i].amp = 1; | |
voices[i].note = note; | |
voices[i].freq = noteToFreq(note); | |
voices[i].osc.amplitude(1); | |
voices[i].osc.frequency(voices[i].freq); | |
break; | |
} | |
} | |
Serial.printf("Active Voices: %0x\n", activeVoices); | |
} | |
void OnNoteOff(byte channel, byte note, byte vel) { | |
for(i = 0; i < 6; i++) { | |
//Serial.printf("i = %0d \t v = %02x \t a = %02x\n", i, (1<<i), (activeVoices & (1<<i))); | |
//Serial.printf("v[i].note = %02x\n", voices[i].note); | |
if(voices[i].note == note && (activeVoices & (1<<i)) != 0 ) { | |
//Serial.printf("Voice %0d Off.", i); | |
voices[i].note = 0xff; | |
voices[i].amp = 0; | |
voices[i].osc.amplitude(0); | |
activeVoices &= ~(1<<i); | |
break; | |
} | |
} | |
Serial.printf("Active Voices: %0x\n", activeVoices); | |
} | |
// Convert MIDI note to tonal freq. | |
// | |
// Formula: 440 * 2^( midi_note_val - 69) / 12) | |
float noteToFreq(byte note) { | |
float freq = 440 * pow(2, (float(note - 69) / 12)); | |
// Serial.printf("Note: %x // Freq: %.2fHz\n", note, freq); | |
return freq; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment