2010-07-22 134 views
3

我有问题循环流媒体ogg vorbis文件。循环流媒体.ogg音频 - OpenAL

这是代码:

fslStream_OGG::fslStream_OGG() 
{ 
className = "fslSound"; 
iMemSize = 0; 
iLength = 0; 
bSourceRelative = false; 
bIsLooping = false; 
bForceStop = false; 
bActive = false; 
source = buffer = 0; 
current_gain = 1.0f; 
outer_gain = 0; 
snd_info.uiChannels = snd_info.uiFrequency = snd_info.uiSampling = 0; 
} 

fslStream_OGG::~fslStream_OGG() 
{ 
if (bStreamCreated) 
{ 
    alSourceStop(source); 
    Empty(); 
    alDeleteSources(1,&source); 
    alDeleteBuffers(2,buffers); 
    ov_clear(&oggStream); 
} 
} 

bool fslStream_OGG::Update() 
{ 
ALenum state; 
alGetSourcei(source,AL_SOURCE_STATE,&state); 

if (state == AL_PAUSED || !bActive) return false; 

int processed; 
    alGetSourcei(source,AL_BUFFERS_PROCESSED,&processed); 

    while (processed--) 
    { 
     ALuint bufferI; 
     alSourceUnqueueBuffers(source,1,&bufferI); 
     Stream(bufferI); 
    if (bActive) alSourceQueueBuffers(source,1,&bufferI); 
    } 

if (state == AL_STOPPED || !bActive) 
{ 
    bActive = false; 
    StreamSetPos(0.0f); 
    if (bForceStop) return false; 

    if (bIsLooping) 
    { 
    alSourceStop(source); // <- *** note these *** 
    Empty(); // <- *** 2 lines of code *** 
    StreamPlay(); 
    alSourcePlay(source); 
    } 
    else 
    { 
    return true; 
    } 
} 

return false; 
} 

void fslStream_OGG::StreamPlay() 
{ 
if (!bActive) 
{ 
    bActive = true; 
    bForceStop = false; 
    Stream(buffers[0]); 
    Stream(buffers[1]); 

    alSourceQueueBuffers(source,2,buffers); 
} 
} 

bool fslStream_OGG::Open(const char* strFile) 
{ 
bStreamCreated = false; 
vorbis_info* vorbisInfo; 
oggFile = fopen(strFile,"rb"); 

if (!oggFile) return false; 

if (ov_open_callbacks(oggFile,&oggStream,NULL,0,OV_CALLBACKS_DEFAULT) != 0) 
{ 
    fclose(oggFile); 
    return false; 
} 

vorbisInfo = ov_info(&oggStream,-1); 

if (vorbisInfo->channels == 1) 
    format = AL_FORMAT_MONO16; 
else format = AL_FORMAT_STEREO16; 

alGenBuffers(2,buffers); 
alGenSources(1,&source); 

iLength = (long)(ov_time_total(&oggStream,-1) * 1000.0); 
snd_info.uiChannels = (format == AL_FORMAT_MONO8 || format == AL_FORMAT_MONO16)? 1:2; 
snd_info.uiSampling = (format == AL_FORMAT_MONO8 || format == AL_FORMAT_STEREO8)? 8:16; 
snd_info.uiFrequency = vorbisInfo->rate; 

bStreamCreated = true; 
bIsStream = true; 

return true; 
} 

void fslStream_OGG::Stream(ALuint bufferI) 
{ 
int size = 0; 
int section; 
int result; 

bActive = true; 

while (size < OGG_STREAM_BUFFER_SIZE) 
{ 
    result = ov_read(&oggStream,data + size,OGG_STREAM_BUFFER_SIZE - size,0,2,1,&section); 

    if (result > 0) 
    { 
    size += result; 
    } 
    else 
    { 
    if (result < 0) return; else break; 
    } 
} 

if (size == 0) { bActive = false; return; } 

    alBufferData(bufferI,format,data,size,snd_info.uiFrequency); 
} 

void fslStream_OGG::Empty() 
{ 
int queued; 
alGetSourcei(source,AL_BUFFERS_QUEUED,&queued); 

while (queued--) 
{ 
     ALuint bufferI; 
    alSourceUnqueueBuffers(source,1,&bufferI); 
} 
} 

void fslStream_OGG::StreamSetPos(float p) 
{ 
ov_time_seek(&oggStream,p); 
} 

float fslStream_OGG::StreamGetPos() 
{ 
return (float)ov_time_tell(&oggStream); 
} 

注2行代码我已经标有***。

在所有情况下,文件开始播放正常并在播放结束时倒带。然而:

没有这2行代码,当重复的文件听起来“损坏”。如果让我们再说一遍,听起来更“堕落”。我相信这是因为当流重复时,OpenAl和Vorbis解码器在写入/读取缓冲区时会“不同步”。

如果我添加这两行代码,该文件重复没有发声损坏。但是,文件不会无缝地重复;它会在结束之前倒转几个厘秒。我怀疑这是因为在倒带开始之前缓冲区没有播放到最后。

如果有人能伸出援助之手,我将不得不承担任何责任。

很多感谢,

比尔

回答

2

似乎,我已经解决了这一问题(我不会肯定没有广泛的测试)。

我有固定的更新方法如下:

bool fslStream_OGG::Update() 
{ 
    ALenum state; 
    alGetSourcei(source,AL_SOURCE_STATE,&state); 

    //if (state == AL_PAUSED || !bActive) return false; // <- WRONG 
    if (state == AL_PAUSED) return false; 

    int processed; 
    alGetSourcei(source,AL_BUFFERS_PROCESSED,&processed); 

    while (processed--) 
    { 
     ALuint bufferI; 
     alSourceUnqueueBuffers(source,1,&bufferI); 
     Stream(bufferI); 
     if (bActive) alSourceQueueBuffers(source,1,&bufferI); 
    } 

    //if (state == AL_STOPPED || !bActive) /// <- WRONG 
    if (state == AL_STOPPED) 
    { 
     bActive = false; 
     StreamSetPos(0.0f); 
     if (bForceStop) return false; 

     if (bIsLooping) 
     { 
      //alSourceStop(source); // <- I have added these 
      //Empty();    // <- 2 lines of code 
      StreamPlay(); 
      alSourcePlay(source); 
     } 
     else 
     { 
      return true; 
     } 
    } 

    return false; 
} 

这些2行代码似乎不是现在是必要的。将不得不测试它与不同的操作系统,硬件等...

+0

嘿,男人,我有一个非常类似的问题(有一个非常类似的'更新'功能;看起来像我们看同一个教程。去解决这个问题?我的循环问题与您的问题相同。在重新启动流之前,它会跳回几毫秒。但它也会做到这一点没有循环。当它到达音频文件的末尾时,它会在停止前重播最后几秒的声音。一个恼人的小抖动。你是怎么用这个解决方案的? – Anthony 2010-07-29 01:19:04