Java Audio Clip#getFramePosition() very slow on Raspberry Pi











up vote
3
down vote

favorite
1












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);
}
}
}









share|improve this question

















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 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















up vote
3
down vote

favorite
1












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);
}
}
}









share|improve this question

















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 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













up vote
3
down vote

favorite
1









up vote
3
down vote

favorite
1






1





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);
}
}
}









share|improve this question















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






share|improve this question















share|improve this question













share|improve this question




share|improve this question








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 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


















  • 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
















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

















active

oldest

votes











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














 

draft saved


draft discarded


















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






























active

oldest

votes













active

oldest

votes









active

oldest

votes






active

oldest

votes
















 

draft saved


draft discarded



















































 


draft saved


draft discarded














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





















































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







Popular posts from this blog

Guess what letter conforming each word

Port of Spain

Run scheduled task as local user group (not BUILTIN)