AVAudioEngine手动渲染模式处理输入时数据充足却报错如何解决?
问题:AVAudioEngine手动渲染模式连接输入节点时返回InsufficientDataFromInputNode状态
仅使用播放器节点时AVAudioEngine手动渲染功能正常,但连接输入节点后,明明输入缓冲区有充足数据,调用renderOffline:却返回AVAudioEngineManualRenderingStatusInsufficientDataFromInputNode状态,测试代码如下:
- (void)testManualRendering { auto engine = [[AVAudioEngine alloc] init]; auto format = [[AVAudioFormat alloc] initStandardFormatWithSampleRate:44100.0 channels:2]; auto inputBuffer = [[AVAudioPCMBuffer alloc] initWithPCMFormat:format frameCapacity:1024]; auto abl = inputBuffer.mutableAudioBufferList; XCTAssert(abl != NULL); XCTAssertEqual(abl->mNumberBuffers, 2); [engine connect:engine.inputNode to:engine.mainMixerNode format:format]; NSError* error; [engine enableManualRenderingMode:AVAudioEngineManualRenderingModeOffline format:format maximumFrameCount:1024 error:&error]; XCTAssertNil(error); XCTAssert([format isEqual:engine.manualRenderingFormat]); NSLog(@"manualRenderingFormat: %@", engine.manualRenderingFormat); auto success = [engine.inputNode setManualRenderingInputPCMFormat:format inputBlock:^const AudioBufferList * _Nullable(AVAudioFrameCount inNumberOfFrames) { XCTAssert(abl->mBuffers[0].mDataByteSize <= inNumberOfFrames * sizeof(float)); XCTAssert(abl->mBuffers[1].mDataByteSize <= inNumberOfFrames * sizeof(float)); return abl; }]; XCTAssert(success); [engine startAndReturnError:&error]; XCTAssertNil(error); auto outputBuffer = [[AVAudioPCMBuffer alloc] initWithPCMFormat:format frameCapacity:1024]; XCTAssertNotNil(outputBuffer); XCTAssert(engine.isInManualRenderingMode); auto status = [engine renderOffline:32 toBuffer:outputBuffer error:&error]; if(status == AVAudioEngineManualRenderingStatusInsufficientDataFromInputNode) { printf("manual rendering failed: AVAudioEngineManualRenderingStatusInsufficientDataFromInputNode\n"); } XCTAssertEqual(status, AVAudioEngineManualRenderingStatusSuccess); if (error) { NSLog(@"error: %@", error); } XCTAssertNil(error); }
解决方案
核心问题:输入缓冲区未设置有效帧数
你创建的inputBuffer仅初始化了frameCapacity(缓冲区最大容量),但未设置frameLength(实际有效音频帧数)。AVAudioEngine无法识别缓冲区中可用的数据量,因此判定为数据不足。
修复步骤
修改输入节点的inputBlock,在返回AudioBufferList前,将inputBuffer.frameLength设置为请求的inNumberOfFrames:
auto success = [engine.inputNode setManualRenderingInputPCMFormat:format inputBlock:^const AudioBufferList * _Nullable(AVAudioFrameCount inNumberOfFrames) { // 关键:设置缓冲区实际有效的帧数 inputBuffer.frameLength = inNumberOfFrames; // 可选:如果需要测试真实音频数据,可以在这里填充inputBuffer的mData(比如填0) memset(abl->mBuffers[0].mData, 0, inNumberOfFrames * sizeof(float)); memset(abl->mBuffers[1].mData, 0, inNumberOfFrames * sizeof(float)); XCTAssert(abl->mBuffers[0].mDataByteSize == inNumberOfFrames * sizeof(float)); XCTAssert(abl->mBuffers[1].mDataByteSize == inNumberOfFrames * sizeof(float)); return abl; }];
额外注意事项
- 手动渲染模式下,输入块必须返回包含准确有效帧数的缓冲区,否则引擎会持续返回
InsufficientDataFromInputNode。 - 若要填充真实音频数据,需确保
mData中的字节数与frameLength * 格式字节数匹配,避免数据越界或无效。
内容的提问来源于stack exchange,提问作者Taylor
相关产品推荐
相关产品推荐

