Java Понимание ByteArrayOutputStream и ByteArrayInputStream
Я читал эту статью: http://www.java-tips.org/java-se-tips-100019/120-javax-sound/917-capturing-audio-with-java-sound-api.html Я не знаю не хочу писать весь код до статьи...
Мне нужно уточнить мое понимание, и мне нужно объяснение об использовании ByteArrayInputStream и ByteArrayOutputStream...
На основании полного кода:
В методе captureAudio(), фокусирующемся на цикле
while (running) {
int count = line.read(buffer, 0, buffer.length);
if (count > 0) {
out.write(buffer, 0, count);
}
}
out.close();
По определению (проверьте строки 64 и 65):
final TargetDataLine line = (TargetDataLine)
AudioSystem.getLine(info);
в строке 79: строка является микрофоном и // считывает аудиоданные из входного буфера строки данных. Другими словами, байты, поступающие с микрофона, находятся или хранятся в байтах. buffer
,
По строке 81:
out.write(buffer, 0, count);
out
является объектом ByteArrayOutputStream..
Класс ByteArrayOutputStream API Java IO позволяет вам захватывать данные, записанные в поток в массиве. Вы записываете свои данные в ByteArrayOutputStream, а когда закончите, вызываете метод ByteArrayOutputStream для toByteArray(), чтобы получить все записанные данные в байтовом массиве. Буфер автоматически увеличивается при записи данных в него.
По моим словам: ByteArrayOutputStream
будет расти, принимая байты из буфера, определенного в количестве count
На другой стороне:
В методе playAudio().
Я вижу, что в первой строке (строка 101 полного кода) взяты все байты!!!
byte audio[] = out.toByteArray();
https://docs.oracle.com/javase/7/docs/api/java/io/ByteArrayOutputStream.html
Создает вновь выделенный байтовый массив. Его размер является текущим размером этого выходного потока, и в него было скопировано допустимое содержимое буфера.
Теперь в строках (102 и 103)
InputStream input =
new ByteArrayInputStream(audio);
В строках (105 до 107) байты передаются через:
final AudioInputStream ais =
new AudioInputStream(input, format,
audio.length / format.getFrameSize());
фокусировка во время цикла и вблизи линий
int count;
while ((count = ais.read(
buffer, 0, buffer.length)) != -1) {
if (count > 0) {
line.write(buffer, 0, count);
}
}
line.drain();
line.close();
Байты взяты из ais
И линия (линии 110 и 111) представляет ораторов
final SourceDataLine line = (SourceDataLine)
AudioSystem.getLine(info);
Вопрос 1:
out
из метода captureAudio будет принимать байты бесконечно, но как input
, из метода playAudio, берет именно байты, необходимые для их последовательного звучания?
Помните: out.toByteArray();
взять все байты, но динамики не звучат многократно одинаковые байты...
Вопрос 2:
Могу ли я обработать эту ситуацию для чтения из микрофона (TargetDataLine) и записи в динамик (SourceDataLine), не используя эти два объекта (ByteArrayOutputStream и ByteArrayInputStream), как связанную статью?
Как следующий код:
while (running) {
int count = microphone.read(buffer, 0, buffer.length);
if (count > 0) {
speaker.write(buffer, 0, count);
}
}
speaker.drain();
speaker.close();
Вопрос 3:
Как я могу реализовать Repeater (захватывать звук с микрофона и проигрывать его на динамиках, бесконечно, 1 или 2 часа)?
Примечание: не беспокоясь о проблемах хранения байтов в памяти (без сохранения в файле) без задержек воспроизведения.
1 ответ
Я не знаком с Sound API.
Но нет особой причины, по которой ваш последний фрагмент кода не должен работать, если предположить, что ввод можно бесконечно читать, а вывод - бесконечно. Единственная проблема заключается в том, останавливается ли один конец или другой (здесь мой недостаток в знании Sound API вступает в игру).
Если выходная сторона останавливается по какой-либо причине, то входная сторона может потенциально переполнить некоторый внутренний буфер, что приведет к потере информации. Если ввод глохнет, это не такая уж большая проблема. Я не знаю, действительно ли это проблема с Sound API. Напротив, если бы было два потока (или использующих асинхронный ввод-вывод), один управляющий входом, а другой управляющий выходом, сторона ввода предоставила бы вашей программе возможность кэшировать входящие данные, используя вашу семантику, а не API-интерфейсы. семантика, в то время как выходной канал остановлен.
Проблемы с ByteArrayStreams - это просто механизмы заполнения и каждого расширяющегося байтового массива без самостоятельного управления им, и, аналогичным образом, добавление семантики потока в базовый байтовый массив (который имеет все виды полезных возможностей).