AudioConverter包的数量是错误的

时间:2012-12-05 12:35:44

标签: ios core-audio audio-converter

我已经设置了一个类,在给定输入和输出AudioStreamBasicDescription的情况下将音频从一种格式转换为另一种格式。当我将线性PCM从麦克风转换为iLBC时,当我从AudioUnitRender函数给出1024个数据包时,它会工作并给我6个数据包。然后我通过UDP将这226个字节发送到在不同设备上运行的同一个应用程序。问题是,当我使用相同的类转换回线性PCM以提供音频单元输入时,AudioConverterFillComplexBuffer函数不提供1024个数据包,它给出960 ...这意味着音频单元输入期望4096字节(立体声为2048 x 2),但我只能给它3190左右,所以它听起来真的很破碎和扭曲......

如果我提供AudioConverter 1024个LinearPCM数据包,转换为iLBC,转换回LinearPCM,我肯定会再次获得1024个数据包吗?

音频转换器功能:

-(void) doConvert {

    // Start converting
    if (converting) return;
    converting = YES;

    while (true) {

        // Get next buffer
        id bfr = [buffers getNextBuffer];
        if (!bfr) {
            converting = NO;
            return;
        }

        // Get info
        NSArray* bfrs = ([bfr isKindOfClass:[NSArray class]] ? bfr : @[bfr]);
        int bfrSize = 0;
        for (NSData* dat in bfrs) bfrSize += dat.length;

        int inputPackets = bfrSize / self.inputFormat.mBytesPerPacket;
        int outputPackets = (inputPackets * self.inputFormat.mFramesPerPacket) / self.outputFormat.mFramesPerPacket;

        // Create output buffer
        AudioBufferList* bufferList = (AudioBufferList*) malloc(sizeof(AudioBufferList) * self.outputFormat.mChannelsPerFrame);
        bufferList -> mNumberBuffers = self.outputFormat.mChannelsPerFrame;
        for (int i = 0 ; i < self.outputFormat.mChannelsPerFrame ; i++) {
            bufferList -> mBuffers[i].mNumberChannels = 1;
            bufferList -> mBuffers[i].mDataByteSize = 4*1024;
            bufferList -> mBuffers[i].mData = malloc(bufferList -> mBuffers[i].mDataByteSize);
        }

        // Create input buffer
        AudioBufferList* inputBufferList = (AudioBufferList*) malloc(sizeof(AudioBufferList) * bfrs.count);
        inputBufferList -> mNumberBuffers = bfrs.count;
        for (int i = 0 ; i < bfrs.count ; i++) {
            inputBufferList -> mBuffers[i].mNumberChannels = 1;
            inputBufferList -> mBuffers[i].mDataByteSize = [[bfrs objectAtIndex:i] length];
            inputBufferList -> mBuffers[i].mData = (void*) [[bfrs objectAtIndex:i] bytes];
        }

        // Create sound data payload
        struct SoundDataPayload payload;
        payload.data = inputBufferList;
        payload.numPackets = inputPackets;
        payload.packetDescriptions = NULL;
        payload.used = NO;

        // Convert data
        UInt32 numPackets = outputPackets;
        OSStatus err = AudioConverterFillComplexBuffer(converter, acvConverterComplexInput, &payload, &numPackets, bufferList, NULL);
        if (err)
            continue;

        // Check how to output
        if (bufferList -> mNumberBuffers > 1) {

            // Output as array
            NSMutableArray* array = [NSMutableArray arrayWithCapacity:bufferList -> mNumberBuffers];
            for (int i = 0 ; i < bufferList -> mNumberBuffers ; i++)
                [array addObject:[NSData dataWithBytes:bufferList -> mBuffers[i].mData length:bufferList -> mBuffers[i].mDataByteSize]];

            // Save
            [convertedBuffers addBuffer:array];

        } else {

            // Output as data
            NSData* newData = [NSData dataWithBytes:bufferList -> mBuffers[0].mData length:bufferList -> mBuffers[0].mDataByteSize];

            // Save
            [convertedBuffers addBuffer:newData];

        }

        // Free memory
        for (int i = 0 ; i < bufferList -> mNumberBuffers ; i++)
            free(bufferList -> mBuffers[i].mData);

        free(inputBufferList);
        free(bufferList);

        // Tell delegate
        if (self.convertHandler)
            //dispatch_async(dispatch_get_main_queue(), self.convertHandler);
            self.convertHandler();

    }

}

转换为iLBC时的格式:

// Get input format from mic
UInt32 size = sizeof(AudioStreamBasicDescription);
AudioStreamBasicDescription inputDesc;
AudioUnitGetProperty(self.ioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &inputDesc, &size);

// Set output stream description
size = sizeof(AudioStreamBasicDescription);
AudioStreamBasicDescription outputDescription;
memset(&outputDescription, 0, size);
outputDescription.mFormatID         = kAudioFormatiLBC;
OSStatus err = AudioFormatGetProperty(kAudioFormatProperty_FormatInfo, 0, NULL, &size, &outputDescription);

从iLBC转换时的格式:

// Set input stream description
size = sizeof(AudioStreamBasicDescription);
AudioStreamBasicDescription inputDescription;
memset(&inputDescription, 0, size);
inputDescription.mFormatID        = kAudioFormatiLBC;
AudioFormatGetProperty(kAudioFormatProperty_FormatInfo, 0, NULL, &size, &inputDescription);

// Set output stream description
UInt32 size = sizeof(AudioStreamBasicDescription);
AudioStreamBasicDescription outputDesc;
AudioUnitGetProperty(unit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &outputDesc, &size);

1 个答案:

答案 0 :(得分:1)

您必须使用中间缓冲区从足够的传入数据包中保存足够的字节,以完全匹配音频单元输入所请求的数量。取决于压缩格式的任何一个UDP数据包是否正确大小将无法正常工作。

AudioConverter可以缓冲样本并根据压缩格式更改数据包大小。