Playing Ogg Vorbis Files With Allegro

Playing Ogg Vorbis Files With Allegro

Ogg Vorbis is an open-source, royalty-free audio compression format. From my (limited) experience, the quality is as good or better than mp3, and the compression is slightly better (smaller files.) Unlike mp3, however, it is totally free and unpatented (mp3 uses Fraunhofer compression, which is patented.) Because of the open and free nature of Ogg Vorbis, I am going to focus on that as the audio format, so you won't have to worry about any copyright infringements.

There are a number of ways to stream an Ogg Vorbis file in your application. You can develop your own routines from the vorbis library, use the Allegro audio routines, or use a library by Vincent Penquerc'h to simplify working with Vorbis files and Allegro. Guess which one we're going with…

Requirements

Alogg can be compiled with options for fixed-point support (useful for mobile devices), URL support, and threaded streaming. We'll start without any of these options so we can just get an audio file playing.

Assuming you have Dev-C++ and Allegro installed, it is now time to install Alogg. Download and decompress the files to a temporary folder. Before going any further, lets build the documentation.

Build Alogg Documentation

You will need the makedoc.exe utility that came with Allegro (it will be in the \Allegro\docs\ folder,) so copy that to the alogg source directory. Open a DOS prompt and go to the directory containing the alogg files. type make docs type=html or make docs type=texi and the documentation will be created. You can refer to this for more assistance in setting up alogg in your environment.

Setup the Ogg/Vorbis Library

In order to build (and use) Alogg, we are going to need the Ogg/Vorbis library. The simplest thing to do is to download the Win32 SDK from http://www.vorbis.com. Extract the contents of this file, and move the contents of the include folder to your Dev-C++ include path and copy the contents of the lib file to your Dev-C++ library path. Maintain the directory structure with the header files (i.e. \include\ogg\ogg.h.) Also, copy the binary files (in the bin folder) to your \windows\system32 directory.

Compile Alogg

Simply type make then make install to compile and install the alogg library. You may get errors about a missing _G_config.h header file. It is in the GCC-2.95.3 package, located here (not sure why its not in the more recent packages.) Unzip the package, and copy the file to your include directory.

That's all you need to do to install the basic alogg library. Now lets put it to use.


Your First Alogg Project

For our example of playing an Ogg/Vorbis audio file, we will do nothing more than create a window with Allegro, then play a hard-coded audio file. For kicks, we can display the name of the file on the screen. As an exercise, you might want to play with playing a file specified on the command line. Or not.

Create a Project

Create an Allegro file as described in the <a rel="nofollow" title="http://dratek.com/component/option,com_openwiki/Itemid,52/id,tutorial:tut_devcpp_allegro_intro/" class="urlextern" href="../../../../../../../component/option,com_openwiki/Itemid,52/id,tutorial:tut_devcpp_allegro_intro/">Dev-C++ and Allegro tutorial</a> (you can even use my template to generate the project.

Get an Ogg File

Kinda basic, but necessary. I'll pretty much leave this up to you, but you can check out http://www.vorbis.com for some samples. I'll be using Mists of Time for this example. Once you have the file, copy it to your project directory.

Include the Alogg Library

At the top of your code, where you are placing your includes, add the following line:

#include <alogg\alogg.h>

Define the Size of an Audio Block

The block size will determine how much of the audio is read into memory at a time. A small block size will use less memory, and load fast, but could sound choppy. A large block size will sound good (usually,) but requires more memory and more time to load. You may need to play with this (or make it user definable) in order to get the right value.

#define	BLOCK_SIZE	4096

Declare Audio Stream Variables

At the start of the main procedure, declare the following variables:

	// Streaming audio variables:
	struct	alogg_stream	*pStream;
	int	iStreamUpdate	= 1;			// Initialize to >0
	char	pszAudioFile[ 256 ];

Specify the name of the Audio File

We need to fill in the audio file name variable with the name we are using. This will be the full name of the file you are using.

	// Specify the name of the audio file:
	sprintf( pszAudioFile, "Mists_of_Time-4T.ogg" );

Initialize the Alogg Library

Just after initializing Allegro, initialize Alogg:

	// Initialize Alogg:
	alogg_init();

Display The Name Of The Audio File (optional)

Just for fun, go to the method that displays the welcome message (if you are using the template) and change it to display the name of the audio file:

	textout_centre( screen, font, pszAudioFile,
					SCREEN_W / 2.0, SCREEN_H / 2.0,
					makecol( 255, 255, 255 ) );

Set the Per-Voice Volume

As more voices are reserved for the digital sound driver, Allegro reduces the volume of each in order to (hopefully) avoid distortion. Check out the Allegro documentation for more, but by using a value of 0, we can play all samples at the maximum value without distortion.

 	// Set the per-voice volume:
 	set_volume_per_voice( 0 );

Initialize the Sound Module

The following parameters are generally sufficient for initializing the audio. If the return value is less than 0, then the sound initialization failed.

 	// Initialize the sound module:
	if ( install_sound( DIGI_AUTODETECT, MIDI_AUTODETECT, NULL ) < 0 )
	{
		fprintf(stderr,"Failed to initialize sound module\n");
		alogg_exit();
		exit(1);
	}

Begin Streaming

Grab the first block of audio data, and start streaming the audio file:

	// Start streaming the audio:
	if ( !( pStream = alogg_start_streaming( pszAudioFile, BLOCK_SIZE ) ) )
	{
		fprintf( stderr, "Failed to start streaming %s\n", pszAudioFile );
		alogg_exit();
		exit(1);
	}

Loop Until the User Presses ''ESC''

If you are using the template from the Dev-C++ and Allegro tutorial, replace the call to readkey() with a while loop. We will stay in the loop until the escape key is pressed:

  	while ( !key[ KEY_ESC ] )
 	{

Read the Next Block

If we haven't reached the end of the stream yet, update the stream and read another block of audio data:

		// If iStreamUpdate is greater than 0, then there is still
		// more audio data to stream. If it is 0, then we've come
		// to the end of the file, and if its less than 0, there
		// was an error.
		if ( iStreamUpdate > 0 )
		{
			iStreamUpdate	= alogg_update_streaming( pStream );
		}
	}

Cleanup

After the user presses the escape key, we need to shutdown the audio processing. First we stop streaming the Ogg file, then we exit the Alogg library:

 	// Stop the audio streaming:
 	alogg_stop_streaming( pStream );
 
	// Exit the alogg library:
 	alogg_exit();

Set Linker Parameters

The following linker parameters must be added under project options:

    -lalogg
    -lalleg
    -lvorbisfile
    -lvorbis
    -logg

When using the above method of streaming, you will need to make sure you either update the stream often enough, or that your block size is large enough, so that the audio plays smoothly. In a game, it might be a good idea to simply update the audio stream every frame.

Build and Run

You should now be ready to build the application and run it to listen to your audio file.


Downloads

MyFirstAlogg.zip The above application, ready for Dev-C++.
DevCpp_AloggStreaming_template.zip A project template for Dev-C++ to generate a simple Alogg application, like the one above.