Jump to content

  • Log In with Google      Sign In   
  • Create Account

Like
0Likes
Dislike

Introduction to Ogg Vorbis

By Anthony "TangentZ" Yuen | Published Dec 29 2003 06:17 AM in Game Programming

ogg sound data file openal vorbis buffer audio files
If you find this article contains errors or problems rendering it unreadable (missing images or files, mangled code, improper text formatting, etc) please contact the editor so corrections can be made. Thank you for helping us improve this resource



Overview

In this article, I will show you a very easy way to set up a system to play Ogg Vorbis (.ogg) files through the use of the Ogg Vorbis SDK and OpenAL. I choose OpenAL because I want my example code
to be as cross-platform as possible. The example code should compile and run under Windows and Unix/Linux. It should not be too difficult to substitute OpenAL with other audio API such as DirectSound
or fmod. I have included a small sample OGG file (Bomb.ogg) in case you do not have one handy.


What is Ogg Vorbis?

Ogg Vorbis (or just OGG) is an open-source audio compression format similar to MP3. (Actually, the file .ogg file format can contain other things, but let's just assume it is audio data for the
rest of this article.) One of the biggest advantages it has over MP3 is that it is patent-free. This means you do not need to pay a license fee in order to encode or decode OGG files. I don't know
about you, but to me, that is a very big plus!


If you want to know more about Ogg Vorbis, I urge you to read the Ogg Vorbis FAQ.


Getting Started

First, head over to Ogg Vorbis Home to download a copy of the SDK. If you are feeling adventurous, you can even download the source files and compile them
yourself. (Hey, it is open-source!) The SDK is cross-platform, so you can develop your application under Windows or Unix/Linux.


The Ogg Vorbis SDK comes in the form of header files and DLLs (so under Unix/Linux). Just put the header files (ogg/ogg.h, vorbis/vorbis.h, vorbis/vorbisfile.h, and vorbis/vorbisenc.h) and add the
include path to your favorite compiler environment (I use Visual Studio .NET 2003). The DLL (or .so) files (ogg.dll, vorbis.dll, vorbisfile.dll, and vorbisenc.dll) should be somewhere in the PATH.
Under Windows, you will also need to add the import libraries (ogg.lib, vorbis.lib vorbisfile.lib, and vorbisenc.lib) to your project so they can be linked to your application.


As the name of this article implies, I use OpenAL (Open Audio Library) as the underlying API to actually generate the sound through the speakers. There already
exist other resources concerning OpenAL (for example, here), so I will not spend too much time on explaining OpenAL in this
article. I will just assume that you have the OpenAL SDK correctly configured on your system.


Initialization

Here, I will just show the relevant code to setting up OpenAL for audio output. If something looks unfamiliar to you, please feel free to refer to other resources.



#include < AL/al.h >

#include < AL/alut.h >

#include < vorbis/vorbisfile.h >

#include < cstdio >

#include < iostream >

#include < vector >



#define BUFFER_SIZE   32768     // 32 KB buffers



using namespace std;

int main(int argc, char *argv[])

{

  ALint state;                // The state of the sound source

  ALuint bufferID;            // The OpenAL sound buffer ID

  ALuint sourceID;            // The OpenAL sound source

  ALenum format;              // The sound data format

  ALsizei freq;               // The frequency of the sound data

  vector < char > bufferData; // The sound buffer data from file



  // Initialize the OpenAL library

  alutInit(&argc, argv);



  // Create sound buffer and source

  alGenBuffers(1, &bufferID);

  alGenSources(1, &sourceID);

  

  // Set the source and listener to the same location

  alListener3f(AL_POSITION, 0.0f, 0.0f, 0.0f);

  alSource3f(sourceID, AL_POSITION, 0.0f, 0.0f, 0.0f);


Decoding OGG files

Opening file for binary reading

At this point, the system is all ready to go. The one thing that is missing is the actual sound data! OK, let's write a function that can load OGG files into memory.





void LoadOGG(char *fileName, vector < char > &buffer, ALenum &format, ALsizei &freq)

{

  int endian = 0;             // 0 for Little-Endian, 1 for Big-Endian

  int bitStream;

  long bytes;

  char array[BUFFER_SIZE];    // Local fixed size array

  FILE *f;



  // Open for binary reading

  f = fopen(fileName, "rb");


Up to this point, things should look very familiar. The function simply uses the fopen() function to open the given file for binary reading.


Opening file for decoding

Next, we declare some variables that the Ogg Vorbis SDK uses.



  vorbis_info *pInfo;

  OggVorbis_File oggFile;


Then comes the act of passing control over to the SDK. Note that there is no need to call fclose() anymore once this is done.



  ov_open(f, &oggFile, NULL, 0);


Information retrieval

After opening the file for decoding, we can extract a little bit of information about the compressed audio data in the file. At the very least, we need to know the number of channels (1 for mono
and 2 for stereo) and the sampling frequency of the audio data. We can do it like this:



  // Get some information about the OGG file

  pInfo = ov_info(&oggFile, -1);



  // Check the number of channels... always use 16-bit samples

  if (pInfo->channels == 1)

    format = AL_FORMAT_MONO16;

  else

    format = AL_FORMAT_STEREO16;

  // end if



  // The frequency of the sampling rate

  freq = pInfo->rate;


Decoding the data

Now we are ready to decode the OGG file and put the raw audio data into the buffer. We use a fixed size buffer and keep on reading until there is no more data left, like this:



  do {

    // Read up to a buffer's worth of decoded sound data

    bytes = ov_read(&oggFile, array, BUFFER_SIZE, endian, 2, 1, &bitStream);

    // Append to end of buffer

    buffer.insert(buffer.end(), array, array + bytes);

  } while (bytes > 0);


Clean up

Now all the audio data has been decoded and stuffed into the buffer. We can release the file resources (resource leaks are bad!).



  ov_clear(&oggFile);

}


Note that there is no need to call fclose(). It is already done for us. Neat.


Playing the sound

It is now time to get back to our main(). The next step is to upload the raw audio data to the OpenAL sound buffer and attach the buffer to the source.



  // Upload sound data to buffer

  alBufferData(bufferID, format, &bufferData[0], static_cast < ALsizei > (bufferData.size()), freq);



  // Attach sound buffer to source

  alSourcei(sourceID, AL_BUFFER, bufferID);


Finally! We are ready to play the sound! Let's do that!



  // Finally, play the sound!!!

  alSourcePlay(sourceID);

  // This is a busy wait loop but should be good enough for example purpose

  do {

    // Query the state of the souce

    alGetSourcei(sourceID, AL_SOURCE_STATE, &state);

  } while (state != AL_STOPPED);


After the sound is finished playing, we should clean up.



  // Clean up sound buffer and source

  alDeleteBuffers(1, &bufferID);

  alDeleteSources(1, &sourceID);



  // Clean up the OpenAL library

  alutExit();



  return 0;

} // end of main


We are done!


To run the example program, just supply the name of the OGG file you want to play. For example, "SimpleOGG
Bomb.ogg"


Conclusion

Ogg Vorbis is a very nice alternative to the MP3 audio compression format. Its biggest selling point is that it is patent-free. Using the Ogg Vorbis SDK and OpenAL, it is very easy to add the
ability to play OGG files in an application, as this article has demonstrated. I hope this article has been useful to you.


Obviously, there is more to Ogg Vorbis than what I have shown you in this article. For example, you can program an OGG encoder right in your application. For long background music, you should also
consider streaming the OGG data rather than loading everything into one big chunk. Given a typical 1:10 compression ratio, a piece of 5-minute music can easily eat up 50+ MB of memory if the entire
file is decoded! There won't be a lot of room left for other things! These are topics best left for future articles.


TangentZ
tangentz@hotmail.com








Comments

Note: Please offer only positive, constructive comments - we are looking to promote a positive atmosphere where collaboration is valued above all else.




PARTNERS