Java Audio Clip#getFramePosition() very slow on Raspberry Pi
up vote
3
down vote
favorite
The code snippet at the bottom of this question runs fine on my desktop PC, calls to clip.getFramePosition()
take 1ms or less. On my Pi 3 Model B+ running Raspbian Stretch and JDK 8u191, it takes around 900ms to call the same function. This seems way too slow.
I'm actually trying to play an MP3 file via JLayer, but the issue also occurs with WAV files and it's easier to reproduce with a WAV file as no external dependencies are needed,
CPU and Memory
The Pi's CPU and memory usage as reported by top
are never greater than 10% when running the code. I've also tried preloading the audio into a byte
array and playing that instead of the stream. It has the same issue, so this doesn't appear to be a disk I/O bottleneck.
Blocking
At runtime, the clip
object is an instance of com.sun.media.sound.DirectAudioDevice.DirectDL
, and its getLongFramePosition()
method has a synchronized block that calls a native
method:
synchronized(this.lockNative) {
var1 = DirectAudioDevice.nGetBytePosition(this.id, this.isSournce, this.bytePosition);
}
So it's possible that something is blocking my call. However, I would have thought querying a Clip
's progress while it's playing is a reasonable thing to do.
What could it be?
Can anybody shed some light on this slowness? Am I misusing the API, or could this just be an issue with Raspbian's Java Audio implementation?
Update #1: Ubuntu MATE + Liberica
I tried running the code against Ubuntu MATE with Liberica JRE 11 and the slowness still occurred.
Update #2: External sound card
I plugged an external USB sound card into my pi and played the audio through that. I didn't expect it to fix the issue, and it didn't.
Update #3: Use JLayer directly
Playing an MP3 via the JLayer AdvancedPlayer
class instead of through the Java Sound API is a bit better. It takes around 50ms to get the progress instead of 900ms, but that's still very slow.
Update #4: Use Pi 3 Model B
I have a Pi 3 Model B (not B+) laying around. It has the same issue when running the latest Raspbian. With Raspbian Jessie (2016-03-18) it's a bit faster (~700ms) but not much.
Sample Code
import java.io.File;
import java.io.InputStream;
import java.util.Date;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
public class Main {
public static void main(String args) throws Exception {
File file = new File("/home/pi/beat.wav");
AudioInputStream ais = AudioSystem.getAudioInputStream(file);
AudioFormat format = ais.getFormat();
Clip clip = AudioSystem.getClip();
clip.open(ais);
clip.start();
for (int i = 0; i < 100; i++) {
long start = new Date().getTime();
long pos = clip.getFramePosition();
long duration = new Date().getTime() - start;
System.out.println("Pos: " + pos + ", duration: " + duration);
Thread.sleep(10);
}
}
}
java audio raspberry-pi
This question has an open bounty worth +50
reputation from Chris Parton ending in 2 hours.
This question has not received enough attention.
Either a fix or a definitive explanation of why this method is so slow to call on a Pi would be greatly appreciated.
add a comment |
up vote
3
down vote
favorite
The code snippet at the bottom of this question runs fine on my desktop PC, calls to clip.getFramePosition()
take 1ms or less. On my Pi 3 Model B+ running Raspbian Stretch and JDK 8u191, it takes around 900ms to call the same function. This seems way too slow.
I'm actually trying to play an MP3 file via JLayer, but the issue also occurs with WAV files and it's easier to reproduce with a WAV file as no external dependencies are needed,
CPU and Memory
The Pi's CPU and memory usage as reported by top
are never greater than 10% when running the code. I've also tried preloading the audio into a byte
array and playing that instead of the stream. It has the same issue, so this doesn't appear to be a disk I/O bottleneck.
Blocking
At runtime, the clip
object is an instance of com.sun.media.sound.DirectAudioDevice.DirectDL
, and its getLongFramePosition()
method has a synchronized block that calls a native
method:
synchronized(this.lockNative) {
var1 = DirectAudioDevice.nGetBytePosition(this.id, this.isSournce, this.bytePosition);
}
So it's possible that something is blocking my call. However, I would have thought querying a Clip
's progress while it's playing is a reasonable thing to do.
What could it be?
Can anybody shed some light on this slowness? Am I misusing the API, or could this just be an issue with Raspbian's Java Audio implementation?
Update #1: Ubuntu MATE + Liberica
I tried running the code against Ubuntu MATE with Liberica JRE 11 and the slowness still occurred.
Update #2: External sound card
I plugged an external USB sound card into my pi and played the audio through that. I didn't expect it to fix the issue, and it didn't.
Update #3: Use JLayer directly
Playing an MP3 via the JLayer AdvancedPlayer
class instead of through the Java Sound API is a bit better. It takes around 50ms to get the progress instead of 900ms, but that's still very slow.
Update #4: Use Pi 3 Model B
I have a Pi 3 Model B (not B+) laying around. It has the same issue when running the latest Raspbian. With Raspbian Jessie (2016-03-18) it's a bit faster (~700ms) but not much.
Sample Code
import java.io.File;
import java.io.InputStream;
import java.util.Date;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
public class Main {
public static void main(String args) throws Exception {
File file = new File("/home/pi/beat.wav");
AudioInputStream ais = AudioSystem.getAudioInputStream(file);
AudioFormat format = ais.getFormat();
Clip clip = AudioSystem.getClip();
clip.open(ais);
clip.start();
for (int i = 0; i < 100; i++) {
long start = new Date().getTime();
long pos = clip.getFramePosition();
long duration = new Date().getTime() - start;
System.out.println("Pos: " + pos + ", duration: " + duration);
Thread.sleep(10);
}
}
}
java audio raspberry-pi
This question has an open bounty worth +50
reputation from Chris Parton ending in 2 hours.
This question has not received enough attention.
Either a fix or a definitive explanation of why this method is so slow to call on a Pi would be greatly appreciated.
new Date().getTime()
is equivalent toSystem.currentTimeMillis()
. There is no guarantee that the system clock actually has millisecond accuracy.
– greg-449
Nov 7 at 12:34
@greg-449 this is just a snippet to reproduce the issue. The slowness is definitely present.
– Chris Parton
Nov 7 at 22:08
add a comment |
up vote
3
down vote
favorite
up vote
3
down vote
favorite
The code snippet at the bottom of this question runs fine on my desktop PC, calls to clip.getFramePosition()
take 1ms or less. On my Pi 3 Model B+ running Raspbian Stretch and JDK 8u191, it takes around 900ms to call the same function. This seems way too slow.
I'm actually trying to play an MP3 file via JLayer, but the issue also occurs with WAV files and it's easier to reproduce with a WAV file as no external dependencies are needed,
CPU and Memory
The Pi's CPU and memory usage as reported by top
are never greater than 10% when running the code. I've also tried preloading the audio into a byte
array and playing that instead of the stream. It has the same issue, so this doesn't appear to be a disk I/O bottleneck.
Blocking
At runtime, the clip
object is an instance of com.sun.media.sound.DirectAudioDevice.DirectDL
, and its getLongFramePosition()
method has a synchronized block that calls a native
method:
synchronized(this.lockNative) {
var1 = DirectAudioDevice.nGetBytePosition(this.id, this.isSournce, this.bytePosition);
}
So it's possible that something is blocking my call. However, I would have thought querying a Clip
's progress while it's playing is a reasonable thing to do.
What could it be?
Can anybody shed some light on this slowness? Am I misusing the API, or could this just be an issue with Raspbian's Java Audio implementation?
Update #1: Ubuntu MATE + Liberica
I tried running the code against Ubuntu MATE with Liberica JRE 11 and the slowness still occurred.
Update #2: External sound card
I plugged an external USB sound card into my pi and played the audio through that. I didn't expect it to fix the issue, and it didn't.
Update #3: Use JLayer directly
Playing an MP3 via the JLayer AdvancedPlayer
class instead of through the Java Sound API is a bit better. It takes around 50ms to get the progress instead of 900ms, but that's still very slow.
Update #4: Use Pi 3 Model B
I have a Pi 3 Model B (not B+) laying around. It has the same issue when running the latest Raspbian. With Raspbian Jessie (2016-03-18) it's a bit faster (~700ms) but not much.
Sample Code
import java.io.File;
import java.io.InputStream;
import java.util.Date;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
public class Main {
public static void main(String args) throws Exception {
File file = new File("/home/pi/beat.wav");
AudioInputStream ais = AudioSystem.getAudioInputStream(file);
AudioFormat format = ais.getFormat();
Clip clip = AudioSystem.getClip();
clip.open(ais);
clip.start();
for (int i = 0; i < 100; i++) {
long start = new Date().getTime();
long pos = clip.getFramePosition();
long duration = new Date().getTime() - start;
System.out.println("Pos: " + pos + ", duration: " + duration);
Thread.sleep(10);
}
}
}
java audio raspberry-pi
The code snippet at the bottom of this question runs fine on my desktop PC, calls to clip.getFramePosition()
take 1ms or less. On my Pi 3 Model B+ running Raspbian Stretch and JDK 8u191, it takes around 900ms to call the same function. This seems way too slow.
I'm actually trying to play an MP3 file via JLayer, but the issue also occurs with WAV files and it's easier to reproduce with a WAV file as no external dependencies are needed,
CPU and Memory
The Pi's CPU and memory usage as reported by top
are never greater than 10% when running the code. I've also tried preloading the audio into a byte
array and playing that instead of the stream. It has the same issue, so this doesn't appear to be a disk I/O bottleneck.
Blocking
At runtime, the clip
object is an instance of com.sun.media.sound.DirectAudioDevice.DirectDL
, and its getLongFramePosition()
method has a synchronized block that calls a native
method:
synchronized(this.lockNative) {
var1 = DirectAudioDevice.nGetBytePosition(this.id, this.isSournce, this.bytePosition);
}
So it's possible that something is blocking my call. However, I would have thought querying a Clip
's progress while it's playing is a reasonable thing to do.
What could it be?
Can anybody shed some light on this slowness? Am I misusing the API, or could this just be an issue with Raspbian's Java Audio implementation?
Update #1: Ubuntu MATE + Liberica
I tried running the code against Ubuntu MATE with Liberica JRE 11 and the slowness still occurred.
Update #2: External sound card
I plugged an external USB sound card into my pi and played the audio through that. I didn't expect it to fix the issue, and it didn't.
Update #3: Use JLayer directly
Playing an MP3 via the JLayer AdvancedPlayer
class instead of through the Java Sound API is a bit better. It takes around 50ms to get the progress instead of 900ms, but that's still very slow.
Update #4: Use Pi 3 Model B
I have a Pi 3 Model B (not B+) laying around. It has the same issue when running the latest Raspbian. With Raspbian Jessie (2016-03-18) it's a bit faster (~700ms) but not much.
Sample Code
import java.io.File;
import java.io.InputStream;
import java.util.Date;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
public class Main {
public static void main(String args) throws Exception {
File file = new File("/home/pi/beat.wav");
AudioInputStream ais = AudioSystem.getAudioInputStream(file);
AudioFormat format = ais.getFormat();
Clip clip = AudioSystem.getClip();
clip.open(ais);
clip.start();
for (int i = 0; i < 100; i++) {
long start = new Date().getTime();
long pos = clip.getFramePosition();
long duration = new Date().getTime() - start;
System.out.println("Pos: " + pos + ", duration: " + duration);
Thread.sleep(10);
}
}
}
java audio raspberry-pi
java audio raspberry-pi
edited Nov 9 at 4:45
asked Nov 7 at 11:56
Chris Parton
785612
785612
This question has an open bounty worth +50
reputation from Chris Parton ending in 2 hours.
This question has not received enough attention.
Either a fix or a definitive explanation of why this method is so slow to call on a Pi would be greatly appreciated.
This question has an open bounty worth +50
reputation from Chris Parton ending in 2 hours.
This question has not received enough attention.
Either a fix or a definitive explanation of why this method is so slow to call on a Pi would be greatly appreciated.
new Date().getTime()
is equivalent toSystem.currentTimeMillis()
. There is no guarantee that the system clock actually has millisecond accuracy.
– greg-449
Nov 7 at 12:34
@greg-449 this is just a snippet to reproduce the issue. The slowness is definitely present.
– Chris Parton
Nov 7 at 22:08
add a comment |
new Date().getTime()
is equivalent toSystem.currentTimeMillis()
. There is no guarantee that the system clock actually has millisecond accuracy.
– greg-449
Nov 7 at 12:34
@greg-449 this is just a snippet to reproduce the issue. The slowness is definitely present.
– Chris Parton
Nov 7 at 22:08
new Date().getTime()
is equivalent to System.currentTimeMillis()
. There is no guarantee that the system clock actually has millisecond accuracy.– greg-449
Nov 7 at 12:34
new Date().getTime()
is equivalent to System.currentTimeMillis()
. There is no guarantee that the system clock actually has millisecond accuracy.– greg-449
Nov 7 at 12:34
@greg-449 this is just a snippet to reproduce the issue. The slowness is definitely present.
– Chris Parton
Nov 7 at 22:08
@greg-449 this is just a snippet to reproduce the issue. The slowness is definitely present.
– Chris Parton
Nov 7 at 22:08
add a comment |
active
oldest
votes
active
oldest
votes
active
oldest
votes
active
oldest
votes
active
oldest
votes
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53189006%2fjava-audio-clipgetframeposition-very-slow-on-raspberry-pi%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
new Date().getTime()
is equivalent toSystem.currentTimeMillis()
. There is no guarantee that the system clock actually has millisecond accuracy.– greg-449
Nov 7 at 12:34
@greg-449 this is just a snippet to reproduce the issue. The slowness is definitely present.
– Chris Parton
Nov 7 at 22:08