【问题标题】:Creating a UWP DLL using Windows::Media::SpeechSynthesis使用 Windows::Media::SpeechSynthesis 创建 UWP DLL
【发布时间】:2019-10-25 17:11:48
【问题描述】:

我目前正在尝试使用命名空间 Windows::Media::SpeechSynthesis 开发语音合成 UWP DLL。我读过这个documentation 和微软page 专用于命名空间。我试图在代码中实现命名空间。

头文件

#pragma once

#include <stdio.h>
#include <string>
#include <iostream>
#include <ppltasks.h>

using namespace Windows::Media::SpeechSynthesis;
using namespace Windows::UI::Xaml::Controls;
using namespace Windows::UI::Xaml::Media;
using namespace Windows::Media::Playback;

namespace SDKTemplate
{
    class TextToSpeechDll
    {
        public:
           __declspec( dllexport ) void ttsInitialize();

        private:
           MediaElement ^media;
    };
}

Cpp 文件

#include "stdafx.h"
#include "Dll2.h"

using namespace SDKTemplate;
using namespace Platform;
using namespace Concurrency;

void TextToSpeechDll::ttsInitialize()
{
    SpeechSynthesizer ^synth = ref new SpeechSynthesizer();
    // The object for controlling the speech synthesis engine (voice).
    synth = ref new SpeechSynthesizer();
    // The string to speak.
    String^ text = "Hello World";

    // Generate the audio stream from plain text.
    task<SpeechSynthesisStream ^> speakTask = create_task( synth->SynthesizeTextToStreamAsync( text ) );
    speakTask.then( [this, text]( task<SpeechSynthesisStream^> synthesisStreamTask )
    {
        SpeechSynthesisStream ^speechStream = synthesisStreamTask.get();
        // Send the stream to the media object.
        // media === MediaElement XAML object.
        media->AutoPlay = true;
        media->SetSource( speechStream, speechStream->ContentType );
        media->Play();
    } );
}

我可以加载 DLL 文件和我导出的函数。但是,当我尝试调用该函数时,出现以下错误

我在 Microsoft page 上尝试了该示例,但它有些不起作用,我不知道为什么。我还测试了Github 上提供的 Windows 通用示例,这是一个重新组合文本到语音和语音识别的 UWP 应用。

有人遇到过类似的问题吗?当我没有接口时,我不应该使用 XAML 元素吗?


编辑 1

我按照@Peter Torr - MSFT 的建议修改了有关函数导出的头文件

#pragma once

#include <stdio.h>
#include <string>
#include <iostream>
#include <ppltasks.h>

using namespace Windows::Media::SpeechSynthesis;
using namespace Windows::UI::Xaml::Controls;
using namespace Windows::UI::Xaml::Media;
using namespace Windows::Media::Playback;

namespace SDKTemplate
{
   public ref class TextToSpeechDll sealed
   {
      public:
         void ttsInitialize();

      private:
         MediaElement ^media = ref new MediaElement();
   };
}

但是,当我编译时,我在这一行收到一个新错误

speakTask.then( [this]( task<SpeechSynthesisStream^> synthesisStreamTask )

我研究了这个错误,如果我理解正确,它来自 DLL 函数的导入。

另外,我这样调用函数

_ttsUwpDll->ttsInitialize();

我们来到这里

void NxWindowsTtsUwpDll::ttsInitialize()
{
   int retVal = 0;
   try
   {
      retVal = _ttsInitialize();
   }
   catch( ... )
   {
      printf( "Exception in ttsInitialize\n" );
   }
   //return retVal;
}

【问题讨论】:

  • 为什么您使用导出的 C++ 类而不是 WinRT 组件?你能展示你是如何初始化和使用这个类的吗?例如,在给出的代码中,media 从未分配给。
  • @PeterTorr-MSFT 我编辑了我的帖子(编辑 1)关于你问我的问题。你能解释一下我如何分配变量media吗?
  • 我相信 MediaElement 在使用前需要在 XAML 树中。您要实现的总体方案是什么?
  • @PeterTorr-MSFT 我正在尝试制作一个 DLL 文件。你认为它可以与 MediaPlayer 元素一起使用吗?
  • “制作一个DLL”是如何,而不是what。为什么是 DLL,而不是 LIB 或 EXE? MediaElement 有什么用途? MediaPlayer 是更好的选择吗?等

标签: uwp text-to-speech c++-cx speech-synthesis


【解决方案1】:

在 MainPage 中,我初始化 dll 文件并调用“ttsInitialize”函数,如下代码所示。

MainPage::MainPage()
{
 InitializeComponent();
 TextToSpeechDll* gf = new TextToSpeechDll();
 gf->ttsInitialize();
}

在 Dll.h 文件中,我像下面的代码一样初始化 MediaElement,其他代码和你一样。

MediaElement^ media = ref new MediaElement();

当我运行项目时,它可以工作。 您可以尝试一下,如果仍然有问题,请显示您初始化 dll 文件的详细信息。

【讨论】:

  • 如果我理解正确,sn-p gf-&gt;ttsInitialize(); 调用函数 ttsInitialize(); 对吗?我已经以这种方式声明了 MediaElement。我想如果它适合您,您可以通过启用 Consume Windows Runtime Extension (Yes/ZW) 来配置项目属性?
  • 是的,方法“gf->ttsInitialize();”调用您在 DLL 文件中声明的函数“ttsInitialize()”,我确实通过启用使用 Windows 运行时扩展(是/ZW)来配置项目属性。
  • 我实现了方法“gf->ttsInitialize();”在另一个班级,它仍然不起作用。
  • 您能否详细说明如何初始化 DLL 文件?如果在 MainPage 中初始化 DLL,它会起作用吗?另外,我是根据你第一次提供的代码而不是(编辑1)中的代码创建DLL文件,你也用它来测试吗?可以浏览here查看DLL文件的配置。
【解决方案2】:

我找到了我的问题的答案。我没有使用MediaElement,而是使用了MediaPlayer。现在它可以工作了,但我仍然需要弄清楚如何让引擎说话而不限制它的时间。 Sleep( 3000 ) 表示语音会持续 3 秒。但是,如果句子超过 3 秒,就会被删减。 这是程序的代码。

int TextToSpeechUwpDll::ttsSpeak( const char* text )
{
   SpeechSynthesizer ^speak = ref new SpeechSynthesizer();
   MediaPlayer ^player = ref new MediaPlayer;

   int wchars_num = MultiByteToWideChar( CP_ACP, 0, text, -1, NULL, 0 );
   wchar_t* texts = new wchar_t[wchars_num];
   MultiByteToWideChar( CP_ACP, 0, text, -1, texts, wchars_num );
   String ^sentence = ref new String( texts );

   task<SpeechSynthesisStream ^> speakTask = create_task( speak->SynthesizeTextToStreamAsync( sentence ) );
   speakTask.then( [player, sentence]( SpeechSynthesisStream ^speechStream )
   {
      player->Source = MediaSource::CreateFromStream( speechStream, speechStream->ContentType );
      player->AutoPlay = false;
      player->Play();
      Sleep( 3000 );
   } );

   return true;
}

【讨论】:

  • 这并不能回答您提出的问题。它可能会解决您的最终问题,但不能回答问题。因此,您不应该接受它作为答案。这不是堆栈溢出的工作方式。它是关于一般问题和答案,而不是关于解决个人的直接问题。这不是论坛。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-02
  • 1970-01-01
相关资源
最近更新 更多