2011-07-22 39 views
4

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サンプルレートをサポートしていますか?

+1

私はハードウェアがAudioConverterNewSpecificを使用してソフトウェアコーデックを強制し、mManufacturer kAppleSoftwareAudioCodecManufacturerを指定することにより、シミュレータと同じように動作するように得ることができます。 ハードウェアコーデックの使い方を知ることは、まだ素晴らしいことです! – welch1820

答えて

0

32KHz入力PCMのデフォルト出力BitRateは48000ビット、44.1KHz入力PCMのデフォルト出力BitRateは64000ビットです。 デフォルトの出力BitRateを使用すると、32KHzの入力で大きなノイズが発生します。 these codes from apple`s sampleを使用しても、44.1KHzの入力は少しノイズがあります。

それから私は、両方がうまく機能32KHzの& 44.1KHzの、64kbsにoutputBitRateを修正。

UInt32 outputBitRate = 64000; // 64kbs 
UInt32 propSize = sizeof(outputBitRate); 
if (AudioConverterSetProperty(m_converter, kAudioConverterEncodeBitRate, propSize, &outputBitRate) != noErr) { 
} else { 
    NSLog(@"upyun.com uplivesdk UPAACEncoder error 102"); 
} 
+0

rotoava、私の質問にコメントしていただけますか?私はあなたがこの経験を持っているのを見ます。 http://stackoverflow.com/questions/41638475/how-to-set-bitrate-correctly-for-aac-encoding-osx – mbaros

関連する問題