SoundCatcher
ABSTRACT
SoundCatcher is an open-air gestural controller designed to control a looper and time-freezing sound patch. It makes use of ultrasonic sensors to measure the distance of the performer’s hands to the device located in a microphone stand. Tactile and visual feedback using a pair of vibrating motors and LEDs are provided to note the performer when he/she is inside the sensed space. In addition, the motors velocity are scaled for each hand distance to the microphone stand to provide tactile cues about hand position.
SoundCatcher (performance rehearsal) : explorations in audio-looping and time-freezing using an open-air gestural controller from Gabriel Vigliensoni on Vimeo.
This was my final project for the MUMT 620 seminar (Gestural Control of Sound Synthesis) at McGill University. Here a link to the project report.
PROJECT DESIGN TIMELINE
Week 1 (October 26) : Sensors characteristics study and testing for contactless motion capture and actuators characteristics study and testing for vibrational representation of sound
100% Done !
- Study on sensors noticed me that Ping Ultrasound sensors behaves more linear and accurate that Sharp infrared, which was my first election.
- my first approach was to place sensors pointing toward the center of the performance, but using ultrasound sensor this will be no possible. Moreover, the mic stand seems to be a good position to place sensors, using it as a reference point.
- motor actuators are a cheap way to give clues to the performer on system status changes, limiting a virtual space or giving tactons information (tactile icons). However its representation of frequency is linked to amplitude, so I will look for other complementary ways to represent it.
Week 2 (November 2) : Sensor Interface Study / Arduino Patch Development
100% done !
- the arduino patch is working, it can measure the distance of both hands to the ultrasound sensors. The motors velocity reacts related to the distance.
- a transistor mini circuit was implemented in order to power the motors to take care of the arduino digital outputs.
- it seems that a pedal control is an interesting place to switching on/off the looper or some FXs. A vibrotactile actuator can be placed there, indeed. Nice idea, I will take a look on it.
Week 3 (November 9) : Max/MSP Patch Design
100% done !
- I am figuring how to send information from the computer to the Arduino in order to control the actuators from Max/MSP. Marko Timlin recommended me SimpleMessageSystem (check the code for Arduino and MaxMSP in arduino.cc. Also, take a look at the objects ‘messenger’, ‘firmata’, and ‘Maxuino’. Firmata is used in the Arduino and Maxuino in Max/MSP). Do not forget to set both baud values to the same rate.
- on the actuators side, I will take a look at the ‘surface transducer’, that sounds louder than piezo discs and can be mounted also in every surface.
Week 4 (November 16) : Device Setup Development
100 done !
- It sounds interesting to try a multimapping structure for the controller. Joe Malloch suggested to use the mapping abstractions of the OSCMapper at the Digital Orchestra Toolbox.
- the live input freezing is OK. I took a long time (more than required, actually) to setup the Arduino to only send the state change of the footswitch, not each value for every sample position.
- I will go for the BPM synchronization and subdivision right now ! OK ! I can read clock information from the digital audio workstation in order to derive a beat. I am using this beat timing to enforce the loop to be triggered on-time. Although this is a very useful trick to be in sync anytime, from time to time could be non that musical (to think…)
Week 5 (November 24) : Music Piece Composition / Rehearsal
100 % done !
- Ooops! A lot of work looking for the tech-flex, shrink-tube and the plastic box to put all elements together. At last, my son Vito save me with a Lego box. Darryl Cameron, from Music Tech McGill, gave a bunch of good advices to make nice holes with the drill.
- The prototype is finished, it sounds great, vibrates awesome, and also looks nice.
Week 6 (December 3) : MUMT620 Project Presentation
100% done !
- Although I forgot my melodica, and that made me run to be on time, the final presentation was actually very good !
4 Responses to 'SoundCatcher'
Subscribe to comments with RSS or TrackBack to 'SoundCatcher'.


Awesome! smart friend! We miss u monito!
Pablo Rockdriguez
14 Dec 09 at 7:54 pm
I think you r a genius my friend. don´t stop!!!!!!
and happy birthday!!!!!!
Cuti Aste
6 Jan 10 at 7:10 am
hello.
nice project! i am working on something similar but am having trouble getting 2 ping sensors to send to max simultaneously. could you explain or share your code?
cheers
Calum Scott
20 Feb 10 at 1:38 pm
Hi Calum,
here is my code to get the two (((Ping))) sensor’s data. In Max/MSP you must read the serial bus. It is well commented, so the configuration is straightforward.
Good luck,
Gabriel
////////////////////////////
///// SOUND CATCHER /////
////////////////////////////
///////////////////////////
// DECLARING VARIABLES //
///////////////////////////
int ultraSoundSensor7 = 7; // Sensor L assigned to Digital Input 7
int ultraSoundSensor8 = 8; // Sensor R assigned to Digital Input 8
int ultrasoundValue7 = 0; // Sensor L initial value
int ultrasoundValue8 = 0; // Sensor R initial value
int sensibility = 600; // Sensor sensibility distance in cms
int timecount = 0; // Echo counter
int val = 0; // Auxiliar sensor reading variable
int ledPinL = 12; // Left LED
int ledPinR = 11; // Right LED
int motorL = 9; // Left Motor
int motorR = 10; // Right Motor
int ledSwitch = 13; // Footswitch LED
int inSwitch = 2; // Footswitch input in Input 2
int valSwitch = 0; // Present footswitch value
int valSwitchOld = 0; // Previous footswitch value
int change = 0; // Footswitch change state
////////////////////////////////////
// DECLARING INPUT AND OUTPUTS //
////////////////////////////////////
void setup() {
Serial.begin(9600); // Sets the baud rate
pinMode(motorL, OUTPUT); // Declaring Dig9 as output for Left Motor
pinMode(motorR, OUTPUT); // Declaring Dig10 as output for Right Motor
pinMode(ledPinL, OUTPUT); // Declaring Dig12 as output for Left Led
pinMode(ledPinR, OUTPUT); // Declaring Dig11 as output for Right Led
pinMode(ledSwitch, OUTPUT); // Declaring Dig13 as output for Footswitch
pinMode(inSwitch, INPUT); // Declaring Dig2 as input for Footswitch
}
///////////////////////////////////
// READING ULTRASOUND SENSOR //
///////////////////////////////////
int getSensorValue(int sUltraSoundSensor) {
timecount = 0;
val = 0;
pinMode(sUltraSoundSensor, OUTPUT); // Switch signalpin to output
// ——————————————————————-
// Send low-high-low pulse to activate the trigger pulse of the sensor
// ——————————————————————-
digitalWrite(sUltraSoundSensor, LOW); // Send low pulse
delayMicroseconds(2); // Wait for 2 microseconds
digitalWrite(sUltraSoundSensor, HIGH); // Send high pulse
delayMicroseconds(5); // Wait for 5 microseconds
digitalWrite(sUltraSoundSensor, LOW); // Holdoff
// —————————-
// Listening for the echo pulse
// —————————-
pinMode(sUltraSoundSensor, INPUT); // Switch signalpin to input
val = digitalRead(sUltraSoundSensor); // Append signal value to val
while(val == LOW) { // Loop until pin reads a high value
val = digitalRead(sUltraSoundSensor);
}
while(val == HIGH) { // Loop until pin reads a high value
val = digitalRead(sUltraSoundSensor);
timecount = timecount +1; // Count echo pulse time
}
return timecount;
}
//////////////////////////////////////////////
// WRITING OUT VALUES TO THE SERIAL PORT //
//////////////////////////////////////////////
void loop() {
ultrasoundValue7 = getSensorValue(ultraSoundSensor7); // Append echo pulse time to ultrasoundValue
delay(9);
if (ultrasoundValue7 > sensibility) { // limiting to sensibility
ultrasoundValue7 = sensibility;
digitalWrite(ledPinL, LOW);
digitalWrite(motorL, LOW);
}
else {
digitalWrite(ledPinL, HIGH);
analogWrite(motorL, map(ultrasoundValue7, 50, sensibility, 255, 0));
}
ultrasoundValue8 = getSensorValue(ultraSoundSensor8); // Append echo pulse time to ultrasoundValue
delay(10);
if (ultrasoundValue8 > sensibility) { // limiting to sensibility
ultrasoundValue8 = sensibility;
digitalWrite(ledPinR, LOW);
digitalWrite(motorR, LOW);
}
else {
digitalWrite(ledPinR, HIGH);
analogWrite(motorR, map(ultrasoundValue8, 50, sensibility, 255, 0));
}
// ———————————-
// Footswitch reading and led writing
// ———————————-
valSwitch = digitalRead(inSwitch); // read input value
change = valSwitch – valSwitchOld; // calculating if there was change
if (valSwitch == HIGH) { // check if the input is HIGH (i.e., button released)
digitalWrite(ledSwitch, LOW); // turns LED OFF
valSwitch = 0;
valSwitchOld = 0;
}
else {
digitalWrite(ledSwitch, HIGH); // turn LED ON
valSwitch = 1;
valSwitchOld = 1;
}
if (change != 0) { // changing change variable to send footswitch status
change = 1;
valSwitchOld = valSwitch;
}
/////////////////////////////////////
// PRINTING DATA IN THE SERIAL BUS //
/////////////////////////////////////
Serial.print(ultrasoundValue7);
Serial.print(“\t”);
Serial.print(ultrasoundValue8);
Serial.print(“\t”);
Serial.print(abs(change));
Serial.println();
}
admin
20 Feb 10 at 2:02 pm