"Use case"
That got narrowed down from 8 files tested to 6 files for the sake of not pushing resources.
Then I came to my senses and realized that I would only ever use a single sample at a time.
Single sample, midi control, with a "stutter" feature that upon note-off event leaves the sample in a playing state but with a playback rate of 0.
The next note-on event pushes a new playback rate into the variable.
No sampling software I have does this, but I haven't tried everything out there. It's gimmicky but fun gimmicky. ( I do have Stutter Edit but that's not exactly a sampler. )
Here is that engine stripped down.
#include <MIDI.h>
#include "SD.h"
#include <Audio.h>
#include <TeensyVariablePlayback.h>
#include <USBHost_t36.h>
MIDI_CREATE_INSTANCE(HardwareSerial, Serial1, MIDI1);
USBHost myusb;
USBHub hub1(myusb);
USBHub hub2(myusb);
USBHub hub3(myusb);
USBHub hub4(myusb);
MIDIDevice midi01(myusb);
MIDIDevice midi02(myusb);
MIDIDevice midi03(myusb);
MIDIDevice midi04(myusb);
AudioPlaySdResmp sample1;
AudioOutputI2S2 i2s2;
AudioFilterBiquad filter1;
AudioFilterBiquad filter2;
AudioEffectEnvelope envelope1;
AudioEffectEnvelope envelope2;
AudioEffectEnvelope * envelopeQueue[2] = {&envelope1, &envelope2};
AudioMixer4 outmix1;
AudioMixer4 outmix2;
AudioConnection voice1filter(sample1, 0, filter1, 0);
AudioConnection voice2filter(sample1, 1, filter2, 0);
AudioConnection voice1envelope(filter1, 0, envelope1, 0);
AudioConnection voice2envelope(filter2, 0, envelope2, 0);
AudioConnection patchCordVoice1A(envelope1, 0, outmix1, 0);
AudioConnection patchCordVoice2A(envelope2, 0, outmix2, 0);
AudioConnection patchCordOut1(outmix1, 0, i2s2, 0);
AudioConnection patchCordOut2(outmix2, 0, i2s2, 1);
double fwdMIDIPitches[97] = {.062500, .066192, .070112, .074324, .078745, .083425, .088390, .093645, .099212, .105112, .111360, .117986, //0
.125, .132425, .140305, .14865, .157495, .166855, .176775, .18729, .198425, .21022, .222725, .23597, //1
.25, .264865, .280615, .29730, .31498, .333705, .35355, .374575, .39685, .420445, .445445, .471935, //2
.5, .529725, .561225, .59460, .629955, .667415, .707105, .74915, .7937, .840895, .89090, .94387, //3
1, 1.05945, 1.12245, 1.18920, 1.259925, 1.334835, 1.41421, 1.49830, 1.58740, 1.68179, 1.781785, 1.88775, //4
2, 2.11892, 2.244915, 2.37841, 2.51984, 2.66967, 2.82841, 2.99661, 3.17480, 3.36358, 3.563955, 3.77549, //5
4, 4.423784, 4.48984, 4.75682, 5.03966, 5.33935, 5.65685, 5.99322, 6.34962, 6.72718, 7.12714, 7.55100, //6
8, 8.47570, 8.97970, 9.51366, 10.07936, 10.67868, 11.31370, 11.98650, 12.69920, 13.45440, 14.25442, 15.10200, //7
16
};
double revMIDIPitches[97] = { -.062500, -.066192, -.070112, -.074324, -.078745, -.083425, -.088390, -.093645, -.099212, -.105112, -.111360, -.117986, //0
-.125, -.132425, -.140305, -.14865, -.157495, -.166855, -.176775, -.18729, -.198425, -.21022, -.222725, -.23597, //1
-.25, -.264865, -.280615, -.29730, -.31498, -.333705, -.35355, -.374575, -.39685, -.420445, -.445445, -.471935, //2
-.5, -.529725, -.561225, -.59460, -.629955, -.667415, -.707105, -.74915, -.7937, -.840895, -.89090, -.94387, //3
-1, -1.05945, -1.12245, -1.18920, -1.259925, -1.334835, -1.41421, -1.49830, -1.58740, -1.68179, -1.781785, -1.88775, //4
-2, -2.11892, -2.244915, -2.37841, -2.51984, -2.66967, -2.82841, -2.99661, -3.17480, -3.36358, -3.563955, -3.77549, //5
-4, -4.423784, -4.48984, -4.75682, -5.03966, -5.33935, -5.65685, -5.99322, -6.34962, -6.72718, -7.12714, -7.55100, //6
-8, -8.47570, -8.97970, -9.51366, -10.07936, -10.67868, -11.31370, -11.98650, -12.69920, -13.45440, -14.25442, -15.10200, //7
-16
};
char* filename;
char* fetchedFile = "TALK.WAV";
union {
double pb1 = 1;
uint8_t pb1uint8_ts[8];
} pb1;
float voice1Avol = 0.8;
float voice1Bvol = 0.8;
float filter1Q = .7;
int filter1Frequency = 16000;
float filter2Q = .7;
int filter2Frequency = 16000;
long position1 = -999;
long position2 = -999;
elapsedMillis counter1;
elapsedMillis counter2;
boolean stutter1 = true;
boolean sample1fwd = true;
uint8_t sample1channel = 1;
void setup() {
MIDI1.begin(MIDI_CHANNEL_OMNI);
MIDI1.turnThruOff();
MIDI1.setHandleNoteOn(sampleNoteOn);
MIDI1.setHandleNoteOff(sampleNoteOff);
midi01.setHandleNoteOn(sampleNoteOn);
midi01.setHandleNoteOff(sampleNoteOff);
midi02.setHandleNoteOn(sampleNoteOn);
midi02.setHandleNoteOff(sampleNoteOff);
midi03.setHandleNoteOn(sampleNoteOn);
midi03.setHandleNoteOff(sampleNoteOff);
midi04.setHandleNoteOn(sampleNoteOn);
midi04.setHandleNoteOff(sampleNoteOff);
SD.begin(BUILTIN_SDCARD);
myusb.begin();
AudioMemory(96);
sample1.enableInterpolation(true);
sample1.setPlaybackRate(pb1.pb1);
outmix1.gain(0, 0.9);
outmix1.gain(1, 0);
outmix1.gain(2, 0);
outmix1.gain(3, 0);
outmix2.gain(0, 0.9);
outmix2.gain(1, 0);
outmix2.gain(2, 0);
outmix2.gain(3, 0);
filter1.setLowpass(0, filter1Frequency, filter1Q);
filter1.setLowpass(1, filter1Frequency, filter1Q);
filter1.setLowpass(2, filter1Frequency, filter1Q);
filter2.setLowpass(0, filter2Frequency, filter2Q);
filter2.setLowpass(1, filter2Frequency, filter2Q);
filter2.setLowpass(2, filter2Frequency, filter2Q);
envelope1.sustain(1);
envelope2.sustain(1);
envelope1.release(1);
envelope2.release(1);
filename = "TALK.WAV";
}
void loop() {
myusb.Task();
midi01.read();
midi02.read();
midi03.read();
midi04.read();
MIDI1.read();
testfire();
}
void testfire() {
if (!sample1.isPlaying()) {
envelope1.noteOff();
sample1.playWav(filename1);
envelope1.noteOn();
}
void sampleNoteOn(uint8_t channel, uint8_t note, uint8_t velocity) {
if (channel == sample1channel) {
if (sample1fwd == true) {
pb1.pb1 = fwdMIDIPitches[note];
}
if (sample1fwd == false) {
pb1.pb1 = revMIDIPitches[note];
}
sample1.setPlaybackRate(pb1.pb1);
if (stutter1 == true) {
if (!sample1.isPlaying()) {
envelope1.noteOff();
sample1.playWav(filename);
envelope1.noteOn();
}
envelope1.noteOn();
}
if (stutter1 == false) {
if (!sample1.isPlaying()) {
envelope1.noteOff();
sample1.playWav(filename);
envelope1.noteOn();
}
}
}
}
void sampleNoteOff(uint8_t channel, uint8_t note, uint8_t velocity) {
if (channel == sample1channel) {
if (stutter1 == true) {
pb1.pb1 = 0.0;
sample1.setPlaybackRate(pb1.pb1);
envelope1.noteOff();
}
if(stutter1==false){
envelope1.noteOff();
if(!envelope1.isActive()){
sample1.stop();
}
}
}
}
void audiodebug() {
AudioProcessorUsageMaxReset();
Serial.print(AudioProcessorUsageMax());
Serial.print(" , ");
Serial.println(AudioMemoryUsageMax());
}