MIDI Oscillator Project

Status
Not open for further replies.

warblingwombats

New member
Hey everyone,

I just got my first Teensy & audio shield this week and my first project with it has been to attempt an FM oscillator that work with hardware MIDI for my larger eurorack style synth. Here's a quick breakdown of the features I'm looking to implement:

-Main oscillator that receives MIDI info from my SQ-1 (through 6n138 optocoupler circuit like the one found here: https://www.pjrc.com/teensy/td_libs_MIDI.html)
-FM oscillator that adjusts timbre of the main osc, with pots for modulation amount & modulation frequency
-Main osc bend function for fine tuning to my other instruments
-ADSR envelope controls (yet to be added, the values are set constant for the first test)
-Gate out (this will be the last function I add once I get everything else to work)

My basis for this project has been the code and videos done by Notes & Volts on his Teensy synth project and I've been working on adapting his code and tossing out what I don't need. Here's a link to that project: https://www.notesandvolts.com/2018/11/teensy-synth-part-9-midi-input.html

So I've already created some test code that only includes MIDI input, main osc pitch bend, and the fm osc controls to make debugging a little easier. I've been staring at this code for a few days now, making small tweaks, and I'm not getting any audio output. I uploaded one of the Teensy audio example sketches and verified that the audio output works, the Teensy seems to be working just fine, and my optocoupler circuit is setup correctly. Based on this, I think the problem is my code (the part I'm the worst at), could anyone give me some pointers or direct me to some similar projects to help me wrap my head around this? Thanks everyone!

Test code:
//Board: Teensy 3.2 / 3.1
//USB type: Serial & MIDI
//CPU Speed: 96MHz (overclock)

#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>
#include <MIDI.h>

// GUItool: begin automatically generated code
AudioSynthWaveform waveform2; //xy=214,351
AudioSynthWaveform waveform1; //xy=216,309
AudioSynthWaveformModulated waveformMod1; //xy=382,337
AudioEffectEnvelope envelope1; //xy=544,337
AudioOutputI2S i2s1; //xy=729,345
AudioConnection patchCord1(waveform2, 0, waveformMod1, 1);
AudioConnection patchCord2(waveform1, 0, waveformMod1, 0);
AudioConnection patchCord3(waveformMod1, envelope1);
AudioConnection patchCord4(envelope1, 0, i2s1, 0);
AudioConnection patchCord5(envelope1, 0, i2s1, 1);
AudioControlSGTL5000 sgtl5000_1; //xy=444,644
// GUItool: end automatically generated code

const byte BUFFER = 8; //Size of keyboard buffer
const float noteFreqs[128] = {8.176, 8.662, 9.177, 9.723, 10.301, 10.913, 11.562, 12.25, 12.978, 13.75, 14.568, 15.434, 16.352, 17.324, 18.354, 19.445, 20.602, 21.827, 23.125, 24.5, 25.957, 27.5, 29.135, 30.868, 32.703, 34.648, 36.708, 38.891, 41.203, 43.654, 46.249, 48.999, 51.913, 55, 58.27, 61.735, 65.406, 69.296, 73.416, 77.782, 82.407, 87.307, 92.499, 97.999, 103.826, 110, 116.541, 123.471, 130.813, 138.591, 146.832, 155.563, 164.814, 174.614, 184.997, 195.998, 207.652, 220, 233.082, 246.942, 261.626, 277.183, 293.665, 311.127, 329.628, 349.228, 369.994, 391.995, 415.305, 440, 466.164, 493.883, 523.251, 554.365, 587.33, 622.254, 659.255, 698.456, 739.989, 783.991, 830.609, 880, 932.328, 987.767, 1046.502, 1108.731, 1174.659, 1244.508, 1318.51, 1396.913, 1479.978, 1567.982, 1661.219, 1760, 1864.655, 1975.533, 2093.005, 2217.461, 2349.318, 2489.016, 2637.02, 2793.826, 2959.955, 3135.963, 3322.438, 3520, 3729.31, 3951.066, 4186.009, 4434.922, 4698.636, 4978.032, 5274.041, 5587.652, 5919.911, 6271.927, 6644.875, 7040, 7458.62, 7902.133, 8372.018, 8869.844, 9397.273, 9956.063, 10548.08, 11175.3, 11839.82, 12543.85};
byte globalNote = 0;
byte globalVelocity = 0;
const float DIV127 = (1.0 / 127.0);
float bendFactor = 1;
int bendRange = 12;

MIDI_CREATE_INSTANCE(HardwareSerial, Serial1, MIDI);

int mainfreq = 440;
int fmamp = 0.75;
int atk = 10.5;
int dec = 35;
int sus = 1;
int rel = 300;

int FmFreqPot = A2;
int FmAmpPot = A3;
int BendPot = A6;
int FmPotAmt = 0;
int BendPotAmt = 0;
int FmFreqAmt = 1;
// int EnvAtkPot = A3;
// int EnvDecPot =

void setup() {
AudioMemory(20);

MIDI.begin(MIDI_CHANNEL_OMNI);

MIDI.setHandleNoteOn(myNoteOn);
MIDI.setHandleNoteOff(myNoteOff);

sgtl5000_1.enable();
sgtl5000_1.volume(0.2);

waveform1.begin(WAVEFORM_SINE);
waveform1.amplitude(0.75);
waveform1.frequency(mainfreq);

waveform2.begin(WAVEFORM_SINE);
waveform2.amplitude(fmamp);
waveform2.frequency(mainfreq * FmFreqAmt);

envelope1.delay(0);
envelope1.attack(atk);
envelope1.hold(0);
envelope1.decay(dec);
envelope1.sustain(sus);
envelope1.release(rel);
}

void loop() {
// put your main code here, to run repeatedly:
MIDI.read();
pots();
}

void myNoteOn(byte channel, byte note, byte velocity) {
if ( note > 23 && note < 108 ) {
globalNote = note;
globalVelocity = velocity;
keyBuff(note, true);
}
}

void myNoteOff(byte channel, byte note, byte velocity) {
if ( note > 23 && note < 108 ) {
keyBuff(note, false);
}
}

void myPitchBend(byte channel, int bendPotAmt) {
float bendF = BendPotAmt;
bendF = bendF *bendRange;
bendF = bendF / 12;
bendFactor = pow(2, bendF);
oscSet();
}

void keyBuff(byte note, bool playNote) {
static byte buff[BUFFER];
static byte buffSize = 0;

// Add Note
if (playNote == true && (buffSize < BUFFER) ) {
oscPlay(note);
buff[buffSize] = note;
buffSize++;
return;
}

// Remove Note
else if (playNote == false && buffSize != 0) {
for (byte found = 0; found < buffSize; found++) {
if (buff[found] == note) {
for (byte gap = found; gap < (buffSize - 1); gap++) {
buff[gap] = buff[gap + 1];
}
buffSize--;
buff[buffSize] = 255;
if (buffSize != 0) {
oscPlay(buff[buffSize - 1]);
return;
}
else {
oscStop();
return;
}
}
}
}
}

void oscPlay(byte note) {
waveform1.frequency(noteFreqs[note] * bendFactor);
waveform2.frequency(noteFreqs[note] * bendFactor * FmFreqAmt);
float velo = 0.75 * (globalVelocity * DIV127);
waveform1.amplitude(0.75);
waveform2.amplitude(FmPotAmt);
envelope1.noteOn();
}

void oscStop() {
envelope1.noteOff();
}

void oscSet() {
waveform1.frequency(noteFreqs[globalNote] * bendFactor);
waveform2.frequency(noteFreqs[globalNote] * bendFactor * FmFreqAmt);
}


void pots() {
FmPotAmt = analogRead (FmAmpPot);
FmPotAmt = map (FmPotAmt, 0, 1023, 0, 1);

BendPotAmt = analogRead (BendPot);
BendPotAmt = map (BendPotAmt, 0, 1023, 0, 12);

FmFreqAmt = analogRead (FmFreqPot);
FmFreqAmt = map (FmFreqAmt, 0, 1023, 0, 10);
}
 
Status
Not open for further replies.
Back
Top