Одновременная запись и чтение в Byte[] для задержки живого звука на произвольное время.JAVA

Программисты JAVA общаются здесь
Ответить Пред. темаСлед. тема
Anonymous
 Одновременная запись и чтение в Byte[] для задержки живого звука на произвольное время.

Сообщение Anonymous »

Я пытаюсь написать приложение на Java, которое может принимать входной сигнал микрофона, записывать его в буфер, который затем можно прочитать и вывести на динамик с произвольной задержкой; цель состоит в том, чтобы задержать радиотрансляцию с момента начала прямой трансляции до момента окончания прямой трансляции, совпадающего с началом трансляции. Я немного не в своей тарелке, поскольку у меня больше опыта в веб-интерфейсе и мире API, поэтому, пожалуйста, будьте любезны.
У меня это работало в .Net в Windows, но я решил перенести на Java, чтобы сделать его более кроссплатформенным. Судя по тому, что я слышу из динамиков, проблема, с которой я столкнулся, заключается в повреждении данных буфера, в котором хранится звук, и по какой-то причине зацикливания воспроизведения. Я не уверен, что с этим делать, поскольку у меня нет реального опыта работы с многопоточностью в Java и определенно не чтения и записи в один и тот же бит памяти. Я просто неправильно понимаю, как работает многопоточность?
Это ситуация, когда мне следует объединить буфер в несколько буферов и переключаться в зависимости от задержки между ними? Если да, то я не совсем уверен, как это будет работать динамически. Будем благодарны за любую помощь.
Вот дамп кода...

Main.java

Код: Выделить всё

// Imports removed for brevity

public class Main {
public static void main(String[] args) {
int Delay = 1000;
int Runtime = 5000;

var recorder = new AudioRecorder();

Thread.sleep(Delay); //Exceptions from these are handled in the actual code.
//Removed to keep clutter low

recorder.startPlayback();

Thread.sleep(Runtime);

recorder.stopCapture();

Thread.sleep(Delay);

recorder.stopPlayback();
}

AudioRecorder.java

Код: Выделить всё

// Imports removed for brevity

public class AudioRecorder {

Capture capture;
Playback playback;
AudioFormat format;

byte[] buffer;
int bufferLengthInBytes;

private AudioFormat.Encoding encoding = new AudioFormat.Encoding("PCM_SIGNED");
private int sampleSizeInBits = 16;
private int channels = 2;
private int frameSize = sampleSizeInBits / 8 * channels;
private float rate = 44100.0f;
private boolean bigEndian = true;
private int length;

SourceDataLine sourceLine;
TargetDataLine targetLine;
DataLine.Info sourceInfo = new DataLine.Info(SourceDataLine.class, format);
DataLine.Info targetInfo = new DataLine.Info(TargetDataLine.class, format);

public AudioRecorder() {
int runtime = 6000;

capture = new Capture();
playback = new Playback();

format = new AudioFormat(encoding, rate, sampleSizeInBits, channels, frameSize, rate, bigEndian);
bufferLengthInBytes = (int)(runtime * rate * frameSize / 1000);
length = bufferLengthInBytes / format.getFrameSize();
buffer = new byte[bufferLengthInBytes];

try {
sourceLine = (SourceDataLine) AudioSystem.getLine(sourceInfo);
sourceLine.open(format, bufferLengthInBytes);

targetLine = (TargetDataLine) AudioSystem.getLine(targetInfo);
targetLine.open(format, targetLine.getBufferSize());

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

}

public void startCapture() {
capture.start();
}

public void stopCapture() {
capture.interrupt();
}

public void startPlayback() {
playback.start();
}

public void stopPlayback() {
playback.interrupt();
}

class Capture extends Thread {
boolean finished = false;
public void run() {
System.out.println("Recording...");
sourceLine.start();
while (!finished) {
// recording

sourceLine.write(buffer, 0, buffer.length);

if(Thread.interrupted()) {
finished = true;
}
}
sourceLine.flush();
sourceLine.stop();
sourceLine.close();
sourceLine = null;
System.out.println("Recording stopped.");
}
}

class Playback extends Thread {
boolean finished = false;
public void run() {
System.out.println("Playing...");
int numBytesRead;
targetLine.start();
while (!finished) {
// playback

numBytesRead = targetLine.read(buffer, 0, buffer.length);
if (numBytesRead == -1) break;

if(Thread.interrupted()) {
finished = true;
}
}

targetLine.drain();
targetLine.stop();
targetLine.close();
targetLine = null;
System.out.println("Playback stopped.");
}
}
}

Я также пытался реализовать это с помощью runnables, основываясь на примере от самой Sun, и был примерно в том же месте, с гораздо большим количеством кода и графическим интерфейсом. Я также безуспешно пытался реализовать прямые потоки.
Я думаю, что упускаю небольшую деталь, которая будет совершенно очевидна для некоторых из вас, кто знает об этом. Я не старший разработчик в каком-либо смысле этого слова, и мне было бы полезно получить хорошее образование по этому вопросу от любого, кто готов меня обучить.
Спасибо за комментарии и ответы, если вы считаете меня и моя проблема достаточно достойна вашего времени!

Подробнее здесь: https://stackoverflow.com/questions/784 ... y-amount-o
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «JAVA»