Manual: Playable
The Playable interface defines functionality that you would expect from a tape deck or CD player. Implementing classes are usually playing an audio file. Playable is implemented by AudioPlayer and AudioSnippet.
Playing and Pausing
When you have a Playable object you can start and stop playback by using play() and pause(). When you use play() the sound will begin playing from the current position. If you’ve just loaded the file, it will start from the beginning. If it was playing for a while and then you paused it, it will begin playing from where it was paused. You can use isPlaying() to find out whether or not a sound is currently playing. As of Minim 1.1, when a sound finishes playing and has not been set to loop (see below), isPlaying() will continue to return true until pause() is called. This inconsistency will be fixed in the next release.
Code Sample (online example)
import ddf.minim.*; AudioPlayer groove; // this class is defined in a separate file // see the online example for the code WaveformRenderer waveform; void setup() { size(512, 200); // always start Minim first Minim.start(this); groove = Minim.loadFile("groove.mp3", 512); waveform = new WaveformRenderer(); // see the example Recordable >> addListener for more about this groove.addListener(waveform); textFont(createFont("Arial", 12)); } void draw() { background(0); // see waveform.pde for an explanation of how this works waveform.draw(); if ( groove.isPlaying() ) { text("The player is playing.", 5, 15); } else { text("The player is not playing.", 5, 15); } } void keyPressed() { if ( key == 'p' ) { groove.play(); } if ( key == 's' ) { groove.pause(); } } void stop() { // always close Minim audio classes when you are done with them groove.close(); super.stop(); }
Rewinding
Calling rewind() on a Playable object resets the “playhead” to the beginning of the sound. Rewinding doesn’t change the play state of a Playable so if it is playing or looping when you rewind, it will continue to play or loop after you rewind it.
Code Sample (online example)
import ddf.minim.*; AudioPlayer groove; WaveformRenderer waveform; void setup() { size(512, 200); // always start Minim first Minim.start(this); groove = Minim.loadFile("groove.mp3", 512); groove.loop(); waveform = new WaveformRenderer(); // see the example Recordable >> addListener for more about this groove.addListener(waveform); } void draw() { background(0); // see waveform.pde for an explanation of how this works waveform.draw(); } void keyPressed() { if ( key == 'r' ) groove.rewind(); } void stop() { // always close Minim audio classes when you are done with them groove.close(); super.stop(); }
Looping
Often you want a sound to loop for a given number of times or perhaps indefinitely. This can be accomplished by using the loop methods:
void loop() void loop(int numLoops)
Calling the version with no arguments will make the sound loop indefinitely, while calling the version with an int will loop the sound the specified number of times. It should be noted that looping the sound one time will cause the sound to be played twice, looping the sound two times will cause it to be played three times and so on. You can find out whether or not a sound has been set to loop by calling isLooping(). This will be true as long as there are loops left to be played, even if you pause the sound. There is currently no way to find out how many loops are left to be played. If you call play() before the sound has looped the number of times you’ve asked for, it will cancel out the looping behaviour and play to the end of the sound and stop. This can be useful if you want the sound to stop looping but don’t want the sound to cut off in the middle.
Code Sample (online example)
import ddf.minim.*; AudioPlayer groove; // this class is defined in a separate file // see the online example for the code WaveformRenderer waveform; void setup() { size(512, 200); // always start Minim first Minim.start(this); groove = Minim.loadFile("groove.mp3", 512); waveform = new WaveformRenderer(); // see the example Recordable >> addListener for more about this groove.addListener(waveform); textFont(createFont("Arial", 12)); } void draw() { background(0); // see waveform.pde for an explanation of how this works waveform.draw(); if ( groove.isLooping() ) { text("The player is looping.", 5, 15); } else { text("The player is not looping.", 5, 15); } } void keyPressed() { if ( key == 'p' ) { groove.play(); } if ( key == 'l' ) { groove.loop(); } } void stop() { // always close Minim audio classes when you are done with them groove.close(); super.stop(); }
Cueing
When you cue, it is always measured from the beginning of the recording. So cue(100) will set the “playhead” at 100 milliseconds from the beginning no matter where it currently is. Cueing a Playable object will not change the playstate, meaning that if it was already playing it will continue playing from the cue point, but if it was not playing, cueing will not start playback, it will simply set the point at which playback will begin. If an error occurs while trying to cue, the position will not change. If you try to cue to a negative position or try to cue past the end of the recording, the amount will be clamped to zero or length().
Code Sample (online example)
import ddf.minim.*; AudioPlayer groove; WaveformRenderer waveform; void setup() { size(512, 200); // always start Minim first Minim.start(this); groove = Minim.loadFile("groove.mp3", 512); groove.loop(); waveform = new WaveformRenderer(); // see the example Recordable >> addListener for more about this groove.addListener(waveform); } void draw() { background(0); // see waveform.pde for an explanation of how this works waveform.draw(); } void keyPressed() { if ( key == 'c' ) { groove.cue(5000); } } void stop() { // always close Minim audio classes when you are done with them groove.close(); super.stop(); }
Skipping
When you skip, it is always measured from the current position of the recording. So skip(100) will set the “playhead” at 100 milliseconds from the current position. A sort of fast-forward. It is also possible to skip in a negative direction. So skip(-200) will set the “playhead” to 200 milliseconds before the current position. Using skip will not change the playstate of a Playable, meaning that if it was already playing it will continue playing from the new position, but if it was not playing, skipping will not start playback, it will simply set the point at which playback will begin. If an error occurs while trying to skip, the position will not change. If you try to skip to a position that is less than zero or try to skip past the end of the recording, the position will be clamped to zero or length().
Code Sample (online example)
import ddf.minim.*; AudioPlayer groove; WaveformRenderer waveform; void setup() { size(512, 200); // always start Minim first Minim.start(this); Minim.debugOn(); groove = Minim.loadFile("groove.mp3", 512); groove.loop(); waveform = new WaveformRenderer(); // see the example Recordable >> addListener for more about this groove.addListener(waveform); } void draw() { background(0); // see waveform.pde for an explanation of how this works waveform.draw(); } void keyPressed() { if ( key == 'f' ) { groove.skip(100); } if ( key == 'r' ) { groove.skip(-500); } } void stop() { // always close Minim audio classes when you are done with them groove.close(); super.stop(); }
Position and Length
The position method of a Playable returns the current position of the “playhead” in milliseconds. In other words, it’s how much of the recording has been played. The length method returns how long the Playable is in milliseconds (1 ms = 1/1000 of a second). The example below demonstrates how you could use the position and length methods to visualize where in the recording the “playhead” is.
Code Sample (online example)
import ddf.minim.*; AudioPlayer groove; WaveformRenderer waveform; void setup() { size(512, 200); // always start Minim first Minim.start(this); groove = Minim.loadFile("groove.mp3", 512); waveform = new WaveformRenderer(); // see the example Recordable >> addListener for more about this groove.addListener(waveform); groove.loop(); } void draw() { background(0); // see waveform.pde for an explanation of how this works waveform.draw(); float x = map(groove.position(), 0, groove.length(), 0, width); stroke(255, 0, 0); line(x, height/2 - 30, x, height/2 + 30); } void stop() { // always close Minim audio classes when you are done with them groove.close(); super.stop(); }