Java: Как использовать микрофонный вход в качестве входа для медиаплеера JavaFX?
Я хочу воспроизводить микрофонный вход в режиме реального времени с помощью медиаплеера JavaFX (для анализа его частот). Проблема в том, что MediaPlayer принимает только строки в качестве источника. Я знаю, как записать вход микрофона в байтовый массив и в файл.
Использование байтового массива в качестве источника для MediaPlayer (для меня) невозможно. Я попытался использовать временный файл, но это вызывает следующую ошибку:
Exception in thread "JavaFX Application Thread" MediaException: MEDIA_UNSUPPORTED : Empty signature!
Я думаю, что это так, потому что я использую файл в качестве ввода, в то время как я все еще записываю в него новые данные. Мой полный код до сих пор:
public class Music {
static AudioFormat format;
static DataLine.Info info;
public static void input(int i, int j, int pinState) {
format = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, 44100, 16, 2, 4, 44100, false);
try {
info = new DataLine.Info(TargetDataLine.class, format);
final TargetDataLine targetLine = (TargetDataLine) AudioSystem.getLine(info);
targetLine.open();
AudioInputStream audioStream = new AudioInputStream(targetLine);
File temp = File.createTempFile("Input", ".wav");
temp.deleteOnExit();
Thread targetThread = new Thread() {
public void run() {
targetLine.start();
try {
AudioSystem.write(audioStream, AudioFileFormat.Type.WAVE, temp);
} catch (IOException e) {
e.printStackTrace();
}
}
};
targetThread.start();
Media media = new Media(temp.toURI().toURL().toString());
MediaPlayer player = new MediaPlayer(media);
player.setAudioSpectrumThreshold(-100);
player.setMute(false);
player.setAudioSpectrumListener(new AudioSpectrumListener() {
@Override
public void spectrumDataUpdate(double timestamp, double duration, float[] magnitudes, float[] phases) {
if(Var.nodeController[i] == 3) { //testing if the targetLine should keep on capturing sound
} else {
targetLine.stop();
targetLine.close();
player.stop();
}
}
});
player.play();
} catch (LineUnavailableException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Мне нужно найти решение использовать вход микрофона в качестве входа MediaPlayer, используя файл или байтовый массив или любое другое возможное решение.
1 ответ
Я собираюсь предположить, что следующая библиотека может быть полезной. https://github.com/SzymonKatra/AudioAnalyzer
Обратите внимание, что он использует FFmpeg, который утверждает, что:
Полное кроссплатформенное решение для записи, конвертации и потоковой передачи аудио и видео.
Ключевым компонентом (основанным на моем беглом просмотре) является класс FFTAnalyzer.java, который, как говорится в документации, основан на коде / алгоритме FFT из Принстона.
Итак, основной план (я считаю) будет следующим:
- получить микрофонный вход (поток байтов) от targettdataline
- преобразовать N кадров байтов в нормализованные числа с плавающей запятой или удваивать и упаковать как массив для отправки в FFTAnalyzer.analyze(double[] samples)
- запросить результаты анализа через FFTAnalyzer.getAmplitude ()
- изучите результат для каждой полосы выравнивания и примените сглаживание соответствующим образом
- повторение
Мне неясно, сколько именно библиотеки нужно. Может случиться так, что, поскольку вы не имеете дело с проблемами с видео или кроссплатформенностью, потребуется только один или два класса из этой библиотеки.