Аудиосистема Java и TargetDataLine

Я пытаюсь захватить звук с линейного входа с моего ПК, для этого я использую AudioSystem. Существует один из двух вариантов использования статического метода AudioSystem.write: запись в файл или запись в поток. Я могу заставить его нормально писать в файл, но всякий раз, когда я пытаюсь записать в поток, я получаю исключение java.io.IOException (длина потока не указана). Что касается моего буфера, я использую ByteArrayOutputStream. Есть ли другой тип потока, который я должен использовать или испортить где-то еще?

Также в связанной теме можно попробовать звуковую строку в (TargetDataLine) напрямую, вызвав читать. Является ли это предпочтительным способом захвата звука или использования AudioSystem?

Обновите запрошенный исходный код:

final private TargetDataLine line;
final private AudioFormat format;
final private AudioFileFormat.Type fileType;
final private AudioInputStream audioInputStream;
final private ByteArrayOutputStream bos;

// Constructor, etc.

public void run()
{
    System.out.println("AudioWorker Started");
    try
    {
        line.open(format);
        line.start();

        // This commented part is regarding the second part
        // of my question
        // byte[] buff = new byte[512];
        // int bytes = line.read(buff, 0, buff.length);

        AudioSystem.write(audioInputStream, fileType, bos);

    }
    catch ( Exception e )
    {
        e.printStackTrace();
    }

    System.out.println("AudioWorker Finished");
}


// Stack trace in console
AudioWorker Started
java.io.IOException: stream length not specified
    at com.sun.media.sound.WaveFileWriter.write(Unknown Source)
    at javax.sound.sampled.AudioSystem.write(Unknown Source)
    at AudioWorker.run(AudioWorker.java:41)
AudioWorker Finished

person Venus    schedule 28.02.2009    source источник
comment
Опубликуйте трассировку стека, по крайней мере, несколько верхних кадров, вплоть до вашего приложения.   -  person erickson    schedule 28.02.2009


Ответы (4)


Из AudioSystem.write JavaDoc:

Записывает поток байтов, представляющий аудиофайл указанного типа, в предоставленный выходной поток. Некоторые типы файлов требуют, чтобы длина была записана в заголовок файла; такие файлы не могут быть записаны от начала до конца, если их длина не известна заранее. Попытка записи файла такого типа завершится с ошибкой IOException, если длина аудиофайла типа AudioSystem.NOT_SPECIFIED.

person jonathan.cone    schedule 28.02.2009
comment
Это похоже на запись в файлы (хотя файлы тоже являются потоками ..)? Но как это применимо к записи в OutputStream? Значит ли это, что это невозможно? - person Venus; 01.03.2009
comment
@srand, я думаю, это имеет смысл, поскольку вы не выполняете потоковую передачу (для чего требуется другой механизм), поэтому, по сути, вам нужно указать длину перед записью в выходной поток. - person Johnydep; 06.02.2012

Поскольку формат Wave требует записи длины в начале файла, модуль записи запрашивает метод getFrameLength вашего файла AudioInputStream. Когда это возвращает NOT_SPECIFIED, потому что ваша запись «живых» данных пока еще неуказанной длины, писатель выдает исключение.

File-ориентированный обходит это, записывая фиктивные данные в поле длины, затем повторно открывая файл, когда запись завершена, и перезаписывая эту область файла.

Используйте выходной формат, которому не требуется длина заранее (au), или используйте AudioInputStream, который возвращает допустимую длину кадра, или используйте File версию API.

person erickson    schedule 02.03.2009
comment
Насколько я понимаю, AudioSystem.write пишет только в файлы? - person Venus; 03.03.2009
comment
В чем тогда польза подписи с OutputStream? - person Alessandro Dionisi; 18.03.2015
comment
@AlessandroDionisi Работает для некоторых форматов, например .au - person erickson; 18.03.2015

Вам следует ознакомиться с учебником Ричарда Болдуина по Ява звук. В конце статьи есть полный список источников, где он использует чтение TargetDataLine для захвата звука.

person Brendan Cashman    schedule 11.03.2009

Вы также можете попробовать использовать JMF, который немного волосатый, но работает немного лучше, чем javax.sound.sampled. На странице JMF есть довольно много руководств, в которых описывается, как записывать с линейного входа или микрофонных каналов.

person Brother Logic    schedule 28.02.2009