OpenAL oggVorbis streaming problems

Started by
3 comments, last by RaveniX 18 years, 3 months ago
I posted this a few weeks ago in Alternative Game Libraries forum but no response and I say the other OpenAL topic in here had a bunch so I'm reposting it where more will see. I followed this tutorial found here http://www.devmaster.net/articles/openal-tutorials/lesson8.php It works great for me and everything sounds great and perfect on my computer and select others. Then there are some computers where a split second of the streaming music is heard and it cuts out completely. Some computers will play the split second and stop but when you open the game back up again will stream the music perfectly. And one computer I tested would do this and play the music fine but when you moved the window the game was in, would cut the music. (I could move the window on my computer all I wanted and the music continued to play.) I know this is kind of a strange problem and was wondering if anyone has run in to this or have any idea why it will only work on some and not all?
Advertisement
Are you using the code verbatim from the tutorial? I also used this as a guide for developing my OpenAL audio engine recently (as in, a week ago). I didn't use this code though, because I thought it was very "spaghetti-like" and a general mess, so instead I used the concepts and designed my own class that streams audio music. If you wrote your own code, post it here and I may be able to help. Also, what buffer size are you using and how many buffers?

Hero of Allacrost - A free, open-source 2D RPG in development.
Latest release June, 2015 - GameDev annoucement

Yes, I had the same issue! When you move, minimise, maximize or resize the window the audio stream stops playing. I solved this easily by handling the Resize message of the window. When this message is fired i simply wait to check if the window is not minimized and has focus then Resume playback of the streams. Works perfectly. If you need the audio to play no matter what uninterrupted you need to put the audio decoding into a thread. This way you can do as you please with the interface without stopping the audio.

Hope that helps... :)

Regards,
RaveniX.
Thanks for the tip RaveniX. I'll get that a shot and see how it goes.

Here's my code for further scrunity. It's not verbatim from the tutorial but is still very close.

oggStream.h
#ifndef OGGSTREAM_#define OGGSTREAM_//#include <string>//#include <iostream>//using namespace std;#include <AL/al.h>#include <vorbis/vorbisfile.h>#define BUFFER_SIZE (4096 * 4)class oggStream{    public:	oggStream() { fileOpened = 0; }        void open(char* filename);        void release();        //void display();        bool playback();        bool playing();        bool update();    protected:        bool stream(ALuint buffer);        void empty();        void check();        //string errorString(int code);    private:        FILE*           myOggFile;        OggVorbis_File  myOggStream;        vorbis_info*    vorbisInfo;        vorbis_comment* vorbisComment;        ALuint buffers[2];        ALuint source;        ALenum format;	bool fileOpened;};#endif


oggStream.cpp
#include "oggStream.h"void oggStream::open(char* filename){    int result;        if(!(myOggFile = fopen(filename, "rb")))        return;//throw string("Could not open Ogg file.");    if((result = ov_open(myOggFile, &myOggStream, NULL, 0)) < 0)    {        fclose(myOggFile);                return;//throw string("Could not open Ogg stream. ") + errorString(result);    }    vorbisInfo = ov_info(&myOggStream, -1);    vorbisComment = ov_comment(&myOggStream, -1);    if(vorbisInfo->channels == 1)        format = AL_FORMAT_MONO16;    else        format = AL_FORMAT_STEREO16;                    alGenBuffers(2, buffers);    check();    alGenSources(1, &source);    check();        alSource3f(source, AL_POSITION,        0.0, 0.0, 0.0);    alSource3f(source, AL_VELOCITY,        0.0, 0.0, 0.0);    alSource3f(source, AL_DIRECTION,       0.0, 0.0, 0.0);    alSourcef (source, AL_ROLLOFF_FACTOR,  0.0          );    alSourcei (source, AL_SOURCE_RELATIVE, AL_TRUE      );	fileOpened = 1;}void oggStream::release(){	if (fileOpened == 1)	{		alSourceStop(source);		empty();		alDeleteSources(1, &source);		check();		alDeleteBuffers(1, buffers);		check();		ov_clear(&myOggStream);		fileOpened = 0;	}}//void oggStream::display()//{//    cout//        << "version         " << vorbisInfo->version         << "\n"//        << "channels        " << vorbisInfo->channels        << "\n"//        << "rate (hz)       " << vorbisInfo->rate            << "\n"//        << "bitrate upper   " << vorbisInfo->bitrate_upper   << "\n"//        << "bitrate nominal " << vorbisInfo->bitrate_nominal << "\n"//        << "bitrate lower   " << vorbisInfo->bitrate_lower   << "\n"//        << "bitrate window  " << vorbisInfo->bitrate_window  << "\n"//        << "\n"//        << "vendor " << vorbisComment->vendor << "\n";//        //    for(int i = 0; i < vorbisComment->comments; i++)//        cout << "   " << vorbisComment->user_comments << "\n";//        //    cout << endl;//}bool oggStream::playback(){	if (fileOpened == 1)	{		if(playing())			return true;	        		if(!stream(buffers[0]))			return false;	        		if(!stream(buffers[1]))			return false;	    		alSourceQueueBuffers(source, 2, buffers);		alSourcePlay(source);	}    return true;}bool oggStream::playing(){    ALenum state;        alGetSourcei(source, AL_SOURCE_STATE, &state);        return (state == AL_PLAYING);}bool oggStream::update(){	int processed;	bool active = true;	if (fileOpened == 1)	{		alGetSourcei(source, AL_BUFFERS_PROCESSED, &processed);		while(processed--)		{			ALuint buffer;	        			alSourceUnqueueBuffers(source, 1, &buffer);			check();			active = stream(buffer);			alSourceQueueBuffers(source, 1, &buffer);			check();		}	}    return active;}bool oggStream::stream(ALuint buffer){    char pcm[BUFFER_SIZE];    int  size = 0;    int  section;    int  result;    while(size < BUFFER_SIZE)    {        result = ov_read(&myOggStream, pcm + size, BUFFER_SIZE - size, 0, 2, 1, &section);            if(result > 0)            size += result;        else            if(result < 0)                return 0;//cout << "error" << endl;//throw errorString(result);            else                break;    }        if(size == 0)        return false;            alBufferData(buffer, format, pcm, size, vorbisInfo->rate);    check();        return true;}void oggStream::empty(){    int queued;        alGetSourcei(source, AL_BUFFERS_QUEUED, &queued);        while(queued--)    {        ALuint buffer;            alSourceUnqueueBuffers(source, 1, &buffer);        check();    }}void oggStream::check(){	int error = alGetError();	if(error != AL_NO_ERROR)	{		//cout << "OpenAL error was raised." << endl;	}}//string oggStream::errorString(int code)//{//    switch(code)//    {//        case OV_EREAD://            return string("Read from media.");//        case OV_ENOTVORBIS://            return string("Not Vorbis data.");//        case OV_EVERSION://            return string("Vorbis version mismatch.");//        case OV_EBADHEADER://            return string("Invalid Vorbis header.");//        case OV_EFAULT://            return string("Internal logic fault (bug or heap/stack corruption.");//        default://            return string("Unknown Ogg error.");//    }//}


Here's a minor breakdown of main.cpp which does everything
#include "oggStream.h"//background musicchar level_1[] = "music\\level_1.ogg";char deathMusic[] = "music\\death.ogg";oggStream ogg;char *music;void render(){	if (!ogg.update())	{		ogg.release();		if (mike.health != 0) // if music != death then restart it from the beginning		{			ogg.open(music);			ogg.playback();		}		else // death sound is done playing, restart level		{		}	}//here's where i draw all of my openGl stuff}int main(int argc, char** argv){	music = level_1;	ogg.open(music);	ogg.playback();//set up opengl window and all the other stuff related to it}
The code looks fine.

The problem is that you are decoding and swapping in a loop which stops when the window is resized/dragged. And because it stopped you can't swap the buffers. So openal gets to the end of the buffer and stops playing as it should do. if you put this in a thread the buffer swapping will work regardless of what you do to the window.

Or better yet put the decoding in a dll and just send messages to it from the main app. It can't be interupted by the main app lagging then.

This topic is closed to new replies.

Advertisement