Sign in to follow this  

OpenAL oggVorbis streaming problems

This topic is 4357 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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?

Share this post


Link to post
Share on other sites
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?

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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[i] << "\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 music
char 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
}


Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites

This topic is 4357 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this