2

現在、インターネット経由で mp3 オーディオをストリーミングしています。AudioFileStream を使用して、CFReadStreamRef からの mp3 ストリームを解析し、AudioConverterFillComplexBuffer を使用して mp3 をデコードし、変換された PCM データをリング バッファーにコピーし、最後に RemoteIO を使用して PCM を再生します。

私が現在直面している問題は、AudioConverterFillComplexBuffer が常に 0 (エラーなし) を返すことですが、変換結果が正しくないようです。細かいところ、気づけますが、

A. UInt32 *ioOutputDataPacketSize は、送信した値と同じ値を保持します。

B. convertData.mBuffers[0].mDataByteSize は、常に出力バッファのサイズに設定されています (バッファの大きさは関係ありません)。

C. 出力データでクリック ノイズしか聞こえません。

以下は、オーディオをレンダリングするための私の手順です。私の Audio キューの実装でも同じ手順が機能するので、AudioConverterFillComplexBuffer を呼び出す場所または AudioConverterFillComplexBuffer のコールバックのどちらにも問題はなかったと思います。

私は長い間この問題に悩まされてきました。どんな助けでも大歓迎です。

  1. AudioFileStream を開きます。

    // オーディオ ファイル ストリーム パーサーを作成します AudioFileTypeID fileTypeHint = kAudioFileMP3Type;
    AudioFileStreamOpen(self, MyPropertyListenerProc, MyPacketsProc, fileTypeHint, &audioFileStream);

  2. 解析されたデータをコールバック関数 ("MyPacketsProc") で処理します。

    void MyPacketsProc(void * inClientData, UInt32 inNumberBytes, UInt32 inNumberPackets, const void * inInputData, AudioStreamPacketDescription *inPacketDescriptions) { @synchronized(self) { // オーディオ コンバーターを初期化します。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);
    }
    

    }

  3. コールバック関数 ("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;

}

  1. RemoteIO コンポーネントを使用して再生します。

  2. 入力と出力の AudioStreamBasicDescription。

入力:

サンプルレート: 16000 フォーマット ID: .mp3

フォーマット フラグ: 0

パケットあたりのバイト数: 0

パケットあたりのフレーム数: 576

フレームあたりのバイト数: 0

フレームあたりのチャネル: 1

チャンネルあたりのビット数: 0

出力:

サンプルレート: 44100

フォーマットID:lpcm

フォーマット フラグ: 3116

パケットあたりのバイト数: 4

パケットあたりのフレーム数: 1

フレームあたりのバイト数: 4

フレームあたりのチャネル: 1

チャンネルあたりのビット数: 32

4

0 に答える 0