您的位置:首页 > 其它

WPF,Silverlight与XAML读书笔记第四十二 - 多媒体支持之音、视频和语音

2013-06-09 09:37 399 查看

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



音频

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

SoundPlayer

MediaPlayer

SoundPlayerAction

MediaElement和MediaLine

SoundPlayer

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

仅支持wave格式音频文件

不支持同时播放多个音频

无法控制音量

下面是一段简单的示例:

SoundPlayer player = new SoundPlayer("lily.wav");
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属性。下面的例子中我们给按钮添加一个事件触发器,实现在点击按钮时播放一段声音。

<Button>A Button With Sounds
<Button.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<EventTrigger.Actions>
<SoundPlayerAction Source="click.wav"/>
</EventTrigger.Actions>
</EventTrigger>
<EventTrigger RoutedEvent="Button.MouseEnter">
<EventTrigger.Actions>
<SoundPlayerAction Source="hover.wav"/>
</EventTrigger.Actions>
</EventTrigger>
</Button.Triggers>
</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属性可以得到当前播放的位置。

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

MediaPlayer player = new MediaPlayer();
player.Open(new Uri("moon.wma", UriKind.Relative));
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中包含了几套不同的语音,使合成语音有不同的效果。仍然通过一段代码来展示语音合成。

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


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

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

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

synthesizer.SelectVoice("Microsoft Sam");


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

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


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

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


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

synthesizer.SetOutputToDefaultAudioDevice();


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

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


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

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

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


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

语音识别

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

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

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


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

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



提示:在一个系统上第一次使用语音识别时要先完成一个语音识别向导,另外,在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:

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


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

SpeechRecognizer recognizer = new SpeechRecognizer();
SrgsDocument doc = new SrgsDocument();
SrgsRule command = new SrgsRule("command",new SrgsOneOf("stop","go"));
doc.Rules.Add(command);
doc.Root = command;
recognizer.LoadGrammar(new Grammar(doc));


使用GrammarBuilder

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

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


VideoBrush

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

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

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


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

本文完

参考:

《WPF揭秘》
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐