// See: https://forum.pjrc.com/threads/60488
// Try to implement the MusicDSPModel filter
// on Teensy 4.0 using the Play and Record
// queues
// The samples must be normalized to a fraction
// of full-scale for input to the Process function
// and then multiplied by full-scale afterwards.
// If this is defined, the sine wave will
// be played unmodified to the output.
// The only difference is that the Process
// function isn't called.
// This works which proves that the synthesized
// audio is being passed through the queues
// to the output.
//#define STRAIGHT_THROUGH
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <MIDI.h>
#include <midi_UsbTransport.h>
float midicc_Array[128]; // scaled 0-1 values for midi 7-bit
// amplitude of signal
#define WAVE_AMP 32000
#define MDSPM
#ifdef MDSPM
#include "MusicDSPModel.h"
MusicDSPMoog mDSPm(44100);
#else
#include "RKSimulationModel.h"
RKSimulationMoog mDSPm(44100);
#endif
volatile float vcf_cutoff;
boolean midi_flag = HIGH;
// GUItool: begin automatically generated code
AudioSynthWaveform waveform1; //xy=410,296
AudioRecordQueue queue1; //xy=558,297
AudioPlayQueue queue2; //xy=748,298
AudioOutputUSB usb1; //xy=909,404
AudioOutputI2S i2s1; //xy=973,300
AudioConnection patchCord1(waveform1, queue1);
AudioConnection patchCord2(queue2, 0, i2s1, 0);
AudioConnection patchCord3(queue2, 0, i2s1, 1);
AudioConnection patchCord4(queue2, 0, usb1, 0);
AudioConnection patchCord5(queue2, 0, usb1, 1);
AudioControlSGTL5000 sgtl5000; //xy=418,383
// GUItool: end automatically generated code
uint32_t now = 0;
void setup(void)
{
Serial.begin(9600);
while(!Serial && (millis() - now) < 5000);
// Audio connections require memory. and the record queue
// uses this memory to buffer incoming audio.
AudioMemory(10);
// Enable the audio shield. select input. and enable output
sgtl5000.enable();
sgtl5000.volume(0.4);
// amp Frq waveform
waveform1.begin(WAVE_AMP,120,WAVEFORM_SAWTOOTH);
// Default is 0.1
mDSPm.SetResonance(0.2);
// Default is 1000
mDSPm.SetCutoff(1000);
for (byte i = 0; i < 128; i++) { //lets create an array to deal with converting 7-bit midi (0-127) to 0-1 res
midicc_Array [i] = 0.00787402 * i;
}
usbMIDI.setHandleControlChange(OnCC); // set handle for MIDI continuous controller messages
// Start the record queue
queue1.begin();
}
float samplebuf[AUDIO_BLOCK_SAMPLES];
void loop(void)
{
short *bp;
// When an input buffer becomes available
// process it
if (queue1.available() >= 1) {
bp = queue1.readBuffer();
// Copy the int16 samples into floats
for(int i = 0;i < AUDIO_BLOCK_SAMPLES;i++) {
samplebuf[i] = *bp++/(float)WAVE_AMP;
}
// Free the input audio buffers
queue1.freeBuffer();
usbMIDI.read();
#ifndef STRAIGHT_THROUGH
// This processes and returns floating point samples
mDSPm.Process(samplebuf,AUDIO_BLOCK_SAMPLES);
#endif
bp = queue2.getBuffer();
// copy the processed data back to the output
for(int i = 0; i < AUDIO_BLOCK_SAMPLES; i++) {
*bp++ = samplebuf[i]*(float)WAVE_AMP;
}
// and play it back into the audio queues
queue2.playBuffer();
}
// volume control
static int volume = 0;
// Volume control
int n = analogRead(15);
if (n != volume) {
volume = n;
sgtl5000.volume(n / 1023.);
}
}
//handle all incoming midi messages
void OnCC(byte channel, byte controller, byte value) {
switch (controller) {
case 0:
//do nothing
break;
case 1:
mDSPm.SetResonance(midicc_Array [value]);
break;
case 2:
int scaledVcf = midicc_Array [value] * 10000;
mDSPm.SetCutoff(scaledVcf);
break;
}
}
//////////////////////////////////////////////////////////////////////////////////////