Фрагмент кода в нижней части этого вопроса отлично работает на моем настольном ПК, вызовы clip.getFramePosition()
занимают 1 мс или меньше. На моем Pi 3 Model B + с Raspbian Stretch и JDK 8u191 для вызова одной и той же функции требуется около 900 мс. Это кажется слишком медленным.
На самом деле я пытаюсь воспроизвести файл MP3 через JLayer, но проблема также возникает с файлами WAV, и легче воспроизводить файл WAV, так как не требуется никаких внешних зависимостей,
Процессор и память
ЦП и использование памяти Pi, о которых сообщает top
, никогда не превышают 10% при запуске кода. Я также попытался предварительно загрузить аудио в массив byte
и воспроизвести его вместо потока. У него та же проблема, поэтому это не узкое место дискового ввода / вывода.
Блокировка
Во время выполнения объект clip
является экземпляром com.sun.media.sound.DirectAudioDevice.DirectDL
, а его метод getLongFramePosition()
имеет синхронизированный блок, который вызывает метод native
:
synchronized(this.lockNative) {
var1 = DirectAudioDevice.nGetBytePosition(this.id, this.isSournce, this.bytePosition);
}
Так что, возможно, что-то блокирует мой звонок. Тем не менее, я бы подумал, что запрос прогресса Clip
во время его игры - разумная вещь.
Что бы это могло быть?
Кто-нибудь может пролить свет на эту медлительность? Неправильно ли я использую API или это может быть просто проблемой реализации Java Audio в Raspbian?
Обновление № 1: Ubuntu MATE + Liberica
Я попытался запустить код для Ubuntu MATE с помощью Liberica JRE 11, но медлительность все еще возникала.
Обновление № 2: Внешняя звуковая карта
Я подключил внешнюю звуковую карту USB к своему пи и проиграл через нее звук. Я не ожидал, что это решит проблему, и это не так.
Обновление № 3: используйте JLayer напрямую
Воспроизведение MP3 через класс JLayer AdvancedPlayer
вместо API Java Sound немного лучше. Требуется около 50 мс, чтобы получить прогресс вместо 900 мс, но это все еще очень медленно.
Обновление № 4: Используйте модель Pi 3 B
У меня есть Pi 3 Модель B (не B +), лежащая вокруг. У него та же проблема при запуске последней Raspbian. С Raspbian Jessie (2016-03-18) это немного быстрее (~ 700 мс), но не намного.
Пример кода
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);
}
}
}