Welcome to MSDN Blogs Sign in | Join | Help

Syndication

Video Playback in XNA Game Studio 3.1

Michael did a post some time back to give an overview of the new video playback feature. Here’re some additional tips that might help -

Adding video to your project

  • In a nutshell - make sure your videos are encoded with Windows Media Video v9 codecs, are using the CBR format and that they have an audio track (also encoded with CBR). If you’re using Windows Media Encoder, select “File download (computer playback)” for your encoding destination format. This will give you the options to select CBR encoding for both video and audio streams.

image

  • The video clip must have an audio track otherwise the build will fail with - Please make sure that the video is not DRM protected and is a valid single-pass CBR encoded video file (yeah, I know, we could done better and added some info about the missing audio track here). This is an unfortunate limitation of  the native technology we depend on for playback but you can always mute the playback – “VideoPlayer.IsMuted = true”.
  • I’ve discovered that attempting to add a “silent” or “blank” audio track in Windows Media Encoder can be troublesome (sometimes the video will get “stuck” on the first frame on Windows). I’ve successfully used the encoder to do screen captures and format conversions (e.g AVI to WMV). If my source content didn’t have an audio track I used Windows Movie Maker to add one there.   
    • Adding an audio track to your movie in Windows Movie Maker takes little more skill than knowing how to drag and drop. 
    • When publishing the movie from Windows Movie Maker, select “DVD Quality” encoding which should give you the encoded video in CBR format.

Video playback

  • You shouldn’t have to call Video.GetTexture more than once per frame. The video stream decoder runs on a separate thread and handles synchronization with the audio track. Calling GetTexture always returns the last fully decoded frame. If a new frame is not quite ready it returns without doing anything but you still incur that managed to native call penalty.
  • If you want to show the same video on multiple screens in your game, just get the current video frame once and use it multiple times in your drawing code. This will ensure that all the screens show perfectly synchronized playback. If you call GetTexture multiple times there’s a chance that the frame can update in between two calls and the screens will look out of sync.
  • Playback of multiple videos is supported but playing back multiple high-res videos may not be such a great idea. Decoding video streams is expensive and the cost goes up quickly with the resolution of the source content.

 

     

Posted Saturday, June 20, 2009 12:01 AM by ashtat | 0 Comments

SoundEffect API Changes in Game Studio 3.1

Shawn beat me to the punch and did this great post on the changes to the SoundEffect API in XNA GS 3.1.  Here’re some tips if you’re trying to migrate your 3.0 code to the new release.

“Fire and Forget” Playback

  • SoundEffect.Play methods are now exclusively for “Fire and Forget” sounds. Instead of returning a SoundEffectInstance they’ll return a bool – “true” for successful playback and “false” instead of throwing the InstancePlayLimitException. XNA Framework will dispose these sounds as soon as they’re done playing. 
// this will play a 2D fire and forget sound effect with default
// volume, pitch and pan
SoundEffect effect = Content.Load<SoundEffect>(“GameSoundEffect”);
bool effectPlayed = effect.Play();
 
// This will play a 2D fire and forget sound effect with specified volume, pitch and pan
bool effectPlayed = effect.Play(0.8f, 1.0f, 0.0f);
  • You can only playback 2D, non-looping sounds using this “fire and forget” mechanism. For everything else – there’s “Create, Configure and Play”.

“Create, Configure and Play”

  • The SoundEffect.CreateInstance method returns a SoundEffectInstance object. The lifetime of this instance is completely controlled by the game. In other words you need to call Dispose on the instance returned by this method when you’re done with it. The usage pattern is -
    1. Create a SoundEffectInstance by calling SoundEffect.CreateInstance.
    2. Configure the SoundEffectInstance by setting all the properties. As you’ll notice, some of these properties are locked into place once you call Play.
    3. Call SoundEffectInstance.Play.
    4. When you’re done with the sound, call SoundEffectInstance.Dispose.

    // game controls the lifetime of the sound effect instance 
    SoundEffect effect = Content.Load< SoundEffect>(“GameSoundEffect”);
    SoundEffectInstance instance = effect.CreateInstance();
    instance.Play();
    instance.Dispose();

  • All SoundEffect.Play3D methods have been deprecated. Instead, game can now configure the SoundEffectInstance object returned by the SoundEffect.CreateInstance method for 2D/3D positioning and looping before playback. This configuration is locked into place on the first Play call made on the instance.
    • By default all instances are created as 2D non-looping sound effects.
// this will play a 2D non-looping sound effect
SoundEffect effect = Content.Load<SoundEffect>(“GameSoundEffect”);
SoundEffectInstance instance = effect.CreateInstance();
instance.Play(); 
    • Calling Apply3D on a SoundEffectInstance before calling Play configures it as a 3D positioned sound.
// this will play a 3D positioned non-looping sound effect
SoundEffect effect = Content.Load<SoundEffect>(“GameSoundEffect”);
SoundEffectInstance instance = effect.CreateInstance();
instance.Apply3D(listener, emitter);
instance.Play();
    • Setting the “IsLooped” property before calling Play configures the instance as a looping sound.
// this will play a 2D looping sound effect
SoundEffect effect = Content.Load<SoundEffect>(“GameSoundEffect”);
SoundEffectInstance instance = effect.CreateInstance();
instance.IsLooped = true;
instance.Play();
// this will play a 3D positioned looping sound effect
SoundEffect effect = Content.Load<SoundEffect>(“GameSoundEffect”);
SoundEffectInstance instance = effect.CreateInstance();
instance.IsLooped = true;
instance.Apply3D(listener, emitter);
instance.Play();
    • If you call both Pan and Apply3D (why would you do that?) the last call wins and determines if the sound is configured as a 2D or 3D positioned.
// this will play a 2D positioned looping sound effect.
// setting the Pan in this case overrides Apply3D.
SoundEffect effect = Content.Load<SoundEffect>(“GameSoundEffect”);
SoundEffectInstance instance = effect.CreateInstance();
instance.IsLooped = true;
instance.Apply3D(listener, emitter);
instance.Pan = 1.0f;
instance.Play();

Helper Extension Class

Here’s a helper class that may ease the pain of moving your code to the new world order.  Remember though, this is a helper for “Create and Configure” playback so you still need to explicitly dispose the instance when you’re done.

public static class SoundEffectExtensions
{
    public static SoundEffectInstance Play3D(this SoundEffect effect, AudioListener listener, AudioEmitter emitter)
    {
        return Play3D(effect, listener, emitter, 1f, 0f, false);
    }
 
    public static SoundEffectInstance Play3D(this SoundEffect effect, AudioListener listener, AudioEmitter emitter, float volume, float pitch, bool loop)
    {
        return Play3D(effect, new AudioListener[] { listener }, emitter, volume, pitch, loop);
    }
 
    public static SoundEffectInstance Play3D(this SoundEffect effect, AudioListener [] listeners, AudioEmitter emitter, float volume, float pitch, bool loop)
    {
        SoundEffectInstance instance = effect.CreateInstance();
        instance.Volume = volume;
        instance.Pitch = pitch;
        instance.IsLooped = loop;
        instance.Apply3D(listeners, emitter);
        instance.Play();
        return instance;
    }
 
    public static SoundEffectInstance Play2D(this SoundEffect effect)
    {
        return Play2D(effect, 1f, 0f, 0f, false);
    }
 
    public static SoundEffectInstance Play2D(this SoundEffect effect, float volume)
    {
        return Play2D(effect, volume, 0f, 0f, false);
    }
 
    public static SoundEffectInstance Play2D(this SoundEffect effect, float volume, float pitch, float pan, bool loop)
    {
        SoundEffectInstance instance = effect.CreateInstance();
        instance.Volume = volume;
        instance.Pitch = pitch;
        instance.Pan = pan;
        instance.IsLooped = loop;
        instance.Play();
        return instance;
    }
}

Posted Monday, June 15, 2009 6:13 PM by ashtat | 3 Comments

Filed under: , ,

Greetings Fellow Humans

Here I am, a little late to the MSDN blog party. But then again, my timing might not be so bad after all. Yesterday we announced the release of XNA Game Studio 3.1. Having spent a great deal of 2009 working on this baby it’s absolutely awesome to see it being set free to roam the big wide world. And it’s even more exciting to see what games you, the ultra-talented Indie developer lot, will build to entertain us!

Here’re some factoids about me –

  • I work on the XNA team constantly humbled by the sheer awesomeness of my coworkers.
  • I mainly work on the Audio and Media APIs – but then I also get to work on whatever it is that needs me working on it.
  • I grew up in India, the land of curry and other mythical things (oh yeah…now there’s a future post!).
  • I live in Seattle with my wife and our feline love-child Navin R. Johnson.
  • In my spare time I enjoy – playing music (guitar, piano, kazoo…), cooking and eating delicious food, brewing and drinking delicious beer etc. etc. You get the drift.

And now it’s time for me to think of posting something useful… :)

Posted Friday, June 12, 2009 10:00 PM by ashtat | 1 Comments

Page view tracker