2010-07-22 2 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; 
} 

사람들이 개 라인은 이제 필요하지 않을 것 같다. 다른 OS, 하드웨어 등으로 테스트해야 할 것입니다 ...

+0

안녕하세요, 저는 아주 비슷한 문제가 있습니다 (매우 유사한'Update' 함수로, 같은 튜토리얼을 읽은 것처럼 보입니다). 이 솔루션을 가지고 가나 요? 루핑에 관한 나의 문제는 당신과 동일했다. 스트림을 다시 시작하기 전에 몇 밀리 초 뒤로 이동합니다. 그러나 루핑 없이도이 작업을 수행 할 수 있습니다. 오디오 파일이 끝나면 멈추기 전에 마지막 몇 ms의 사운드를 재생합니다. 성가신 작은 지터. 이 솔루션을 어떻게 나왔습니까? – Anthony