zoukankan      html  css  js  c++  java
  • WPF,Silverlight与XAML读书笔记第四十二 多媒体支持之音、视频和语音

    说明:本系列基本上是《WPF揭秘》的读书笔记。在结构安排与文章内容上参照《WPF揭秘》的编排,对内容进行了总结并加入一些个人理解。

    音频

    在WPF中播放音频有以下几种方式:

    • SoundPlayer
    • MediaPlayer
    • SoundPlayerAction
    • MediaElement和MediaLine

    SoundPlayer

        SoundPlayer是随.NET Framework 2.0一起发布的类,其实对Win32 PlaySound API的一个封装,这是在WPF中播放声音最简单的方式,所以其也有一系列限制。

    • 仅支持wave格式音频文件
    • 不支持同时播放多个音频
    • 无法控制音量

    下面是一段简单的示例:

    1 SoundPlayer player = new SoundPlayer("lily.wav"); 
    2 player.Play();

        SoundPlayer构造函数接受一个文件名或一个URL。上面代码中调用的Play方法将会在另一个线程上异步播放声音。另一个方法PlaySync在当前线程上播放该声音,PlayLooping会实现循环异步播放声音,直至显式调用Stop方法停止为止。

        默认情况下,SoundPlayer会在第一次调用Play相关方法时才加载文件,但由于文件可能存在于网络上,由于缓冲文件等原因可能造成播放前的停顿。解决这个问题,我们可以手动调用Load或LoadAsync方法提前加载文件。

        使用位于System.Media下的SystemSounds类可以播放一些系统声音。SystemSounds包含很多类,如Beep,Exclamation,Question等表示不同的系统声音,这些属性都是SystemSound类型,可以直接调用它们的Play方法异步非循环的播放声音。

    SoundPlayerAction

        这个类最大的作用就是可以将SoundPlayer无缝的融入XAML,在不用编写C#代码的情况下播放声音。SoundPlayerAction派生自TriggerAction,我们可以直接使用它来设置Trigger的Actions属性。下面的例子中我们给按钮添加一个事件触发器,实现在点击按钮时播放一段声音。

     1 <Button>A Button With Sounds
     2     <Button.Triggers>
     3         <EventTrigger RoutedEvent="Button.Click">
     4             <EventTrigger.Actions>
     5                 <SoundPlayerAction Source="click.wav"/>
     6             </EventTrigger.Actions>
     7         </EventTrigger>
     8         <EventTrigger RoutedEvent="Button.MouseEnter">
     9             <EventTrigger.Actions>
    10                 <SoundPlayerAction Source="hover.wav"/>
    11             </EventTrigger.Actions>
    12         </EventTrigger>
    13     </Button.Triggers>
    14 </Button>

    同样使用这个类有更多的限制,你甚至不能循环播放或预先加载声音。

    MediaPlayer

        这个类位于System.Windows.Media命名空间,它是WPF中一个可选的较高级的音频播放功能工具。这个类基于Windows Media Player构建,支持Windows Media Player所支持的多种音频格式(当然其也支持视频,在介绍WPF中视频一节还会再次深入讲述这个类)。通过多个Media Player的实例,可以实现音频同时播放(一个实例同一时间只能播放一个文件)。float类型的Volumn属性用于调整音量,范围由0到1,默认值是0.5。下面列举更多的音频控制方式:

    • 当CanPause属性为true时,可以通过Pause方法停止音频。
    • 设置IsMuted为true可以将音频静音
    • 通过设置Balance来调整左右扬声器平衡
    • 通过设置SpeedRatio来改变支持变速的音频格式的音频的速度,这个值即表示速度变化的倍数,默认值为1.0
    • 通过NaturalDuration属性可以得到音频文件的长度,Position属性可以得到当前播放的位置。

    照例给出一段简单的示例代码:

    1 MediaPlayer player = new MediaPlayer();
    2 player.Open(new Uri("moon.wma", UriKind.Relative));
    3 player.Play();

    如代码所示,我们用Open打开文件,Play播放文件。相应的还有Pause,Stop和Close来控制文件播放。

    视频

        WPF对视频的支持也是通过前面介绍的Media Player,MediaElement级MediaTimeLine来实现。所以Windows Media Player所支持的视频格式如wmv,avi,mpg都可以在WPF中使用。但在程序中使用MediaPlayer类时,要保证最终运行的系统中安装有Windows Media Player 10或更高版本。有关Media Element的话题同样见多媒体控件部分。

    语音

    .NET Framework中新增了一系列语音相关的API,位于System.Speech命名空间下,这些类主要支持语音识别语音合成,这套API并没有为WPF做特殊处理,即没有添加依赖属性,路由事件等特性,所以我们只能在C#代码中使用这些类。

    语言合成由Microsoft SAPI SDK来支持。SAPI SDK中包含了几套不同的语音,使合成语音有不同的效果。仍然通过一段代码来展示语音合成。

    1 SpeechSynthesizer synthesizer = new SpeechSynthesizer();
    2 synthesizer.Speak("测试语音合成");

    要使这段代码工作,需要引用System.Speech.dll,并引用System.Speech.Synthesis命名空间。合成语音的声音、速度和音量可以在控制面板语音合成项中设置。

    使用SpeakAsync方法可以异步播放合成语言,此时也可以通过设置SpeechSynthesizer的Rate和Volumn属性来改变声音的速度和音量。Rate的范围是-10到10,而Volumn的范围是0到100。通过调用SpeakAsyncCancelAll取消处于等待状态的语音合成。

    调用SelectVoice方法可以改变合成语音使用的声音,如代码:

    1 synthesizer.SelectVoice("Microsoft Sam");

    或者通过指定性别和年龄来选择一个声音,如:

    1 synthesizer.SelectVoiceByHints(VoiceGender.Female,VoiceAge.Senior);

    上面介绍的所有例子,转换后的语音会默认输出到扬声器,通过以下代码你可以将其输出到一个.wav文件:

    1 synthesizer.SetOutputToWaveFile(@"C:\mySpeech.wav");

    而如下的代码可以将输出恢复到扬声器:

    1 synthesizer.SetOutputToDefaultAudioDevice();

        新的Speech API支持W3C标准 – 语言合成标记语言SSML。通过SSML,可以将复杂的语言封装在一个单独的模块中。通过调用SpeakSsml和SpeakSsmlAsync方法可以向SpeechSynthesizer传入SSML内容,SSML是标准的XML格式文件,我们可以通过PromptBuilder以编程方式轻松的构件SSML。下面是一段PromptBuilder的使用示例:

     1 //构造PromptBuilder
     2 PromptBuilder promptBuilder = new PromptBuilder();
     3 //普通文本
     4 promptBuilder.AppendText("A common text Line");
     5 //逐字读出每一个字母
     6 promptBuilder.AppendTextWithHint("WPF", SayAs.SpellOut);
     7 //如下可以更好的阅读一个时间
     8 promptBuilder.AppendTextWithHint(DateTime.Now.ToString("hh:mm"), SayAs.Time);
     9 //停顿
    10 promptBuilder.AppendBreak(new TimeSpan(0, 0, 2));
    11 //单独设置一段文本的语音效果,也可使文本形成段落效果
    12 promptBuilder.StartVoice("Microsoft Sam");
    13 promptBuilder.StartStyle(new PromptStyle(PromptRate.ExtraFast));
    14 promptBuilder.AppendText("A special text line");
    15 promptBuilder.EndStyle();
    16 promptBuilder.EndVoice();
    17 //甚至可以这样播放一段SSML
    18 promptBuilder.AppendAudio("sample.wav");
    19 //传入SpeechSynthesizer
    20 SpeechSynthesizer synthesizer = new SpeechSynthesizer();
    21 synthesizer.SpeakAsync(promptBuilder);

    如代码,我们将PromptBuilder对象直接传给Speak/SpeakAsync中接受PromptBuilder的重载。通过PromptBuilder的ToXml()方法,我们可以得到以xml表示的SSML。作为一个W3C标准XML格式的SSML可以很方便的用于.NET以外的平台。

    Speak与SpeakAsync还有一个接受FilePrompt的重载,通过这个重载我们可以方便的将多种格式的文件传入SpeechSynthesizer,下面代码展示了部分FilePrompt的构建:

    1 synthesizer.SpeakAsync(new FilePrompt("text.txt", SynthesisMediaType.Text)); 
    2 synthesizer.SpeakAsync(new FilePrompt("content.ssml", SynthesisMediaType.Ssml)); 
    3 synthesizer.SpeakAsync(new FilePrompt("sound.wav", SynthesisMediaType.WaveAudio));

    这里我们看到了第二种实现在文本转语言中播放wav的方法。

    语音识别

    语音识别与上文语言合成进行恰好相反的工作,其由音频中提取语言,并将其转换为文本,要使用语音识别需要计算机中安装有语音识别引擎,Windows Vista自带了一个语音识别引擎,Office Xp之后的版本也带有一个语音识别引擎。

    要在代码中实现语音识别也要先添加对System.Speech.dll引用,不同的是这里要引用System.Speech.Recognition命名空间。下面代码给出一个最基本的使用的范例:

    1 SpeechRecognizer recognizer = new SpeechRecognizer(); 
    2 recognizer.SpeechRecognized += new EventHandler<SpeechRecognizedEventArgs>(recognizer_SpeechRecognized);

    当语音被识别后,事件被触发,回调函数被调用,在其中可以处理识别到的文本:

    1 void recognizer_SpeechRecognized(object sender, SpeechRecognizedEventArgs e)
    2 {
    3     textBox.Text += e.Result.Text;
    4 }

    提示:在一个系统上第一次使用语音识别时要先完成一个语音识别向导,另外,在Windows Vista以上版本中,语音识别被集成到任何一个可以获取输入的文本框(WPF或WinForm等程序中的)中,只需要对着麦克风讲话系统就会将识别结果填入文本框中。

     

    使用SRGS

        语音识别规范(SRGS – Speech Recognition Grammar Specification)是W3C标准,你可以定义一个SRGS语法,通过其方便SpeechRecognizer捕获一些有效的输入,并忽略无意义的结果。SRGS也被定义成标准的XML格式,在.NET中使用SRGS,我们需要先构造一个SrgsDocument对象(所有SRGS相关的对象都定义于System.Speech.Recognition.SrgsGrammar命名空间中),下面的代码中我们定义了一个SrgsDocument并将其传入SpeechRecognizer:

    1 SpeechRecognizer recognizer = new SpeechRecognizer(); 
    2 SrgsDocument doc = new SrgsDocument("grammar.xml"); 
    3 recognizer.LoadGrammar(new Grammar(doc));

    上面的例子中,Srgs来自xml文件,我们也可以在内存中定义并使用SRGS。下面的代码中我们定义了一个SrgsDocument,这个文档表示由输入音频中匹配stop和go两条命令。

    1 SpeechRecognizer recognizer = new SpeechRecognizer();
    2 SrgsDocument doc = new SrgsDocument();
    3 SrgsRule command = new SrgsRule("command",new SrgsOneOf("stop","go"));
    4 doc.Rules.Add(command);
    5 doc.Root = command;
    6 recognizer.LoadGrammar(new Grammar(doc));

    使用GrammarBuilder

        如同我们可以使用PromptBuilder方便的构建SSML,.NET中也提供了一个GrammarBuilder对象来定义SRGS;以解决手工编写SRGS xml或使用SrgsGrammar API定义SRGS都很麻烦的问题,下面的代码使用GrammerBuilder实现了与上面代码等价的功能:

    1 SpeechRecognizer recognizer = new SpeechRecognizer();
    2 GrammarBuilder builder = new GrammarBuilder(new Choices("stop","go"));
    3 recognizer.LoadGrammar(new Grammar(builder));

    VideoBrush

    通过使用视频刷可以对一个区域使用视频进行填充,这个画刷SourceName的值需要设置为一个MediaElement控件的x:Name属性。这个MediaElement用来加载视频,我们需要其隐藏并不响应任何鼠标事件,这可以通过将MediaElement的透明度设置为0并将IsHitTestVisible属性设置为false来做到。在加载视频后我们可以通过Stretch等属性控制视频刷的效果。

    下面的示例中,我们通过视频刷绘制文本框的前景色

    1 <TextBlock FontFamily="Courier New" FontSize="72" FontWeight="Bold" TextWrapping="Wrap" Text="Hello">
    2     <TextBlock.Foreground>
    3         <VideoBrush SourceName="vid" />
    4     </TextBlock.Foreground>
    5 </TextBlock>

    关于MediaElement,其对音频及视频的支持统一放到控件之多媒体控件一节介绍

    本文完

    参考:

    《WPF揭秘》

  • 相关阅读:
    12 个最佳 GNOME(GTK)主题
    Ubuntu18.04解决鼠标移动到Gnome顶栏左上角窗口不能平铺( Activites Overview 界面),和应用程序扩展不好用问题。
    常用的GNOME Shell 扩展
    11 个使用 GNOME 3 桌面环境的理由
    值得尝试的十款 GNOME Shell 扩展
    Python快速教程 尾声(转)
    宽恕
    EF code First数据迁移学习笔记(转)
    异步编程 In .NET(转)
    bootstrap + requireJS+ director+ knockout + web API = 一个时髦的单页程序
  • 原文地址:https://www.cnblogs.com/lsxqw2004/p/4632188.html
Copyright © 2011-2022 走看看