(X) Hide this
    • Login
    • Join
      • Say No Bots Generate New Image
        By clicking 'Register' you accept the terms of use .

Exploring Silverlight-XNA integration on Windows Phone 7

(3 votes)
Levente Mihály
>
Levente Mihály
Joined Apr 27, 2010
Articles:   7
Comments:   16
More Articles
17 comments   /   posted on Aug 30, 2010
Categories:   Gaming , Windows Phone

This article is compatible with the latest version of Silverlight for Windows Phone 7.

Windows Phone 7 platform provides two different frameworks for developing applications: Silverlight and XNA. XNA is a game-specific framework. If you want to write a 3D game, or a loop-based game with a lot of effects, textures and motion, you should choose XNA. So why should a SilverlightShow reader care about XNA? Because the two platforms are more-or-less compatible with each other, meaning you can use XNA assemblies in your Windows Phone 7 Silverlight applications. Here’s a brief introduction to the Silverlight-XNA integration.

First of all, you can download source codes for

- MicDemo – recording with microphone

- SoundEffectDemoMSDN code modified for Silverlight: playing and applying 3D positioning effects to a SoundEffect

- SongDemo – playing back a song

- PictureDemo – loading and saving pictures with MediaLibrary

XNA assemblies, limitations

In a Silverlight WP7 application we can use all the XNA assemblies except Microsoft.Xna.Framework.Game and Microsoft.Xna.Framework.Graphics. Sadly, this kind of kills the concept of a game with Silverlight menus or a Silverlight application with some 3D XNA graphic.

Enabling XNA

When you first run your Silverlight application that uses the XNA Framework, you might get an exception like this:

FrameworkDispatcher

The FrameworkDispatcher.Update method triggers event processing in the XNA Framework. It is automatically called whenever Game.Update is called. In Silverlight though, we don’t have a Game.Update, thus we have to call the FrameworkDispatcher.Update method manually.

The easiest way is to create a class like this:

 public class XNAAsyncDispatcher : IApplicationService
         {
             private DispatcherTimer frameworkDispatcherTimer;
             public XNAAsyncDispatcher(TimeSpan dispatchInterval)
             {
                 this.frameworkDispatcherTimer = new DispatcherTimer();
                 this.frameworkDispatcherTimer.Tick += new EventHandler(frameworkDispatcherTimer_Tick);
                 this.frameworkDispatcherTimer.Interval = dispatchInterval;
             }
  
             void IApplicationService.StartService(ApplicationServiceContext context)
             {
                 this.frameworkDispatcherTimer.Start();
             }
             void IApplicationService.StopService()
             {
                 this.frameworkDispatcherTimer.Stop();
             }
             void frameworkDispatcherTimer_Tick(object sender, EventArgs e)
             {
                 FrameworkDispatcher.Update();
             }
  
         }

and add it to ApplicationLifetimeObjects collection:

 // Constructor
 public App()
 {
     ...
     this.ApplicationLifetimeObjects.Add(
        new XNAAsyncDispatcher(TimeSpan.FromTicks(333333))
        );
 }

The standard rendering rate for XNA is 30fps so we configure the DispatcherTimer according to that.

Audio and Media

The Microsoft.Xna.Framework.Audio and Media namespaces offer  a lot of options. Playing back sound effects, dynamic sound effects, recording audio with the microphone, applying 3D effects to audio, and the list goes on…

SoundEffect

The SoundEffect class can be useful in a Silverlight game where you have a lot of sounds, often playing at the same time. Using the SoundEffect class to play a wave sound should be better performance-wise than using Silverlight’s MediaElement. Here’s how to load and play a sound file in a loop with XNA:

 SoundEffect se = SoundEffect.FromStream(TitleContainer.OpenStream("hand-clap-1.wav"));
 soundEffectInstance = se.CreateInstance();
 soundEffectInstance.IsLooped = true;
 soundEffectInstance.Play();

The TitleContainer static class provides filestream access in XNA. In the Play method we can also pass volume, pitch and panning values.

It’s very easy to apply positional effects to the sound, by calling the Apply3D method on the SoundEffectInstance, and passing one or more AudioListener instances and an AudioEmitter.

Microphone

Windows Phone 7 provides access to the microphone via the Microsoft.Xna.Audio.Microphone class. The quality is 16-bit Mono.

 Microphone mic = Microphone.Default;
 MemoryStream micStream = new MemoryStream();
 byte[] buffer;
 SoundEffect recordedSE;
        
 // Constructor
 public MainPage()
 {
    InitializeComponent();
    mic.BufferReady += new EventHandler<EventArgs>(mic_BufferReady);
    mic.BufferDuration = TimeSpan.FromMilliseconds(1000);
    buffer = new byte[mic.GetSampleSizeInBytes(mic.BufferDuration)];            
 }
   
 void mic_BufferReady(object sender, EventArgs e)
 {
    mic.GetData(buffer);
    if (isRecording)
    {
      micStream.Write(buffer, 0, buffer.Length);
    }
 }

Now we can start recording by calling the mic.Start() method, and stop recording with mic.Stop().

We can play it back:

 SoundEffect recSE = new SoundEffect(micStream.ToArray(), mic.SampleRate, AudioChannels.Mono);
 recSE.Play();

Or save it to the application’s isolated storage:

 using (var isf = IsolatedStorageFile.GetUserStoreForApplication())
 {
    using (var isfstream = new IsolatedStorageFileStream("record.pcm", FileMode.Create, isf))
    {
      isfstream.Write(micStream.ToArray(), 0, (int)micStream.Length);
    }
 }

Media

The Microsoft.Xna.Framework.Media namespace provides access to the Media Library. With the MediaLibrary class we can play back songs and load pictures from the user’s collection on the device. Saving pictures to the MediaLibrary is also allowed, but this is not true for songs. Another limitation is that we can’t get access to DRM protected music.

To load a picture from the media library, we must select the device’s library source. In the following code snippet I’m loading the first picture of the user’s library:

 foreach (var source in MediaSource.GetAvailableMediaSources())
 {
     if (source.MediaSourceType == MediaSourceType.LocalDevice)
     {
       ml = new MediaLibrary(source);
       if (ml.Pictures.Count > 0)
       {
         var bitmap = new BitmapImage();      
         bitmap.SetSource(ml.Pictures[0].GetImage());
         img.Source = bitmap;
       }
       break;
     }
 }

And we can write to the library using the MediaLibrary.SavePicture method:

 ml.SavePicture("TestPic", TitleContainer.OpenStream("Chrysanthemum.jpg"));

Regarding the emulator’s Songs library,  it is empty, unlike the Pictures, which contains some sample images. To make things worse, even on the unlocked emulator I couldn’t find any way to upload some mp3s to the emulator’s library.

Still, the Song class is useful, we can load our files (or download, save to isolated storage and then load), and play them as background music. The Song class has also properties for artist, rating, playcount etc. They can be played using the MediaPlayer static class.

 Song song = Song.FromUri("I Will Not Bow", new Uri("02.I Will Not Bow.mp3", UriKind.Relative));
 if (MediaPlayer.GameHasControl)
 {
   MediaPlayer.Play(song);
 }

In XNA for Windows or Xbox, MediaPlayer can provide visualization data, so you can display audio visualization easily (sound waves, bars etc) via the MediaPlayer.GetVisualizationData method. In Windows Phone 7 it is not available (it won’t throw an exception if we call it, but will only return a bunch of zeros), so you will have to find your own way to give graphical feedback.

MathHelper, Vectors

XNA contains a lot of classes required by game developing including a Vector class with 2,3 or 4 components, Rectangle class with intersect checking and a MathHelper static class. This gives somewhat an out-of-the-box solution for checking collisions, playground etc.

GameServices

The GameServices assembly gives you access to Xbox Live parts, but i’m not sure if it’s usable in a Silverlight based game. Even if you are developing an XNA game, you will need to be a registered Xbox Live developer to gain access to the GameServices.AchievementCollection for example.

Summary

Well, I think I covered the most promising scenarios, but I’m also sure, that a lot of new ideas will come about. On the audio level the integration is good, and apart from a few missing things, it’s definitely usable. The absence of the Game and Graphics assemblies really hurts, with them the Silverlight-XNA integration would reach a whole new level. We don’t have to go too far to imagine an XNA game with Silverlight menus, scoreboard, etc. or a Silverlight application with 3D models loaded with XNA. I hope in the next versions of Windows Phone 7 this level will be reached, and until then we can use the non-graphical components in our Silverlight applications.


Subscribe

Comments

  • -_-

    RE: Exploring Silverlight-XNA integration on Windows Phone 7


    posted by Darick on Oct 16, 2010 00:42

    I'm trying to play an audio file from isolatedstorage, but I'm getting an error when trying to set the uri.  Can you give a better example of playing an audio file from isolatedstorage?

    thanks,

    Darick

  • wildfox

    RE: Exploring Silverlight-XNA integration on Windows Phone 7


    posted by wildfox on Oct 16, 2010 13:35

    hi,

    are you using the IsolatedStorage (eg. download the sound on runtime and saving to IsolatedStorage) or just adding to the project as content? If the latter, make sure it's build action is set to "Content" (in the Properties window)

  • -_-

    RE: Exploring Silverlight-XNA integration on Windows Phone 7


    posted by Darick on Oct 17, 2010 05:32
    IsolatedStorage.
  • wildfox

    RE: Exploring Silverlight-XNA integration on Windows Phone 7


    posted by wildfox on Oct 17, 2010 17:28

    after you saved it:

     using (var isf = IsolatedStorageFile.GetUserStoreForApplication())
                    {
                        using (var isfstream = new IsolatedStorageFileStream("effect.wav", FileMode.Create, isf))
                        {
                            isfstream.Write(soundByteArray, 0, (int)soundByteArray.Length);
                        }
                    }

    you can play it like this:

    using (var isf = IsolatedStorageFile.GetUserStoreForApplication())
                    {
                        using (var file = isf.OpenFile("effect.wav", FileMode.Open))
                        {
                            byte[] buffer = new byte[file.Length];
                            file.Read(buffer, 0, (int)file.Length);
                            effectSE = new SoundEffect(buffer, sampleRate, AudioChannels.Mono);
                        }
                    }

                    effectSE .Play();

  • -_-

    RE: Exploring Silverlight-XNA integration on Windows Phone 7


    posted by John on Oct 20, 2010 05:22
    Thanks for posting this - really helped me out.  FYI, having the line numbers in your code samples make it a pain in the ass to copy your code.
  • wildfox

    RE: Exploring Silverlight-XNA integration on Windows Phone 7


    posted by wildfox on Oct 20, 2010 10:06

    Thanks, you're right, something is wrong with the snippet boxes, the copy icon is not appearing. I'll try to fix it.

  • -_-

    RE: Exploring Silverlight-XNA integration on Windows Phone 7


    posted by tsjDEV on Oct 30, 2010 08:43

    Hello,

    thanks for your post. I want to play a simple sound after pressing a button in Silverlight with the XNA-Framework. I realize this with your code snippet, but it don't work. The program told me, that there was no definition for ApplicationLifetimeObjects. Where have I put that? I've put it in the constructor of my MainPage, was this wrong?

    Thanks.

  • wildfox

    RE: Exploring Silverlight-XNA integration on Windows Phone 7


    posted by wildfox on Oct 30, 2010 11:50

    Hi,

     you have to put this in the App's constructructor (in App.xaml.cs)

    public App()
            {

    ..

    this.ApplicationLifetimeObjects.Add(new XNAAsyncDispatcher(TimeSpan.FromTicks(333333)));

    ..

    };

    and this is the ApplicationLifeTimeObjects (but i think you have that figured out):

    http://msdn.microsoft.com/en-us/library/system.windows.application.applicationlifetimeobjects%28VS.95%29.aspx

  • -_-

    RE: Exploring Silverlight-XNA integration on Windows Phone 7


    posted by tsjDEV on Oct 30, 2010 15:08

    Thanks a lot!

    Now everything is working fine.

  • -_-

    FrameworkDispatcher


    posted by Siavash Mortazavi on Oct 30, 2010 23:16

    Thanks for your really useful article,

    I had some problems with updating that "FrameworkDispatcher", and you solved it ;)

  • wildfox

    RE: Exploring Silverlight-XNA integration on Windows Phone 7


    posted by wildfox on Oct 31, 2010 10:36
    glad to help, thanks :)
  • -_-

    RE: Exploring Silverlight-XNA integration on Windows Phone 7


    posted by dev on Nov 18, 2010 23:24

    When I add the XNAAsyncDispatcher to my application I get this exception on exit:

    A first chance exception of type 'System.Threading.ThreadAbortException' occurred in Microsoft.Xna.Framework.dll 

    Do you know why this is happening?

    Thanks

  • wildfox

    RE: Exploring Silverlight-XNA integration on Windows Phone 7


    posted by wildfox on Nov 20, 2010 13:55
    I couldn't reproduce it, but you can still stop it in the Application_Closing and Application_Deactivated (App.xaml.cs) methods by stopping its DispatchTimer.
  • -_-

    RE: Exploring Silverlight-XNA integration on Windows Phone 7


    posted by windblow on Nov 24, 2010 08:01

    Hi, I have a question regarding integrating the XNA's MediaLibrary

      I am trying to use MediaLibrary to load all the songs and then play the songs using MediaPlayer.play(song). However, I find that it only works when the emulator is started by Visual Studio debug mode. Otherwise, the MediaLibrary cannot find any song in the mediaLibrary(including on the real phone). A workaround is if I enter Gamehub first, then run my application, it will load all the songs from the MediaLibrary with no problem. I know this might be a bug in WP7. But do you have any idea what does the "entering gamehub" do so that the songs in the MediaLibrary is accessible again?

    Thanks!

  • -_-

    RE: Exploring Silverlight-XNA integration on Windows Phone 7


    posted by DriftBottles on Nov 24, 2010 08:43
    I have the same question with windblow. It will be great that you have insight on this.  Thanks!
  • wildfox

    RE: Exploring Silverlight-XNA integration on Windows Phone 7


    posted by wildfox on Nov 26, 2010 10:47
    I'm kinda clueless here, it seems like a bug. On the emulator I can't load songs from the MediaLibrary (it's empty), and I don't have a device yet. What method are you using? Did you try this one maybe? http://msdn.microsoft.com/en-us/wp7trainingcourse_2dgamedevelopmentwithxnapart2lab_topic2.aspx
  • -_-

    RE: Exploring Silverlight-XNA integration on Windows Phone 7


    posted by Wellwisher on Apr 05, 2011 10:24
    Dont download this.. This is not working in VS2010 and it affects my C drive and slow down my system performance...  Be careful..

Add Comment

Login to comment:
  *      *