gpt4 book ai didi

android - AudioRecord 有时会跳过音频数据

转载 作者:行者123 更新时间:2023-11-29 00:12:29 24 4
gpt4 key购买 nike

我使用 AudioRecord 在 wav 文件中录制音频。我在辅助线程的循环中执行 read() 操作,数据在另一秒内传递到队列中。写入文件的线程。

问题如下:当我选择将音频数据保存在外部 SD 卡中时,音频包含一些跳跃/失真(仅有时)。其他用户在内部 SD 卡上保存时也有此问题

这就是我实例化 AudioRecord 对象的方式:

initBufferSize = assureMinBufferSize();
if (minBufferSize == AudioRecord.ERROR_BAD_VALUE) {
throw new Exception("" + ErrorCodes.ERROR_CODE_0);
}
else if (minBufferSize == AudioRecord.ERROR) {
throw new Exception("" + ErrorCodes.ERROR_CODE_0);
}

buffer = new byte[initBufferSize];
aRecorder = new AudioRecord(mSource, sRate, nChannel, AudioFormat.ENCODING_PCM_16BIT, initBufferSize);

这就是我合并 AudioRecorder 对象的方式:

private class AudioReaderRunnable implements Runnable {
private volatile boolean stopped;

@Override
public void run() {
while (!stopped) {
while(mState == State.RECORDING){
read();
}
}

Log.i(getClass().getName(), "AudioReade thread stopped!");
}

private void read(){

if(aRecorder == null)
return;

// "dirty" patch for some null crash for some users
if(buffer == null)
buffer = new byte[initBufferSize];

//int x = aRecorder.read(buffer, 0, buffer.length);
int x = readFully(buffer, 0, buffer.length);
if(x <= 0)
return;

payloadSize += x;

mWavData.arrayCopy(buffer);

mWavData.setGain(rGain);
mWavData.setBitsPerSamples(bitsPerSample);
mWavData.setNrChannels(nChannelsNumber);

// send audio to another thread for writing
mAudioWritter.add(audioData);
}

private int readFully(byte[] data, int off, int length) {
int read = 0;
int result = 0;
int requestedSize = length;

if(aRecorder == null){
return read;
}

try {
result = aRecorder.read(data, off, requestedSize);
} catch (Exception e) {
Log.e(getClass().getName(), e.getMessage(), e);
if(aRecorder == null)
return read;
}

read = result;

while (requestedSize != result && !stopped) {
if(aRecorder == null)
return read;

requestedSize -= result;
try {
result = aRecorder.read(data, result - 1, requestedSize);
} catch (Exception e) {
Log.e(getClass().getName(), e.getMessage(), e);
if(aRecorder == null)
return read;
}
read += result;
}

return read;
}

public void stopThread() {
stopped = true;
}
}

最佳答案

我在 Xamarin.Android 上遇到了类似的问题,我是这样解决的:

AudioRecord 缓冲区就像一个窗口 - 当缓冲区被填满时,它会从头开始重写。因此,我们需要确保缓冲区足够大,以便我们在重写之前从中读取它。

这里有一个大问题 - 当垃圾收集器启动时,它会停止所有应用程序线程大约一秒钟 - 这足以让记录器将大约 100KB 的数据写入缓冲区(当使用 44100Hz 单声道 Pcm16bit 时),但我们在此期间不读取,因为应用程序线程已停止!因此,如果缓冲区不够大,数据会在我们有机会读取和写入文件之前被重写。结果,音频文件丢失了垃圾收集期间录制的音频。

因此,您需要使用足够大的 bufferSize 来初始化 AudioRecord,以便在垃圾回收事件之后继续存在。对于不同的音频配置,这将是不同的大小。对我来说(使用 44100Hz,单声道,PCM16 位),缓冲区大小 512,000 就可以了。

我不确定 GC 在原生 Android 上是如何工作的,但我相信它可能是相似的。

关于android - AudioRecord 有时会跳过音频数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29233388/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com