One Big HeadacheLoading file formats is always a pain to do. Loading a WAV file proves to be no different. It is a long function, that probably could have been broken up a little bit better, but for now it will have to do. It works and that is all I am concerned about. So, have a peek at it. The code is fairly simple it is just long. I will skim over the first few parts since they are just setting things up. The code starts out by finding the first available sound in our array. If it finds none, it issues an error and then returns to the caller. Once we have a valid sound id to hold our new sound we can start playing with the file, and setting the structures up for use. We start by initializing the structures to 0 to make sure we don't have any left over remnants from previous loads. Once that is complete, we get to open up our WAV file using the multimedia I/O functions found in the Winmm.lib file. Once the file is opened successfully we descend into the internals of the file. This merely takes us to relevant sections in the header so we can setup our structures for loading. A few sections need to be traversed and then we are ready to get the wave format information. With our wave information intact we can ascend up the file and then down into our data chunk. Once "inside" we allocate memory for our data and then we grab it with the mmioRead() function. Finally, we can close the file ... and the ugly part is over. Then, we do some more setting of values in structures and clearing things out. All stuff you have seen before, so it should look familiar by now. We are getting ready to create the sound buffer with all these assignments. Normally I would just say "here is where we create the sound buffer" ... but there is something very weird going on here. If you notice we aren't able to pass in the sound buffer parameter. The reason is that we need to pass in the address. So, the line right before the call uses the LEA (Load Effective Address) instruction to obtain the address of our variable. The reason for this is just a quirk on the INVOKE syntax and something we need to workaround. By loading the address before the call, we can place it in the modified invoke statement without troubles. Another small thing you might want to jot down is that we can't use EAX to hold that value. The reason is that the macro I defined, DSBINVOKE, uses EAX when manipulating things ... this is the only reason, normally you could use it without trouble. Never forget, macros are placed directly into your code ... even if they don't make sense. Once we have our buffer created we lock the buffer, copy the memory over to the new buffer locations, and then unlock the buffer. The only thing that might seem a little confusing is the method I have chosen to copy the sound data over. Remember how we copied using DWORD's in our Draw_Bitmap() routine? If not, go back and refresh your memory because it is very important. For those of you that do recall ... that is almost exactly what we are doing here. The only thing that is different, is we have to make sure that our data is on a 4-byte boundary. We do this by AND'ing the length with 3 ... this is the same as Number mod 4 ... then moving byte by byte until we hit zero. At that point we are on a 4-byte boundary and can move DWORD's once again. It is the same basic concept that we have seen before only this time we have to do the checking for alignment ourselves since the data is not guaranteed to be on even 4-byte boundaries. Once all of that is out of the way we can free the buffer, along with our headache, and we are finished. The sound is now loaded, in the buffer, and we can return the sound's ID to the caller so that they can play the sound later on. One thing I do want to mention is that this WAV loader should be able to load WAV files of any format (8-bit, 16-bit, stereo, mono, etc.). Yet, only 8-bit sounds can be utilized in the DirectSound buffers. The reason is we only set the cooperative level to normal, instead of exclusive. So, if you want to load in, and play, 16-bit sounds you will need to alter the DS_Init() procedure, and put DirectSound into exclusive mode. With that, our sound module is complete. It is definitely not "state-of-the-art" ... but hey, it works and it removes a lot of the DirectX burden that would normally be placed on us. Luckily though, we get to talk about something a lot more fun: Screen Transitions.
|
|