Skip to content

Commit

Permalink
add polyphony
Browse files Browse the repository at this point in the history
  • Loading branch information
chee committed Jan 11, 2021
1 parent 8778c9d commit be48896
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 26 deletions.
5 changes: 5 additions & 0 deletions README.md
@@ -0,0 +1,5 @@
# wavetablet

This is mostly just a little wrapper around paul's teensy audio library synth_wavetable, updated to make sure it runs on the ATSAMD51 with adafruit's atsamd fork of Audio.

the `decoder.py` here is taken the teensy AudioSynthWaveform repo, with changes to make it output parsed soundfonts in the format expressed in the `synth_wavetable.cpp` file from the Audio repo
112 changes: 86 additions & 26 deletions src/main.cc
@@ -1,23 +1,37 @@
#include <Arduino.h>
#include <SPI.h>
#include <Wire.h>
#include <AudioStream.h>
#include <Audio.h>
#include <AudioStream.h>
#include <SPI.h>
#include <USB-MIDI.h>
#include <Wire.h>
#include <synth_wavetable.h>
#include <AnalogSaw_samples.h>
#include <Flute_100kbyte_samples.h>

// #include <AnalogSaw_samples.h>
// #include <Flute_100kbyte_samples.h>
#include <lead_samples.h>
auto instrument = lead;

// Audio mixers can take 4 inputs
// Let's have 8 inputs in total for an 8-finger polyphonic synth
AudioMixer4 left_hand;
AudioMixer4 right_hand;

AudioSynthWavetable synth1;
AudioSynthKarplusStrong string1;
AudioConnection patch1(synth1, 0, left_hand, 0);
AudioConnection patch2(string1, 0, left_hand, 1);
const int len_voices = 4 * 2;

AudioSynthWavetable wavetable0, wavetable1, wavetable2, wavetable3, wavetable4,
wavetable5, wavetable6, wavetable7;
AudioSynthWavetable *wavetables[]{&wavetable0, &wavetable1, &wavetable2,
&wavetable3, &wavetable4, &wavetable5,
&wavetable6, &wavetable7};

AudioConnection tl0(wavetable0, 0, left_hand, 0);
AudioConnection tl1(wavetable1, 0, left_hand, 1);
AudioConnection tl2(wavetable2, 0, left_hand, 2);
AudioConnection tl3(wavetable3, 0, left_hand, 3);
AudioConnection tr4(wavetable4, 0, right_hand, 0);
AudioConnection tr5(wavetable5, 0, right_hand, 1);
AudioConnection tr6(wavetable6, 0, right_hand, 2);
AudioConnection tr7(wavetable7, 0, right_hand, 3);

// mixers can take mixers as inputs, so let's create another to be sent to both
// speakers. pc2064v1 will be a polyphonic synth with monophonic output
Expand All @@ -33,27 +47,75 @@ AudioConnection patch_right_ear(mixer, 0, audioOut, 1);
// some day to replace this with tinyusb again
USBMIDI_CREATE_DEFAULT_INSTANCE();

class Voice {
public:
int id;
byte note;
int age;
};

Voice voices[len_voices];

int age = 0;

void play(Voice *voice, byte note, byte velocity) {
auto wt = wavetables[voice->id];
voice->note = note;
voice->age = age++;
wt->playNote(voice->note, velocity);
}

void noteOn(byte channel, byte note, byte velocity) {
Serial.printf("c: %d, note: %d, v: %d", channel, note, velocity);
AudioNoInterrupts();
synth1.playNote(note, 100);
// string1.noteOn(synth1.noteToFreq(note), 0.9);
AudioInterrupts();
int oldest_age = infinity();
int oldest_index = 0;

// get a free one
for (int i = 0; i < len_voices; i++) {
if (wavetables[i]->getEnvState() ==
AudioSynthWavetable::envelopeStateEnum::STATE_IDLE) {
return play(&voices[i], note, velocity);
}

// ok, a releasing one then
if (wavetables[i]->getEnvState() ==
AudioSynthWavetable::envelopeStateEnum::STATE_RELEASE) {
return play(&voices[i], note, velocity);
}

// or the eldest
if (voices[i].age < oldest_age) {
oldest_index = i;
oldest_age = voices[i].age;
}
}

play(&voices[oldest_index], note, velocity);
}

void noteOff(byte channel, byte note, byte velocity) {
Serial.printf("c: %d, note: %d, v: %d", channel, note, velocity);
synth1.stop();
bool nothing = true;
for (int i = 0; i < len_voices; i++) {
if (wavetables[i]->getEnvState()) {
nothing = false;
}
if (voices[i].note == note) {
wavetables[i]->stop();
}
}
if (nothing) {
age = 0;
}
}

void setup() {
synth1.setInstrument(lead);
synth1.amplitude(1);
Serial.println("hello, jerg");
left_hand.gain(0, 1.0);
right_hand.gain(0, 1.0);
mixer.gain(0, 0.5);
mixer.gain(1, 0.5);
for (int i = 0; i < len_voices; i++) {
voices[i].id = i;
wavetables[i]->setInstrument(instrument);
wavetables[i]->amplitude(1);
}

mixer.gain(0, 0.01);
mixer.gain(1, 0.01);
AudioMemory(22);
AudioProcessorUsageMaxReset();
AudioMemoryUsageMaxReset();
Expand All @@ -62,6 +124,4 @@ void setup() {
MIDI.setHandleNoteOff(noteOff);
}

void loop() {
MIDI.read();
}
void loop() { MIDI.read(); }

0 comments on commit be48896

Please sign in to comment.