У меня это работало в .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.");
}
}
}
Я думаю, что упускаю небольшую деталь, которая будет совершенно очевидна для некоторых из вас, кто знает об этом. Я не старший разработчик в каком-либо смысле этого слова, и мне было бы полезно получить хорошее образование по этому вопросу от любого, кто готов меня обучить.
Спасибо за комментарии и ответы, если вы считаете меня и моя проблема достаточно достойна вашего времени!
Подробнее здесь: https://stackoverflow.com/questions/784 ... y-amount-o