Thread: DirectX Question

  1. #1
    Registered User
    Join Date
    Nov 2004
    Posts
    69

    DirectX Question

    Ok, Iv been working on an engine for a game im going to produce with my friend. Sofar we have pretty much all the graphics and input done. I started looking around for how to add sound to my engine, and the only thing that came up was DirectX Sound, so I read a tutorial, and implemented it. Only problem is I can only have one sound playing at a time.


    Code:
    Example:
    LoadSegment(hwnd, "keypress.wav")
    if (keyPressed['Z'] || keyPressed['z'])
    			{		
    if (dmusicPerformance->IsPlaying(dmusicSegment, NULL) != S_OK)
    PlaySegment(dmusicPerformance, dmusicSegment);
    			}
    This function only lets me load one sound, and play it. Is there a way I can get it to play multiple sounds?

  2. #2
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    Use PlaySegmentEx and specify that it is a secondary sound segment. Primary sound segments will cause the current segment to stop playing. Primary segments are intended mainly for musical scores since it doesn't make much sense having two of them playing at one time.

    I would highly recommend the book DirectX 9: Audio Exposed available at www.amazon.com. It is an excellent book and covers just about every aspect of DirectMusic and the underlying DirectSound arhictecture and usage.

    But here is a sound class that will do what you want. This is a work in progress but myself and Shakti, also from this board, have used this sound engine extensively in our projects and it works quite well. I designed it with simplicity in mind. As of right now it does not support any audiopaths except for the default one.

    But it does support:

    • Music and sound at the same time with no conflicts and no mixing issues
    • Total separation of music and sound effects to alleviate possible music/effects conflicts
    • Any number of sounds can play at any time
    • Easily extensible by adding new classes or adding functions to the existing classes.
    • Auto loading of WAV files using the default DirectMusic loader object
    • Super fast hair-trigger sound effects - latency can be dialed as low as you want provided the card driver can handle it and provided you are using DirectX 9.0.
    • Streaming of huge WAV files with no glitching, no pausing, and supports streaming music while sound effects play.
    • Music scripting via DirectMusic scripting support
    • Can readily be extended to load DLS segments, bands, tracks, and groove levels.
    • Can be extended to support lyric tracks used to synchronize graphics and sound
    • Presents a very simple easy to use interface - 4 lines of code can get your system up and running.
    • All sounds are stored exactly once in memory, but can be played any number of times, from any number of 3D locations (when audiopath support is implemented, at any point in time.
    • All resources are handled by the sound system - nothing is required of the programmer for correct shutdown
    • Can be extended to support any effect, filter or plug-in used inside of DirectMusic including but not limited to reverb, occlusion, distortion, flange, normalization, equalization, etc.
    • Readily supports looped and non-looped sounds playing at the same time.
    • Fully DirectX 9.0 compatible and supports 8,16 and 24-bit sound depending on hardware configuration
    • Hands-off segment handling - nothing required of the programmer for static or dynamic segments.
    • Simple ID-based system
    • Centralized code structure - all play/stop requests are handled by one class - segments are invisible to the programmer.


    Those are just some of the things this sound engine can do and/or be implemented using it's base object by simply adding classes. The sky is the limit.

    I will also include my Music System class. This is a class designed as an extension to the CDXAudio class that handles all music requests, track changes, stopping/starting music based on random timers, continuous random music at random intervals. It has an extremely simple interface and you can get it running with about 3 lines of code provided CDXAudio is already instantiated.


    Now how to use the sound engine:

    First you must instantiate a CDXAudio object. You can do this either on the heap or on the stack. The constructors for all of the classes in the sound engine do not require any parameters.

    Code:
    #include "CDXAudio.h"
    
    CDXAudio  SFX;
    CDXAudio is the base DirectMusic object. But you do not play sounds through CDXAudio. All sounds/music are played through CDXSoundEmitter.

    Code:
    CDXSoundEmitter *SFXSystem;
    Now you must create the CDXAudio object. You pass how many pchannels you want to use for this performance to the CDXAudio::Create() function. If you are just playing WAV files, 1 pchannel will do fine. For a complete description of pchannels and the Microsoft Synthesizer consult the book I mentioned or the DirectMusic help file.

    Code:
    SFX.Create(1);
    This creates a DirectMusic object that uses 1 pchannel. Now you have the option of setting the latency for this object. Latency is an object-wide property and affects all sounds played on the performance. Any latency can be used but I recommend 5 to 10 ms for best performance. If you do not set the latency, the default DirectMusic latency will be chosen which is normally in the 75 to 80 ms range.

    Code:
    SFX.SetLatency(5);
    This sets the latency of the DirectMusic object to 5 ms. That's extremely fast.

    Now to create the CDXSoundEmitter object. Create requires 2 parameters: the Performance object and the Loader object. It just so happens that when you create a valid CDXAudio object these are automatically created. Just call their respective Getxx functions to retrieve them.

    Code:
    SFXSystem=new CDXSoundEmitter;
    
    SFXSystem->Create(SFX.GetLoader(),SFX.GetPerformance);
    That's it. All you have to do now is load sounds and save the returned ID's to gain access to them. But the sound engine startup is finished and it is ready to be used.

    Here is how you load a sound:

    Code:
    DWORD TestID=(SFXSystem->LoadSound(L"Hello.wav"));
    To play the sound call Play and specify CDX_SECONDARY_SEG if you want the sound to be played as a secondary segment.

    SFXSystem->Play(TestID,CDX_SECONDARY_SEG);

    The default play mode is CDX_SECONDARY_SEG.

    That's it. Your sound should be playing and provided the game loop lasts long enough, you should hear it.

    To play another sound simply load it, save the ID, and play it using the ID. As long as it is a CDX_SECONDARY_SEG it will be auto-mixed by DirectMusic with the currently playing sounds.

    So here is the complete code required to get it running:


    Code:
    #include "CDXAudio.h"
    
    CDXAudio SFX;
    CDXSoundEmitter *SFXSys;
    
    SFX.Create(1);
    SFX.SetLatency(5);
    SFXSys=new CDXSoundEmitter();
    SFXSys->Create(SFX.GetLoader(),SFX.GetPerformance());
    DWORD MySoundID=SFXSys->LoadSound(L"MySound.wav");
    SFXSys->Play(MySoundID,CDX_SECONDARY_SEG);
    Music has the same setup. Create another CDXAudio object and do the same init for it. Load your music files and then use my other class to play them randomly or create your own class to handle playback.

    CMusicSystem
    Now for a description of how to use the music system.

    Code:
    #include "CMusicSystem.h"
    
    CDXAudio MusicObject;
    CDXSoundEmitter *MusicEmitter;
    CMusicSystem MusicPlayer;
    ...
    ...
    
    
    MusicObject.Create(1);
    MusicObject.SetLatency(5);
    MusicEmitter=new CDXSoundEmitter();
    MusicEmitter->Create(MusicObject.GetLoader(),MusicObject.GetPerformance());
    
    CMusicSystem MusicPlayer;
    
    MusicPlayer.Create(MusicEmitter);
    MusicPlayer.AddScore(L"MySong1.wav");
    MusicPlayer.AddScore(L"MySong2.wav");
    
    MusicPlayer.Start();
    Then in your main render loop or game loop simply call Update.

    Code:
    void Render(float fTimeDelta)
    {
    ...
    ...
      MusicPlayer.Update(fTimeDelta);
    ...
    ...
    }
    There is some debugging support inside of the class. If you know how to instantiate a CD3DFont object you can specify that font as the debug output font by calling CMusicSystem::SetDebugFont().

    Playback of music is automatic. It will randomly choose from the scores you have added to its list and will play them not only in random order but with random periods of silence between them so the player never gets inundated with music or bored to tears by silence.

    Here are the files. I hope this helps you. But take my advice and get the book and you can code your own sound engine. This one is far from complete but its a good starting point.

  3. #3
    Registered User
    Join Date
    Nov 2004
    Posts
    69
    Havent tested it yet, hope it works. Thanks!

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Total newb directx invisable geometry question
    By -pete- in forum Game Programming
    Replies: 5
    Last Post: 08-13-2006, 01:45 PM
  2. Exam Question - Possible Mistake?
    By Richie T in forum C++ Programming
    Replies: 15
    Last Post: 05-08-2006, 03:44 PM
  3. Very simple question, problem in my Code.
    By Vber in forum C Programming
    Replies: 7
    Last Post: 11-16-2002, 03:57 PM
  4. DirectX question, please read!
    By Crossbow in forum Game Programming
    Replies: 2
    Last Post: 12-12-2001, 07:18 PM
  5. Simple DirectX question
    By Crossbow in forum Windows Programming
    Replies: 1
    Last Post: 12-12-2001, 12:44 AM