Over a million developers have joined DZone.

Text-to-Speech With Windows 10 IoT Core, UWP, and a Pi (Part 2)

DZone 's Guide to

Text-to-Speech With Windows 10 IoT Core, UWP, and a Pi (Part 2)

Bring audio balancing and text-to-speech to your smart home! See how to use Windows 10 IoT Core and a Raspberry Pi to program TTS announcements.

· IoT Zone ·
Free Resource

In my previous post, I've written about using a Raspberry Pi running Windows 10 IoT Core for text-to-speech services for my smart home. As I mentioned in that post, I have speakers in two floors wired to an amplifier connected to a Raspberry Pi. The thing is that each of the speakers is wired to its own audio channel — the ground floor speaker is wired to the left channel and the upper floor speaker is wired to the right channel.

It may not be what you'd call a true stereo when listening to music, but it plays a big role with speech running through the house. With such wiring, I can target the floor I want to convey the speech through, either exclusively or with a subtle mix, e.g. 100% volume to the ground floor and only 10% to the upper floor (it's basically how audio balancing works). This basically lets me cover these use cases and more:

  • Want to call your children to lunch when they're playing in their rooms upstairs? Use the upper floor speaker.
  • Somebody at the door? Send the message to both floors equally.
  • Late at night? Kids sleeping? Maybe use the ground floor speakers at full and the upstairs speakers at a minimum.
  • Etc...

The scenarios are limitless. And the MediaPlayer class from my previous example offers just what I needed to implement this — audio balance. You can simply set the balance prior to playing your audio, like this:

public async Task SayAsync(string text, double balance)
    speechPlayer.AudioBalance = balance;
    using (var stream = await speechSynthesizer.SynthesizeTextToStreamAsync(text))
        speechPlayer.Source = MediaSource.CreateFromStream(stream, stream.ContentType);

This code is from my previous blog post, with an additional parameter for setting the AudioBalance property prior to playing the synthesized speech.

Playing Speech Remotely

Of course, the real fun begins when you're able to control your audio player remotely, e.g. from an application or even a web browser. To achieve this, I have put together a simple "web server" that runs as a background service on Windows 10 IoT Core. I've used the SimpleWebServer from the IoTBlockly code sample as a base for my own implementation of a "poor man's web API server," just trying to simulate controllers, etc. I won't go into that code, as it's very hacky, absolutely not production ready, complete, or even tested, but it appears to work OK for my current needs. The full source code I've used for this blog post is included in my sample project; I'm only listing the part that controls the speech here:

internal class SayController : Controller
    private readonly SpeechService _speechService;

    public SayController(SpeechService speechService)
        _speechService = speechService;

    public async Task<WebServerResponse> Get(string text, string floor)
        if (string.IsNullOrEmpty(floor))
            await _speechService.SayAsync(text, 0)
        else if (floor.ToLower() == "up")
            await _speechService.SayAsync(text, -1);
            await _speechService.SayAsync(text, 1);
        return WebServerResponse.CreateOk("OK");

The code is pretty self-explanatory — the first parameter contains the text that should be spoken, and the second parameter is the name of the floor the text should be spoken on ("up" sets the audio balance to the left channel and "down" to the right).

With such a server setup on my Raspberry Pi (the sample is set to listen on port 8085), it's easy for me to make my home say the synthesized text on a specific floor by simply calling its URL:


The sample source code for this post is available on GitHub.

raspberry pi ,iot ,windows 10 iot core ,text-to-speech ,tutorial

Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}