Я читал эту статью: 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#toByteArray()
Создает вновь выделенный массив байтов. Его размер равен текущему размеру этого выходного потока, и в него было скопировано действительное содержимое буфера.
Теперь в строках (102 и 103)
InputStream input =
new ByteArrayInputStream(audio);
В строках (от 105 до 107) байты передаются:
final AudioInputStream ais =
new AudioInputStream(input, format,
audio.length / format.getFrameSize());
фокусировка в цикле while и рядом с линиями
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:
Как я могу реализовать повторитель (захватывать звук с микрофона и воспроизводить его на динамиках, бесконечно, 1 или 2 часа)?
Примечание: не беспокоясь о проблемах с хранением байтов в памяти (без сохранения в файл) без задержек воспроизведения.