You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

iOS Core Audio:如何将双声道AudioBufferList拆分为单声道双Buffer?

音频格式转换实现方案(交错16位PCM → 非交错浮点PCM)

原输入格式参数

mFormatID = kAudioFormatLinearPCM,
mFormatFlags = 14,
mChannelsPerFrame = 2,
mBytesPerPacket = 4,
mFramesPerPacket = 1,
mBytesPerFrame = 4,
mBitsPerChannel = 16,
mSampleRate = 44100

原数据为双声道交错式16位有符号整数PCM,对应AudioBufferList仅包含1个Buffer,双声道数据交替存储。目标需转换为双声道非交错式32位浮点PCM,对应AudioBufferList包含2个Buffer,每个Buffer仅存单声道数据,以此匹配流会话enqueueAudioBuffer的要求。

核心转换步骤与代码实现

1. 计算关键参数并初始化目标AudioBufferList

从原CMSampleBuffer提取AudioBufferList,计算总帧数后分配目标结构内存:

// 你的输入样本Buffer
CMSampleBufferRef sampleBuffer = ...;
AudioBufferList *inputABL = (AudioBufferList *)CMSampleBufferGetAudioBufferListWithRetainedBlockBuffer(
    sampleBuffer,
    NULL,
    NULL,
    0,
    NULL,
    NULL,
    kCMSampleBufferFlag_AudioBufferList_Assure16ByteAlignment,
    NULL
);

// 计算总帧数:原数据总字节数 / 每帧字节数
UInt32 totalFrames = inputABL->mBuffers[0].mDataByteSize / inputABL->mBuffers[0].mBytesPerFrame;
// 每个声道的浮点数据字节数:帧数 * Float32字节数
UInt32 perChannelByteSize = totalFrames * sizeof(Float32);

// 初始化目标AudioBufferList
AudioBufferList *outputABL = (AudioBufferList *)malloc(sizeof(AudioBufferList) + sizeof(AudioBuffer) * 1);
outputABL->mNumberBuffers = 2;
// 左声道Buffer
outputABL->mBuffers[0].mNumberChannels = 1;
outputABL->mBuffers[0].mDataByteSize = perChannelByteSize;
outputABL->mBuffers[0].mData = malloc(perChannelByteSize);
// 右声道Buffer
outputABL->mBuffers[1].mNumberChannels = 1;
outputABL->mBuffers[1].mDataByteSize = perChannelByteSize;
outputABL->mBuffers[1].mData = malloc(perChannelByteSize);

2. 执行交错整数到非交错浮点的转换

遍历每帧数据,拆分左右声道并完成格式转换:

// 原数据指针转为16位有符号整数类型
int16_t *inputData = (int16_t *)inputABL->mBuffers[0].mData;
// 目标左右声道浮点指针
Float32 *leftChannelData = (Float32 *)outputABL->mBuffers[0].mData;
Float32 *rightChannelData = (Float32 *)outputABL->mBuffers[1].mData;

for (UInt32 i = 0; i < totalFrames; i++) {
    // 交错数据中,左声道是第2i个整数,右声道是第2i+1个整数
    int16_t leftInt = inputData[2 * i];
    int16_t rightInt = inputData[2 * i + 1];
    
    // 将16位整数转为-1.0~1.0范围的浮点值
    leftChannelData[i] = leftInt / 32768.0f;
    rightChannelData[i] = rightInt / 32768.0f;
}

3. 资源释放与后续处理

转换完成后传入流会话处理,使用完毕后释放内存:

// 传入流会话处理
[yourStreamSession enqueueAudioBuffer:outputABL atPresentationTime:presentationTime];

// 释放分配的内存
free(outputABL->mBuffers[0].mData);
free(outputABL->mBuffers[1].mData);
free(outputABL);
CFRelease(inputABL);

杂音原因说明

原数据为双声道交错存储,若直接以非交错格式解析,或未完成整数到浮点的格式转换,会导致音频数据被错误解析(比如将两个16位整数当成一个32位浮点值),最终产生杂音。上述转换严格匹配目标格式要求,可解决声道不匹配问题。

内容的提问来源于stack exchange,提问作者Juan Gil

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 07:20:28