0

OpenAL でストリームを再生する必要があります。しかし、バッファとソースで何をする必要があるのか​​ わかりません。私の疑似コード:

    FirstTime = true;

        while (true)
        {
        if (!FirstTime)
                {
                    alSourceUnqueueBuffers(alSource, 1, &unbuf);
                }
        //get buffer to play in boost::array buf (882 elements) (MONO16).
                if (NumberOfSampleSet >=3)
                {
                    alBufferData(alSampleSet[NumberOfSampleSet], AL_FORMAT_MONO16, buf.data(), buf.size(), 44100);
                    alSourceQueueBuffers(alSource, 1, &alSampleSet[NumberOfSampleSet++]);
                    if (NumberOfSampleSet == 4)
                    {
                        FirstTime = false;
                        NumberOfSampleSet = 0;
                    }
                }
alSourcePlay(alSource);
    }

私は何を間違っていますか?スピーカーでは、繰り返しクリックを聞きます。サウンドを再生するためにバッファをどうする必要があるか教えてください。

4

1 に答える 1

4

4 つのバッファ (それぞれ 882 サンプル) と 44kHz のソースでは (4 * 882/ (2 * 44100) ) = 0.04 秒の再生しかできません。これは単なる「クリック」です。

To produce longer sounds you should load more data (though only two buffers is usually sufficient).

Imagine you have a 100Mb of uncompressed .wav file. Just read say 22050 samples (that is 44100 bytes of data) and enqueue them to the OpenAL's queue associated with Source. Then read another 22050 samples into the second buffer and enqueue them also. Then just switch buffers (like you do now at NumberOfSampleSet == 4) and repeat until the file is not finished.

If you want a pure sine wave of e.g. 440Hz, then using the same 22050-sample buffers just fill them with the values of sine wave:

const int BufferSize = 22050;
const int NumSamples = 44100;
// phase offset to avoid "clicks" between buffers
int LastOffset = 0;
const float Omega = 440.0f;
for(int i = 0 ; i < BufferSize ; i++)
{
    float t = ( 2.0f * PI * Omega * ( i + LastOffset ) ) / static_cast<float>( NumSamples );

    short VV = (short)(volume * sin(t));;

    // 16-bit sample: 2 bytes
    buffers[CurrentBuffer][i * 2 + 0] = VV & 0xFF;
    buffers[CurrentBuffer][i * 2 + 1] = VV >> 8;
}
LastOffset += BufferSize / 2;
LastOffset %= FSignalFreq;

EDIT1:

To process something in real-time (with severe latency, unfortunately) you have to create the buffers, push some initial data and then check for how much data OpenAL needs:

int StreamBuffer( ALuint BufferID )
{
    // get sound to the buffer somehow - load from file, read from input channel (queue), generate etc.

    // do the custom sound processing here in buffers[CurrentBuffer]

    // submit more data to OpenAL
    alBufferData( BufferID, Format, buffers[CurrentBuffer].data(), buffers[CurrentBuffer].size(), SamplesPerSec );
}

int main()
{
    ....

    ALuint FBufferID[2];

    alGenBuffers( 2, &FBufferID[0] );

    StreamBuffer( FBufferID[0], BUFFER_SIZE );
    StreamBuffer( FBufferID[1], BUFFER_SIZE );

    alSourceQueueBuffers( FSourceID, 2, &FBufferID[0] );

    while(true)
    {
        // Check how much data is processed in OpenAL's internal queue
        ALint Processed;
        alGetSourcei( FSourceID, AL_BUFFERS_PROCESSED, &Processed );

        // add more buffers while we need them
        while ( Processed-- )
        {
            Luint BufID;

            alSourceUnqueueBuffers( SourceID, 1, &BufID );

            StreamBuffer(BufID);

            alSourceQueueBuffers( SourceID, 1, &BufID );
        }
    }

    ....
}
于 2013-02-25T11:12:23.643 に答える