#include <SDL/SDL.h>
#include <SDL/SDL_mixer.h>
#include <gl/glu.h>
#include <ogg/ogg.h>
#include <vorbis/vorbisfile.h>
#include <al/alut.h>
#include <al/al.h>
#include <al/alc.h>
#include <stdio.h>
#define BUFFER_SIZE 4096
void thisIsEmpty();
void doCheck();
char *errorString(int);
void open(char*);
void open2(char*);
FILE *fp;
char *oggFile = "Water.ogg";
OggVorbis_File oggStream;
vorbis_info* vorbisInfo;
vorbis_comment* vorbisComment;
ALuint buffers[2];
//char* alBuffer; //data for the buffer
//ALenum alFormatBuffer; //for the buffer format
//ALsizei alFreqBuffer; //for the frequency of the buffer
//long alBufferLen; //the bit depth
//ALboolean alLoop; //looped
ALuint alSampleSet;
ALuint alSource; //buffer source
ALenum format;
ov_callbacks vorbisCallbacks;
// Struct that contains the pointer to our file in memory
typedef struct SggFile
{
char* dataPtr; // Pointer to the data in memoru
int dataSize; // Sizeo fo the data
int dataRead; // How much data we have read so far
}SOggFile;
size_t VorbisRead(void *ptr /* ptr to the data that the vorbis files need*/,
size_t byteSize /* how big a byte is*/,
size_t sizeToRead /* How much we can read*/,
void *datasource /* this is a pointer to the data we passed into ov_open_callbacks (our SOggFile struct*/)
{
size_t spaceToEOF; // How much more we can read till we hit the EOF marker
size_t actualSizeToRead; // How much data we are actually going to read from memory
SOggFile* vorbisData; // Our vorbis data, for the typecast
// Get the data in the right format
vorbisData = (SOggFile*)datasource;
// Calculate how much we need to read. This can be sizeToRead*byteSize or less depending on how near the EOF marker we are
spaceToEOF = vorbisData->dataSize - vorbisData->dataRead;
if ((sizeToRead*byteSize) < spaceToEOF)
actualSizeToRead = (sizeToRead*byteSize);
else
actualSizeToRead = spaceToEOF;
// A simple copy of the data from memory to the datastruct that the vorbis libs will use
if (actualSizeToRead)
{
// Copy the data from the start of the file PLUS how much we have already read in
memcpy(ptr, (char*)vorbisData->dataPtr + vorbisData->dataRead, actualSizeToRead);
// Increase by how much we have read by
vorbisData->dataRead += (actualSizeToRead);
}
// Return how much we read (in the same way fread would)
return actualSizeToRead;
}
//---------------------------------------------------------------------------------
// Function : VorbisSeek
// Purpose : Callback for the Vorbis seek function
// Info :
//---------------------------------------------------------------------------------
int VorbisSeek(void *datasource /*this is a pointer to the data we passed into ov_open_callbacks (our SOggFile struct*/,
ogg_int64_t offset /*offset from the point we wish to seek to*/,
int whence /*where we want to seek to*/)
{
size_t spaceToEOF; // How much more we can read till we hit the EOF marker
ogg_int64_t actualOffset; // How much we can actually offset it by
SOggFile* vorbisData; // The data we passed in (for the typecast)
// Get the data in the right format
vorbisData = (SOggFile*)datasource;
// Goto where we wish to seek to
switch (whence)
{
case SEEK_SET: // Seek to the start of the data file
// Make sure we are not going to the end of the file
if (vorbisData->dataSize >= offset)
actualOffset = offset;
else
actualOffset = vorbisData->dataSize;
// Set where we now are
vorbisData->dataRead = (int)actualOffset;
break;
case SEEK_CUR: // Seek from where we are
// Make sure we dont go past the end
spaceToEOF = vorbisData->dataSize - vorbisData->dataRead;
if (offset < spaceToEOF)
actualOffset = (offset);
else
actualOffset = spaceToEOF;
// Seek from our currrent location
vorbisData->dataRead += actualOffset;
break;
case SEEK_END: // Seek from the end of the file
vorbisData->dataRead = vorbisData->dataSize+1;
break;
default:
printf("*** ERROR *** Unknown seek command in VorbisSeek\n");
break;
};
return 0;
}
//---------------------------------------------------------------------------------
// Function : VorbisClose
// Purpose : Callback for the Vorbis close function
// Info :
//---------------------------------------------------------------------------------
int VorbisClose(void *datasource /*this is a pointer to the data we passed into ov_open_callbacks (our SOggFile struct*/)
{
// This file is called when we call ov_close. If we wanted, we could free our memory here, but
// in this case, we will free the memory in the main body of the program, so dont do anything
return 1;
}
//---------------------------------------------------------------------------------
// Function : VorbisTell
// Purpose : Classback for the Vorbis tell function
// Info :
//---------------------------------------------------------------------------------
long VorbisTell(void *datasource /*this is a pointer to the data we passed into ov_open_callbacks (our SOggFile struct*/)
{
SOggFile* vorbisData;
// Get the data in the right format
vorbisData = (SOggFile*)datasource;
// We just want to tell the vorbis libs how much we have read so far
return vorbisData->dataRead;
}
void open(char *path)
{
int result;
if(!(fp = fopen(path, "rb")))
printf("Could not open Ogg file.");
if((result = ov_open(fp, &oggStream, NULL, 0)) < 0)
{
fclose(fp);
exit(0);
fprintf(stderr,"Could not Open for playing!",SDL_GetError());
}
vorbisInfo = ov_info(&oggStream, -1);
vorbisComment = ov_comment(&oggStream, -1);
if(vorbisInfo->channels == 1)
format = AL_FORMAT_MONO16;
else
format = AL_FORMAT_STEREO16;
printf("this is just before the genbuffers!\n");
alGenBuffers(2, buffers);
printf("this is just before the doCheck!\n");
doCheck();
printf("this is just after the doCheck!\n");
alGenSources(1, &alSource);
doCheck();
alSource3f(alSource, AL_POSITION, 0.0, 0.0, 0.0);
alSource3f(alSource, AL_VELOCITY, 0.0, 0.0, 0.0);
alSource3f(alSource, AL_DIRECTION, 0.0, 0.0, 0.0);
alSourcef (alSource, AL_ROLLOFF_FACTOR, 0.0 );
alSourcei (alSource, AL_SOURCE_RELATIVE, AL_TRUE );
}
void open2(char *path)
{
/************************************************************************************************************************
Heres a total bodge, just to get the file into memory. Normally, the file would have been loaded into memory
for a specific reason e.g. loading it from a pak file or similar. I just want to get the file into memory for
the sake of the tutorial.
************************************************************************************************************************/
FILE* tempOggFile;
int sizeOfFile;
char tempChar;
int tempArray;
SOggFile a;
printf("Before fopen\n");
if(!(tempOggFile = fopen(path, "rb")))
printf("Could not open Ogg file.");
printf("AFter fopen\n");
// Find out how big the file is
sizeOfFile = 0;
while (!feof(tempOggFile))
{
tempChar = getc(tempOggFile);
sizeOfFile++;
}
// Save the data into memory
printf("Before a.dataPtr\n");
a.dataPtr = malloc(sizeof(sizeOfFile)); //new char[sizeOfFile];
printf("After a.dataPtr\n");
rewind(tempOggFile);
tempArray = 0;
while (!feof(tempOggFile))
{
a.dataPtr[tempArray] = getc(tempOggFile);
tempArray++;
}
// Close the ogg file
fclose(tempOggFile);
// Save the data in the ogg memory file because we need this when we are actually reading in the data
// We havnt read anything yet
a.dataRead = 0;
// Save the size so we know how much we need to read
a.dataSize = sizeOfFile;
/************************************************************************************************************************
End of nasty 'just stick it in memory' bodge...
************************************************************************************************************************/
// This is really the only thing that is different from the original lesson 8 file...
// Now we have our file in memory (how ever it got there!), we need to let the vorbis libs know how to read it
// To do this, we provide callback functions that enable us to do the reading. the Vorbis libs just want the result
// of the read. They dont actually do it themselves
// Save the function pointersof our read files...
vorbisCallbacks.read_func = VorbisRead;
vorbisCallbacks.close_func = VorbisClose;
vorbisCallbacks.seek_func = VorbisSeek;
vorbisCallbacks.tell_func = VorbisTell;
// Open the file from memory. We need to pass it a pointer to our data (in this case our SOggFile structure),
// a pointer to our ogg stream (which the vorbis libs will fill up for us), and our callbacks
if (ov_open_callbacks(&a, &oggStream, NULL, 0, vorbisCallbacks) != 0)
printf("Could not read Ogg file from memory");
/************************************************************************************************************************
From now on, the code is exactly the same as in Jesse Maurais's lesson 8
************************************************************************************************************************/
vorbisInfo = ov_info(&oggStream, -1);
vorbisComment = ov_comment(&oggStream, -1);
if(vorbisInfo->channels == 1)
format = AL_FORMAT_MONO16;
else
format = AL_FORMAT_STEREO16;
alGenBuffers(2, buffers);
doCheck();
alGenSources(1, &alSource);
doCheck();
alSource3f(alSource, AL_POSITION, 0.0, 0.0, 0.0);
alSource3f(alSource, AL_VELOCITY, 0.0, 0.0, 0.0);
alSource3f(alSource, AL_DIRECTION, 0.0, 0.0, 0.0);
alSourcef (alSource, AL_ROLLOFF_FACTOR, 0.0 );
alSourcei (alSource, AL_SOURCE_RELATIVE, AL_TRUE );
}
void release()
{
alSourceStop(alSource);
thisIsEmpty();
alDeleteSources(1, &alSource);
doCheck();
alDeleteBuffers(1, buffers);
doCheck();
ov_clear(&oggStream);
}
/*
void display()
{
int i;
printf("version ", vorbisInfo->version);
printf("\n");
printf("channels ", vorbisInfo->channels);
printf("\n");
printf("rate (hz) ", vorbisInfo->rate);
printf("\n");
printf("bitrate upper ", vorbisInfo->bitrate_upper);
printf("\n");
printf("bitrate nominal ", vorbisInfo->bitrate_nominal);
printf("\n");
printf("bitrate lower ", vorbisInfo->bitrate_lower);
printf("\n");
printf("bitrate window ", vorbisInfo->bitrate_window);
printf("\n");
printf("\n");
printf("vendor ", vorbisComment->vendor);
printf("\n");
for(i = 0; i < vorbisComment->comments; i++)
{
printf(" ", vorbisComment->user_comments);
printf("\n");
}
printf("\n");
}
*/
int playback()
{
if(playing())
{
printf("it returns 1 at playback\n");
//return 1;
}
if(!stream(buffers[0]))
return 0;
if(!stream(buffers[1]))
return 0;
alSourceQueueBuffers(alSource, 2, buffers);
printf("just before the alSourcePlay!\n");
alSourcePlay(alSource);
printf("just after the alSourcePlay!\n");
return 1;
}
int playing()
{
ALenum state;
//printf("I should be playing now!\n");
alGetSourcei(alSource, AL_SOURCE_STATE, &state);
//printf("This is the state: %d\n\n", state);
if(state == AL_PLAYING)
{
//printf("this is playing\n");
return 1;
}
else
{
printf("I am not playing...\n");
}
return 0;
}
int update()
{
int processed;
int active = 1;
alGetSourcei(alSource, AL_BUFFERS_PROCESSED, &processed);
doCheck();
while(processed--)
{
ALuint buffer;
alSourceUnqueueBuffers(alSource, 1, &buffer);
doCheck();
active = stream(buffer);
doCheck();
alSourceQueueBuffers(alSource, 1, &buffer);
doCheck();
}
return active;
}
int stream(ALuint buffer)
{
char pcm[BUFFER_SIZE];
int size = 0;
int section;
int result;
while(size < BUFFER_SIZE)
{
result = ov_read(&oggStream, pcm + size, BUFFER_SIZE - size, 0, 2, 1, §ion);
if(result > 0)
size += result;
else
if(result < 0)
printf("%s", errorString(result));
else
break;
}
if(size == 0)
return 0;
alBufferData(buffer, format, pcm, size, vorbisInfo->rate);
doCheck();
return 1;
}
void thisIsEmpty()
{
int queued;
alGetSourcei(alSource, AL_BUFFERS_QUEUED, &queued);
while(queued--)
{
ALuint buffer;
alSourceUnqueueBuffers(alSource, 1, &buffer);
doCheck();
}
}
void doCheck()
{
int error = alGetError();
if(error != AL_NO_ERROR)
printf("OpenAL error was raised. %d\n",error);
}
char *errorString(int code)
{
char *stringError = "";
switch(code)
{
case OV_EREAD:
stringError = "Read from media.";
case OV_ENOTVORBIS:
stringError = "Not Vorbis data.";
case OV_EVERSION:
stringError = "Vorbis version mismatch.";
case OV_EBADHEADER:
stringError = "Invalid Vorbis header.";
case OV_EFAULT:
stringError = "Internal logic fault (bug or heap/stack corruption.";
default:
stringError = "Unknown Ogg error.";
}
return stringError;
}
int main(int argc, char *argv[])
{
SDL_Init(SDL_INIT_VIDEO);
SDL_SetVideoMode(800, 600, 0, SDL_OPENGL | SDL_HWSURFACE );
SDL_Event event;
SDL_Rect showRect;
SDL_Surface *screen;
ALCcontext *Context;
ALCdevice *Device;
Device = alcOpenDevice((ALubyte*)"DirectSound3D");
//Device = alcOpenDevice((ALubyte*)"DirectSound3D");
if (Device == NULL)
{
printf("this isn't working!");
exit(-1);
}
printf("device is not null!\n");
//Create context(s)
Context=alcCreateContext(Device,NULL);
//Set active context
alcMakeContextCurrent(Context);
// Clear Error Code
alGetError();
open(oggFile);
//display();
//play the sound
if(!playback())
printf("Ogg refused to play.\n");
//playback();
while(update())
{
while(SDL_PollEvent(&event))
{
switch( event.type )
{
case SDL_KEYDOWN:
switch (event.key.keysym.sym)
{
case SDLK_ESCAPE:
break;
}
break;
case SDL_QUIT:
exit (0);
break;
}
}
if(!playing())
{
if(!playback())
fprintf(stderr,"Ogg abruptly stopped.\n",SDL_GetError());
else
fprintf(stderr,"Ogg stream was interrupted.\n",SDL_GetError());
}
}
release();
#if 1
//delete our source
/*alDeleteSources(1,&alSource);
//delete our buffer
alDeleteBuffers(1,&alSampleSet);*/
//Get active context
Context=alcGetCurrentContext();
//Get device for active context
Device=alcGetContextsDevice(Context);
//Disable context
alcMakeContextCurrent(NULL);
//Release context(s)
alcDestroyContext(Context);
//Close device
alcCloseDevice(Device);
#endif
SDL_Quit();
return(0);
}
OpenAL Ogg Vorbis problem with C
Hi everyone. I'm doing my program in C,SDL,OpenGL, and OpenAL using Ogg Vorbis for audio. Following Lesson 8 and converting it to C, I got a small Ogg file to play. I'm now trying to use a larger file and using Lesson 9 at devmaster.net so I can stream the Ogg files. When I use the function open in main, it plays a small ogg file, but when I use open2, it crashes. I know I have to use a malloc instead of new for "a.dataPtr = malloc(sizeof(sizeOfFile)); //new char[sizeOfFile];", but do it as a char.
Here's the code.
[Edited by - CoderGuy on February 28, 2006 9:41:33 PM]
First thing that jumps out is that your malloc is wrong:-
(sizeof(sizeOfFile)) give yous the size of the variable (i.e. 4 bytes), not the contents of the variable.
remove the sizeof and it should be ok,
Paul
(sizeof(sizeOfFile)) give yous the size of the variable (i.e. 4 bytes), not the contents of the variable.
remove the sizeof and it should be ok,
Paul
Ah, thanks for noticing that. I changed it to a.dataPtr = (char *)malloc(sizeOfFile), but now I hear the ogg file, and it plays just for a second and then I get a segmentation fault.
I thought there was an issue with the devmaster articles not working for larger files. Also you don't want the size of the file as its compressed? Just go nuts an allocate a few megs of RAM to test it.
Standard stuff:-
Do you have the callstack? What is it?
What is the actual error/exception message?
Paul
Do you have the callstack? What is it?
What is the actual error/exception message?
Paul
Error message:
Fatal signal: Segmentation Fault (SDL Parachute Deployed)
I changed the buffer size to be 1031072 now, but still nothing.
I do have the callstack, it's in the open2 function.
Fatal signal: Segmentation Fault (SDL Parachute Deployed)
I changed the buffer size to be 1031072 now, but still nothing.
I do have the callstack, it's in the open2 function.
But where exactly in the open2 function?, the callstack should give you the exact location (down to the assembly memory address) of where the error occured.
And based on that assembly memory address it should tell you why it caused it to crash i.e. unaligned memory access, access to a NULL pointer and so forth.
If you can supply that info it would help us a lot
Paul
And based on that assembly memory address it should tell you why it caused it to crash i.e. unaligned memory access, access to a NULL pointer and so forth.
If you can supply that info it would help us a lot
Paul
I did printf statements at the end of each callback function like
which when ran, each function was reached.
size_t VorbisRead(void *ptr /* ptr to the data that the vorbis files need*/, size_t byteSize /* how big a byte is*/, size_t sizeToRead /* How much we can read*/, void *datasource /* this is a pointer to the data we passed into ov_open_callbacks (our SOggFile struct*/){ size_t spaceToEOF; // How much more we can read till we hit the EOF marker size_t actualSizeToRead; // How much data we are actually going to read from memory SOggFile* vorbisData; // Our vorbis data, for the typecast // Get the data in the right format vorbisData = (SOggFile*)datasource; // Calculate how much we need to read. This can be sizeToRead*byteSize or less depending on how near the EOF marker we are spaceToEOF = vorbisData->dataSize - vorbisData->dataRead; if ((sizeToRead*byteSize) < spaceToEOF) actualSizeToRead = (sizeToRead*byteSize); else actualSizeToRead = spaceToEOF; // A simple copy of the data from memory to the datastruct that the vorbis libs will use if (actualSizeToRead) { // Copy the data from the start of the file PLUS how much we have already read in memcpy(ptr, (char*)vorbisData->dataPtr + vorbisData->dataRead, actualSizeToRead); // Increase by how much we have read by vorbisData->dataRead += (actualSizeToRead); } // Return how much we read (in the same way fread would) printf("Reached end of VorbisRead\n"); return actualSizeToRead;}
which when ran, each function was reached.
? umm sorry I don't quite udnerstand, I mean does the debugger that you are running have the ability to show you the current callstack of the code when it crashed?
i.e.
Paul
i.e.
Paul
Are you using the latest ogg/vorbis libs from xiph.org?
I had the same error message you did whenever I tried to call ov_open. Then it would blow up.
In the end I had to build the ogg/vorbis libs to match the runtime of the library I'm dropping them into (multithreaded DLL)..
hth,
I had the same error message you did whenever I tried to call ov_open. Then it would blow up.
In the end I had to build the ogg/vorbis libs to match the runtime of the library I'm dropping them into (multithreaded DLL)..
hth,
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement