Recording in is implemented by saving timestamps for the triggered
audio samples after the record button has been tapped. The MIDlet
includes a Sample
class, which is used to save a
timestamp and associate the correct drum pad with it. When the pad
is played while recording is on, a new Sample
object
gets created and pushed into a Vector
called tape
.
protected void pointerPressed(int x, int y) { // ... for (int i = 0; i < 4; i++) { Pad pad = pads[i]; if (pad.contains(x, y)) { if (recording) { // Record sample tape.addElement(new Sample(pad)); } // Play sound assigned to the pad SoundManager.playSound(pad.getSound()); pad.setHit(true); // ... } } // ... }
The Sample
constructor takes the Pad
object as a parameter, retrieves the sound associated with the Pad
object, and saves the current time in milliseconds as
a timestamp.
public Sample(Pad pad) { this.pad = pad; this.sound = pad.getSound(); this.time = System.currentTimeMillis(); }
The playback uses a Timer
and TimerTasks
to schedule individual drum strokes.
The timestamp is used for scheduling TimerTasks
as
the following code demonstrates. The play
method
loops through the samples in the tape
vector, and
the correct time for each Sample
is calculated by
subtracting the timestamp of the first Sample
from
the timestamp of the Sample
being scheduled. Here
the timer is called drummer:
public void playTape() { if (tape != null && tape.size() > 0) { playback = true; recordBtn.disable(); playBtn = stopPlaybackBtn; int length = tape.size(); int i = 0; long startTime = ((Sample) tape.elementAt(0)).time; // Schedule recorded samples while (i < length) { final Sample sample = (Sample) tape.elementAt(i); drummer.schedule(new TimerTask() { public void run() { SoundManager.playSound(sample.sound); sample.pad.setHit(true); } }, sample.time - startTime); i++; } // Schedule task for stopping the playback TimerTask end = new TimerTask() { public void run() { stopTape(); } }; drummer.schedule(end, ((Sample) tape.lastElement()).time - startTime + 100); } }