我目前正在通过互联网传输mp3音频。我正在使用AudioFileStream来解析mp3 steam 来自CFReadStreamRef,使用AudioConverterFillComplexBuffer解码mp3并复制转换后的PCM 将数据放入环形缓冲区,最后使用RemoteIO播放PCM。
我目前面临的问题是AudioConverterFillComplexBuffer始终返回0(无错误)但转换 结果似乎不正确。详情请注意,
一个。 UInt32 * ioOutputDataPacketSize保持与我发送的值相同。
B中。 convertedData.mBuffers [0] .mDataByteSize总是被设置为outputbuffer的大小(无论缓冲区有多大)。
℃。我只能通过输出数据听到咔嗒声。
以下是我渲染音频的程序。 我相信,同样的程序适用于我的音频队列实现 在我调用AudioConverterFillComplexBuffer或AudioConverterFillComplexBuffer的回调的地方,我没有出错。
我长期以来一直坚持这个问题。任何帮助将受到高度赞赏。
打开AudioFileStream。
//创建一个音频文件流解析器
AudioFileTypeID fileTypeHint = kAudioFileMP3Type;
AudioFileStreamOpen(self,MyPropertyListenerProc,MyPacketsProc,fileTypeHint,& audioFileStream);
处理回调函数中的已解析数据(“MyPacketsProc”)。
void MyPacketsProc(void * inClientData, UInt32 inNumberBytes, UInt32 inNumberPackets, const void * inInputData, AudioStreamPacketDescription * inPacketDescriptions) { @synchronized(个体经营) { //初始化音频转换器。 if(!audioConverter) AudioConverterNew(& asbd,& asbd_out,& audioConverter);
struct mp3Data mSettings;
memset(&mSettings, 0, sizeof(mSettings));
UInt32 packetsPerBuffer = 0;
UInt32 outputBufferSize = 1024 * 32; // 32 KB is a good starting point.
UInt32 sizePerPacket = asbd.mBytesPerPacket;
// Calculate the size per buffer.
// Variable Bit Rate Data.
if (sizePerPacket == 0)
{
UInt32 size = sizeof(sizePerPacket);
AudioConverterGetProperty(audioConverter, kAudioConverterPropertyMaximumOutputPacketSize, &size, &sizePerPacket);
if (sizePerPacket > outputBufferSize)
outputBufferSize = sizePerPacket;
packetsPerBuffer = outputBufferSize / sizePerPacket;
}
//CBR
else
packetsPerBuffer = outputBufferSize / sizePerPacket;
// Prepare the input data for the callback.
mSettings.inputBuffer.mDataByteSize = inNumberBytes;
mSettings.inputBuffer.mData = (void *)inInputData;
mSettings.inputBuffer.mNumberChannels = 1;
mSettings.numberPackets = inNumberPackets;
mSettings.packetDescription = inPacketDescriptions;
// Set up our output buffers
UInt8 * outputBuffer = (UInt8*)malloc(sizeof(UInt8) * outputBufferSize);
memset(outputBuffer, 0, outputBufferSize);
// describe output data buffers into which we can receive data.
AudioBufferList convertedData;
convertedData.mNumberBuffers = 1;
convertedData.mBuffers[0].mNumberChannels = 1;
convertedData.mBuffers[0].mDataByteSize = outputBufferSize;
convertedData.mBuffers[0].mData = outputBuffer;
// Convert.
UInt32 ioOutputDataPackets = packetsPerBuffer;
OSStatus result = AudioConverterFillComplexBuffer(audioConverter,
converterComplexInputDataProc,
&mSettings,
&ioOutputDataPackets,
&convertedData,
NULL
);
// Enqueue the ouput pcm data.
TPCircularBufferProduceBytes(&m_pcmBuffer, convertedData.mBuffers[0].mData, convertedData.mBuffers[0].mDataByteSize);
free(outputBuffer);
}
}
从其回调函数(“converterComplexInputDataProc”)中提供音频转换器。
OSStatus converterComplexInputDataProc(AudioConverterRef inAudioConverter, UInt32 * ioNumberDataPackets, AudioBufferList * ioData, AudioStreamPacketDescription ** ioDataPacketDescription, void * inUserData) { struct mp3Data THIS =(struct mp3Data )inUserData;
if (THIS->inputBuffer.mDataByteSize > 0)
{
*ioNumberDataPackets = THIS->numberPackets;
ioData->mNumberBuffers = 1;
ioData->mBuffers[0].mDataByteSize = THIS->inputBuffer.mDataByteSize;
ioData->mBuffers[0].mData = THIS->inputBuffer.mData;
ioData->mBuffers[0].mNumberChannels = 1;
if (ioDataPacketDescription)
*ioDataPacketDescription = THIS->packetDescription;
}
else
*ioDataPacketDescription = 0;
return 0;
}
使用RemoteIO组件播放。
输入和输出AudioStreamBasicDescription。
输入:
采样率:16000 格式ID:.mp3
格式标志:0
每个数据包的字节数:0
每个数据包的帧数:576
每帧字节数:0
每帧频道数:1
每通道位数:0
输出:
采样率:44100
格式ID:lpcm
格式标志:3116
每个数据包的字节数:4
每个数据包的帧数:1
每帧字节数:4
每帧频道数:1
每通道位数:32