Difference between revisions of "Tutorial: Playing Sounds in a Separate Thread"
(→Main Java Class) |
(→Thread Class) |
||
Line 309: | Line 309: | ||
<br /> | <br /> | ||
<source lang="java"> | <source lang="java"> | ||
+ | // MyThread.java | ||
+ | // D. Thiebaut | ||
+ | // A class that implements a thread that runs a continuous loop where | ||
+ | // every 10 ms it checks to see if the member variable playNow is true. | ||
+ | // If it is, it starts playing a sound, then goes back to sleep for 10 ms. | ||
+ | // | ||
import ddf.minim.*; | import ddf.minim.*; |
Revision as of 10:47, 11 January 2014
--D. Thiebaut (talk) 17:54, 10 January 2014 (EST)
This tutorial present a simple Processing sketch that uses a thread to play sounds. Two circles bounce inside a rectangular box and a "beep" is generated every time they touche the boundaries. Two different versions are proposed, one using Processing's native IDE, one using Eclipse.
|
The Main Sketch
// NoisyBalls.pde
// D. Thiebaut
// A sketch that animates two balls bouncing off the walls.
// It uses the minim library to play sounds.
import ddf.minim.signals.*;
import ddf.minim.*;
import ddf.minim.analysis.*;
import ddf.minim.ugens.*;
import ddf.minim.effects.*;
// the coordinates and speeds of two circles
int x1, y1, deltax1, deltay1;
int x2, y2, deltax2, deltay2;
// the thread that plays the sounds...
MyThread sonar;
void setup() {
// create the sound player
Minim minim = new Minim(this);
AudioPlayer player = minim.loadFile( "sonar.wav" );
// define geometry and window
textAlign(CENTER);
size( 600, 400 );
smooth();
// position and activate the two circles
x1 = width/2;
y1 = height/2;
deltax1 = 4;
deltay1 = 3;
x2 = width/2;
y2 = height/2;
deltax2 = 2;
deltay2 = 5;
// create the thread and start it.
sonar = new MyThread( minim, player );
sonar.start();
}
void draw() {
// erase window
background( 0 );
// put message in middle
text( "Press any key to quit...", width/2, height/2 );
// show the two moving balls
ellipse( x1, y1, 20, 20 );
ellipse( x2, y2, 20, 20 );
// update positions of Ball 1, and if necessary change direction of movement
x1 += deltax1;
if ( x1 < 0 || x1 > width ) {
deltax1 = -deltax1;
// beep!
sonar.playNow();
}
y1 += deltay1;
if ( y1 < 0 || y1 > height ) {
deltay1 = -deltay1;
// beep!
sonar.playNow();
}
// update positions of Ball 2, and if necessary change direction of movement
x2 += deltax2;
if ( x2 < 0 || x2 > width ) {
deltax2 = -deltax2;
sonar.playNow();
}
y2 += deltay2;
if ( y2 < 0 || y2 > height ) {
deltay2 = -deltay2;
sonar.playNow();
}
}
// keyPressed(): if a key is pressed, simply stop the sketch
void keyPressed() {
// set sonar to stop running
sonar.quit();
// wait 500 ms (1/2 sec)
try {
Thread.sleep( 500 );
}
catch ( InterruptedException e ) {
}
// then exit completely
exit( );
}
The Thread Class
The thread contains an endless loop in its run() method, and will keep on checking the playNow boolean. If it is true, then the beep must be played. The endless loop is controlled by a boolean, which if true will cause the loop to end, and the run() method to stop.
// MyThread.pde
// D. Thiebaut
import ddf.minim.spi.*;
import ddf.minim.signals.*;
import ddf.minim.*;
import ddf.minim.analysis.*;
import ddf.minim.ugens.*;
import ddf.minim.effects.*;
class MyThread extends Thread {
Minim minim;
AudioPlayer player;
boolean quit;
boolean playNow;
MyThread( Minim m, AudioPlayer p ) {
minim = m;
player = p;
quit = false;
playNow = false;
}
public void playNow() {
playNow = true;
}
public void quit() {
quit = true;
}
void run() {
while ( !quit ) {
// wait 10 ms, then check if need to play
try {
Thread.sleep( 10 );
} catch ( InterruptedException e ) {
return;
}
// if we have to play the sound, do it!
if ( playNow ) {
playNow = false;
player.play();
player.rewind();
}
// go back and wait again for 10 ms...
}
}
}
The Sound File
The sound file used is called "sonar.wav" and is available here. It is stored in a folder called data in the main sketch folder.
File Hierarchy
The file hierarchy for this project is the following:
- NoisyBalls (folder)
- NoisyBalls.pde (Processing program)
- MyThread.pde (Thread program)
- data
- sonar.wav (the sound file)
Eclipse Version
To port this sketch to Eclipse, you need to
- create two Java classes in a new project, and import several library files from the Processing 2 Application folder.
- Once the files are imported, add them to the build path (right click on the jar file, select Build Path, then Add to Build Path).
- Create a data folder in the bin folder containing the class files, and store the sonar.wav file in the new data folder.
Main Java Class
// BeepingBalls.java
// D. Thiebaut
// A Java Class that animates two balls bouncing off the walls.
// It uses the minim library and a thread to play a sound file (beep) when
// the balls hit the walls.
import processing.core.PApplet;
import ddf.minim.*;
public class BeepingBalls extends PApplet {
// the coordinates and speeds of two circles
int x1, y1, deltax1, deltay1;
int x2, y2, deltax2, deltay2;
// the thread that plays the sounds...
MyThread sonar;
public void setup() {
// create the sound player
Minim minim = new Minim(this);
AudioPlayer player = minim.loadFile("sonar.wav");
// define geometry and window
textAlign(CENTER);
size(600, 400);
smooth();
// position and activate the two circles
x1 = width / 2;
y1 = height / 2;
deltax1 = 4;
deltay1 = 3;
x2 = width / 2;
y2 = height / 2;
deltax2 = 2;
deltay2 = 5;
// create the thread and start it.
sonar = new MyThread(minim, player);
sonar.start();
}
public void draw() {
// erase window
background(0);
// put message in middle
text("Press any key to quit...", width / 2, height / 2);
// show the two moving balls
ellipse(x1, y1, 20, 20);
ellipse(x2, y2, 20, 20);
// update positions of Ball 1, and if necessary change direction of
// movement
x1 += deltax1;
if (x1 < 0 || x1 > width) {
deltax1 = -deltax1;
// beep!
sonar.playNow();
}
y1 += deltay1;
if (y1 < 0 || y1 > height) {
deltay1 = -deltay1;
// beep!
sonar.playNow();
}
// update positions of Ball 2, and if necessary change direction of
// movement
x2 += deltax2;
if (x2 < 0 || x2 > width) {
deltax2 = -deltax2;
sonar.playNow();
}
y2 += deltay2;
if (y2 < 0 || y2 > height) {
deltay2 = -deltay2;
sonar.playNow();
}
}
// keyPressed(): if a key is pressed, simply stop the sketch
public void keyPressed() {
// set sonar to stop running
sonar.quit();
// wait 500 ms (1/2 sec)
try {
Thread.sleep(500);
} catch (InterruptedException e) {
}
// then exit completely
exit();
}
}
Thread Class
// MyThread.java
// D. Thiebaut
// A class that implements a thread that runs a continuous loop where
// every 10 ms it checks to see if the member variable playNow is true.
// If it is, it starts playing a sound, then goes back to sleep for 10 ms.
//
import ddf.minim.*;
class MyThread extends Thread {
Minim minim;
AudioPlayer player;
boolean quit;
boolean playNow;
MyThread( Minim m, AudioPlayer p ) {
minim = m;
player = p;
quit = false;
playNow = false;
}
public void playNow() {
playNow = true;
}
public void quit() {
quit = true;
}
public void run() {
while ( !quit ) {
// wait 10 ms, then check if need to play
try {
Thread.sleep( 10 );
} catch ( InterruptedException e ) {
return;
}
// if we have to play the sound, do it!
if ( playNow ) {
playNow = false;
player.play();
player.rewind();
}
// go back and wait again for 10 ms...
}
}
}