Reputation: 305
How can you ensure the transition between two pieces of audio is seamless?
In a JavaFX application, I am using the javafx.scene.media.MediaPlayer
to play an intro-piece, which is proceeded by the main/looping-piece. The media is played just fine, but the issue is the transition and loop.
Here is what I am currently doing:
private static void foo(final Media intro, final Media loop) {
final MediaPlayer introPlayer = new MediaPlayer(intro);
introPlayer.play();
final MediaPlayer loopPlayer = new MediaPlayer(loop);
loopPlayer.pause(); // An attempt to load the media so it will be ready to be played.
introPlayer.setOnEndOfMedia(loopPlayer::play());
loopPlayer.setOnEndOfMedia(() -> loopPlayer.seek(Duration.ZERO));
//loopPlayer.setCycleCount(Integer.MAX_VALUE); // Similar to the above line, but there is still a delay between loops.
}
The MediaPlayer::pause does help some, but there is a very noticeable delay between the end of the intro media and the start of the looping media. Furthermore, there is another noticeable delay between the end of the looping media and the repeat.
I additionally tried using javafx.scene.media.AudioClip
, since it supposedly has less overhead than a javafx.scene.media.MediaPlayer
. I wrote my own listener to tell when the track ended (and to immediately thereafter start the looping piece), but I still saw a similar delay.
Here were some similar posts I found, but did not provide a solution to the problem:
JavaFX MediaPlayer playing background music loop with small intro music
This one is definitely relevant (coincidentally, it is almost the anniversary of that post), but I am already using a .wav formatted media file and still experience a delay.
Which is similar to what I tried with the Audioclip, exept I used a scheduled executor to time when to replay the audio. (Where I still experienced a delay).
And, as a final note, I have tested my audio in Audacity, where they transitioned and looped seamlessly.
What are some recommended solutions for these types of problems?
Edit:
Upvotes: 0
Views: 819
Reputation: 7910
I realize it's been a while since you posted. Have you found an answer? I am wondering if you loaded loopPlayer
before playing introPlayer
, if that would help.
If MediaPlayer's "listener" is just kind of sluggish, maybe switching to using Java's SourceDataLine
with a LineListener
used to trigger the looping cue would work more seamlessly? (I would use a Clip
for the looping playback.)
Last suggestion, I have an audio library AudioCue that could work for this. The library includes an AudioCueListener
that can trigger an event (such as starting another AudioCue
playing) when a cue ends. But limitations of the library would require that you hold your music in memory, and that the source files be .wav's.
Upvotes: 1
Reputation: 686
The AudioClip Javadocs state that an AudioClip represents a segment of audio that can be played with minimal latency and are usable immediately. However, it also states
Media objects are however better suited for long-playing sounds. This is primarily because AudioClip stores in memory the raw, uncompressed audio data for the entire sound, which can be quite large for long audio clips. A MediaPlayer will only have enough decompressed audio data pre-rolled in memory to play for a short amount of time so it is much more memory efficient for long clips, especially if they are compressed.
Depending on the length of the looping media, an AudioClip
might be better suited for you. Instead of needing a ScheduledExecutorService
to replay the audio, you can use AudioClip.setCycleCount(AudioClip.INDEFINITE)
to loop forever.
Using this info, I believe your best bet is to use a MediaPlayer
for the intro and then utilize MediaPlayer#setOnEndOfMedia
to call the looping AudioClip
; possibly having a small delay between the intro and looping transition but seamless after that.
Upvotes: 0