Hey Guys,
Our sound loader is finished and ready to go. Before I go into details of how OpenAL (Open Audio Library) manages sound, I want to talk a bit about our resource manager. If you recall, our resource manager was a set of libraries that let us load assets (art) into our program:
You'll notice that sound loading and the other associated resource components feed into our resource manager. These resource components are all going to share a similar design. Each of these components are going to be a collection of classes that let us load a general asset of a given type, render the loaded asset when we need to, and destroy the asset when we are done.
Here’s an example:
If we want to load a sound file, it must have some sort of load functionality, it must be able to render the sound to the speakers, and when we are done we want to be able to de-initialize the sound system and exit.
So in general, most of our resource component classes will look something like this:
class resource_component{public: resource_component(); // Where we destroy the data used ~resource_component(); bool load_data(char * path); void render_data(void); private: data resource_data;};
We will be using functions to initialize and de-initialize the systems that our resource components are built on. For example, our OpenAL system will have a pair of functions like this:
bool init_sound();bool deinit_sound();
Why use classes for our resource components? The probability is that we are going to want to load many different files using the same code into different pieces of data...which is essentially what a class is (a grouping of common functions that act on different data, which is stored in an object) :)
Why not use inheritance in this case? If we are going to have all resource components share a common architecture why not abstract it into a parent class? While this might be a scalable solution at the moment, later on I think it would only cause us grief. Currently inheritance would let us reinforce the architecture we want to promote. Beyond this benefit, there are really no other gains. Inheritance is useful when used to stop code duplication (MFC is a good example...I can’t believe I just said that :) ...), but this is not the case with resource components because sound, for example, is very different from graphics and therefore they share very little common code. If we do decide to use inheritance, then there are several issues we would have to cope with. The first is scalability. Our resource components are very different, so it is conceivable that the interfaces to these components will vary drastically as we add more features until the architecture we are attempting to enforce is ignored. The second issue is code reuse. If we decide to transplant our sound subsystem into another project, we are also going to have to transplant the inheritance tree, which may or may not be needed in the other project.
Classes however, work great for the resource components because it’s easy to think of a sound or a 3d model as an individual loaded object. Sitting right on top of our resource components is the resource manager. The resource manager will manage all of our resource components so that the game doesn't have to. The manager is essentially a set of functions. Why not classes?...you'll see in a moment ;) The resource manager provides the standard init and deinit functions to initialize and de-initialize the manager. In it's load function it will initialize all of the systems that our resource components use (ie init_sound() ect). It will then use the classes of our resource components to load all of our assets. The load will happen when the resource manager initializes. The resource manager can then provide functions like:
// Standard initialization functionsbool init_resource_manager(); // All of our assets are loaded herevoid deinit_resource_manager();// The manager will then provide asset rendering functions as they relate to chessvoid draw_knight(float x, float y);void draw_knight_on_board(int x, int y); //uses draw_knight and knows how to position pieces on the boardvoid move_knight(int x1, int y1, int x2, int y2); //uses draw_knight_on_board as well as some animation, and plays a sound when the piece lands at its destination// Display a message in the menuvoid menu_message(char * message);
This is the point at which the game starts to look more like chess. As we build the resource manager we start to automate more and more tasks, reducing a lot of the work we have to do later. We can also incorporate different effects like model loading and playing a sound into these functions (ie in the move_knight function) as we build the resource manager. Doing all of the initialization in init_resource_manager() will also abstract all of the resource component loading from the rest of the game. For example, as far as the game context is concerned it can freely call draw_knight() without having to worry if the knight asset was loaded, or even exists for that matter :)
Okay, now for some sound loading...Before you begin you will need to install two sound sdks (otherwise the program wont compile); OpenAL, which is used to render our sound objects and OGG/Vorbis which is used to load our sound objects from disk.
You can find OpenAL at:
http://developer.creative.com/landing.asp?cat=1&sbcat=31⊤=38The installer I used for this project was:
http://developer.creative.com/articles/article.asp?cat=1&sbcat=31⊤=38&aid=45The installer also comes with some great documentation, but you can also find docs equivilent to the red book at:
http://chopenal.sourceforge.net/OpenAL.pdfYou can find Ogg/Vorbis at:
http://www.vorbis.com/download.pspThe installer I used for this project was:
http://www.vorbis.com/files/1.0.1/windows/OggVorbis-win32sdk-1.0.1.zipThe install for this sdk is a bit tough; post if you have any trouble. You can also find good programmer documentation at:
http://www.xiph.org/ogg/vorbis/docs.htmllol, someone once asked me what I read for liesure. I said lord of the rings and technical documentation :) Anyway, back on topic...When I started programming with sound, I had no idea what I was doing. So, I looked up the problem and lo and behold it was already done for me :D I used a combination of two gamedev articles to produce our sound library. Instaed of giving you guys a tutorial on the library, I think it would be good exercize if I gave you guys the articles and the library. If you get stumped feel free to post.
Heres the place to sart; its an introduction to OpenAL:
http://www.gamedev.net/reference/articles/article2008.aspAnd the place to finish; the article details how to use Ogg with OpenAL:
http://www.gamedev.net/reference/articles/article2031.aspYou can download a the new source code at:
http://www.eng.uwaterloo.ca/~rramraj/Gamedev/chess_tutorial/src_tree/chess_src.zipNo worries if you dont understand any or all the details of the implementation. All that really matters is that you understand how the interfaces work :). I did a limited unit test for the sound source. I'm fairly sure most of the functions work (direct calls to OpenAL) but extending the test would be a good exercise.
You can find some really good ogg authoring tools for your test at:
http://www.snapfiles.com/freeware/gmm/fwaudiocodec.htmlNext on our to do list is a texture loading resource component. Good luck with Ogg and OpenAL :)
Will post later,
- llvllatrix