【iOS笔记】AudioUnit录音异常(听起来类似于丢帧丢数据)
在做语音识别项目时候发现一个问题,识别率奇低无比……所以就把原始音频数据录下来,发现音频丢数据。实验机器:iPhone6s iOS12问题代码如下:OSStatus AudioUnitInput::RecordCallback(void *inRefCon,AudioUnitRenderActionFlags *ioActionFlags,const A...
在做语音识别项目时候发现一个问题,识别率奇低无比……所以就把原始音频数据录下来,发现音频丢数据。
实验机器:iPhone6s iOS12
问题代码如下:
OSStatus AudioUnitInput::RecordCallback(
void *inRefCon,
AudioUnitRenderActionFlags *ioActionFlags,
const AudioTimeStamp *inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList *ioData)
{
int count = 0;
OSStatus status = noErr;
if (inNumberFrames > 0) {
AudioUnitInput *ars = (AudioUnitInput *)inRefCon;
status = AudioUnitRender(ars->mRecordUnit,
ioActionFlags,
inTimeStamp,
inBusNumber,
inNumberFrames,
ars->recordBufList);
} else {
NSLog(@"inNumberFrames is %d", inNumberFrames);
}
return noErr;
}
…………
…………
…………
bufferByteSize = ComputeRecordBufferSize(&mRecordFormat,
kBufferDurationSeconds);
NSLog(@"Compute recorder %f seconds data buffer size is %d.",
kBufferDurationSeconds,
bufferByteSize);
recordBufList = (AudioBufferList *)malloc(sizeof(AudioBufferList));
recordBufList->mNumberBuffers = 1;
recordBufList->mBuffers[0].mNumberChannels = 1;
recordBufList->mBuffers[0].mDataByteSize = bufferByteSize * 2;
recordBufList->mBuffers[0].mData = malloc(bufferByteSize * 2);
以上代码可以看出,AudioBufferList我是在初始化的时候进行了malloc,然后在recordCallback中进行数据获取。理论上这样是没问题的,很多教程这么写。mData的malloc大小是通过计算的,bufferByteSize是20ms 16k 16bit的大小,即640。但是我发现recordCallback中frame数为341,即682字节,所以我就malloc了640的两倍。这里还有一个很好玩的点,就是如果我把playout开起来进行echo,在playCallback进行数据保存,这样获取的数据就非常正常。
以下给出两种解决方法:
1. 把malloc放在recordCallback中进行,记得用完后要free!
OSStatus AudioUnitInput::RecordCallback(
void *inRefCon,
AudioUnitRenderActionFlags *ioActionFlags,
const AudioTimeStamp *inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList *ioData)
{
int count = 0;
OSStatus status = noErr;
UInt16 numSamples = inNumberFrames*1;
if (inNumberFrames > 0) {
AudioUnitInput *ars = (AudioUnitInput *)inRefCon;
ars->recordBufList = (AudioBufferList *)malloc(sizeof(AudioBufferList));
ars->recordBufList->mNumberBuffers = 1;
ars->recordBufList->mBuffers[0].mNumberChannels = 1;
ars->recordBufList->mBuffers[0].mDataByteSize = numSamples * sizeof(UInt16);
ars->recordBufList->mBuffers[0].mData = malloc(numSamples * sizeof(UInt16));
status = AudioUnitRender(ars->mRecordUnit,
ioActionFlags,
inTimeStamp,
inBusNumber,
inNumberFrames,
ars->recordBufList);
} else {
NSLog(@"inNumberFrames is %d", inNumberFrames);
}
return noErr;
}
2.还有一种是不用malloc了,也是在recordCallback中分配一个AudioBufferList
OSStatus AudioUnitInput::RecordCallback(
void *inRefCon,
AudioUnitRenderActionFlags *ioActionFlags,
const AudioTimeStamp *inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList *ioData)
{
int count = 0;
OSStatus status = noErr;
AudioBufferList bufferList;
UInt16 numSamples = inNumberFrames*1;
UInt16 samples[numSamples];
memset(&samples, 0, sizeof(samples));
bufferList.mNumberBuffers = 1;
bufferList.mBuffers[0].mData = samples;
bufferList.mBuffers[0].mNumberChannels = 1;
bufferList.mBuffers[0].mDataByteSize = numSamples * sizeof(UInt16);
if (inNumberFrames > 0) {
AudioUnitInput *ars = (AudioUnitInput *)inRefCon;
status = AudioUnitRender(ars->mRecordUnit,
ioActionFlags,
inTimeStamp,
inBusNumber,
inNumberFrames,
&bufferList);
} else {
NSLog(@"inNumberFrames is %d", inNumberFrames);
}
return noErr;
}
具体为什么还不是很清楚,难道是堆栈的问题?
参考文章:https://blog.csdn.net/wuxinyanzi/article/details/49782969
感谢
更多推荐
所有评论(0)