我需要在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);
}
我做错了什么?在发言者中我听重复点击。请告诉我我需要用缓冲区来播放我的声音?
答案 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 );
}
}
....
}