The Sonar Tonebank is a simple musical instrument that uses a range sensor to trigger sound samples. Players can create musical soundscapes by moving in front of the range sensor, which maps pitch to distance. This project was created using an Arduino, a PING sonar sensor and the Minim sound library in Processing.
// SONAR TONEBANK
// 1.0
// Jeff Watson
// 27 April 2009
import processing.serial.*;
import ddf.minim.*;
// arduino variables
Serial myPort; // The serial port
// video variables
// minim variables
Minim minim;
AudioSample bell;
AudioSample bell2;
AudioSample bell3;
AudioSample bell4;
AudioSample bell5;
AudioSample bell6;
AudioSample bell7;
AudioSample bell8;
AudioSample bell9;
AudioSample bell10;
AudioSample bell11;
AudioSample bell12;
AudioSample bell13;
AudioSample bell14;
AudioSample bell15;
AudioSample bell16;
// visualizer variables
void setup () {
size(640, 480, P2D);
background(0);
noStroke();
minim = new Minim(this);
bell = minim.loadSample(“F#3.wav”, 2048);
bell2 = minim.loadSample(“G#3.wav”, 2048);
bell3 = minim.loadSample(“A#3.wav”, 2048);
bell4 = minim.loadSample(“C#4.wav”, 2048);
bell5 = minim.loadSample(“D#4.wav”, 2048);
bell6 = minim.loadSample(“F#4.wav”, 2048);
bell7 = minim.loadSample(“G#4.wav”, 2048);
bell8 = minim.loadSample(“A#4.wav”, 2048);
bell9 = minim.loadSample(“C#5.wav”, 2048);
bell10 = minim.loadSample(“D#5.wav”, 2048);
bell11 = minim.loadSample(“F#5.wav”, 2048);
bell12 = minim.loadSample(“G#5.wav”, 2048);
bell13 = minim.loadSample(“A#5.wav”, 2048);
bell14 = minim.loadSample(“C#6.wav”, 2048);
bell15 = minim.loadSample(“D#6.wav”, 2048);
bell16 = minim.loadSample(“F#6.wav”, 2048);
// List all the available serial ports
println(Serial.list());
// Open whatever port is the one you’re using.
myPort = new Serial(this, Serial.list()[1], 9600);
// don’t generate a serialEvent() unless you get a newline character:
myPort.bufferUntil(‘\n’);
}
void draw () {
// everything happens in the serialEvent()
}
void serialEvent (Serial myPort) {
// get the ASCII string:
String inString = myPort.readStringUntil(‘\n’);
if (inString != null) {
// trim off any whitespace:
inString = trim(inString);
// convert to an int and map to the screen height:
float inByte = float(inString);
int VideoMod = int(inString);
println(VideoMod);
// 1st Octave
if ( VideoMod < 5 )
{
bell.trigger();
delay(33);
fill(0,0,255);
rect(1,0,128,480);
}
else if ( VideoMod < 8 )
{
bell2.trigger();
delay(33);
fill(13,82,122);
rect(129,0,128,480);
}
else if ( VideoMod < 11 )
{
bell3.trigger();
delay(33);
fill(0,0,255);
rect(257,0,128,480);
}
else if ( VideoMod < 14 )
{
bell4.trigger();
delay(33);
fill(13,82,122);
rect(385,0,128,480);
}
else if ( VideoMod < 17 )
{
bell5.trigger();
delay(33);
fill(0,0,255);
rect(513,0,128,480);
}
// 2nd Octave
else if ( VideoMod < 20 )
{
bell6.trigger();
delay(33);
fill(0,0,0);
rect(0,0,640,480);
fill(0,0,255,191);
rect(1,0,128,480);
}
else if ( VideoMod < 23 )
{
bell7.trigger();
delay(33);
fill(0,0,0);
rect(0,0,640,480);
fill(13,82,122,191);
rect(129,0,128,480);
}
else if ( VideoMod < 26 )
{
bell8.trigger();
delay(33);
fill(0,0,0);
rect(0,0,640,480);
fill(0,0,255,191);
rect(257,0,128,480);
}
else if ( VideoMod < 29 )
{
bell9.trigger();
delay(33);
fill(0,0,0);
rect(0,0,640,480);
fill(13,82,122,191);
rect(385,0,128,480);
}
else if ( VideoMod < 32 )
{
bell10.trigger();
delay(33);
fill(0,0,0);
rect(0,0,640,480);
fill(0,0,255,191);
rect(513,0,128,480);
}
// 3rd Octave
else if ( VideoMod < 35 )
{
bell11.trigger();
delay(33);
fill(0,0,0);
rect(0,100,640,380);
fill(0,0,255,127);
rect(1,0,128,480);
}
else if ( VideoMod < 38 )
{
bell12.trigger();
delay(33);
fill(0,0,0);
rect(0,100,640,380);
fill(13,82,122,191);
rect(129,0,128,480);
}
else if ( VideoMod < 41 )
{
bell13.trigger();
delay(33);
fill(0,0,0);
rect(0,100,640,380);
fill(0,0,255,191);
rect(257,0,128,480);
}
else if ( VideoMod < 44 )
{
bell14.trigger();
delay(33);
fill(0,0,0);
rect(0,100,640,380);
fill(13,82,122,191);
rect(385,0,128,480);
}
else if ( VideoMod < 47 )
{
bell15.trigger();
delay(33);
fill(0,0,0);
rect(0,100,640,380);
fill(0,0,255,191);
rect(513,0,128,480);
}
// Extra note clears screen
else if ( VideoMod < 50 )
{
bell16.trigger();
delay(33);
background(0);
}
else if ( VideoMod > 50 )
{
}
}
}
During the early prototyping phase, I also made a simple Theremin using the PING sensor, based on Alberto Bietti’s excellent documentation. The piezo speaker and button on the current version of the project are remnants of this prototype; I’ve left them on there for now for demoing purposes.