首页 > 解决方案 > 使用 AudioConverterFillComplexBuffer 转换 AudioBuffer 时出错

问题描述

我正在尝试使用 AudioConverterFillComplexBuffer 减少录制的音频数据的缓冲区大小(稍后我想将其转换回来并使用 Audiounit 播放),我使用的代码如下所示。

 - (void)captureOutput:(AVCaptureOutput *)captureOutput
    didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer
           fromConnection:(AVCaptureConnection *)connection
    {
        SInt16 buffer[length];
        CMBlockBufferCopyDataBytes(blockBufferRef, 0, length, buffer);
        NSData * data = [[NSData alloc] initWithBytes:buffer length:length];
        if(!fConverter)
        {
            [self ConverterSetup:asbd1];
        }
        [self Convert:data];
    }

    -(void)ConverterSetup:(AudioStreamBasicDescription)sourceDesc
    {
        AudioStreamBasicDescription fOutputFormat = {0};
        memset(&fOutputFormat, 0, sizeof(fOutputFormat));
        fOutputFormat.mSampleRate = 32000;
        fOutputFormat.mFormatID = kAudioFormatLinearPCM;
        fOutputFormat.mFormatFlags = kAudioFormatFlagIsBigEndian | kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
        fOutputFormat.mBytesPerPacket = fOutputFormat.mBytesPerFrame =4;//4 * sizeof(SInt16);
        fOutputFormat.mFramesPerPacket = 1;
        fOutputFormat.mChannelsPerFrame = 1;
        fOutputFormat.mBitsPerChannel = 32;

        OSStatus err = AudioConverterNew(&sourceDesc, &fOutputFormat,&fConverter);  //converts mFormat -> mFileStreamFormat
        if(err != noErr)
        {
            NSError *error = [NSError errorWithDomain:NSOSStatusErrorDomain code:err userInfo:nil];
                    NSLog(@"Error = %@", error);
            return ;
        }

        SInt32 channelMap[] = { 0, 0 };
        err = AudioConverterSetProperty(fConverter, kAudioConverterChannelMap, 2*sizeof(SInt32), channelMap);

        UInt32 quality = kAudioConverterQuality_Medium;
        err = AudioConverterSetProperty(fConverter,
                                        kAudioConverterSampleRateConverterQuality,
                                        sizeof(UInt32),
                                        &quality);
    }



    -(void)Convert:(NSData*)data
    {

        AudioBufferList  inBufferList_new;
        inBufferList_new.mNumberBuffers = 1;
        inBufferList_new.mBuffers[0].mNumberChannels = 1;
        inBufferList_new.mBuffers[0].mData = (void *)data.bytes;
        inBufferList_new.mBuffers[0].mDataByteSize = [data length];

        char szBuf[1024];
        int  nSize = sizeof(szBuf);
        AudioBufferList fAudioOutputBuffer;
        fAudioOutputBuffer.mNumberBuffers              = 1;
        fAudioOutputBuffer.mBuffers[0].mNumberChannels = 1;
        fAudioOutputBuffer.mBuffers[0].mDataByteSize   = nSize;
        fAudioOutputBuffer.mBuffers[0].mData           = szBuf;
        UInt32 outputDataPacketSize               = nSize;

        UInt numPackets = nSize;//inBufferList_new.mBuffers[0].mDataByteSize;

       OSStatus err = AudioConverterFillComplexBuffer(fConverter, ConverterProc, &inBufferList_new, &numPackets, &fAudioOutputBuffer, NULL);
        if(err != noErr)
        {
            NSError *error = [NSError errorWithDomain:NSOSStatusErrorDomain code:err userInfo:nil];
            NSLog(@"%@", error);

        }
        else
        {
            NSData *data=[NSData dataWithBytes:(UInt8*)fAudioOutputBuffer.mBuffers[0].mData length:fAudioOutputBuffer.mBuffers[0].mDataByteSize];
            NSLog(@"Converted data length = %d", [data length]);
        }

    }


OSStatus ConverterProc(AudioConverterRef inAudioConverter,
                                        UInt32* ioNumberDataPackets,
                                        AudioBufferList* ioData,
                                        AudioStreamPacketDescription** outDataPacketDescription,
                                        void* inUserData)
{
    OSStatus err = kAudioUnitErr_InvalidPropertyValue;


    AudioBufferList bufferList = *(AudioBufferList*)inUserData;
    ioData->mBuffers[0].mNumberChannels = 1;
    ioData->mBuffers[0].mData           = bufferList.mBuffers[0].mData;
    ioData->mBuffers[0].mDataByteSize   = bufferList.mBuffers[0].mDataByteSize;

    return err;
}

我得到的错误是 Error Domain=NSOSStatusErrorDomain Code=-10851 "(null)"。谁能找出这段代码的问题。

标签: macoscore-audioaudiounit

解决方案


https://android.googlesource.com/platform/external/mpg123/+/3d540f5de5b3a28ce6ad855cef7d9d9a44242c07/src/output/coreaudio.c

可以看到代码:

if(ao->channels == 1) {
            SInt32 channelMap[2] = { 0, 0 };
            if(AudioConverterSetProperty(ca->converter, kAudioConverterChannelMap, sizeof(channelMap), channelMap)) {
                error("AudioConverterSetProperty(kAudioConverterChannelMap) failed");
                return(-1);
            }
        }



推荐阅读