2

ネットワークから取った音を再生する必要があります。10msごとに、882バイトのサウンド(モノラル、16ビット、44100 Hz)を取得します。そしてこれを行う:

while (!ExitKey)
    {
        boost::system::error_code error;
        size_t len = VoiceSocket->read_some(boost::asio::buffer(buf), error);
        if (len==0)
        {
            continue;
        }
        alGenSources(1, &alSource);
        alGenBuffers(1, &alSampleSet);
        alBufferData(alSource, AL_FORMAT_MONO16, buf.data(), buf.size(), 44100);
        alSourcei(alSource, AL_BUFFER, alSampleSet);
        alSourcePlay(alSource);
    }

しかし、私の音は再生されません。これをファイルに送信すると、ファイルにサウンドがあるため、buf変数にサウンドがあります。

4

3 に答える 3

4

コードにalListener. これは間違いとしては少し明白すぎるように思えますが、ソケットからゼロ以外のデータが入ってくると仮定すると、リスナーも音も聞こえません。

編集: もう一度見てみると、大きな結果をもたらす小さなタイプミスがあります。alBufferData(alSource, ...)する必要がありますalBufferData(alSampleSet, ...)。ソースではなく、バッファ オブジェクトを埋めたい。それ以外の場合は、当然のことながらサウンドを生成しない空のバッファーを再生しています。

また、コードは一般的に非効率的であり、意図したとおりに機能しないことに注意してください。

10 ミリ秒ごとに受信するすべてのパケットに対して、新しいソース (およびバッファ) を生成することは絶対にしたくありません。これにより、ある程度のサウンドが生成されますが、必要なものではありません。ネットワークのジッター (必然的に発生します) がなくても、これは可聴ギャップなしではうまく再生されません。

ループに入る前に、1 つのソースと少なくとも 3 つのバッファー (5 つまたは 6 つ) を生成します。1 つのソースは、ストリーミングしている限り存続し、その間再生を続けます。

ループに入る前に少なくとも 2 つのバッファーを受信します。これらのバッファをalSourceQueueBuffers受信した順序でソース ( ) にキューに入れ、再生を開始します。新しいパケットを受信するたびに、データを新しいバッファーに読み取り (割り当てられたバッファーの空きリストからプルします)、キューに入れます。

バッファーをアンキューし、フリーになったらフリー リストに再利用します (最初にクエリを実行してください)。

こうすることで、OpenAL はサウンドの再生中に読み取るデータを常に保持します。これは、良好な結果を得るために重要です。飢えさせることはありません。

于 2013-02-18T10:48:36.070 に答える
0

私はこのコードを書きます:

void Sound::GoChat()
{
    device = alcOpenDevice(NULL);
    //
    ofstream file;
    file.open("TESTSPEAKER", std::ios_base::binary);
    context = alcCreateContext(device, NULL);
    alcMakeContextCurrent(context);
    // alGetError();
    char *alBuffer;
    ALenum alFormatBuffer;
    ALsizei alFreqBuffer;
    long alBufferLen;
    ALboolean alLoop;
    unsigned int alSource;
    unsigned int alSampleSet[3];
    boost::array <char, 882> buf;
    int NumberOfSampleSet = 0;
    alGenSources(1, &alSource);
    alGenBuffers(3, alSampleSet);
    //
    alBufferData(alSampleSet[0], AL_FORMAT_MONO16, buf.data(), buf.size(), 44100);
    alBufferData(alSampleSet[1], AL_FORMAT_MONO16, buf.data(), buf.size(), 44100);
    alBufferData(alSampleSet[2], AL_FORMAT_MONO16, buf.data(), buf.size(), 44100);
    alSourceQueueBuffers(alSource, 3, alSampleSet);
    //
    while (!ExitKey)
    {
        alSourceUnqueueBuffers(alSource, 3, alSampleSet);
        boost::system::error_code error;
        size_t len = VoiceSocket->read_some(boost::asio::buffer(buf), error);
        if (len==0)
        {
            continue;
        }
        file.write(buf.data(), 882);

        alBufferData(alSampleSet[0], AL_FORMAT_MONO16, buf.data(), buf.size(), 44100);
        alBufferData(alSampleSet[1], AL_FORMAT_MONO16, buf.data(), buf.size(), 44100);
        alBufferData(alSampleSet[2], AL_FORMAT_MONO16, buf.data(), buf.size(), 44100);

        alSourcei(alSource, AL_BUFFER, alSampleSet[0]);
        alSourcei(alSource, AL_BUFFER, alSampleSet[1]);
        alSourcei(alSource, AL_BUFFER, alSampleSet[2]);
            alSourceQueueBuffers(alSource, 3, alSampleSet);
        //
        //alSourcei(alSource, AL_LOOPING, alSampleSet);         
        alSourcePlay(alSource);
        alErr = alGetError();
        //
    }
    VoiceSocket->close();
    file.close();
}

しかし、これも機能しません(

于 2013-02-20T10:31:18.523 に答える
0

そのため、生のバッファに有効なデータがある場合は、alGetError を使用して OpenAL 関数をチェックし、それらのいくつかが失敗したかどうかを確認し、失敗した理由を見つける必要があります。質問の説明から、この基本的なチェックが行われたことがわかりませんでした。

于 2013-02-18T09:03:00.843 に答える