现在我在我的Audio Unit proc中获取PCM音频,它将传入的音频缓冲区数据写入循环缓冲区以便在其他地方使用。
现在我想获取iLBC音频数据,因此我将AudioStreamBasicDescription
mFormatID
更改为kAudioFormatiLBC
。
但现在它崩溃了:
错误:StreamFormat kAudioUnitErr_FormatNotSupported
那么iLBC如何使用音频单元正确实现?
非常感谢!
答案 0 :(得分:1)
放手一搏
mRecordFormat.mSampleRate = 8000.0;
mRecordFormat.mFormatID = kAudioFormatiLBC;
mRecordFormat.mChannelsPerFrame = 1;
答案 1 :(得分:0)
嗨,这是我将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.编码数据:
-(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;
}
试试这个!