diff --git a/ArduinoMidiDrums.ino b/ArduinoMidiDrums.ino
index 8eade8f..4867591 100644
--- a/ArduinoMidiDrums.ino
+++ b/ArduinoMidiDrums.ino
@@ -1,226 +1,244 @@
-/*
- * Copyright (c) 2015 Evan Kale
- * Email: EvanKale91@gmail.com
- * Website: www.ISeeDeadPixel.com
- * www.evankale.blogspot.ca
- *
- * This file is part of ArduinoMidiDrums.
- *
- * ArduinoMidiDrums is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-//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 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);
-}
+/*
+ * Copyright (c) 2015 Evan Kale
+ * Email: EvanKale91@gmail.com
+ * Website: www.ISeeDeadPixel.com
+ * www.evankale.blogspot.ca
+ *
+ * This file is part of ArduinoMidiDrums.
+ *
+ * ArduinoMidiDrums is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+//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
+
+//Piezo scaling defines
+#define SNARE_SCALE 20 // 100 is 100% of raw value - that is no scaling
+#define LTOM_SCALE 50 // < 100 scales the velocity down so that you have to hit harder to get maximum velocity
+#define RTOM_SCALE 50 // > 100 scales the velocity up so you get maximum velocity with softer hits
+#define LCYM_SCALE 50
+#define RCYM_SCALE 50
+#define KICK_SCALE 100
+
+//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 scales for each pad
+unsigned short velScale[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 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 * velScale[slot] / 100;
+ }
+ 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);
+}