You are making history with this stuff!!

I got the velocity sensitive piezo drum pads working with the V2. It is proof of concept and not very stable one, but with little bit tinkering it might be a great live drumming example. I used some of the code from Spooky's MIDI drum project…
http://todbot.com/blog/2006/10/29/spooky-arduino-projects-4-and-musical-arduino//*
Created by WilliamK @ Wusik Dot Com (c) 2011 - http://arduino.wusik.com
8-Bit PCM Sound using PWM on the 16-bit Timer1 - a total of 6 voices at 22068hz
Sound on Pins 9 and 10 (use a 10k resistor on each pin and a capacitor to filter any noise)
A note, in order to keep the code at 22khz we used a near 8-bit value of 242, while 8-bit would be 255.
The included WAV to Code converter will output samples using 242 as the max value possible instead.
*/
#include <stdint.h>
#include <avr/interrupt.h>
#include <avr/io.h>
#include <avr/pgmspace.h>
#include "PCM_Sound.h"
// ======================================================================================= //
#define MIDIactivityPin 13
#define SHOWFREEMEM 1
#define MAXVOICES 6
unsigned long MIDIactivityMillis = millis()+25;
byte MIDIactivity = 0;
unsigned int sampleLen[MAXVOICES];
int samplePos[MAXVOICES][2]; // tune/fine //
unsigned char* samplePCM[MAXVOICES];
unsigned int mixer[2] = {363,363};
unsigned char voice = 0;
char rate[MAXVOICES][2]; // tune/fine //
unsigned char notevel[MAXVOICES];
unsigned char noteVelMatrix[6][242]; // This is used to add Velocity without doing any heavy processing divisions //
byte incomingByte;
byte note;
byte noteOn = 0;
byte state = 0;
byte sound = 0;
int treshold = 100;
int val = 0;
int t = 0;
// ======================================================================================= //
// Checks the RAM left - the ATmega328 has only 2K of RAM //
#if SHOWFREEMEM
extern unsigned int __data_start;
extern unsigned int __data_end;
extern unsigned int __bss_start;
extern unsigned int __bss_end;
extern unsigned int __heap_start;
extern void *__brkval;
int freeMemory()
{
int free_memory;
if((int)__brkval == 0)
free_memory = ((int)&free_memory) - ((int)&__bss_end);
else
free_memory = ((int)&free_memory) - ((int)__brkval);
return free_memory;
}
#endif
// ======================================================================================= //
void setup()
{
memset(sampleLen,0,sizeof(sampleLen));
memset(samplePos,0,sizeof(samplePos));
memset(samplePCM,0,sizeof(samplePCM));
memset(rate,0,sizeof(rate));
memset(notevel,3,sizeof(notevel));
// Create the Velocity Matrix Values //
float val = 0.0f;
float valr = 1.0f;
for (int x=0; x<6; x++)
{
if (x == 1) valr = 0.80f;
else if (x == 2) valr = 0.60f;
else if (x == 3) valr = 0.35f;
else if (x == 4) valr = 0.20f;
else if (x == 5) valr = 0.08f;
for (int v=0; v<242; v++)
{
if (x == 0) noteVelMatrix[x][v] = v;
else
{
val = (((2.0f/242.0f)*float(v))-1.0f)*valr;
noteVelMatrix[x][v] = (unsigned int)((val+1.0f)*(242.0f/2.0f));
}
}
}
pinMode(9,OUTPUT);
pinMode(10,OUTPUT);
pinMode(A0,INPUT);
pinMode(A1,INPUT);
pinMode(A2,INPUT); // piezo 1
pinMode(A3,INPUT); // piezo 2
pinMode(A4,INPUT);
pinMode(A5,INPUT);
// pinMode(MIDIactivityPin,OUTPUT);
// digitalWrite(MIDIactivityPin,LOW);
// 16 Bit Timer Setup //
// 16000000 (CPU CLOCK) / 726 (10 Bits) = 22068 samples-per-second (put a filter to remove anything above 10.5khz)
TCCR1A = _BV(COM1A1) | _BV(COM1B1) | _BV(WGM11); // Fast PWM Timer
TCCR1B = _BV(WGM12) | _BV(WGM13) | _BV(CS10); // Non-Phase Inverting - No Prescaler
ICR1 = (726-1); // Max value of 726 (9-bits is 511 and 10-bits is 1023) - 1 (the processor counts over)
TIMSK1 = _BV(TOIE1); // timer overflow interrupt
OCR1A = OCR1B = 363; // (242/2)*3
sei(); // enable global interrupts
#if SHOWFREEMEM
Serial.begin(38400);
Serial.print("Free Mem: ");
Serial.println(freeMemory());
Serial.println("");
#endif
// MIDI Startup //
// !!! Tests // Serial.begin(31250);
}
// ======================================================================================= //
boolean pingVoice = true;
unsigned char getFreeVoice(void)
{
if (pingVoice)
{
pingVoice = false;
if (samplePCM[0] == 0) return 0;
if (samplePCM[1] == 0) return 1;
if (samplePCM[2] == 0) return 2;
if (samplePCM[3] == 0) return 3;
if (samplePCM[4] == 0) return 4;
if (samplePCM[5] == 0) return 5;
}
else
{
pingVoice = true;
if (samplePCM[5] == 0) return 5;
if (samplePCM[4] == 0) return 4;
if (samplePCM[3] == 0) return 3;
if (samplePCM[2] == 0) return 2;
if (samplePCM[1] == 0) return 1;
if (samplePCM[0] == 0) return 0;
}
return 5;
}
// ======================================================================================= //
void playNote(unsigned char note, unsigned char velocity)
{
if (note < 60) return;
sound = note-60;
if (sound >= PCMtotal) return;
voice = getFreeVoice();
samplePCM[voice] = 0; // First stop any sound reference //
// !!! TEST // rate[voice][0] = 1; // Tune
// !!! TEST // rate[voice][1] = 0; // Fine
if (rate[voice][0] > 0) samplePos[voice][0] = 0; else samplePos[voice][0] = PCMlen[sound]-1;
samplePos[voice][1] = 0;
notevel[voice] = 5-min(5,velocity/25);
sampleLen[voice] = PCMlen[sound];
samplePCM[voice] = PCMdata[sound];
}
// ======================================================================================= //
boolean flipFlop = false;
boolean isReverse = false;
void checkInterface(void)
{
isReverse = !digitalRead(A0);
if (digitalRead(A1))
{
rate[0][1] = rate[1][1] = rate[2][1] = rate[3][1] = rate[4][1] = rate[5][1] = 0;
rate[0][0] = rate[1][0] = rate[2][0] = rate[3][0] = rate[4][0] = rate[5][0] = ((isReverse) ? -1 : 1);
}
else
{
rate[0][1] = rate[1][1] = rate[2][1] = rate[3][1] = rate[4][1] = rate[5][1] = analogRead(A5)/11;
rate[0][0] = rate[1][0] = rate[2][0] = rate[3][0] = rate[4][0] = rate[5][0] = (analogRead(A4)/110) * ((isReverse) ? -1 : 1);
}
}
// ======================================================================================= //
void loop()
{
// Piezos in analog pins 2 and 3
// 1M resistor also between pin and ground
val = analogRead(A2);
if( val >= treshold ) {
t=0;
while(analogRead(A2) >= treshold/2) {
t++;
}
checkInterface();
playNote(62, val);
delay(t);
}
val = analogRead(A3);
if( val >= treshold ) {
t=0;
while(analogRead(A3) >= treshold/2) {
t++;
}
checkInterface();
playNote(62, val);
delay(t);
}
/* checkInterface();
if (flipFlop) playNote(62, 127); else playNote(63, 127);
delay(40);
checkInterface();
if (flipFlop) playNote(62, 60); else playNote(63, 60);
delay(40);
checkInterface();
if (flipFlop) playNote(62, 40); else playNote(63, 40);
delay(40);
checkInterface();
if (flipFlop) playNote(62, 20); else playNote(63, 20);
checkInterface();
if (flipFlop) playNote(61, 127); else playNote(60, 127);
delay(60);
checkInterface();
if (flipFlop) playNote(61, 40); else playNote(60, 40);
delay(60);
checkInterface();
checkInterface();
if (flipFlop) playNote(66, 127); else playNote(65, 127);
if (flipFlop) playNote(64, 40); playNote(67, 40);
delay(40);
checkInterface();
if (flipFlop) playNote(66, 60); else playNote(65, 60);
if (flipFlop) playNote(64, 20); playNote(67, 20);
delay(40);
checkInterface();
if (flipFlop) playNote(66, 40); else playNote(65, 40);
delay(40);
checkInterface();
flipFlop = !flipFlop; */
}
// ======================================================================================= //
#define nextSample(nv,nm)\
if (samplePos[nv][0] >= sampleLen[nv] || samplePos[nv][0] < 0) samplePCM[nv] = 0;\
if (samplePCM[nv] != 0)\
{\
mixer[nm] += noteVelMatrix[notevel[nv]][(unsigned int)pgm_read_byte(&samplePCM[nv][samplePos[nv][0]])];\
samplePos[nv][0] += rate[nv][0];\
samplePos[nv][1] += rate[nv][1];\
if (samplePos[nv][1] > 120) { samplePos[nv][1] = 0; if (rate[nv][0] > 0) samplePos[nv][0]++; else samplePos[nv][0]--; }\
} else mixer[nm] += 121;
// ======================================================================================= //
ISR(TIMER1_OVF_vect)
{
// Do this first so the PWM is updated faster //
OCR1A = mixer[0];
OCR1B = mixer[1];
// Now Calculate the next samples //
mixer[0] = mixer[1] = 0;
nextSample(0,0);
nextSample(1,0);
nextSample(2,0);
nextSample(3,1);
nextSample(4,1);
nextSample(5,1);
}