Headcrab
Headcrab

Reputation: 7123

UWP speech synthesis without a XAML MediaElement

Every UWP text-to-speech sample I can find uses a MediaElement control created with XAML. E.g., something like this, which works fine:

using namespace Windows::Media::SpeechSynthesis;

//..........

void App::MainPage::buttonSpeak_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)
{
    create_task(synthesizer->SynthesizeTextToStreamAsync(L"I am ready."))
        .then([this](SpeechSynthesisStream ^stream)
    {
        MediaElement ^media = mediaElement; //created in a separate XAML file
        media->AutoPlay = true;
        media->SetSource(stream, stream->ContentType);
        media->Play();
    });
}

How do I adapt it to work without a XAML-based interface (a holographic DirectX application, in my case)? I have tried creating a MediaElement programmatically, e. g. MediaElement ^media = ref new MediaElement();, it always throws "The application called an interface that was marshalled for a different thread" exception.

Upvotes: 1

Views: 678

Answers (3)

the1337chef
the1337chef

Reputation: 21

To supplement Headcrab's answer and use Source instead of SetStreamSource.

replace:

player->SetStreamSource(stream);

with:

player->Source = Windows::Media::Core::MediaSource::CreateFromStream(stream, stream->ContentType)

Upvotes: 1

Headcrab
Headcrab

Reputation: 7123

I did it with MediaPlayer instead of MediaElement.

using namespace Windows::Media::SpeechSynthesis;
using namespace Windows::Media::Playback;

//...

SpeechSynthesizer ^synthesizer = ref new SpeechSynthesizer();
MediaPlayer ^player = ref new MediaPlayer();

//...
create_task(synthesizer->SynthesizeTextToStreamAsync(L"I am ready."))
    .then([this](SpeechSynthesisStream ^stream)
{
    player->SetStreamSource(stream);
    player->Play();
});

It works, although the compiler gives a warning that SetStreamSource is deprecated, and Source should be used instead, but I haven't figured out how to use it.

Upvotes: 0

Marian Dolinský
Marian Dolinský

Reputation: 3492

It's throwing the exception because MediaElement could work only on an UI thread.

You can use AudioGraph. It can run on any thread.

Upvotes: 0

Related Questions