如何获取 openal 中播放源的当前位置?我想我的意思是,在经过你的缓冲区、openal 缓冲区、硬件缓冲区等之后,音频当前在硬件上播放的位置。
我已经简要查看了 api,但我不太确定 AL_SAMPLE_OFFSET/AL_BYTE_OFFSET/AL_SEC_OFFSET 代表什么。如果我正在播放流媒体源,我似乎没有得到不断增加的数字,似乎我在当前播放缓冲区中获得了一个位置? (或所有缓冲区?)
例如,在玩游戏时,我循环并运行以下代码:
alGetSourcef( sources[0], AL_SAMPLE_OFFSET, &secoffset );
printf(" - %f samples\n", secoffset);
并得到
- 0.000000 samples
- 8192.000000 samples
- 9216.000000 samples
- 5632.000000 samples
似乎没有增加。
这是在带有最新 xcode 4.3 的 macos 10.7 上,但我假设它在其他平台上应该类似。
更新:
我尝试增加缓冲区大小,它实际上看起来只是当前播放缓冲区中的当前位置:
- 0.000000 bytes
- 18432.000000 bytes
- 20480.000000 bytes
- 36864.000000 bytes
- 36864.000000 bytes
- 55296.000000 bytes
- 55296.000000 bytes
- 73728.000000 bytes
refilling buffer 2408
re-queued buffer 2408
- 16384.000000 bytes
- 34816.000000 bytes
- 34816.000000 bytes
- 51200.000000 bytes
- 51200.000000 bytes
- 69632.000000 bytes
refilling buffer 2409
re-queued buffer 2409
鉴于此,有没有一种不错的方法可以在多个不同缓冲区中跟踪开放游戏?
这些偏移量是从排队缓冲区的开头开始的。您需要手动计算已未排队的缓冲区的大小并添加到此数字中。
这里,如果您阅读了文档,第 40 页上写着:
位置相对于所有排队缓冲区的开头 对于源,并且 set 调用遍历的任何排队缓冲区都将是 标记为已处理。
我很晚才知道,但如果您使用
libsndfile
,您只需使用模式SEEK_CUR
查找文件,然后将样本转换为秒即可获取当前流播放的位置。 (当然,如果您按样本划分缓冲区块。)在我的情况下,我的样本块是每个缓冲区8192
,并且我的缓冲区计算即时流是4
。如果您使用字节偏移量而不是样本,则会变得有点困难,因为您还需要将字节偏移量转换为样本,然后还需要将其乘以通道数。
float SamplesToSeconds(sf_count_t samples, int sampleRate) {
float seconds = samples / (float) sampleRate;
return seconds;
}
float GetCurrentPlayTime() {
// Retrive the current read samples count.
sf_count_t currentSamples = sf_seek(sndfile, 0, SF_SEEK_CUR);
// Convert the current read samples to seconds.
float sampleRate = 48000; // You get the sample rate from SF_INFO.
float position = SamplesToSeconds(currentSamples);
// playSamplesOffset - is offset that needs to be subtracked from position, because 'currentSamples' is means current read
// samples not the play one.
// In general its to tricky. So when play started it reads first 4 buffers and returns its 'currentSamples' but this is
// not actualy play postion, play position here is should be 0.01 or something like that, im not sure here but it work for my case.
float bufferSampels = 8192;
float bufferCount = 4;
float playSamplesOffset = ((float) bufferSamples / sampleRate) * bufferCount;
position = position - playSamplesOffset;
return position;
}