4 个缓冲区(每个 882 个样本)和 44kHz 源仅提供 (4 * 882/ (2 * 44100) ) = 0.04 秒的播放时间 - 这只是一个“点击”。
要产生更长的声音,您应该加载更多数据(尽管通常只有两个缓冲区就足够了)。
想象一下,您有一个 100Mb 的未压缩 .wav 文件。只需读取 22050 个样本(即 44100 字节的数据)并将它们排入与 Source 关联的 OpenAL 队列。然后将另外 22050 个样本读入第二个缓冲区并将它们也加入队列。然后只需切换缓冲区(就像您现在在 NumberOfSampleSet == 4 处所做的那样)并重复直到文件未完成。
如果你想要一个例如 440Hz 的纯正弦波,那么使用相同的 22050-sample 缓冲区只需用正弦波的值填充它们:
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;
编辑1:
要实时处理某些事情(不幸的是,延迟很严重),您必须创建缓冲区,推送一些初始数据,然后检查 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 );
}
}
....
}