chrisparton1991
Posts: 1
Joined: Thu Nov 08, 2018 10:14 am

Clip#getFramePosition() is very slow

Thu Nov 08, 2018 10:23 am

Hi all,

The code snippet at the bottom of this post 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.

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:

Code: Select all

synchronized(this.lockNative) {
  var1 = DirectAudioDevice.nGetBytePosition(this.id, this.isSource, 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.

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?

Thanks!

P.S. I posted this question on Stack Overflow, but didn't get any response there, so trying here instead.

Sample Code

Code: Select all

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

Return to “Java”