你好,這是我的代碼轉換PCM到的iLBC。
1.創建轉換器:
-(BOOL)createAudioConvert:(CMSampleBufferRef)sampleBuffer {
if (m_converter != nil)
{
return TRUE;
}
AudioStreamBasicDescription inputFormat = *(CMAudioFormatDescriptionGetStreamBasicDescription(CMSampleBufferGetFormatDescription(sampleBuffer)));
AudioStreamBasicDescription outputFormat;
memset(&outputFormat, 0, sizeof(outputFormat));
outputFormat.mSampleRate = 8000;
outputFormat.mFormatID = kAudioFormatiLBC;
outputFormat.mChannelsPerFrame = 1;
// use AudioFormat API to fill out the rest of the description
UInt32 size = sizeof(outputFormat);
AudioFormatGetProperty(kAudioFormatProperty_FormatInfo, 0, NULL, &size, &outputFormat);
outputFormat.mBytesPerPacket = 50;
outputFormat.mFramesPerPacket = 240;
AudioClassDescription *desc = [self getAudioClassDescriptionWithType:kAudioFormatiLBC fromManufacturer:kAppleSoftwareAudioCodecManufacturer];
if (AudioConverterNewSpecific(&inputFormat, &outputFormat, 1, desc, &m_converter) != noErr)
{
printf("AudioConverterNewSpecific failed\n");
return NO;
}
return YES;
}
2.getAudioClassDescriptionWithType
-(AudioClassDescription*)getAudioClassDescriptionWithType:(UInt32)type fromManufacturer:(UInt32)manufacturer { // 獲得相應的編碼器
static AudioClassDescription audioDesc;
UInt32 encoderSpecifier = type, size = 0;
OSStatus status;
memset(&audioDesc, 0, sizeof(audioDesc));
status = AudioFormatGetPropertyInfo(kAudioFormatProperty_Encoders, sizeof(encoderSpecifier), &encoderSpecifier, &size);
if (status)
{
return nil;
}
uint32_t count = size/sizeof(AudioClassDescription);
AudioClassDescription descs[count];
status = AudioFormatGetProperty(kAudioFormatProperty_Encoders, sizeof(encoderSpecifier), &encoderSpecifier, &size, descs);
for (uint32_t i = 0; i < count; i++)
{
if ((type == descs[i].mSubType) && (manufacturer == descs[i].mManufacturer))
{
memcpy(&audioDesc, &descs[i], sizeof(audioDesc));
break;
}
}
return &audioDesc;
}
3.Encode數據:
-(BOOL)encoderData:(CMSampleBufferRef)sampleBuffer Data:(char*)Data Len:(int*)Len {
if ([self createAudioConvert:sampleBuffer] != YES)
{
return NO;
}
CMBlockBufferRef blockBuffer = nil;
AudioBufferList inBufferList;
if (CMSampleBufferGetAudioBufferListWithRetainedBlockBuffer(sampleBuffer, NULL, &inBufferList, sizeof(inBufferList), NULL, NULL, 0, &blockBuffer) != noErr)
{
printf("CMSampleBufferGetAudioBufferListWithRetainedBlockBuffer failed");
return NO;
}
AudioBufferList outBufferList;
outBufferList.mNumberBuffers = 1;
outBufferList.mBuffers[0].mNumberChannels = 1;
outBufferList.mBuffers[0].mDataByteSize = *Len;
outBufferList.mBuffers[0].mData = Data;
UInt32 outputDataPacketSize = 1;
OSStatus err = AudioConverterFillComplexBuffer(m_converter, inputDataProc, &inBufferList, &outputDataPacketSize, &outBufferList, NULL);
printf("AudioConverterFillComplexBuffer\n");
if (err != noErr)
{
printf("AudioConverterFillComplexBuffer failed\n");
return NO;
}
*Len = outBufferList.mBuffers[0].mDataByteSize;
CFRelease(blockBuffer);
return YES;
}
4.Callback功能:
OSStatus inputDataProc(AudioConverterRef inConverter, UInt32 *ioNumberDataPackets, AudioBufferList *ioData,AudioStreamPacketDescription **outDataPacketDescription, void *inUserData) {
ioData->mNumberBuffers = 1;
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;
UInt32 maxPackets = bufferList.mBuffers[0].mDataByteSize/2;
*ioNumberDataPackets = maxPackets;
return noErr;
}
試試這個吧!
嗯...這個代碼初始化音頻單元時,我得到一個錯誤:'AudioUnitInitialize' '錯誤:初始化記錄( '!DAT')' 的DAT代表'kAudioCodecUnsupportedFormatError' –
對不起我的錯誤,我沒有正確閱讀,這是音頻單元鏈的一部分。音頻單元無法寫入壓縮格式。您將需要使用AudioFileServices或AudioConverter來壓縮音頻數據。 –
啊我明白了!這很有道理:)你可能知道一些使用AudioConverter從PCM到iLBC轉換的例子嗎? –