在OpenAL库中播放流

时间:2013-02-25 10:22:09

标签: c++ openal

我需要在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);
    }

我做错了什么?在发言者中我听重复点击。请告诉我我需要用缓冲区来播放我的声音?

1 个答案:

答案 0 :(得分:4)

4个缓冲区(每个882个样本)和44kHz源仅提供(4 * 882 /(2 * 44100))= 0.04秒的播放 - 这只是一个“点击”。

要产生更长的声音,您应该加载更多数据(尽管通常只有两个缓冲区就足够了)。

想象一下,您有一个100Mb的未压缩.wav文件。只需读取22050个样本(即44100字节的数据)并将它们排入与Source关联的OpenAL队列。然后将另外22050个样本读入第二个缓冲区并将它们排队。然后只需切换缓冲区(就像你现在在NumberOfSampleSet == 4那样做)并重复直到文件没有完成。

如果你想要纯正弦波,例如440Hz,然后使用相同的22050样本缓冲区,只需用正弦波的值填充它们:

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:

要实时处理某些内容(遗憾的是,严重延迟),您必须创建缓冲区,推送一些初始数据,然后检查OpenAL需要多少数据:

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 );
        }
    }

    ....
}