Recognizing speech is interesting,
but sometimes you need to communicate with users with voice, too.
Luckily, the Windows Phone includes support to create speech from your
application. Before you can get started, you will need to include the
speech capability (called ID_CAP_SPEECH_RECOGNITION
) to the WMAppManifest.xml
file.
The class involved in generated speech is the SpeedSynthesizer
class. This class supports IDisposable,
so you should create and dispose the class in your Loaded
and Unloaded
event handlers:
public partial class MainPage : PhoneApplicationPage
{
SpeechSynthesizer _synth;
// Constructor
public MainPage()
{
InitializeComponent();
Loaded += MainPage_Loaded;
Unloaded += MainPage_Unloaded;
}
void MainPage_Loaded(object sender, RoutedEventArgs e)
{
_synth = new SpeechSynthesizer();
}
void MainPage_Unloaded(object sender, RoutedEventArgs e)
{
_synth.Dispose();
}
...
}
To use the SpeechSynthesizer
class, just call the SpeakTextAsync
method and supply it with some text to speak:
private async void speakButton_Click(object sender,
RoutedEventArgs e)
{
await _synth.SpeakTextAsync(theText.Text);
}
The SpeakTextAsync
method uses the async
pattern, so it requires the method we marked as async
and use the await
for the speech to be synthesized. When you synthesize speech, it uses
the default voice as specified by the user on the Speech settings, as
shown in Figure 1.
FIGURE 1 Specifying the default language and voice
You can select other voices and languages by using the built-in voices on the phone. The InstalledVoices
class contains a static property that contains all the voices on the
phone. By using a simple LINQ query, you can find a voice that matches
your required language and gender, like so:
var selectedVoices = from voice in InstalledVoices.All
where voice.Gender == VoiceGender.Male &&
voice.Language == "en-GB"
select voice;
_synth.SetVoice(selectedVoices.First());
await _synth.SpeakTextAsync(theText.Text);
In this example, the LINQ query would return a
set of voices that were both male and from Great Britain (okay, I have
a thing about British English). After you have the voice, you simply
have to set it using the SetVoice
method as shown.
The voices support a
number of languages, such as German, Portuguese, French, Spanish, and
Polish. The number of voices and languages might depend on the region
in which the phone was sold. Be aware that the language of the voice
also affects the pronunciation. These voices expect the text to be in
the language that matches the voice. This means that supplying a
language like English to a voice that matches another language will
change the pronunciation. For example, if you supply “Jumping” to a
Spanish voice, it will use the soft “J” sound from Spanish.
The Windows Phone also supports a system called
Proximity. This system uses Near Field Communication (NFC) to allow two
devices to communicate when they are 3–4 cm from each other. Usually
this takes the form of tapping phones together.
Before you can use Proximity, you must add the
capability. Proximity requires both networking and proximity
capabilities (for instance, ID_CAP_NETWORKING
and ID_CAP_PROXIMITY
). After you have them, there are several classes for dealing with proximity. For your applications, you’ll be able to use the ProximityDevice
class to get the default device to work with using the GetDefault
method:
public partial class MainPage : PhoneApplicationPage
{
ProximityDevice _device;
// Constructor
public MainPage()
{
InitializeComponent();
Loaded += MainPage_Loaded;
}
void MainPage_Loaded(object sender, RoutedEventArgs e)
{
_device = ProximityDevice.GetDefault();
}
...
}
By calling GetDefault
, the main ProximityDevice
is returned. Because this object is expensive to get, you should
retrieve it at the page level and keep it around instead of creating it
on every call.
In addition, the device might not be available
due to the user not allowing NFC on the device. In that case, the
returned object is a null reference. You should check for this before
using:
if (_device != null)
{
// ...
}
After you have the ProximityDevice
,
you can publish and subscribe to messages to be passed. You must first
have a known message name. The NFC standard requires that this message
name be a protocol and a subtype separated by a period. For the Windows Phone (and Windows 8), the protocol must be “Windows”; the subtype is up to you. After you have the message name, you can send a message using the ProximityDevice
’s PublishMessage
method:
const string MESSAGETYPE = "Windows.FunWithNFC";
long _pubId = -1;
private void publishButton_Click(object sender, EventArgs e)
{
if (_device != null)
{
// Publish new message
_pubId = _device.PublishMessage(MESSAGETYPE, "Hello World");
}
}
The body of the message can be in multiple
formats. There are methods for binary and text. In this case, we’re
just sending a simple text message. The call to PublishMessage
returns a long integer that is used to unpublish a message. Only one
message can be pending at a time. That means that if you want to
republish a message, you must unpublish the first one, like so:
const string MESSAGETYPE = "Windows.FunWithNFC";
long _pubId = -1;
private void publishButton_Click(object sender, EventArgs e)
{
if (_device != null)
{
// Remove old message if needed
if (_pubId != -1) _device.StopPublishingMessage(_pubId);
// Publish new message
_pubId = _device.PublishMessage(MESSAGETYPE, "Hello World");
status.Text = "Published Message";
}
}
The other side of the call is to support subscribing to the message on another phone. In this case you will want to call the ProximityDevice
’s SubscribeForMessage
:
long _subId = -1;
private void subscribeButton_Click(object sender, EventArgs e)
{
if (_device != null)
{
// Unsubscribe if needed
if (_subId != -1) _device.StopSubscribingForMessage(_subId);
// Subscribe to message
_subId = _device.SubscribeForMessage(MESSAGETYPE, OnMsgRecd);
status.Text = "Subscribed for Message";
}
}
The SubscribeForMessage
method takes the message type to listen for and a callback for when the message is received. Like the PublishMessage
method, SubscribeForMessage
returns an ID so you can stop subscribing to the message before subscribing to a new message.
One important caveat for using Proximity is
that the emulator doesn’t support emulating the Proximity device so you
have to use a physical phone for your testing. In most cases, this will
take two phones to do the actual testing.