Mar 30 2011

Voice Memo source for WP7

Category: MobileJoel Ivory Johnson @ 18:00

This question keeps coming up in the forums so I decided to put the application together and make it publically available. If you head over to CodeProject you'll find a small article that I uploaded on making a voice memo application on Windows Phone 7. Among other things is demonstrates how to convert the raw recording bytes to a proper wave file, simple serialization, and a few other tid bits. For the sake of the article I did send the code through certification. 

However the application looks ugly right now. I've got a graphic artist that I'll be paying to design the UI for me and since I'm paying her for this I've decided not to include the graphic assets that she is producing in the code that I'm gicing away for free. 

There's no obligations attached to the code. But if you use it in your own products I would appreciate a heads up just so that I know where it's being used. 

Share photos on twitter with Twitpic

Tags: , ,

Mar 7 2011

Serializing the Unserializable

Category: MobileJoel Ivory Johnson @ 13:33

I came across a post in the Windows Phone developer forums that got me thinking for a moment. The poster had asked how to serialize a class that was not serializable. The class of interest was the StrokeCollection class. The solution for this problem has actually been around for a while but under different terms. If you pick up a design patterns book and look up Data Transfer Object (DTO) you'll see what I'm talking about. For the sake of those that don't have a design patterns book handy I'll describe the concept.

A DTO exists for the sake of storing data in an object that is suitable for crossing boundaries. More times than not when I see some one talking about a DTO it is for an object that is going from an application to a database. But it's not restricted to that scenario. For the sake of answering the question for the poster I can assume that he or she wanted to transfer the data to a file. The representation of the data in a file is also a form that is suitable for transfer over a wire.

To accomplish the task I made a few classes that have some (but not all) of the same properties as the classes I needed to serialize. I didn't need to replicate all of the properties because I'm not interested in saving all of the data that the class provides. As far as functionality goes the only thing that I've put on these classes is functions for converting from the DTO to the original class and vice versa. The StrokeCollection class uses a number of other classes to represent it's data. StrokeCollection caontains instances of Stroke, which contains instances of StylusPointCollection, and that contains instances of StylusPoint. I created a similar hierarchy with the members of that hierarchy marked as serializable (with the [DataContract] attribute). For saving and loading the data I've made use of the serialization code from a previous post.

    [DataContract]
    public class StrokeDto
    {

        public StrokeDto()
        {
        }

        public StrokeDto(Stroke source)
        {
            this.StylusPointDtos = new StylusPointDtoCollection(source.StylusPoints);
        }

        public Stroke ToStroke()
        {
            Stroke retVal = new Stroke();
            if(this.StylusPointDtos!=null)
                StylusPointDtos.ForEach((o)=>retVal.StylusPoints.Add(o.ToStylusPoint()));
            return retVal;
        }

        [DataMember]
        public StylusPointDtoCollection StylusPointDtos { get; set; }
    }

    public class StrokeDtoCollection: List
    {
        public StrokeDtoCollection()
        {
        }

        public StrokeDtoCollection(StrokeCollection source):this()
        {
            foreach(Stroke s in source)
            {
                this.Add(new StrokeDto(s));
            }
        }

        public StrokeCollection ToStrokeCollection()
        {
            StrokeCollection retVal = new StrokeCollection();
            this.ForEach((o)=>retVal.Add(o.ToStroke()));
            return retVal;
        }
    }

    [DataContract]
    public class StylusPointDto
    {

        [DataMember]
        public double X { get; set;  }

        [DataMember]
        public double Y { get; set;  }

        [DataMember]
        public float PressureFactor { get; set;  }

        public StylusPointDto()
        {}

        public StylusPointDto(StylusPoint source)
        {
            this.X = source.X;
            this.Y = source.Y;
            this.PressureFactor = source.PressureFactor;
        }

        public StylusPoint ToStylusPoint()
        {
            return new StylusPoint(this.X, this.Y) {PressureFactor = this.PressureFactor};
        }
    }
    public class StylusPointDtoCollection : List
    {

        public StylusPointDtoCollection(): base()
        {}

        public StylusPointDtoCollection(StylusPointCollection source): this()
        {
            var sourceList = (from point in source select new StylusPointDto(point)).ToArray();
            this.AddRange(sourceList);
        }

        public StylusPointCollection ToStylusPointCollection()
        {
            var retVal = new StylusPointCollection();
            this.ForEach((o) => retVal.Add(o.ToStylusPoint()));
            return retVal;
        }
    }

With my class hierarchy and the serialization code I was able to load and save the stokes in a few lines of code. 

 

//Save the Strokes
var valuesaveDto = new StrokeDtoCollection(myInkPresenter.Strokes);
_myInkSaver.SaveMyData(valuesaveDto,"MyInk.ink");


//Load the Strokes
var valueDto = _myInkSaver.LoadMyData("MyInk.ink");
myInkPresenter.Strokes = valueDto.ToStrokeCollection();


Screen Shot of Drawing Program

I've put together an example program (see link at top of article) that uses the code. Word of warning, I've not implemented any tombstoning code in it. But draw what eer you like and then click on the Save button. After you exit from the program when you go back into it you'll see your picture reload.

 

Tags: ,

Nov 15 2010

Writing a Proper Wave File

Category: MobileJoel Ivory Johnson @ 07:22

Currently one of the reoccuring questions I see in the Windows Phone 7 forums deals with playing back data that was recorded from the Microphone. Often time developers will write the sound bytes that they receive from a microphone to a file and then try to export them for playback or play them back using the media classes on the phone only to find that the file can't be processed. During my lunch break today I had a chance to throw something together that I think will point those developers in the right direction.

Why Won't the File Play

The file won't play because none of the components or software to which it has has been given know anything about the file. If you record from the Microphone and dump the raw bytes to a file the things you are not writing include the sample rate, number of bits per sample, the file format, and so on. You need to prepend the file with all of these things for it to be usable by the media classes. Having done a quick Bing search I found a description of the needed header on https://ccrma.stanford.edu/courses/422/projects/WaveFormat/. Using that I put together a quick desktop application that produces a playable wave file. I targeted the desktop because the computer I'm using doesn't have the phone developer tools. But the code will pretty much be the same for the desktop as on the phone. The only difference will be in the creation of your file. While I am creating a file stream directly you would create a stream in isolated storage.

Simulating Audio Data

I need some data to write to my file. As is my preference I've created a function that will populate an array of bytes with the output of the Sine function. As it's parameters it takes the sample rate, the length of time that I want the sound to play, the wave's frequency, and it's magnitude (with 0 being the lowest magnitude and 1 being the greatest) and returns the data in a byte array. You would populate your array with the bytes from the recording instead. The code I used to do this follows.

public static byte[] CreateSinWave( 
        int sampleRate, 
        double frequency, 
        TimeSpan length, 
        double magnitude
    )
{
    int sampleCount = (int)(((double)sampleRate) * length.TotalSeconds);
    short[] tempBuffer = new short[sampleCount];
    byte[] retVal = new byte[sampleCount*2];
    double step = Math.PI*2.0d/frequency;
    double current = 0;
            
    for(int i=0;i<tempBuffer.Length;++i)
    {
        tempBuffer[i] = (short)(Math.Sin(current) * magnitude * ((double)short.MaxValue));
        current += step;
    }

    Buffer.BlockCopy(tempBuffer,0,retVal,0,retVal.Length);
    return retVal;
}

Populating the Wave Header

There are better ways to do this, much better ways. But I'm just trying to create something satisficing in a short period of time.

Trival Fact: Satisficing is a phrase coined by Herbert Simon to mean sufficiently satisfying. A satisficing solution may not be the best solution, but it get's the job done!

.

Looking on the chart that describes a wave header I wrote either literal bytes or calculated values, where the calculated values are based on sample rate, number of channels, and a few other factors. There's not a lot to say about it, but the code follows.

static byte[] RIFF_HEADER = new byte[] { 0x52, 0x49, 0x46, 0x46 };
static byte[] FORMAT_WAVE = new byte[] { 0x57, 0x41, 0x56, 0x45 };
static byte[] FORMAT_TAG  = new byte[] { 0x66, 0x6d, 0x74, 0x20 };
static byte[] AUDIO_FORMAT = new byte[] {0x01, 0x00};
static byte[] SUBCHUNK_ID  = new byte[] { 0x64, 0x61, 0x74, 0x61 };
private const int BYTES_PER_SAMPLE = 2;

public static void WriteHeader(
     System.IO.Stream targetStream, 
     int byteStreamSize, 
     int channelCount, 
     int sampleRate)
{

    int byteRate = sampleRate*channelCount*BYTES_PER_SAMPLE;
    int blockAlign = channelCount*BYTES_PER_SAMPLE;

    targetStream.Write(RIFF_HEADER,0,RIFF_HEADER.Length);
    targetStream.Write(PackageInt(byteStreamSize+44-8, 4), 0, 4);

    targetStream.Write(FORMAT_WAVE, 0, FORMAT_WAVE.Length);
    targetStream.Write(FORMAT_TAG, 0, FORMAT_TAG.Length);
    targetStream.Write(PackageInt(16,4), 0, 4);//Subchunk1Size    

    targetStream.Write(AUDIO_FORMAT, 0, AUDIO_FORMAT.Length);//AudioFormat   
    targetStream.Write(PackageInt(channelCount, 2), 0, 2);
    targetStream.Write(PackageInt(sampleRate, 4), 0, 4);
    targetStream.Write(PackageInt(byteRate, 4), 0, 4);
    targetStream.Write(PackageInt(blockAlign, 2), 0, 2);
    targetStream.Write(PackageInt(BYTES_PER_SAMPLE*8), 0, 2);
    //targetStream.Write(PackageInt(0,2), 0, 2);//Extra param size
    targetStream.Write(SUBCHUNK_ID, 0, SUBCHUNK_ID.Length);
    targetStream.Write(PackageInt(byteStreamSize, 4), 0, 4);
}

static byte[] PackageInt(int source, int length=2)
{
    if((length!=2)&&(length!=4))
        throw new ArgumentException("length must be either 2 or 4", "length");
    var retVal = new byte[length];
    retVal[0] = (byte)(source & 0xFF);
    retVal[1] = (byte)((source >> 8) & 0xFF);
    if (length == 4)
    {
        retVal[2] = (byte) ((source >> 0x10) & 0xFF);
        retVal[3] = (byte) ((source >> 0x18) & 0xFF);
    }
    return retVal;
}

That's pretty much all you need to know. To use the code I wrote a simple console mode program.

static void Main(string[] args)
{
    var soundData = WaveHeaderWriter.CreateSinWave(44000, 120, TimeSpan.FromSeconds(60), 1d);
    using(FileStream fs = new FileStream("MySound2.wav", FileMode.Create))
    {
        WaveHeaderWriter.WriteHeader(fs, soundData.Length, 1, 44100);
        fs.Write(soundData,0,soundData.Length);
        fs.Close();
    }
}

I opened the resulting output in Audacity and the results are what I expected.

And of course as a final test I double clicked on the file. It opened in Windows Media Player and played the Sine wave.

So there you have it, the program works! When I get a chance I will try to make a version of this in Windows Phone 7. Those of you that have WPDT without the full version of Visual Studio will not be able to compile this program directly. But the binary is included in the source code if you want to run it.

Tags: ,

Oct 5 2010

Using DynameicSoundEffectInstance

Category: MobileJoel Ivory Johnson @ 16:22

Download the Code (93.1 KB)

After an Atlanta Silverlight Users meeting I was eating with a couple of other MVPs and we were talking about the things we were doing and would like to do with Windows Phone 7. I had mentioned I would like to have direct access to the sound buffer used in XNA. James Ashley immediatly responded with "DynamicSoundEffectInstance!" At the time James had never used it, and I had just discovered it, so I needed to get some more information on how it works. So that night a stayed up a little later than usual so that I could figure out how it works. With the documentation for the method still being in early form I didn't quite find everything that I wanted to know but was able to figure it out.

In writing this I'm going to assume that you know a bit about the mechanics about sound and speakers work. If not you'll want to read the Wikipedia article on Digital to Analog converters.

In this article I simply want to get to the point of being able to play a tone and control it's frequency. From a high level view this is what we will need to do:

 

  1. Create a few byte buffers that will hold the next part of the sound to be played
  2. Populate one of the byte buffers with the wave form to be played
  3. Give the buffer to a DynamicSoundEffectInstance
  4. Tell the SoundEffectInstance to start playing
  5. In response to the BufferNeeded event populate the next buffer and submit it
  6. Goto step 5
Now to convert those steps into something more concrete. Let's start with allocating the buffers. 

Creating the Buffer

The size of the buffer you choose is largely going to be driven by what type of latency you want your sounds to have and the desired quality of the sound you are generating. In general low latency is good. With low latency as there is less of a time difference from when your program generates a sound to when the user hears it. If you made a program to simulate a piano you would want low latency so that the user perceives that the device is playing sound as soon as they press a key on the screen. Naturally you will also want high quality.  But there are trade-offs as you aim for higher quality and lower latency just as there are trade-offs in aiming for low quality and high latency. 

To produce higher quality sounds you will need a higher sample rate. If you raise the sample rate used to play back a sound then you will either need to increase the size of your buffer (so more memory is being consumed) or you will need to populate and supply smaller buffers more frequently (so more CPU time is being consumed). While lower quality uses less memory and less CPU time the negative part is evident; your program won't sound as good. If you were aiming for lower latency you will need to use smaller buffers but that will also mean that the DynamicSoundEffectInstance is requesting new buffers more often (once again more CPU time). My suggestion for the quality of a sound is to aim for something that is good enough. Don't start off at the 48KHz sample rate. Start instead at around 22KHz or lower and see how well that works for your. As for latency with an XNA program aim for a latency that determined by the FPS of your game. If your game is made to run at 30 frames per second then make buffers that are big enough to play 1/30 seconds of sound. A sound can also be in stereo or mono. It goes without saying that twice the memory is needed to generate a sound in stereo than mono.

Let's for now assume that we are creating a DynamicSoundEffectInstance with a sample rate of 22KHz in mono. We could instantiate one with the following:


 

var dynamicSoundEffectInstance = new DynamicSoundEffectInstance(22000,AudioChannels.Mono);

We can calculate the size of the buffers in one of two ways. The DynamicSoundEffectInstance always play 16-bit sound samples (2 bytes). If I wanted to be able to play 1/30th seconds of sound at a 22KHz sample rate the number of bytes needed for this buffer would be 22000*(1/30)*2*1 = 1466. The last two numbers in the equation (2*1) are the number of bytes in a sample multiplied by the number of channels to be played. Were I playing a stereo sample the second number would have been 2 instead of 1. I could have instead asked the DynamicSoundEffectInstance to calculate the size of the needed buffer.

22000*(1d/30d)*dynamicSoundEffectInstance.GetSampleSizeInBytes(TimeSpan.FromSeconds(1d/30d))

Populate the Buffer

The data that you put into buffer is derived from the sound that you are playing. If you've been astutely reading you may have noticed that I've stated that DynamicSoundEffectInstance consumes an array of bytes (8-bits) but the audio must be composed of 16-bit samples. In C++ one might just pass an array to what ever held the data. It would let you do that, even if doing that made no sense. In the C# language one can also do that by wrapping their code in an unsafe block. But many feel that code wrapped in unsafe blocks is potentially not safe (I wonder why). Silverlight won't let you do such th ings. So it's necessary to convert your 16-bit data to byte data using other means. There's a method available for doing so but I'll also describe how to do so manually.

A 16-bit (two byte) number has a high order byte and a low order byte. High and Low order could also be taken to be more significant and less significant. In the decimal number 39 the three is in a more significant position than the nine; it has more of an impact on the final value. The same concept transfers to numbers composed of bytes. Our bytes need to have little endian ordering. The low order byte will need to be placed in our array before the high order byte. The low order byte can be singled out with a bit mask. The high order byte with bit shifting.

byte lowOrder = (byte)(SomeNumber & 0xFF);
byte highOrder = (byte)(SomeNumber >> 0x08); 

Now that you know what needs to be done, here's the utility method that will essentially do the same thing.

Buffer.BlockCopy(
                   sourceBuffer
                 , sourceStartIndex
                 , destinationBuffer
                 , destinationStartIndex
                 , ByteCount)

The sourceBuffer element in this case would be the array of 16-bit integers. The destinationBuffer would be the destination byte buffer. Two things to note. First, the destination buffer must have twice the number of elements as the source buffer (since bytes are half the size of short integers). Second, the last argument is the number of bytes to be copied and not the number of elements. If you get this wrong you'll either get an IndexOutOfRange exception or something that sounds pretty bad.

Start Playing the Sound

Once the DynamicSoundEffectInstance has a buffer I call Play to get things rolling.

Submitting the Buffers to the DynamicSoundEffectInstance

The DynamicSoundEffectInstance has an event called BufferNeeded that will be called when the object is ready for more sound data to be played. If you are making an XNA program you may want to avoid the object getting to the point where it needs to call this. You can reduce overhead by feeding the class data at the same rate at which it is consuming it. This can be easily done by making the buffers big enough to play as much sound as can be played in one cycle of your game loop. If you are making a Silverlight application you'll be making use of this event.From what I've found the DynamicSoundEffectInstance class will hold up to two buffers; playing from one, and has the other in place to be played next. So I prefer to make three buffers so that I have a third buffer into which I can render the next block of sound. When the BufferNeeded event is called it populate and pass the buffer through the SubmitBuffer method. I use the same buffers in a round robin fashion.

FrameworkDispatcher.Update()

This is only needed if you are using the class from within Silverlight. FrameworkDispatcher.Update will need to be called at least once before playing your sound and must continue to be called periodically. The Windows Phone documentation already walks one through a class that will do this. Take a look at this article to see how this class works.

My Sound Function and Controlling the Frequency

While the sound data passed to DynamicSoundEffectInstance must be signed 16-bit integers I wanted to keep my sound generating functions decoupled from this constraint and also decouple from the specific frequency that was being played. I ach ieved these goals in a class I've created named SoundManager. While SoundManager contains the code to generate a sin wave the actual sound function used is assigned to the property SoundFunction. One only needs to assign a different function to this property to generate a different sound.

To decouple from the function from the data format I've created my program so that it expects the sound function to return it's data as a double. The value range returned by the sound function should be in the range of [-1..1]. I'm not doing range checking to avoid the overhead (so if you use my code it's up to you to make sure your code behaves). The function consumes two parameters: a double value to represent time and an integer value to represent channel. Channel would presumably be 0 for the left channel and 1 for the right channel. For generating mono sound this parameter can be ignored. The time parameter indicate which part of the cycle of a sound wave is being requested. The values returned by the sound function from the 0 to 1 would be for one cycle of the sound. From 1 to 2 would be for the second value of the sound, and so on. since the time parameter is being used to represent the position within a cycle instead of actual time the sound function is insulated from the actual frequency being generated. I can change the frequency of the sound being played by increasing or decreasing the intervals between the time values passed. Shorter intervals will lead to lower frequencies. Larger intervals will lead to higher frequencies. Note that the highest frequency that you can create is going to be no higher than half the sample rate. So with a 22 KHz sample rate you would only be able to generate sounds with frequency components as high as 11 KHz. Given that most sounds we hear are a complex mixture of sound components  keep in mind that there may be some frequency components higher than what may be recognized as the dominant frequency. So playing such sounds at a high frequency could result in some of the higher frequency components being stripped out. You can find more information on this concept under the topic Nyquist Rate

 The method FillBuffer will call this function for each sample that it needs to fill the next buffer.

double MySin(double time, int channel) { return Math.Sin(time*Math.PI*2.0d); }

The code for filling the sound buffer is as follows

        void FillBuffer()
        {
            if (SoundFunction == null)
                throw new NullReferenceException("SoundFunction");
            byte[] destinationBuffer = _audioBufferList[CurrentFillBufferIndex];
            if (++CurrentFillBufferIndex >= _audioBufferList.Length)
                CurrentFillBufferIndex = 0;
            short result;
            int currentBufferIndex = 0;
            int deltaBufferIndex = ChannelCount * BytesPerSample;

            for (int i = 0; i < destinationBuffer.Length / (ChannelCount * BytesPerSample); ++i)
            {
                int baseIndex = ChannelCount * BytesPerSample * i;
                //currentBufferIndex = 0;
                for (int c = 0; c < ChannelCount; ++c)
                {
                    result = (short)(MaxWaveMagnitude * SoundFunction(_Time, c));

                    #if(MANUAL_COPY)
                    destinationBuffer[baseIndex + currentBufferIndex] = (byte)(0xFF & result);
                    destinationBuffer[baseIndex + currentBufferIndex] = (byte)(0xFF & (result >> 0x8));
                    currentBufferIndex += deltaBufferIndex;
                    #else
                    _renderingBuffer[i * ChannelCount + c] = result;
                    #endif                    
                    
                }
                _Time += _deltaTime;
            }
            #if(!MANUAL_COPY)
            Buffer.BlockCopy(_renderingBuffer, 0, destinationBuffer, 0, _renderingBuffer.Length*sizeof(short));
            #endif
            OnPropertyChanged("Time");
            OnPropertyChanged("PendingBufferCount");
        }

If you deploy the code attached to this entry you'll have a program that can play a Sin wave. Pretty boring, I know. But I wanted to keep the sound that I was playing in this first mention of DynamicSoundEffectInstance simple. The next time I mention it I want to talk about generating more complex sounds and will probably say little about using the class itself outside of referencing this entry. 

Tags: , ,

Sep 22 2010

What Happened to the WP7 Icon Pack?

Category: MobileJoel Ivory Johnson @ 09:19
In case you were looking for the Windows Phone 7 Icon Pack and noticed all the links to it on the Microsoft Download site are dead, don't worry, getting the icons is easier than you might think. The Icon Pack is now part of Expressions Blend for Windows Phone. When you are working with the application bar and add items you can change the icon used using a drop down in Expressions Blend for Windows Phone. When you select an icon it is automatically added to your project. If you want to get to the icons to work with them yourself you can find them on your drive in C:\Program Files\Microsoft SDKs\Windows phone\v7.0\Icons.

Tags: ,

Sep 19 2010

Getting to System Information on Windows Phone 7

Category: MobileJoel Ivory Johnson @ 02:12

There's a requirement that Windows Phone 7 applications not use more than 90 MB of memory to run. One might wonder how to know how much memory that their program is consuming. You can find that information through the DeviceExtendedProperties class. Given the myrid of programs on Windows Mobile and Android devices that display the technical details of a device I know it is tempting to surface some of this information up to a user. But Microsofts guidance on using it is that the information shouldn't be surfaced. Nor should you try to parse or process this information on the device. Rather the information exposed through this API should be for diagnostic purposes. Note that using this API in your programs will cause the program to need the DeviceInformation permission.

The DeviceExtendedProperties class has two methods that are of interest. object GetString(string) and bool TryGetString(String, out object). For both methods the string argument is the name of the property to be retrieved. The first method will return the value of a property of throw an exception of that property cannot be read. The second method will return true and copy the value of a property to the out variable if the property can be read, otherwise it returns false.

Some of the properties may not have values or may be blank. Here are some of the properties that can be retrieved

PropertyDescription
DeviceManufacturer The name of the manufacturer for the device. This could be blank.
DeviceName The name of the device. This could be blank
DeviceUniqueId The unique hash for the device. This is immutable across firmware updates. It should not be used to identify the user since a device could change ownership.
DeviceTotalMemory The total amount of memory in the device. This value will actually be less than the actual amount of physical memory by some amount
ApplicationCurrentMemoryUsage The amount of memory that the application is presently using
ApplicationPeakMemoryUsage The maximum amount of memory that the program has use

To demonstrate the use of this class there's a link to download sample code at the top of this article. The code retrieves the values for a few of these properties and displays them.

        public void UpdateProperties()
        {
            object temp = null;
            ;
            DeviceManufacturer = (DeviceExtendedProperties.TryGetValue("DeviceManufacturer", out temp))
                                     ? (temp as string)
                                     : String.Empty;
            DeviceName = (DeviceExtendedProperties.TryGetValue("DeviceName", out temp) 
                                    ? (temp as string) : string.Empty);
            DeviceUniqueID = (DeviceExtendedProperties.TryGetValue("DeviceUniqueID", out temp)
                                    ? (temp as byte[])
                                    : new byte[0]);
            DeviceFirmwareVersion = (DeviceExtendedProperties.TryGetValue("DeviceFirmwareVersion", out temp)
                                    ? (temp as string)
                                    : String.Empty);
            DeviceHardwareVersion = (DeviceExtendedProperties.TryGetValue("DeviceHardwareVersion", out temp)
                                    ? (temp as string)
                                    : String.Empty);
            DeviceTotalMemory = (long)DeviceExtendedProperties.GetValue("DeviceTotalMemory");
            ApplicationCurrentMemoryUsage = (long) DeviceExtendedProperties.GetValue("ApplicationCurrentMemoryUsage");
            ApplicationPeakMemoryUsage = (long) DeviceExtendedProperties.GetValue("ApplicationPeakMemoryUsage");
        }

Screenshot of Running Program

Tags: ,

Sep 16 2010

What's New in the Windows Phone 7 RTM SDK?

Category: Joel Ivory Johnson @ 08:35

The Windows Phone 7 SDK was released earlier today. There are a few things that have changed from the Beta to the RTM, a few of which caught my attention. If you want to see the change list you cah find it here.

  • There's a limit of 10 side-loaded applications that can be on a retail device
  • Changes have been made to the picture sharing API
  • Character support encoding has been limited to 4 encodings (utf-9, utf-16, utf-16LE, utf-16BE, ISO-8859-1)
  • XNA Framework strong name has changed
  • Manifest Validation is now turned on

The first item was of interest to me. I've got well over 10 side-loaded applications on my device (some of which or trivial "Hello World" type applications).

Tags: ,

Sep 9 2010

Is my Program running in the Emulator or on a Real Device

Category: Joel Ivory Johnson @ 08:10

There are times in which you would want to know whether or not your program is running in the Windows Phone emulator or on a real device. It's easy to determine on which your application is running with a single line of code. 

 

bool IsInEmulator = Microsoft.Devices.Environment.DeviceType == DeviceType.Emulator;

Tags: ,

Sep 7 2010

Introduction to Windows Phone Programming: Part 2

Category: Joel Ivory Johnson @ 07:10

Introduction to Windows Phone Programming: Part 2

This is part 2 of a multi-part article. For Part 1 see this.

I'm writing a rather lengthy piece on Windows Phone programming and rather than wait for the entire piece to be completed I've decided to start making the sections available in draft form. My intent is to cover XNA (2D and 3D) and Silverlight concepts. I'm planning to put the finished article on CodeProject.com along with the code samples before starting on another piece in which I document the making of an XNA 3D game. If you see anything in this draft that needs to be correct, further detailed, or improved feel free to let me know.

Adding Sound

The sounds that you would need to play in your game in general could be classified as background sounds (such as background music) or incidental sounds (such as sound affects from some event happening). Let's start of making a program that will play a sound using the simplest way available. Create a new XNA Windows Phone Game project. After the project is created right-click on the Content project and select "Add Existing." Navigate to a small PCM *.wav  file on your system and select it to be added to your project. If you don't have any PCM WAV files laying around I'd suggesd downloading a free audio editor such as Audacity and use it to convert a section of a music file to a sound. Once the file is added to your content project rename it to "MySound.wav". You can rename it by right-clicking on the file and selecting the "rename" option. Within the Update() method we are going to add code so that when the user presses and releases any area of the screen the sound will play. Create a new boolean field for the class called _screenPressed and a new field of type SoundEffect named mySoundEffect. Within the LoadContent() method populate mySoundEffect using Content.Load<SoundEffect>("MySound.wav");. Now if you run the program it will play your sound every time you touch the screen.

protected override void Update(GameTime gameTime)
{

    var touchState = TouchPanel.GetState();
    bool touchDetected = touchState.Count > 0;
    if ((!_screenPressed) && (touchDetected))
    {
        mySoundEffect.Play();
    }
    _screenPressed = touchDetected;

    base.Update(gameTime);
}

If you want to be able to do other things with the sound you will need to use the SoundEffectInstance class. A new SoundEffectInstance can be instantiated with a call to the CreateInstance() member of the SoundEffect class. Once you have a SoundEffectInstance you can do things such as pause the sound after begining play, changing the speed at which it plays, or loop the sound. Let's change the program so that it loops the sound as long as the screen is being touched. ADd a new SoundEffectInstance field named soundEffectLoop. In the LoadContent(); method right after mySoundEffect is populated use the CreateInstance() method to populate soundEffectLoop.

protected override void LoadContent()
{
    // Create a new SpriteBatch, which can be used to draw textures.
    spriteBatch = new SpriteBatch(GraphicsDevice);

    mySoundEffect = Content.Load<SoundEffect>("MySoundFile2");
    soundEffectLoop = mySoundEffect.CreateInstance();
}

protected override void Update(GameTime gameTime)
{
    // Allows the game to exit
    if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
        this.Exit();

    var touchState = TouchPanel.GetState();
    bool touchDetected = touchState.Count > 0;
    if ((!_screenPressed) && (touchDetected))
    {

       soundEffectLoop.Play();
    }
    else if ((_screenPressed)&&!(touchDetected))
    {
        soundEffectLoop.Stop();
    }
    _screenPressed = touchDetected;

    base.Update(gameTime);
}
        

Next Section

In the next section I will introduce XNA 3D rendering functionality

 

Tags: ,

Sep 7 2010

Introduction to Windows Phone Programming: Part 1

Category: MobileJoel Ivory Johnson @ 03:48

I'm writing a rather lengthy piece on Windows Phone programming and rather than wait for the entire piece to be completed I've decided to start making the sections available in draft form. My intent is to cover XNA (2D and 3D) and Silverlight concepts. I'm planning to put the finished article on CodeProject.com along with the code samples before starting on another piece in which I document the making of an XNA 3D game. If you see anything in this draft that needs to be correct, further detailed, or improved feel free to let me know.

Introduction

This article will get a .Net developer started with Windows Phone 7 development and introduce the basic application models and services available in WP7.

Prerequisites

My target audience for this article is a developer that is already comfortable with C# and uses a .Net development environment. To VB developers please note that at this time the VB language is not a supported language for creating Windows Phone 7 applications. C# is the only language that is available.

What you need at a Glance

If you were to create a new development environment today these are the things you would need.

  • Windows 7 Machine
  • DirectX 10 WDDM 1.1 Complian Video Card
  • Internet Connection

If you want to sell your applications or install or test them on real hardware you will also need the following:

  • Windows Marketplace for Mobile Registration (99 USD/year)
  • A Windows Phone 7 Device

Just an FYI, your ability to use the Windows Phone tools in an emulator will be rather limited.

Departure from Windows Mobile

One of the hardest things for new Windows Phone Developers to accept (Assuming that developer had experience with previous Windows Mobile operating systems) is that Windows Phone isn't Windows Mobile. While they are both operating systems that run on top of a CE kernel from an API perspective Windows Mobile and Windows Phone have very little in common. Windows Phone 7 has no compatibility with Windows Mobile applications.  Other than an optional restriction to only run signed code Windows Mobile doesn't actively restrict what an application can do.

Any applications that you had written for Windows Mobile would need to be rewritten to run on Windows Phone 7. If your code has proper separation of concerns then the amount of code you have to rewrite will be lower. But either way a different binary is needed.

If you have experience and expectations from developing for Windows Mobile now is the time to leave them behind. The APIs that you are familiar with from Windows Mobile are not present. Instead something entirely different is present. You also do not have access to teh entire system from within your code. Instead your code will run within a sandbox.   I don't want to get into all of the differences here. But understand that Windows Mobile and Windows Phone 7 have very few similarities.

Development Hardware and Software Requirement

To get started with Windows Phone 7 development you will need a computer running either Windows Vista SP 2 or later (any edition except starter edition will do) or a version of Windows 7. You'll need at least 2 gigabytes of RAM. If you plan on using the emulator (and chances are that you will unless you have a Windows Phone 7 device) the video display in your computer must support DirectX 10 and have a WDDM 1.1 complian driver. If your video display doesn't ahve adequate support then the emulator will fail to work properly on your machine.

Optionally the emulator will support a touch screen display for your desktop or laptop if you have one. Better yet if your computer has a multitouch capable display the emulator can take advantage of that too. Every now and then the question comes up on whether or not the emulator supports the multitouch tablets available from Wacom. These tablets translate your gestures into mouse messages such as a scroll message. They don't transmit the actual points at which the multi-touch interactions occur.

Phone Hardware Requirements

The hardware requirements for Windows Phone 7 are much higher than they were for Windows Mobile. Windows Mobile was designed to be able to run on a device with only a 200MHz processor, 32MB ram, and possibly no video accelerator or FPU. The standards for Windows Phone 7 are significantly higher. 

  • Capacitive 4 point Multitouch Screen
  • Accelerometer
  • GPS
  • 5-megapixel or better camera with flash
  • 256 MB RAM
  • 8 Gig Storage
  • DirectX 9 capable GPU
  • 1 GHz processor (Cortex/Scorpion)

These are the minimum hardware requirements. So a phone may exceed these requirements. Additionally all Windows Phones will have three buttons on the front of the device; a sart buttin, a back button, and a search button.

Windows Marketplace for Mobile Registration

If you want to deploy your programs to your own hardware or iyou want to distribute it you will need to be registered in the Marketplace. If you do not register you will still be able to create Windows Phone 7 programs. But these programs will only run within your emulator. (In other words all forms of deployment require Marketplace registration)

Once you are registered in the Marketplace you can register up to three devices as devices that you will use for development. At the time of this writing the exact procedure through which one goes to register a device isnot yet available to the general public (this area of the article will be updated when it is).

Device Registration tool.
Device Registration Tool.

Setup for your Development Environment

For Windows Phone 7 development you have the option of using either one of he full versions of Visual Studio 2010 or the Express version. If you plan on using one of the full versions install it first. After it is installed then proceed with installing the Windows Phone tools.

To install the Windows Phone Tools go to http://developer.windowsphone.com and selec the option to download the Windows Phone tools. The initial download is only three megs. This is just the installer bootstrap. It will examine your system to see what components are needed and then it will download and install those components.

Application Types Supported by Windows Phone 7

Windows Phone 7 supports two application types; Silverlight and XNA. Microsoft's Silverlight technology is available in some form or another on multiple operating system (Windows PC, Linux PC, Mac OS X, Symbian, Windows CE). The technology allows one to build user interfaces declaratively that scale to different resolutions, has built in support for smooth transitions and visual affects, media, and has strong support for web services. XNA is available on Windows Phone, Windows Desktop, and the Xbox 360. The XNA framework is designed with games in mind and has support for hardware accelerated 2-dimensional and 3-dimensional graphics, acces to the audio buffer, and has various resource management features built in.

The general guidance you'll here is that if you are making a game then make an XNA application. If you are making a business application then use Silverlight. But that is just general guidance and not a hard rule. One could make a game using Silverlight or making something fairly business oriented with XNA. You'll want to make your decision based on the type of interactions that you need to have with the user. The two application types have two entirely different ways of presenting a user interface to the user. If you use Silverlight then you get a palette of customizable controls including (but not limited to) the textbox, listbox, buttons, and so on. When designing your layout you can choose from concentrating just on control placement of existing controls, styling how those existing controls will look, and even creating your own controls. If you wanted to do the same thing in XNA you would be responsible for maintaining the placement of the controls in your own variables during runtime and you would also have to write the code to paint the controls to the screen in their proper places. If the user touches the screen you would need to calculate whether or not the touch overlaps with one of the controls (clearly Silverlight comes out to be the winner here). On the otherhand if you need to make an application where the display needs to be updated at a high frequency rate then XNA would be the preferred application type.

Creating a Simple XNA Application

We are going to create a simple XNA based application. Before you get too deep into creating the application let's do a test to ensure that your machine is capable of properly supporing the required functionality in the emulator. Start up Visual Studio 2010 and Create a new Windows Phone project.

 

From the "New Project" dialog select "XNA Game Studio 4.0" and then "Windows Phone Game."

Name the new project "Hello XNA" and select "OK." Once the project is completed press F5 to run it. If your computer doesn't meet the video requirements that I mentioned earlier then you'll receive an error during deployment stating  that the "display adapter does not meet the emulator requirements to run XNA Framework applications." If you get this error you'll either need to have real Windows Phone 7 hardware for testing your application, will need to update the display hardware and/or driver to meet requirements, or you will need to move the project to a different computer.

Incapable Driver Message

If you didn't get any errors congradulations, you'e got compatible hardware! You can stop the project from running and return back to the source code.

The Game Class

When you create an XNA game you will create a class that inherits from the Microsoft.Xna.Framework.Game and will override events on the class. These events will be called as a part of the execution loop that is built into this class.

Method Description
Draw(GameTime) Called to allow your game to render itself.
Update(GameTime) When this method is called you execute your games logic for what is changing within the game's virtual world.
LoadContent() This is where you would load the resources needed by your game.

 

A simplified view of the life cycle of an XNA application is as follows:

XNA Application Lifecycle
  1. Initialize -
  2. LoadContent -
  3. Update -
  4. Draw -
  5. Unload -

The Update and Draw methods will be called in a loop until your application is terminating.

For the first example I only want to get something on the screen. Open a paint editor and using your artistic skills (or in my case the lack thereof) to draw a plane. Draw it from the perspective that one might see if they were at a higher elevation than the plane looking down on it with the front of the plan pointing up. Keep the plan around 32x32 pixels and save it as a PNG file named "Plane.png".

Go back to Visual Studio. You'll see a Content project in your solution. Right-click on the project and select Add -> Existing Item. Navigate to your plane and add it. This will make the plane image available as a Texture2D object. Now that the plane image is available in the content resources we'll need to write the code that will use it.

Open the file for the Game1 class. You'll see that the class already has some members declared. In the section that is declaring fields you will see a declaration for spriteBatch and graphics. After these declare a Texture2D element named _planeTexture and a Vector2 element named _planePosition. The _planeTexture element will contain the plane that you just drew. The _planPosition element will hold the X, Y position of the plane. By default it will be (0, 0) and we will leave it as that for now.

There are a couple of things we will need to do in the methods that we were given. In the LoadContent method we will load the plane image and in the Draw method we will render the plane. Change the two methods so that they look like the following.

 protected override void LoadContent()
 {
     // Create a new SpriteBatch, which can be used to draw textures.
     spriteBatch = new SpriteBatch(GraphicsDevice);
     _planeTexture = Content.Load<Texture2D>("Plane");
 }
	
 protected override void Draw(GameTime gameTime)
 {
     GraphicsDevice.Clear(Color.CornflowerBlue);
     spriteBatch.Begin();
     spriteBatch.Draw(_planeTexture, _planePosition, Color.White);
     spriteBatch.End();
     base.Draw(gameTime);
 }

The purpose of Content.Load<T>() is intuitive. The calls on the sprite batch object are to prepare a queue up a set of graphic operations so that they can be passed to the graphic adapter at once. This is faster than making a call to the graphic adapter for each operation that is requested. If you run the program now you'll see the plan render.

Plane Rendering

The plane renders in the upper left hand corner of the emulator.

Getting Input

XNA supports input from a number of different devices; Xbox controllers, keyboards, mice, accelerometers, and touch screens. The classes for these input devices are available across the different implementations of XNA even if that actual device is not (in which case the class would always return no activity on that virtual device). The next change I'm making to the program is to read from an input device and move the plane.

Reading Touch Input

I know that Windows Phone 7 devices have 4-point multi-touch screens. But I am going to code as though it's a possibility that the target device doesn't. This is because I could potentially recompile this code for something else that doesn't have a touch screen (such as an xbox) or might decide to recompile it for a device that doesn't yet exists. To make sure the code properly adapts to all of the different implementations of XNA I will programmatically ask whether or not a certain input device exists before I attempt to use it. I only check for the presence of a touch screen device once. The static method TouchPanel.GetCapabilities() returns a TouchCapabilities object. I'm interested in the IsConnected member of this class. It contains the value true if there is an available touch screen. I store the result of this in _useTouch. I preferred _useTouch over _hasTouch because it is possible that a device is available but I don't want to use it.

During the Update method I'm just checking to see if the touch point is to the left or right of the center of the plane and move the plan one pixel closer to where ever the touch point is. I maintain the center point for the plane separate from the location of the plane (in a real app I wouldn't do this). They are always updated at the same time so I know they are always in sync. To add this functionality to your program declare a new field of type Vector2 named _planeCenter and a boolean field named _useTouch. Within the Initialize() method initialize the _useTouch with the following code.

protected override void Initialize()
 {
      base.Initialize();
      TouchPanelCapabilities touchCaps = TouchPanel.GetCapabilities();
     _useTouch = touchCaps.IsConnected;
     _useAccelerometer = (Accelerometer.GetCapabilities().IsConnected());
 }

The logic to change the position of the plane based on the touch point goes in the update method. It will look like the following.

if (_useTouch)
{
    TouchCollection touchList = TouchPanel.GetState();
    if (touchList.Count > 0)
    {
        var touchPoint = touchList[0];
        if (touchPoint.Position.X > _planeCenter.X)
        {
            ++_planeCenter.X;
            ++_planePosition.X;
        }
        else if (touchPoint.Position.X < _planeCenter.X)
        {
            --_planeCenter.X;
            --_planePosition.X;
        }
    }
}

If you run the program now the plane will move left or right depending on where you touch the screen. If you extend the logic a little further you can have it move up and down too.

Using the Accelerometer

If you've used the accelerometer class in version 3.x of XNA (or saw my Zune Level code)Game Studio forget what you've learned; the accelerometer isn't a part of XNA anymore. It's available in one of the Windows Phone specific assemblies and the way you access it is different.  Instead of probing a static class for it's state you will need to register for event notification. Start by adding a reference to Microsoft.Devices.Sensors to your class along with an appropriate using statement for it. Add a new field of type Accelerometer named _myAccelerometer and initialize it with the default constructor in the Initialize() method. After initializing it add an event handler for the ReadingChanged event. The event will received the X, Y, and Z readings for the accelerometer.

For those that have already written software in XNA and are porting it over this change woun't make a huge difference to your code. Instead of reading the accelerometer during each cycle of your game's loop you would could store the value you get from the ReadingChanged event into a variable and read from it in your game loop. I'm only interested with moving to the plane to the left and right only. So I'm going to change the accelerometer reading to a tilt direction. If the device is tilted by more than 45 degrees then I'll interpret that as an intentional move. Less than 45 degrees will be considered a "dead-zone" and won't affect the plane. Changing the accelerometer reading is a matter of simple math. I usually work in radians but for the sake of making this code more readable I'll work in degrees. 

void _myAccelerometer_ReadingChanged(object sender, AccelerometerReadingEventArgs e)
{
    float tiltDirection = (180f/(float)Math.PI)*(float)Math.Atan2(e.Y, e.X);
    if((tiltDirection>45)&&(tiltDirection<=135))
    {
        _planeMovement.X = 1;
    }
    else if((tiltDirection>225)&&(tiltDirection<=315))
    {
        _planeMovement.X = -1;
    }
}
	

To test this code you will need a physical Windows Phone device. I'v enot yet acquired one yet but hope to get my hands on one soon.

The GamePad Class

You'll find a GamePad class in the Windows Phone XNA library. It may seem a little strange at first given that Winows Phones don't have a game pad of any type. But since XNA applications can be recompiled for other platforms (Xbox 360 and Windows PC) the presence of the class makes the task of recompiling code for another platform easier. Without the presence of this class it would be necessary to add conditional compilation logic to ensure the class was only visible on platforms that supported it.

I won't go into details of the class here. If you'd like to read more about the GamePad class take a look at this article oon accessing the controller from the PC. The same concept works on the Xbox 360.

 

Part 2 of the article can be found here

Tags: ,

Aug 24 2010

Getting to my Isolated Files (Windows Phone 7)

Category: MobileJoel Ivory Johnson @ 10:58

Download the Code (211 Kilobytes)

A frequent question I see in the MSDN forums is how does one copy their files from Isolated Storage in Windows Phone 7 to their desktop computer. The file system on WP7 isn't exposed so unlike WM6.x you can't just connect it to your desktop and get to any and every file. The general answer given is to create a service that will write files to your desktop's storage and have your WP7 application send the data to that application. There are a lot of ways to do this, so this answer hasn't been enough for some users. I put together this example as an illustration of one of the many ways in which this solution can be built.

In the solution attached to this article you'll find three projects. One project is a Windows Phone 7 application that is made to send data to a service. Another project is the implementation for that service. And the last project is a WPF based GUI that does nothing more than host the service (alternatively the service could have been hosted in IIS or in a service application).

The service has two methods: CopyString(String fileName, string content) for copying string data and CopyBytes(string fileName, byte[] content) for copying binary data

To run the example you would need to start both the WPF application on your desktop (to receive the files) and the application on the phone. On the phone you will enter the name or IP address of your machine (So the phone knows what machine to send the file to) and the port on which the service runs (Default 8001). When you press the upload button on the phone within a few seconds you should see the file's name listed on the PC. The file will be in My Documents\WP7Files\.

If you want to change the port over which the application works you can edit the file that ends with .config in the WPF application.

In this first version of this solution my goal was to only make it work. In a future version I plan to add the ability to transfer large files in chunks, transfer everything in isolated storage, support copying files in both directions, and add security.

This isn't code that you would run in a production environment. Since it is communicating over HTTP instead of HTTPS you don't want to send any sensative data. Currently there's also nothing stopping a rouge client from sending malicious files to the computer (hence the need to add security).

This entry is more geared to some one that has some familiarity with using services in .Net. I'll write step by step instructions for every one else after I further refine this code. If you wanted your own WP7 application to use the service you would need to first run the service locally and then from within Visual Studio right-click on your Windows Phone project, select "Add Service Reference" and type http://localhost:8001/FileCopy/mex/ to add the service reference to your app.

I'll close with the code that was used in the example to read the configuration and then upload a file to the machine identified by the configuration.

public void BeginUpload()
{
    if (IsUploading)
        return;
    string serviceAddress = string.Format("http://{0}:{1}/FileCopy/", this.MachineName, TargetPort);
    ChannelFactory myChannelFactory = new ChannelFactory(new BasicHttpBinding(), new EndpointAddress(serviceAddress));
    //_copyServiceClient = myChannelFactory.CreateChannel(new EndpointAddress(serviceAddress));


    var copyServiceClient = new CopyServiceClient(new BasicHttpBinding(), new EndpointAddress(serviceAddress));
              
    if(UseBinary)
    {
        var encoder = System.Text.UnicodeEncoding.Unicode;
        var byteList = encoder.GetBytes(Content);
        copyServiceClient.CopyBytesCompleted += new EventHandler(copyServiceClient_CopyBytesCompleted);
        copyServiceClient.CopyBytesAsync(FileName, byteList);
    }
    else
    {
        IsUploading = true;
        copyServiceClient.CopyStringCompleted += new EventHandler(copyServiceClient_CopyStringCompleted);
        copyServiceClient.CopyStringAsync(FileName,Content);
    }
}

Tags: ,

Aug 17 2010

Running the Windows Phone Dev Tools on Windows XP

Category: MobileJoel Ivory Johnson @ 04:35

And now for something completely unsupported.

I'm the type of person that prefers to run the latest and greatest operating system. For Windows 2000, XP, Vista, and Windows 7 I started running them while they were still betas. Unfortunately I'm in possession of a machine running Windows XP for a Silverlight project. The Windows Phone tools require Windows Vista or higher with a DirectX 10 video card, so the WP7 tools were a no-go for this machine. For various reasons I wanted the machine to be capable of opening a WP7 projects. The machine was already running Visual Studio 2010 Ultimate and I have other Silverlight development components installed. So I made an attempt to get things up and running and successfully have a machine that will do WP7 development (though the emulator won't run).

Just an FYI, since I already had Visual Studio 2010 and several Silverlight development components installed I didn't need Visual Studio 2010 Express. I'm not sure how things will go for a person without VS2010 preinstalled.

I grabbed the ISO for the Windows Phone 7 tools from http://developer.windowsphone.com. After unpacking the ISO and running setup I received a message about a problem loading the setup components.  I didn't expect that to work. I next started looking at the files that were in the ISO and saw the familiar "wcu" folder (Windows Component Updates). Inside of the WCU folder there were several subfolders. The only one that was important to me was the Windows Phone folder.

Installing these components individually I found that each one of them would run without any complaint or problem. I started with the Expressions Blend trial and XNA Game Studio. After installing the both of those I found that I could create (but not compile) XNA projects and run Expressions Blend for Windows Phone. I installed the other components and was then able to create and compile Windows Phone 7 projects.

When I first tried to run a Windows Phone 7 project I immediately received an error from the emulator. I changed the target device from the emulator to "Windows Phone 7 Device" and ran the project again and it successfully deployed and ran. Now that my Windows XP machine has been elevated to being cable of developing for Windows Phone 7 I'm happy. Onto better things; VMWare just released an update for VMWare Workstation that is said to improve the graphic capabilities. I've already got a virtualized WP7 dev environment in which the emulator doesn't run because of the emulated video card not meeting minimum requirements. I need to see if this update addresses that.

Tags: , ,

Jul 31 2010

Detect Shaking Motion on Windows Phone 7

Category: MobileJoel Ivory Johnson @ 10:12

Download the code

The other day on the MSDN forums some one asked about how to detect a shaking motion on Windows Phone 7. I've been playing with the accelerometer lately so I took great joy in answering this along with providing a working implementation. The question was asking about shaking motion in a left-right direction. I made a class that detects left-right and up-down motion (totally ignoring the Z-axis all together for now). Though extending it to consider the Z-axis wouldn't be hard.

The code for detecting the motion has been abstracted in a class called ShakeDetector. The algorithm used has a few variables/constants defined that can be modified to tune the behaviour of the class. The classes constructor accepts an [optional] parameter of how many times the phone should be shaken before the motion is considered acceptable. can be raised or lowered to control how hard the device needs to be shaken to be considered acceptable. And MinimumShakeTime takes a time span that defines the maximum length of time overwhich a shake sequence must occur to be considered acceptable. One the user moves the phone in a way that meets the requirements for the type of shake we wanted to detect a ShakeDetected event is raise

I've reduced the direction in which the device is moving to one of 8 directions (North, East, South, West, and the directions inbetween those). I could have kept the direction as an angle and just ensured that there was atleast a minimum difference between the angles but I thought using the directions on a map would make it easier for some one else to understand.

void _accelerometer_ReadingChanged(object sender, AccelerometerReadingEventArgs e)
{
    //Does the currenet acceleration vector meet the minimum magnitude that we
    //care about?
    if ((e.X*e.X + e.Y*e.Y) > MinimumAccelerationMagnitudeSquared)
    {
        //I prefer to work in radians. For the sake of those reading this code
        //I will work in degrees. In the following direction will contain the direction
        // in which the device was accelerating in degrees. 
        double degrees = 180.0*Math.Atan2(e.Y, e.X)/Math.PI;
        Direction direction = DegreesToDirection(degrees);

        //If the shake detected is in the same direction as the last one then ignore it
        if ((direction & _shakeRecordList[_shakeRecordIndex].ShakeDirection) != Direction.None)
            return;
        //This is a shake we care about. save in in our list
        ShakeRecord record = new ShakeRecord();
        record.EventTime = DateTime.Now;
        record.ShakeDirection = direction;
        _shakeRecordIndex = (_shakeRecordIndex + 1)%_minimumShakes;
        _shakeRecordList[_shakeRecordIndex] = record;

            CheckForShakes();

    }


}
void CheckForShakes()
{
    int startIndex = (_shakeRecordIndex - 1);
    if (startIndex < 0) startIndex = _minimumShakes - 1;
    int endIndex = _shakeRecordIndex;

    if ((_shakeRecordList[endIndex].EventTime.Subtract(_shakeRecordList[startIndex].EventTime)) <= MinimumShakeTime)
    {
        OnShakeEvent();
    }
}

The example code can be found in my SkyDrive account here. If you want to see the program in action there is a video on YouTube.

Tags: ,

Jul 26 2010

Avoiding Tight Hardware Coupling

Category: Mobile | ProgrammingJoel Ivory Johnson @ 11:24

As a Software Engineer I'm interested in how tightly coupled that one piece of code is to another. Coupling is the amound of dependencies that one entity has on another and tightly coupled code tends to be less portable and adaptable. But the concept of coupling doesn't stop at software. Coupling is also applicable to the relationship between hardware and software and I'm interested in avoiding tight coupling between the hardware and software for my code too.

With real implementations of Windows Phone 7 devices floating around it would be easy for some one to attempt to write an application that is tightly couple to that implementation. In some cases these low risk associated with doing this; for example if one tightly couples to screen resolutions (and there will only be two screen resolutions) it could be some time before some one needs to address another screen resolution. I'm writing a piece of code that is going to be sensative to the sampling rate of the accelerometer. And easy but tightly coupled way to handle this would be to measure the sample rate of the accelerometer and then write my code accordingly. But if I do this then I assume quite a few things. I would be assuming that other phones have the same sample rate. I would assume that the same phone will always have the same sample rate. I don't know that either of these assumptions are true.

The time information returned in the from DateTime.Now is precise enough for me to perform the measurements that I needed. So I wrote a quick application that would measure the accelerometer sample frequency and display it in a text box.

Here is my initial code

       private Accelerometer _accelerometer;

        // Constructor
        public MainPage()
        {
            InitializeComponent();
            this.DataContext = this;

            _accelerometer = new Accelerometer();
            _accelerometer.ReadingChanged += new EventHandler(_accelerometer_ReadingChanged);
            _accelerometer.Start();
        }

        void _accelerometer_ReadingChanged(object sender, AccelerometerReadingEventArgs e)
        {
            DateTime previousUpdate = LastUpdate;
            LastUpdate = DateTime.Now;
            double period = LastUpdate.Subtract(previousUpdate).TotalSeconds;
            double frequency = 1.0/period;
            if (frequency > HighestFrequency)
                HighestFrequency = frequency;

        }

        
// LastUpdate - generated from ObservableField snippet - Joel Ivory Johnson
  private DateTime _lastUpdate;
  public DateTime LastUpdate
  {
    get { return _lastUpdate; }
      set
      {
          if (_lastUpdate != value)
          {
              _lastUpdate = value;
              OnPropertyChanged("LastUpdate");
          }
      }
  }
 //-----      
// HighestFrequency - generated from ObservableField snippet - Joel Ivory Johnson
  private double _highestFrequency;
  public double HighestFrequency
  {
    get { return _highestFrequency; }
      set
      {
          if (_highestFrequency != value)
          {
              _highestFrequency = value;
              Dispatcher.BeginInvoke(() => { OnPropertyChanged("HighestFrequency"); });
            
          }
      }
  }
 //-----


        void OnPropertyChanged(string propertyName)
        {
            if(PropertyChanged!=null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;

        #endregion
    }

Ofcourse there may be those that are curious as to what value a real device will currently returned. Of course publishing that type of information could result in more tightly coupled code being written. I'll post more once the code I am writing is done.

Tags: ,

Dec 11 2009

Popular Misconception: The override that was not

Category: Joel Ivory Johnson @ 09:53

I was interviewing for jobs this past week and at all of the interviews I was presented with questions about object oriented techniques and C#. When asked abouit overriding a method on a class that wasn't marked as virtual I informed the interviewers that it can't be done. I didn't realize that the interviewers were considering my answer to be wrong until yesterday when an interviewer presented to me the answer that he was looking for. He told me that I could override an otherwise unoverridable method by using the new keyword on it. That started a discussion which resulted in the interviewer wondering whether or not the method was really effectively overridden. After I had the discussion with him I realized the earlier interviewers may have also thought that my answer was incorrect.

The misconception comes from an observation of what happens when one uses the new keyword on a method. To make this discussion a little more concrete I'll share some example code.

    class MyBase
    {
        public virtual string MethodA() 
        {
            return "Hello from MethodA";
        }
        public string MethodB()
        {
            return "Hello from MethodB";
        }
    }

What this class does is obvious.It has two methods both of which return a unique string. The class is simple enough that I'm sure you'll trust me when I say it reliably does its job without error. One of the methods is marked as virtual, so it is overridable. The other is not. So now I derrive a class from this base class.

class Derived : MyBase
{
    public override string MethodA()
    {
        return "Hello from Derrived::MethodA";
    }
    public new string MethodB()
    {
        return "Hello from Derived::MethodB";
    }
}

In this derrived class I have overridden MethodA. Since MethodB is not marked as virtual I could not override it so I used the new keyword. Let's test the program to see what type of output it produces.

static void Main(string[] args)
{
    var a = new Derived();
    var b = new MyBase();

    Console.Out.WriteLine(b.MethodA());
    Console.Out.WriteLine(b.MethodB());

    Console.Out.WriteLine(a.MethodA());
    Console.Out.WriteLine(a.MethodB());
}

The output from running this is what one would expect. When I call MethodA and MethodB the the strings derrived in the derrived class are displayed.

Hello from MethodA
Hello from MethodB
Hello from Derrived::MethodA
Hello from Derived::MethodB

Upon seeing this behaviour it seems that the developers I spoke to last week thought this to be the functional equivalent of overriding. But the difference shows up when the instance of the class is handled through either an interface or a base class reference. Let's say I appended the following to the above code.

var c = a as MyBase;

Console.Out.WriteLine(c.MethodA());
Console.Out.WriteLine(c.MethodB());

The output is not consistent with what we would expect an overridden method would produce.

Hello from Derrived::MethodA
Hello from MethodB

The above output demonstrates that when a method has been overridden then the method will be called regardless of the interface used to interact with the object instance. MethodA had been overridden so even though a variable whose type is of the base class is used the overridden implementation is invoked. MethodB was never truly overriden so when a base class reference is used the base class implementation is called.

So then what did the new keyword really do? It allowed some one to create a method that has the same signature and name as an existing method. While the method is called with the same notation that would have been used to call the original method it is not actually performing an override. It is only hiding it. For confirmation one can also look at the C# documentation for the new keyword on MSDN which refers to this as name hiding. http://msdn.microsoft.com/en-us/library/51y09td4(VS.71).aspx#vclrfnew_newmodifier

Name hiding through inheritance takes one of the following forms:

  • A constant, field, property, or type introduced in a class or struct hides all base class members with the same name.
  • A method introduced in a class or struct hides properties, fields, and types, with the same name, in the base class. It also hides all base class methods with the same signature. For more information, see 3.6 Signatures and overloading.
  • An indexer introduced in a class or struct hides all base class indexers with the same signature.

Digging deeper into the documentation we find the following:

The scope of an entity typically encompasses more program text than the declaration space of the entity. In particular, the scope of an entity may include declarations that introduce new declaration spaces containing entities of the same name. Such declarations cause the original entity to become hidden. Conversely, an entity is said to be visible when it is not hidden.

The conclusion: The new keyword is not performing an override, it is a scoping operator.

Tags: