I'm trying to play a sound that loops perfectly where you can't tell when it starts over. I know that I can get an AudioClip or MediaPlayer to loop indefinitely with the setCycleCount method, and this works. However, the audio isn't perfectly continuous; there's a very split second where it's not playing, so it's extremely obvious when it starts over. I know it's not a problem with the audio file itself because when I play it on loop on an audio player, it loops perfectly. I've tried both AudioClip and MediaPlayer, and I tried using setOnEndOfMedia to make it loop instead, but they all had the same problem. Here's an example:
import java.io.File;
import java.net.*;
import java.util.Scanner;
import javafx.scene.media.*;
public class AudioTest {
public static void main(String[] args) {
URI audioURI = new File("filePath").toURI();
AudioClip audio = new AudioClip(audioURI.toString());
audio.setCycleCount(AudioClip.INDEFINITE);
audio.play();
/*
setOnEndOfMedia version
MediaPlayer audio = new MediaPlayer(new Media(audioURI.toString()));
audio.setOnEndOfMedia(new Runnable() {
@Override
public void run() {
audio.seek(Duration.ZERO);
audio.play();
}
});
*/
new Scanner(System.in).next(); // to prevent the program from closing immediately
}
}
and a link to an example audio file: https://drive.google.com/file/d/1NzlqY-K7m__qXE6iKJw3H26KZ8Ql4U2n/view?usp=sharing
My operating system is Windows 11, and I'm using Java 17 and JavaFX 17. My CPU is an 11th Gen Intel(R) Core(TM) i5-1135G7. Is there any way I can fix this?
Here is an example with javax.sound
that loops a wav
file (the sine wave file named tone.wav
that you link in your question).
I loop the sound five times, but you can loop it as many times as you want.
To use it from a JavaFX application, you could wrap the sound playback using javax.sound
in a JavaFX task and supply an interface to it (being careful of the threading coding for concurrent applications).
import javax.sound.sampled.*;
import java.io.IOException;
import java.util.Objects;
import java.util.Scanner;
public class SoundTest {
public static void main(String[] args) throws LineUnavailableException, IOException, UnsupportedAudioFileException {
AudioInputStream stream = AudioSystem.getAudioInputStream(
Objects.requireNonNull(
SoundTest.class.getResource(
"tone.wav"
)
)
);
AudioFormat format = stream.getFormat();
DataLine.Info info = new DataLine.Info(Clip.class, format);
Clip clip = (Clip) AudioSystem.getLine(info);
clip.open(stream);
clip.loop(5);
// clip.start();
new Scanner(System.in).next(); // to prevent the program from closing immediately
}
}
For me, I get a continual, seamless loop of the audio with the javax.sound
playback.
But with the Java MediaPlayer or AudioClip, using your sample code, I get a break between loops as you mention in your question. I do not know why this is and if it is restricted to some attribute of the sound you are playing or some current limitation of JavaFX audio playback on certain or all platforms. You might want to ask the openjfx-dev mailing list for more information.
The test system used was JavaFX 21.0.1 and OpenJDK 21 on an OS X 14.1.2 Mac.
A note on javax.sound
usage.
javax.sound
is an alternate sound playback interface to JavaFX media. The javax.sound
packages are part of the java.desktop
module which is (as of JavaFX 21) required as part of any JavaFX installation (even though the javax.sound
system has nothing to do with JavaFX).
The javax.sound
system might not fit your requirements though as it may not natively play back the sound formats you want, but for certain sound formats it might be a workable alternative.
Oracle provide a tutorial for the javax.sound
API if needed.