It did stick on 1 note the first time I tried it, I tweeked the parameters and got it to kind of work but it's so slow it I don't think it's going to work for me. The sketch in #1 works fine with all my soft ware, with very little latency. I had success with this sketch on a different board but I had to use Hairless which caused problems with the ports.
Code:
#include "MIDIUSB.h"
// First parameter is the event type (0x09 = note on, 0x08 = note off).
// Second parameter is note-on/note-off, combined with the channel.
// Channel can be anything between 0-15. Typically reported to the user as 1-16.
// Third parameter is the note number (48 = middle C).
// Fourth parameter is the velocity (64 = normal, 127 = fastest).
void noteOn(byte channel, byte pitch, byte velocity) {
midiEventPacket_t noteOn = {0x09, 0x90 | channel, pitch, velocity};
MidiUSB.sendMIDI(noteOn);
}
void noteOff(byte channel, byte pitch, byte velocity) {
midiEventPacket_t noteOff = {0x08, 0x80 | channel, pitch, velocity};
MidiUSB.sendMIDI(noteOff);
}
#include "MIDIUSB.h"
//Piezo defines
#define NUM_PIEZOS 6
#define SNARE_THRESHOLD 30 //anything < TRIGGER_THRESHOLD is treated as 0
#define LTOM_THRESHOLD 30
#define RTOM_THRESHOLD 30
#define LCYM_THRESHOLD 100
#define RCYM_THRESHOLD 100
#define KICK_THRESHOLD 50
#define START_SLOT 0 //first analog slot of piezos
//MIDI note defines for each trigger
#define SNARE_NOTE 70
#define LTOM_NOTE 71
#define RTOM_NOTE 72
#define LCYM_NOTE 73
#define RCYM_NOTE 74
#define KICK_NOTE 75
//MIDI defines
#define NOTE_ON_CMD 0x90
#define NOTE_OFF_CMD 0x80
#define MAX_MIDI_VELOCITY 127
//MIDI baud rate
#define SERIAL_RATE 31250
//Program defines
//ALL TIME MEASURED IN MILLISECONDS
#define SIGNAL_BUFFER_SIZE 100
#define PEAK_BUFFER_SIZE 30
#define MAX_TIME_BETWEEN_PEAKS 20
#define MIN_TIME_BETWEEN_NOTES 50
//map that holds the mux slots of the piezos
unsigned short slotMap[NUM_PIEZOS];
//map that holds the respective note to each piezo
unsigned short noteMap[NUM_PIEZOS];
//map that holds the respective threshold to each piezo
unsigned short thresholdMap[NUM_PIEZOS];
//Ring buffers to store analog signal and peaks
short currentSignalIndex[NUM_PIEZOS];
short currentPeakIndex[NUM_PIEZOS];
unsigned short signalBuffer[NUM_PIEZOS][SIGNAL_BUFFER_SIZE];
unsigned short peakBuffer[NUM_PIEZOS][PEAK_BUFFER_SIZE];
boolean noteReady[NUM_PIEZOS];
unsigned short noteReadyVelocity[NUM_PIEZOS];
boolean isLastPeakZeroed[NUM_PIEZOS];
unsigned long lastPeakTime[NUM_PIEZOS];
unsigned long lastNoteTime[NUM_PIEZOS];
void setup()
{
Serial.begin(SERIAL_RATE);
//initialize globals
for(short i=0; i<NUM_PIEZOS; ++i)
{
currentSignalIndex[i] = 0;
currentPeakIndex[i] = 0;
memset(signalBuffer[i],0,sizeof(signalBuffer[i]));
memset(peakBuffer[i],0,sizeof(peakBuffer[i]));
noteReady[i] = false;
noteReadyVelocity[i] = 0;
isLastPeakZeroed[i] = true;
lastPeakTime[i] = 0;
lastNoteTime[i] = 0;
slotMap[i] = START_SLOT + i;
}
thresholdMap[0] = KICK_THRESHOLD;
thresholdMap[1] = RTOM_THRESHOLD;
thresholdMap[2] = RCYM_THRESHOLD;
thresholdMap[3] = LCYM_THRESHOLD;
thresholdMap[4] = SNARE_THRESHOLD;
thresholdMap[5] = LTOM_THRESHOLD;
noteMap[0] = KICK_NOTE;
noteMap[1] = RTOM_NOTE;
noteMap[2] = RCYM_NOTE;
noteMap[3] = LCYM_NOTE;
noteMap[4] = SNARE_NOTE;
noteMap[5] = LTOM_NOTE;
}
void loop()
{
unsigned long currentTime = millis();
for(short i=0; i<NUM_PIEZOS; ++i)
{
//get a new signal from analog read
unsigned short newSignal = analogRead(slotMap[i]);
signalBuffer[i][currentSignalIndex[i]] = newSignal;
//if new signal is 0
if(newSignal < thresholdMap[i])
{
if(!isLastPeakZeroed[i] && (currentTime - lastPeakTime[i]) > MAX_TIME_BETWEEN_PEAKS)
{
recordNewPeak(i,0);
}
else
{
//get previous signal
short prevSignalIndex = currentSignalIndex[i]-1;
if(prevSignalIndex < 0) prevSignalIndex = SIGNAL_BUFFER_SIZE-1;
unsigned short prevSignal = signalBuffer[i][prevSignalIndex];
unsigned short newPeak = 0;
//find the wave peak if previous signal was not 0 by going
//through previous signal values until another 0 is reached
while(prevSignal >= thresholdMap[i])
{
if(signalBuffer[i][prevSignalIndex] > newPeak)
{
newPeak = signalBuffer[i][prevSignalIndex];
}
//decrement previous signal index, and get previous signal
prevSignalIndex--;
if(prevSignalIndex < 0) prevSignalIndex = SIGNAL_BUFFER_SIZE-1;
prevSignal = signalBuffer[i][prevSignalIndex];
}
if(newPeak > 0)
{
recordNewPeak(i, newPeak);
}
}
}
currentSignalIndex[i]++;
if(currentSignalIndex[i] == SIGNAL_BUFFER_SIZE) currentSignalIndex[i] = 0;
}
}
void recordNewPeak(short slot, short newPeak)
{
isLastPeakZeroed[slot] = (newPeak == 0);
unsigned long currentTime = millis();
lastPeakTime[slot] = currentTime;
//new peak recorded (newPeak)
peakBuffer[slot][currentPeakIndex[slot]] = newPeak;
//1 of 3 cases can happen:
// 1) note ready - if new peak >= previous peak
// 2) note fire - if new peak < previous peak and previous peak was a note ready
// 3) no note - if new peak < previous peak and previous peak was NOT note ready
//get previous peak
short prevPeakIndex = currentPeakIndex[slot]-1;
if(prevPeakIndex < 0) prevPeakIndex = PEAK_BUFFER_SIZE-1;
unsigned short prevPeak = peakBuffer[slot][prevPeakIndex];
if(newPeak > prevPeak && (currentTime - lastNoteTime[slot])>MIN_TIME_BETWEEN_NOTES)
{
noteReady[slot] = true;
if(newPeak > noteReadyVelocity[slot])
noteReadyVelocity[slot] = newPeak;
}
else if(newPeak < prevPeak && noteReady[slot])
{
noteFire(noteMap[slot], noteReadyVelocity[slot]);
noteReady[slot] = false;
noteReadyVelocity[slot] = 0;
lastNoteTime[slot] = currentTime;
}
currentPeakIndex[slot]++;
if(currentPeakIndex[slot] == PEAK_BUFFER_SIZE) currentPeakIndex[slot] = 0;
}
void noteFire(unsigned short note, unsigned short velocity)
{
if(velocity > MAX_MIDI_VELOCITY)
velocity = MAX_MIDI_VELOCITY;
midiNoteOn(note, velocity);
midiNoteOff(note, velocity);
}
void midiNoteOn(byte note, byte midiVelocity)
{
Serial.write(NOTE_ON_CMD);
Serial.write(note);
Serial.write(midiVelocity);
}
void midiNoteOff(byte note, byte midiVelocity)
{
Serial.write(NOTE_OFF_CMD);
Serial.write(note);
Serial.write(midiVelocity);
}
is this midi?