Skip to content

Commit 41a0ab5

Browse files
committed
Add helper variable to stop isPlaying() from reporting wrong status (fixes #44)
1 parent 1a3479d commit 41a0ab5

File tree

1 file changed

+20
-7
lines changed

1 file changed

+20
-7
lines changed

src/processing/sound/AudioSample.java

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ public class AudioSample extends SoundObject {
2727
// position within the sample
2828
protected long startFrameCountOffset = 0;
2929

30+
// helper variable for making isPlaying() return true for the fraction of a
31+
// second after play() was called but audio data hasn't been queued yet
32+
private long isPlayingAtLeastUntil = 0;
33+
3034
public AudioSample(PApplet parent, int frames) {
3135
this(parent, frames, false);
3236
}
@@ -133,13 +137,20 @@ protected void initiatePlayer() {
133137
* @Override
134138
**/
135139
public boolean isPlaying() {
136-
// this used to just return dataQueue.hasMore(), but this raises false
137-
// positives as .hasMore() still returns true for a split second after
138-
// dataQueue.clear() has been called. the AudioSample class therefore
139-
// manually sets the isPlaying boolean to true when playback commences,
140-
// but every time the user queries the playing status we check if the
141-
// queue has actually run out in the meantime.
142-
this.isPlaying = this.isPlaying & this.player.dataQueue.hasMore();
140+
// relying on dataQueue.hasMore() alone is problematic because it can
141+
// raise both false positives (return true for a split second after
142+
// dataQueue.clear() has been called) as well as false negatives
143+
// (return false for a split second after audio data has been queued
144+
// but hasn't been transferred into the queue yet). The AudioSample class
145+
// therefore manually sets the isPlaying boolean to true when playback
146+
// commences and false when it is stopped, but also every time the
147+
// playing status is queried we update the boolean based on additional
148+
// checks:
149+
if (this.isPlaying) {
150+
// set isPlaying to false if the queue is empty, UNLESS too little
151+
// time has passed since the last playback command
152+
this.isPlaying = this.player.dataQueue.hasMore() || System.currentTimeMillis() < this.isPlayingAtLeastUntil;
153+
}
143154
return this.isPlaying;
144155
}
145156

@@ -315,6 +326,7 @@ private void loopInternal(int startFrame, int numFrames, int numLoops) {
315326
} else {
316327
this.player.dataQueue.queueLoop(this.sample, startFrame, numFrames);
317328
}
329+
this.isPlayingAtLeastUntil = System.currentTimeMillis() + 50;
318330
this.isPlaying = true;
319331
}
320332

@@ -401,6 +413,7 @@ private void playInternal(int startFrame, int numFrames) {
401413
this.setStartFrameCountOffset();
402414
// only queueImmediate() guarantees that a directly subsequent call to .hasMore() returns true
403415
this.player.dataQueue.queue(this.sample, startFrame, numFrames);
416+
this.isPlayingAtLeastUntil = System.currentTimeMillis() + 50;
404417
this.isPlaying = true;
405418
}
406419

0 commit comments

Comments
 (0)