iPhone/iOSで32KHz PCMを96Kbit AACに変換することに成功した人はいますか?iPhone:AudioConverterFillComplexBufferを使用して32KHz PCMを96Kbit AACにエンコードする際の問題
これはどのハードウェアデバイスでも正しく動作することはありません。私が書いたコードは、シミュレータで正しく動作します。現世代のiPad/iPod/iPhoneで動作させると、私のコードは大量の音声をスキップします。
結果のエンコードされたストリームには、〜640msの「良好な」オーディオ、〜640msの「悪い」オーディオの繰り返しパターンが含まれています。
16ビットリニアおよび8.24固定小数点PCMの両方をエンコードすると同じ結果が得られました。
AudioStreamBasicDescription descPCMFormat;
descPCMFormat.mSampleRate = 32000;
descPCMFormat.mChannelsPerFrame = 1;
descPCMFormat.mBitsPerChannel = sizeof(AudioUnitSampleType) * 8;
descPCMFormat.mBytesPerPacket = sizeof(AudioUnitSampleType);
descPCMFormat.mFramesPerPacket = 1;
descPCMFormat.mBytesPerFrame = sizeof(AudioUnitSampleType);
descPCMFormat.mFormatID = kAudioFormatLinearPCM;
descPCMFormat.mFormatFlags = kAudioFormatFlagsAudioUnitCanonical;
AudioStreamBasicDescription descAACFormat;
descAACFormat.mSampleRate = 32000;
descAACFormat.mChannelsPerFrame = 1;
descAACFormat.mBitsPerChannel = 0;
descAACFormat.mBytesPerPacket = 0;
descAACFormat.mFramesPerPacket = 1024;
descAACFormat.mBytesPerFrame = 0;
descAACFormat.mFormatID = kAudioFormatMPEG4AAC;
descAACFormat.mFormatFlags = 0;
AudioConverterNew(& descPCMFormat, & descAACFormat, &m_hCodec);
UInt32 ulBitRate = 96000;
UInt32 ulSize = sizeof(ulBitRate);
AudioConverterSetProperty(m_hCodec, kAudioConverterEncodeBitRate, ulSize, & ulBitRate);
単純な変換ルーチン:ここ
は、MPEG4-AAC 96kbitsの@ 32KHzのをエンコードするように設定するコードオーディオコンバータです。このルーチン1024個のPCMサンプルのブロックと32ms毎と呼ばれ、符号化されたAACの384のバイトを期待されている:
OSStatus CMyObj::Convert(
const AudioUnitSampleType * pSrc,
const size_t ulSrc,
uint8_t * pDst,
size_t & ulDst)
{
// error and sanity checking removed..
// assume caller is converting 1024 samples to at most 384 bytes
OSStatus osStatus;
m_pSrcPtr = (uint8_t*)pSrc;
m_ulSrcLen = ulSrc; // verified to be 1024*sizeof(AudioUnitSampleType);
AudioBufferList destBuffers;
destBuffers.mNumberBuffers = 1;
destBuffers.mBuffers[0].mNumberChannels = 1;
destBuffers.mBuffers[0].mDataByteSize = 384;
destBuffers.mBuffers[0].mData = pDst;
AudioStreamPacketDescription destDescription;
destDescription.mStartOffset = 0;
destDescription.mVariableFramesInPacket = 0;
destDescription.mDataByteSize = 384;
UInt32 ulDstPackets = 1;
osStatus = AudioConverterFillComplexBuffer(
m_hCodec,
InputDataProc,
this,
& ulDstPackets,
& destBuffers,
& destDescription);
ulDst = destBuffers.mBuffers[0].mDataByteSize;
return osStatus;
}
入力データproceedureは、単にエンコーダ1024のサンプル提供:
static OSStatus CMyObj::InputDataProc(
AudioConverterRef hCodec,
UInt32 *pulSrcPackets,
AudioBufferList *pSrcBuffers,
AudioStreamPacketDescription **ppPacketDescription,
void *pUserData)
{
// error and sanity checking removed
CMyObj *pThis = (CMyObj*)pUserData;
const UInt32 ulMaxSrcPackets = pThis->m_ulSrcLen/sizeof(AudioUnitSampleType);
const UInt32 ulRetSrcPackets = min(ulMaxSrcPackets, *pulSrcPackets);
if(ulRetSrcPackets)
{
UInt32 ulRetSrcBytes = ulRetSrcPackets * sizeof(AudioUnitSampleType);
*pulSrcPackets = ulRetSrcPackets;
pSrcBuffers->mBuffers[0].mData = pThis->m_pSrcPtr;
pSrcBuffers->mBuffers[0].mDataByteSize = ulRetSrcBytes;
pSrcBuffers->mBuffers[0].mNumberChannels = 1;
pThis->m_pSrcPtr += ulRetSrcBytes;
pThis-> m_ulSrcLen -= ulRetSrcBytes;
return noErr;
}
*pulSrcPackets = 0;
pSrcBuffers->mBuffers[0].mData = NULL;
pSrcBuffers->mBuffers[0].mDataByteSize = 0;
pSrcBuffers->mBuffers[0].mNumberChannels = 1;
return 500; // local error code to signal end-of-packet
}
すべてをシミュレータで実行するとうまく動作します。
ただし、デバイスで実行すると、InputDataProcは一貫して呼び出されません。 20回連続してAudioConverterFillComplexBufferを呼び出すと、InputDataProcへの呼び出しが呼び出され、すべてが正常に機能しています。その後、AudioConverterFillComplexBufferへの次の21回の呼び出しに対して、InputDataProcは呼び出されません。このパターンは永遠に繰り返される:
-> Convert
-> AudioConverterFillComplexBuffer
-> InputDataProc
-> results in 384 bytes of 'good' AAC
-> Convert
-> AudioConverterFillComplexBuffer
-> InputDataProc
-> results in 384 bytes of 'good' AAC
.. repeats up to 18 more times
-> Convert
-> AudioConverterFillComplexBuffer
-> results in 384 bytes of 'bad' AAC
-> Convert
-> AudioConverterFillComplexBuffer
-> results in 384 bytes of 'bad' AAC
.. repeats up to 18 more times
それはInputDataProcを呼び出していないので、コンバータは、入力データが「悪い」AACを作成するために取得している
?
誰もがこのアプローチで驚くほど間違ったことを見ていますか?
ハードウェアコーデック(MagicCookiesまたは?)で行う必要がある特別な設定はありますか?
HW AACコーデックは32000サンプルレートをサポートしていますか?
私はハードウェアがAudioConverterNewSpecificを使用してソフトウェアコーデックを強制し、mManufacturer kAppleSoftwareAudioCodecManufacturerを指定することにより、シミュレータと同じように動作するように得ることができます。 ハードウェアコーデックの使い方を知ることは、まだ素晴らしいことです! – welch1820