Adding the sound

Graftgold Memories.

When Hewson released our products in the early days they usually hired a venue and invited various members of the computer press to attend the launch. We enjoyed these very much. It was a chance to show our games personally to the press and enthuse them about the game. It is much better to get your ideas across face to face rather than in a few notes to accompany the game. You can point out lots of little things that they may have overlooked. There was always free drink and goody bags that included photos of the game and usually something quirky to remind them of the game.  A couple of releases really stand out. For Dragontorc the release was held at the London Museum and Andrew Hewson had managed to borrow a replica of a Celtic golden torc from the British Museum where he used to work. It was very impressive and worth a fortune, it came with a security guard. Unfortunately the makers of the replica had a copyright so no photos were allowed. How can you have a copyright on something that is a replica?  I can remember Andrew Hewson wearing it round his neck.  For the release of Ranarama we did an in store signing in Chelmsford. We gave away T shorts and signed copies of the game. I did not think this worked as well as the press did not attend. to be effective we would have to had repeated the signing in many towns like they do for book releases.  
Andrew Braybrook at a launch, probably Gribbly's Day Out

Sometimes Hewson used the launch event to show several games, and this gave us a chance to meet the other programmers that had games published by Hewson and get freebie games to have a look at.
It was a fun day out of the office and our first chance to see what the press thought of our new games. They usually were received really well but the you had a long wait till the reviews came out. It was really important to get a good review and mostly we were not disappointed. If the magazine really liked a game they would often ask for supporting material to make an article about the game. It was an accolade to be mentioned on the cover of a magazine and even better for the game to be the main picture on the cover  such as the Zzap 64 Paradroid cover.  Once Hewson managed to get the actual game box artwork on the cover. This caused an uproar in the industry; the magazines advertisers complained and threatened to not place their ads with the magazine. It was a bit of a coup for Hewson but the publicity was deserved. For once the cover had not pandered to the huge marketed licensed games such as coin ups and film titles. These often were more hype than game. It was about the same time that a magazine panned a licensed game and the publisher immediately tried to get the review changed by exerting financial pressure as they were one of the prime advertisers. I never liked that side of the games industry. For me it was about creativity not money. Later one publisher had a film licence and said to me "I know the game's cr*p but it's a licence to print money."  

Deepest Blue

One of the biggest things on my to do list was the sound engine. I had put this off because I was unsure of what library to use. It looked like the DirectX sound routines were being deprecated. I wanted to stick with a Microsoft solution if possible to minimise dependencies on other peoples software. The recommended approach seemed to be the XAudio library which had been originally developed for the Xbox.

So I started by downloading the Microsoft samples. The problem I always have with these is they do not seem to specify  the libraries and include files they need to compile. So I spent ages looking at compile errors and searching for wanted header files to determine what was needed. I dutifully added the required include and library file paths only to find the compiler still could not find the files. Funny I can see them in one of the directories it lists when I try to open the file. At this point I lost patience, I was wasting too much time. I copied the code over to my environment, converted it to C and it compiled fine.

Another whinge, why do they code samples in unclear C++ where it is really hard to see what is going on.  The samples were so more complicated than they needed to be. In one which demonstrated how to read the format of a file all the reads were done asynchronously using another thread. The process had to wait around all the time for the other thread to complete. all this code obscured the essential flow of decoded the file, as it kept reading just a little bit.

I always get annoyed when documentation or samples say, don't do it like this. Show me the way it should be.  There were places that said it is inefficient to create a voice use it then destroy it. Guess what every sample did.  Rather than all the complications of multithreaded file  reading it would have been better to have given a well written simple implementation  that separated initialisation and in game processing.

I convert things to C because that is my preferred game language. I can see what is going on. I write code that my wife can understand. Not that she reads it although I do writing code as if
 someone else will read it is the key to writing code that is maintainable and works.

So I developed  voice pool objects that managed  voice objects that wrapped XAudio voices. The idea is that you group all SFX that have the same characteristics such as bit size and channels. I go one stage further , my pools manage a set of effects that have the same general purpose in a game.  For example all the console beeps for the controls such as buttons and switches are all grouped in a pool. Then they can have their own voice limit and if I want I can route them all through a shared effect. They have 2d processing that initialises the pan position to reflect the controls screen position.
In game 3d sounds form another pool. This pool has 3d processing so the pan and volume are affected by the position relative to the camera. I have a pool for fire and forget 1 shot SFX and another for repeating SFX such as engines.

I ported across some of the Microsoft sample sounds and rigged up some of my console buttons to trigger them. At first all I got was a sound like static and after each voice in the pool was used I got nothing. I kept going over the file formats to check I had unpacked them properly. The formats were not clear at all. In the wavebank format some items were bit packed. Why? When samples are huge what is the point in trying to save a few bytes  in the defining data? I gradually unravelled the ball of string.  Eventually I was sure I had decoded the wave and wavebank formats correctly. All the figures made sense but I still could not hear a proper sample. Then strangely when I made a mistake and played the wrong voice I heard the sample. Correct the mistake and I heard static. I found a bug that was using another voice by mistake but the SFX was on the previous voice. How can using the wrong voice effect the old voice?  At that point I gave up for the night. In the morning I looked for any code that was being executed with the wrong voice.  I removed some code that was an example of applying a filter and  heard my first proper sample play.  The mistake had applied the filter to an unused voice.  Sanity restored I still had to find why the pools were not working.
My very first sound routine for the Spectrum

For a while I wondered whether you really could reuse voices in the version I was using. Perhaps that is why the sample code did not reuse voices. Or perhaps there was some magic I did not understand that meant the voice was not reset. I read all the documentation on the API again. I found a lecture on making XAudio efficient and it seemed to advocate using exactly the method that I used.  After exploring all the complicated possibilities and ruling them out I had only 1 possibility left. There must be a bug sitting in front of me that I had missed. It was my code that signalled a voice was ready for us. I had separate duplicated code for 2d and 3d pools. I had made a change to the wrong routine so the one I was testing was wrong. Time for a refactor, I got rid of the duplicated code simplifying the route. Now I had sounds playing any number of times. I tried the 3d sounds. Silence. I looked at the results from the Microsoft 3d routine and they seemed ok put not very loud. I tried moving the camera nearer the ship and heard something. it was the scale of the fall off of the sound. If you were 6 foot away from the source you heard nothing. So I adjusted some set up data and heard my 3d sound. with a bit of trial and error I adjusted the constant to make the 3d sound silent at an acceptable distance.

I have a couple of to do's but want to get back to debugging the game. I need to put in a music player. That will use another thread and play ball with the windows media system so you do not get multiple tracks of music playing if another program is using media.  I might need an asynchronous loader for large samples. I might put ambient music phrases in the game that are choreographed with game play, as I did in Bushido. There is so much to do but essentials first.

Programming Tips:

Thinking about the sound in a game is a bit like thinking about a multi-tracked recording of music.  The bass track is really important and acts as a glue for all the sharper sounds. Consider the game Paradroid. The ambient hum of the ships engines acts as a root for all the other effects. On top of the ambient sounds you get the middle range sounds of things moving about. Punching through that you get sharp sounds of something important happening such as a bullet hitting or a beep of a button press. Each of the layers needs to allow the other sounds to be heard.

Rather like a film score the dynamics of the sound effects should emphasise the action in the game. When there is little action you can create a feeling of serenity that changes to suspense by keeping things really quiet except for the odd ambient effect. In Avalon when an enemy was in the next room I added a sound effect like footsteps as a warning and to build up the suspense. In Bushido I had an dynamic music track that cut down to almost silence, then adding the occasional few notes. This was in stark contrast to the full blown theme tune and game SFX when the action started.  


Popular Posts