我正在尝试编写一个函数,在后台播放乐器时录制用户的声音。
我已经相当成功地让 2 个 MediaPlayer 几乎同时启动。使用 Threads 和 CyclicBarrier,我已经能够在每个 5 毫秒内启动 2 个 MediaPlayer,这听起来很不错。
问题是每当我尝试同时启动 MediaRecorder 和 MediaPlayer 时,它们之间会有明显的延迟。这是有问题的,因为当我播放录制的音频和乐器时,它们彼此不同步,因为录制的开始时间与播放器不同。
这是我尝试用于记录器和播放器的函数和 2 个线程。对于篇幅,我深表歉意,但如果有人有更好的想法,我将不胜感激:
private void onRecord(boolean start) {
if (start) {
final CyclicBarrier recordBarrier = new CyclicBarrier(2);
final CyclicBarrier postrecordBarrier = new CyclicBarrier(2);
Thread beatTask = new Thread(new RecordBeatPlayTask(recordBarrier, postrecordBarrier), "Thread 1");
Thread recordTask = new Thread(new RecordVoiceRecordTask(recordBarrier, postrecordBarrier), "Thread 2");
beatTask.start();
recordTask.start();
}
else {
mRecorder.stop();
mRecordBeatPlayer.stop();
mRecorder.release();
mRecorder = null;
mRecordBeatPlayer.release();
mRecordBeatPlayer = null;
}
}
private static class RecordVoiceRecordTask implements Runnable {
private CyclicBarrier barrier;
private CyclicBarrier barrier2;
public RecordVoiceRecordTask(CyclicBarrier barrier, CyclicBarrier barrier2) {
this.barrier = barrier;
this.barrier2 = barrier2;
}
public void run() {
try {
mRecorder = new MediaRecorder();
mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
mRecorderPath = Environment.getExternalStorageDirectory().getAbsolutePath();
mRecorderPath += "/HypeHopRecording.mp4";
mRecorder.setOutputFile(mRecorderPath);
mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
try {
mRecorder.prepare();
} catch (IOException e) {
Log.e("Recorder failed", "prepare() failed");
}
barrier.await();
mRecorder.start();
barrier2.await();
System.out.println(Thread.currentThread().getName() + " has crossed the barrier");
} catch (InterruptedException ex) {
Logger.getLogger(RecordActivity.class.getName()).log(Level.SEVERE, null, ex);
} catch (BrokenBarrierException ex) {
Logger.getLogger(RecordActivity.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
private static class RecordBeatPlayTask implements Runnable {
private CyclicBarrier barrier;
private CyclicBarrier barrier2;
public RecordBeatPlayTask(CyclicBarrier barrier, CyclicBarrier barrier2) {
this.barrier = barrier;
this.barrier2 = barrier2;
}
public void run() {
try {
mRecordBeatPlayer = new MediaPlayer();
try {
mRecordBeatPlayer.setDataSource(mBeatPath);
mRecordBeatPlayer.prepare();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
barrier.await();
mRecordBeatPlayer.start();
barrier2.await();
System.out.println(Thread.currentThread().getName() + " has crossed the barrier");
} catch (InterruptedException ex) {
Logger.getLogger(RecordActivity.class.getName()).log(Level.SEVERE, null, ex);
} catch (BrokenBarrierException ex) {
Logger.getLogger(RecordActivity.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
最佳答案
基本上,'mRecordBeatPlayer.start()' 和用户可以听到声音之间有延迟,你必须测试这个延迟。
关于android - 在 Android 中,如何同步录音和同步播放?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26417771/