Arduino Piano code

by leah

Code for the capacitive sensing piano shown in this video:

Arduino Code
#include <CapSense.h>

const int NUMBER_OF_SENSORS = 10;
CapSense* sensorDefinitions [NUMBER_OF_SENSORS];

#define ARRAYX 1
#define ARRAYY NUMBER_OF_SENSORS
int sensorArray [ARRAYX][ARRAYY];

CapSense note1 = CapSense(3,2);
CapSense note2 = CapSense(3,4);
CapSense note3 = CapSense(6,5);
CapSense note4 = CapSense(6,7);
CapSense note5 = CapSense(9,8);
CapSense note6 = CapSense(9,10);
CapSense note7 = CapSense(12,11);
CapSense note8 = CapSense(A1,A0);
CapSense note9 = CapSense(A1,A2);
CapSense note10 = CapSense(A4,A3);

long start, sensor;
int i, j;

void setup()
{
sensorDefinitions[0] =
&note1;
sensorDefinitions[1] =
&note2;
sensorDefinitions[2] =
&note3;
sensorDefinitions[3] =
&note4;
sensorDefinitions[4] =
&note5;
sensorDefinitions[5] =
&note6;
sensorDefinitions[6] =
&note7;
sensorDefinitions[7] =
&note8;
sensorDefinitions[8] =
&note9;
sensorDefinitions[9] =
&note10;
Serial.begin(9600);
}

void loop()
{
start = millis();
for (i=0;i
<NUMBER_OF_SENSORS;i++)
{
sensor = (*sensorDefinitions[i]).capSense(10);
if (sensor
> 100)
sensorArray[0][i]=1;
else
sensorArray[0][i]=0;
}
sendArray();
}

void sendArray ()
{
for (i=0;i
<ARRAYX;i++)
{
for (j=0;j
<ARRAYY;j++)
{
Serial.print(sensorArray[i][j]);
Serial.print('\t'); //tab character
}
Serial.print('\n'); //new line c
}
Serial.print('!');
}

Processing Code

/**
* Adopted by High-Low Tech from SinePiano by Dan Ellis, dpwe@ee.columbia.edu
*/

import ddf.minim.analysis.*;
import ddf.minim.*;
import ddf.minim.signals.*;
import processing.serial.*;

Minim minim;
AudioOutput out;

Serial myPort;

int ARRAYX = 1;
int ARRAYY = 10;
int [][] sensorArray = new int[ARRAYX][ARRAYY];
int [][] sensorArrayOld = new int[ARRAYX][ARRAYY];
int [][] noteArray = new int[ARRAYX][ARRAYY];

//note definitions
int C4= 262;
int D4= 294;
int E4= 330;
int F4= 349;
int G4= 392;
int A4= 440;
int B4= 494;
int C5= 523;
int D5= 587;

SineWave mySine;
MyNote newNote;

void setup()
{
size(512, 200, P3D);

println(Serial.list());
myPort = new Serial(this, Serial.list()[0], 9600);
myPort.bufferUntil('!');

minim = new Minim(this);
out = minim.getLineOut(Minim.STEREO);

noteArray[0][0]=C4; //z
noteArray[0][1]=D4; //x
noteArray[0][2]=E4; //c
noteArray[0][3]=F4; //v
noteArray[0][4]=G4; //b
noteArray[0][6]=A4; //n
noteArray[0][7]=B4; //m
noteArray[0][8]=C5; //,
noteArray[0][9]=D5; //.
}

void draw()
{
background(0);
stroke(255);
// draw the output waveforms, so there's something to look at
for(int i = 0; i
< out.bufferSize() - 1; i++)
{
float x1 = map(i, 0, out.bufferSize(), 0, width);
float x2 = map(i+1, 0, out.bufferSize(), 0, width);
line(x1, 50 + out.left.get(i)*50, x2, 50 + out.left.get(i+1)*50);
line(x1, 150 + out.right.get(i)*50, x2, 150 + out.right.get(i+1)*50);
}
}

void serialEvent (Serial myPort) {
String inString = myPort.readStringUntil('!');
String[] incomingArrayRows = splitTokens(inString, "\n");
for (int i=0;i
<ARRAYX;i++)
{
String[] incomingArrayEntries = splitTokens(incomingArrayRows[i], "\t");
for (int j=0;j
<ARRAYY;j++)
{
sensorArrayOld[i][j] = sensorArray[i][j];
sensorArray[i][j]=int(incomingArrayEntries[j]);
}
}
float pitch = 0;
for (int i=0;i
<ARRAYX;i++)
{
for (int j=0;j
<ARRAYY;j++)
{
if (sensorArray[i][j]>0 & (sensorArray[i][j]!=sensorArrayOld[i][j]))
{
pitch = noteArray[i][j];
newNote = new MyNote(pitch, 0.3);
}
}
}
}

void stop()
{
out.close();
minim.stop();

super.stop();
}

class MyNote implements AudioSignal
{
private float freq;
private float level;
private float alph;
private SineWave sine;

MyNote(float pitch, float amplitude)
{
freq = pitch;
level = amplitude;
sine = new SineWave(freq, level, out.sampleRate());
alph = .9; // Decay constant for the envelope
out.addSignal(this);
}

void updateLevel()
{
// Called once per buffer to decay the amplitude away
level = level * alph;
sine.setAmp(level);

// This also handles stopping this oscillator when its level is very low.
if (level
< 0.01) {
out.removeSignal(this);
}
// this will lead to destruction of the object, since the only active
// reference to it is from the LineOut
}

void generate(float [] samp)
{
// generate the next buffer's worth of sinusoid
sine.generate(samp);
// decay the amplitude a little bit more
updateLevel();
}

// AudioSignal requires both mono and stereo generate functions
void generate(float [] sampL, float [] sampR)
{
sine.generate(sampL, sampR);
updateLevel();
}

}