Problem Streaming OGG using OpenAL in C++
From what I can tell it is reading in the pcm data to the buffer correctly so I think the problem exists in the way I am handling the buffer after that. The first post is the file loading code I don't believe the problem exists there but it could.
Code:
void WAudio::PlaySoundTrack(u16 volumeGroup)
{
gSoundTrackGroup = volumeGroup;
// Don't load the soundtrack if it is already playing
if(!gSoundTrackSound)
{
DELETE_PTR(gSoundTrackSound);
if (gSoundTrackSource)
{
ReleaseSource(gSoundTrackSource);
}
char fName[WFILE_MAX_PATH_NAME];
gSoundTrackSource = LoadSoundFromFile(gSoundTrackList[gTrackNum], STREAMING, SOUND_NOT3D, fName);
gSoundTrackSound = NewSound(gSoundTrackSource, fName);
//gSoundTrackSound->SetStreaming(true);
gSoundTrackSound->volumeGroup = volumeGroup;
gSoundTrackSound->SetIsLooped(true);
// STT - added this line, which may have been fine in Murphy but broke kaloki.
// I'm disabling this for now. Maybe later figure out where exactly he did the ramp up?
// see comment above.
gSoundTrackSound->SetVolume(0); // ramp volume up later
gSoundTrackSound->Play();
}
gSoundTrackSound->SetVolume(100);
gSoundTrackSound->Play();
}
// The loading code
WtSoundSource WAudio::LoadSoundFromFile(char *strWaveFileName, u16 streaming, u16 sound3D,
char* fName)
{
SoundBufferInfo* sourceBuffer;
// see if we've loaded this one already
sourceBuffer = (SoundBufferInfo *)GetSourceFromName(strWaveFileName);
if (sourceBuffer != INVALID_SOURCE)
{
return((WtSoundSource)sourceBuffer);
}
CHECK_AL_ERROR("preloadwav");
/// Dprintf("WAudio::LoadSoundFromFile Source: %s\n", strWaveFileName);
// make new buffer
sourceBuffer = (SoundBufferInfo *)WMALLOC(sizeof(SoundBufferInfo));
sourceBuffer->loop = false;
sourceBuffer->is3D = 0;
// Streaming needs 2 buffers to work
if(!streaming)
{
sourceBuffer->buffer = (ALuint*)WMALLOC(sizeof(ALuint));
sourceBuffer->numBuffers = 1;
}
else
{
sourceBuffer->buffer = (ALuint*)WMALLOC(2 * sizeof(ALuint));
sourceBuffer->numBuffers = 2;
}
int format;
if (strWaveFileName==NULL || strWaveFileName[0] == 0)
{
return(INVALID_SOURCE);
}
ASSERT(strlen(strWaveFileName) < MAX_SOUND_FILE_NAME);
strcpy(sourceBuffer->fileName, strWaveFileName); // store original unmodified name
alGenBuffers(sourceBuffer->numBuffers, sourceBuffer->buffer);
// Copy buffer[1] into buffer[0] for streaming to work
CHECK_AL_ERROR("initial buffer");
char fileName[WFILE_MAX_PATH_NAME];
// Since we are not using the wfile system, we need to set a bit of the path ourselves.
#ifdef WTARGET_OS_MAC_X
extern char* gMacFilePath;
strcpy(fileName, gMacFilePath);
#else
strcpy(fileName, W_DATA_PATH);
#endif
strcat(fileName, "/");
strcat(fileName, strWaveFileName);
// See if the file has an extension, if not, add .ogg
// Note: This will probably need to be ifdefed for other platforms
// We also used to have .wav(e) support, but ogg is better :)
char *ext = WStringUtils::GetDotExtension(fileName);
if(fName)
strncpy(fName, fileName, 256);
if (!ext)
{
strcat(fileName, ".wave"); // tack it on to the end if it doesn't have it
format = WAV_FILE;
}
else if (strcmp(ext, ".wave") == 0)
{
format = WAV_FILE;
}
else if (strcmp(ext, ".ogg") == 0)
{
format = OGG_FILE;
}
else// if (strcmp(ext, ".gom") == 0)
{
format = OGG_FILE;
}
if (format == WAV_FILE)
{
// --Scott -For some annoying reason, the PC version of this call takes a loop argument, and the mac version
// does not. Sheesh.
#ifdef WTARGET_OS_MAC_X
alutLoadWAVFile(fileName, &sourceBuffer->format, &sourceBuffer->data, &sourceBuffer->size, &sourceBuffer->freq);
#else
alutLoadWAVFile(fileName, &sourceBuffer->format, &sourceBuffer->data, &sourceBuffer->size, &sourceBuffer->freq, &sourceBuffer->loop);
#endif
}
else// if (format == OGG_FILE)
{ // ogg vorbis data.
if(!streaming)
LoadOGGFile(fileName, &sourceBuffer->format, &sourceBuffer->data, &sourceBuffer->size, &sourceBuffer->freq);
}
// Scott - alutLoadWAVFile does not return an error (despite what the spec says), and alGetError
// does not show errors if alutLoadWAVFile fails. To find out if we succeeded, we have to check the
// size. Sheesh.
// Don't unload if we are streaming
if(!streaming)
{
alBufferData(sourceBuffer->buffer[0], sourceBuffer->format, sourceBuffer->data, sourceBuffer->size, sourceBuffer->freq);
CHECK_AL_ERROR("generate buffers");
if (format == OGG_FILE)
{
ASSERT(sourceBuffer->size != 0);
UnloadOGG(sourceBuffer->format, sourceBuffer->data, sourceBuffer->size, sourceBuffer->freq);
}
else
{
alutUnloadWAV(sourceBuffer->format, sourceBuffer->data, sourceBuffer->size, sourceBuffer->freq);
CHECK_AL_ERROR("wavunload");
}
}
sourceBuffer->is3D = false; // default
gBufferList.AppendItem(&sourceBuffer); // add to master buffer list
CHECK_AL_ERROR("delbuf");
return (WtSoundSource)sourceBuffer;
}// LoadSoundFromFile
This is the playback and buffer handling code
Code:
//--------------------------------------------------------------------------------
// Create a new sound based on a sound source.
//--------------------------------------------------------------------------------
WSound * WAudio::NewSound(WtSoundSource soundSource, char* fName)
{
ASSERT(soundSource != NULL);
SoundBufferInfo* theBuffer = (SoundBufferInfo *)soundSource;
WALSound *theSound;
theSound = (theBuffer->numBuffers != 1) ? new WALStreamingSound(fName, theBuffer ) : new WALSound();
theSound->source = soundSource;
alGenSources(1, &theSound->alSource);
CHECK_AL_ERROR("gensource");
gLastSoundCreated = theSound; // track last sound created for easier event handling
ALfloat SourcePos[] = { 0.0, 0.0, 0.0 };
ALfloat SourceVel[] = { 0.0, 0.0, 0.0 };
// set up a bunch of stuff, including binding the buffer to the source
alSourcei (theSound->alSource, AL_BUFFER, theBuffer->buffer[0]);
alSourcef (theSound->alSource, AL_PITCH, 1.0 );
alSourcef (theSound->alSource, AL_GAIN, 1.0 );
alSourcefv(theSound->alSource, AL_POSITION, SourcePos);
alSourcefv(theSound->alSource, AL_VELOCITY, SourceVel);
alSourcei (theSound->alSource, AL_LOOPING, theBuffer->loop);
CHECK_AL_ERROR("alSource"); // check all setup stuff
// by default, loop if the buffer is set that way, same for 3D
theSound->SetIs3D(theBuffer->is3D);
theSound->SetIsLooped(theBuffer->loop == AL_TRUE);
return(theSound);
}// NewSound
//--------------------------------------------------------------------------------
// constructor
// Create WALStreamingSound with no parameters
WALStreamingSound::WALStreamingSound(void):WALSound()
{
}
WALStreamingSound::WALStreamingSound(char* fName, SoundBufferInfo* theBufferIn):WALSound()
{
strncpy(fileName, fName, 256);
file = fopen(fileName, "rb");
if (file == NULL)
return;
oggFile = (OggVorbis_File*)WMALLOC(sizeof(OggVorbis_File));
theBuffer = theBufferIn;
// Try opening the given file
if (ov_open(file, oggFile, NULL, 0) != 0)
{
fclose( file ); // Close file
return;
}
// Get some information about the OGG file
oggInfo = ov_info(oggFile, -1);
theBuffer->freq = oggInfo->rate;
theBuffer->size = BUFFER_SIZE;
// Check the number of channels... always use 16-bit samples
if (oggInfo->channels == 1)
theBuffer->format = AL_FORMAT_MONO16;
else
theBuffer->format = AL_FORMAT_STEREO16;
if(!PlayBack())
{
ASSERT("This sucks");
}
}
// destructor
WALStreamingSound::~WALStreamingSound()
{
if (IsPlaying())
{
StopSound();
}
Release();
ov_clear(oggFile);
if(file)
fclose( file );
// automatically remove us from the list.
WALSound *thisPtr = this;
WAudio::gSoundList.RemoveItem(&thisPtr);
}
void WALStreamingSound::StopSound(void)
{
alSourceStop(alSource);
CHECK_AL_ERROR("stop");
}
void WALStreamingSound::EmptyQueue(void)
{
int queued;
alGetSourcei(alSource, AL_BUFFERS_QUEUED, &queued);
while(queued--)
{
ALuint buffer;
alSourceUnqueueBuffers(alSource, 1, &buffer);
CHECK_AL_ERROR("empty queue streaming");
}
}
bool WALStreamingSound::PlayBack(void)
{
if(IsPlaying())
return true;
if(!Stream(theBuffer->buffer[0]))
return false;
if(!Stream(theBuffer->buffer[1]))
return false;
alSourceQueueBuffers(alSource, 2, theBuffer->buffer);
alSourcePlay(alSource);
return true;
}
void WALStreamingSound::Play()
{
Update();
if(!IsPlaying())
{
if(!PlayBack())
ASSERT("Ogg stream was interrupted");
}
}
void WALStreamingSound::Release()
{
EmptyQueue();
alDeleteSources(1, &alSource);
CHECK_AL_ERROR("release streaming");
alDeleteBuffers(2, theBuffer->buffer);
CHECK_AL_ERROR("release streaming");
}
bool WALStreamingSound::Update()
{
int processed;
bool active = true;
alGetSourcei(alSource, AL_BUFFERS_PROCESSED, &processed);
while(processed--)
{
ALuint buffer;
alSourceUnqueueBuffers(alSource, 1, &buffer);
CHECK_AL_ERROR("update streaming");
active = Stream(buffer);
alSourceQueueBuffers(alSource, 1, &buffer);
CHECK_AL_ERROR("update streaming");
}
return active;
}
bool WALStreamingSound::Stream(ALuint buffer)
{
#ifdef WTARGET_OS_MAC_X
int endian = 1; // 0 for Little-Endian, 1 for Big-Endian
#else
int endian = 0; // 0 for Little-Endian, 1 for Big-Endian
#endif
char data[BUFFER_SIZE];
int size = 0;
int section;
int result;
int arraySize = ov_pcm_total(oggFile, -1);
// Fill this buffer
static int numPasses = 0;
static int totalSize = 0;
while(size < BUFFER_SIZE)
{
numPasses++;
result = ov_read(oggFile, data + size, BUFFER_SIZE - size, endian, 2, 1, & section);
if(result > 0)
size += result;
else if(result < 0)
{
CHECK_AL_ERROR("Stream streaming");
}
else
break;
}
totalSize += size;
if(size == 0)
return false;
alBufferData(buffer, theBuffer->format, data, size, oggInfo->rate);
CHECK_AL_ERROR("Stream streaming");
return true;
}
... and what's the problem?
There's a known bug in the OpenAL that ships with 10.4 which causes frequent crashes on Intel and less-frequent crashes on PowerPC when streaming audio. The fix for this is to get your own version from CVS and use that instead.
CVS builds seem to byte-swap data on Intel machines. If you're using ogg/vorbis, that's easy to work around by lying and telling ogg/vorbis that your Intel Mac is big-endian...
There's a CVS snapshot here: http://onesadcookie.com/svn/repos/Thirdparty which fixed the streaming crash for me. YMMV. It does have the endianness bug in it.
There's a known bug in the OpenAL that ships with 10.4 which causes frequent crashes on Intel and less-frequent crashes on PowerPC when streaming audio. The fix for this is to get your own version from CVS and use that instead.
CVS builds seem to byte-swap data on Intel machines. If you're using ogg/vorbis, that's easy to work around by lying and telling ogg/vorbis that your Intel Mac is big-endian...
There's a CVS snapshot here: http://onesadcookie.com/svn/repos/Thirdparty which fixed the streaming crash for me. YMMV. It does have the endianness bug in it.
Actually the code runs without crashing and compiles just fine and without using streaming the same file plays fine too. It is just the streaming that is not workiing properly. Also this is being written on a PC not a mac so I don't think that will help if it is still the problem. Lol didn't notice this was a mac only dev forum know of any good pc forums?
I've made some progress now
it will stream in the first block of data play it then it gets stuck on playing the second block.
it will stream in the first block of data play it then it gets stuck on playing the second block.
but you've even got WTARGET_OS_MACX in your code... it's wrong (you meant __BIG_ENDIAN__), but it's there!
there are plenty of good streaming AL + ogg/vorbis tutorials out there... I assume you've googled, found, copied, and it's still not working?
there are plenty of good streaming AL + ogg/vorbis tutorials out there... I assume you've googled, found, copied, and it's still not working?
Yes now it is 'working' like I described with the second buffer to be loaded looping constantly. I did have to change one thing to make it work in the sample it never did this line anywhere in the sample but removing it crashes my game.
Which I guess must lock that buffer which is why I was never getting any sound at first. So I changed it to this.
I've also tried it without binding both buffers and binding only the first but that doesn't sound like it would work.
Code:
alSourcei (theSound->alSource, AL_BUFFER, theBuffer->buffer[0]);Code:
alSourcei (theSound->alSource, AL_STREAMING, theBuffer->buffer[0]);
alSourcei (theSound->alSource, AL_STREAMING, theBuffer->buffer[1]);
Possibly Related Threads...
| Thread: | Author | Replies: | Views: | Last Post | |
| OpenAL looping sound problem | Gillissie | 0 | 3,008 |
Sep 16, 2010 12:31 AM Last Post: Gillissie |
|
| openal linking problem on vc++ express 2005 | abousoft | 1 | 3,647 |
Jan 1, 2007 03:55 AM Last Post: sealfin |
|
| Need some help streaming ogg via OpenAL | Malarkey | 4 | 3,677 |
Nov 10, 2005 07:31 PM Last Post: Malarkey |
|
| Streaming Quicktime to OpenGL Texture | Holmes | 5 | 4,504 |
Jul 12, 2004 10:54 PM Last Post: kelvin |
|

