3D SOUND AND GAME CODING

Introduction         
Hardware Support         
Typical game loop         
Velocity parameter         
    Velocity is only required if you want doppler effects. Otherwise you can pass NULL to both FSOUND_3D_Listener_SetAttributes and FSOUND_3D_SetAttributes for the velocity parameter, and no doppler effect will be heard

    This is stressed over and over again, but can't be stressed enough. It is important that the velocity passed to FMOD is METERS PER SECOND and NOT meters per FRAME.

    What does this mean? Use proper velocity vectors from physics code etc, and don't just subtract last frames position from the current position, as this is affected by framerate. (ie the higher the framerate the smaller the position deltas, and therefore smaller doppler effects, which is incorrect)

    If the only way you can get the velocity is to subtract this and last frame's position vectors, then remember to time adjust them from meters per frame back up to meters per second.
    This is done simply by scaling the difference vector obtained by subtracting the 2 position vectors, by one over the frame time delta.

    Here is an example
    velx = (posx-lastposx) * 1000 / timedelta;
    velz = (posy-lastposy) * 1000 / timedelta;
    velz = (posz-lastposz) * 1000 / timedelta;
    timedelta is the time since the last frame in milliseconds. This can be obtained with functions such as timeGetTime().
    So at 60fps, the timedelta would be 16.67ms. if the source moved 0.1 meters in this time, the actual velocity in meters per second would be
    vel = 0.1 * 1000 / 16.67 = 6 meters per second.
    Similarly, if we only have half the framerate of 30fps, then subtracting position deltas will gives us twice the distance that it would at 60fps (so it would have moved 0.2 meters this time)
    vel = 0.2 * 1000 / 33.33 = 6 meters per second still! phew!.
Orientation and coordinate systems         
    Getting the correct orientation set up is essential if you want the source to move around you in 3d space.
    FMOD Uses a left handed coordinate system, (x = right, y = up, z = forwards), which is the same as DirectSound3D and A3D

    If you use a different coordinate system, then you will need to flip certain axis or even swap them around inside the call to FSOUND_3D_Listener_SetAttributes.
    Take the right handed coordinate system, where Z points backwards, or comes out of the screen at you. To convert this to FMOD coordinate system simply negate the Z coordinate of the listener up and forward vector.

    Just think RIGHT, UP, FORWARDS for each element of a vector (ie x,y,z), and map whatever axis fit your model into this, to generate the 2 vectors that points forwards and up.
Channel resource management and low end cards         
    Some soundcards only support 4 or 8 3D hardware channels, whereas other soundcards support 32 and 96 hardware 3D channels.
    What do you do in your game? only play 4 3D hardware based sounds at once to meet the base spec? Not likely. It would be ridiculous to limit yourself to these 4 channels when you have the potential of other high end cards that can do nearly 100 hardware channels at once.

    The solution is to use FSOUND_SetMinHardwareChannels. This function is called once before calling FSOUND_Init.
    What this allows you to do is assume a number of channels will either ALL be played in hardware, or NONE in hardware (therefore in software).
    It basically says 'if the card doesn't have n number of channels, then mix all sounds in software'. This allows you to assume that you have say 16 sounds to be playing at once, and if the hardware has at least that many channels available, it will play them all in hardware. If you come across a card that only supports 4 hardware channels at once, then it fails the criteria and your sounds are played all in software.

    The best thing about this is NO PlaySound's fail because of running out of channels on unexpected cards! You can guarantee a certain number of channels available, and if the hardware is there, then all the better!
Use priorities!         
    FMOD's priority system is there to be used. If you trigger lots of sounds on a limited number of channels, some might be more important than others.
    If you were doing a first person shooter, the player's gunshot sound would be one of the most important sounds. So it should have a high priority set with FSOUND_SetPriority. Other less important sounds would be rejected if the number of allocated channels became full, and that gunshot needed to be heard!