1、第六章 多媒体,学习目的,所谓多媒体,一般是指多种传播信息的载体, 可以包括语言、文字、图像、视频、音频等。计算机多媒体技术就是利用计算机把文字、图形、影象、动画、声音及视频等媒体信息数字化,并用计算机设备呈现给使用者。 学习本章要求能够掌握处理音频、视频、动画和语音的编程方法。,主要内容,6.1 WPF动画 6.2 音频支持 6.3 视频支持 6.4 语音功能介绍,6.1 WPF动画,以每秒5-30幅速度得到动画场景(包括运动物体)瞬间的若干幅静止图片,每幅静止图片被称作一帧,然后按照动作发生的时间顺序,以相同速度播放这些图片,利用人眼视觉暂留特性,重新看到运动场景,这种技术被称作动画。,6
2、.1.1 DispatcherTimer类定时器,2.16节曾经介绍了3种定时器,本节介绍第4种定时器DispatcherTimer类。该类是集成到按指定时间间隔和指定优先级处理的 Dispatcher 队列(参见7.2.3节)中的定时器,该定时按属性Interval指定的时间间隔周期性地自动触发Tick事件。,6.1.2 传统实现动画方法,可改变控件属性值来实现动画,例如下例通过修改正方形控件透明度属性Opacit使其慢慢消失,传统的实现方法是使用定时器事件,在事件函数中修改正方形属性Opacit。 【例6.1】本例在窗体增加一个蓝色正方形,其属性Opacit初始值为1.0。用定时器控制正方
3、形属性Opacity每0.2秒减少0.02,当5秒后,正方形属性Opacity=0,正方形消失。重新令正方形属性Opacity=1.0,重复以上动作。这是一个利用改变属性实现动画的例子。 (1)建立新项目,在窗体增加一个蓝色正方形,在Grid标记中增加如下标记:(2)增加引用命名空间语句: using System.Windows.Threading;,(3)在Window1构造函数最后增加如下语句: DispatcherTimer timer = new DispatcherTimer(); timer.Interval = TimeSpan.FromMilliseconds(100); t
4、imer.Tick += new EventHandler(timer_Tick); timer.Start(); (4)定时器timer的Tick事件函数如下: void timer_Tick(object sender, EventArgs e) rectangle1.Opacity -= 0.02;if (rectangle1.Opacity = 0) rectangle1.Opacity = 1.0; (5)编译运行,可以看到正方形逐渐消失,看不到后,又恢复到原始状态,重新消失。,6.1.3 DoubleAnimation类动画,DoubleAnimation是一个动画类,是Timel
5、ine类的派生类,将Timeline类对象作为内置定时器(又称时间线),可指定定时器的运行时间总长度、开始时间、重复次数、定时间隔等。该类可自动对目标控件的Double类型属性进行控制,完成动画。其常用属性如下: From、To和By:目标控件的Double类型属性的开始值、结束值和增加值。 Duration:Duration类对象,表示播放的时间长度。 BeginTime:TimeSpan类对象,指定动作延迟时间。 AutoReverse:布尔类型,是否重复动作。,Timeline类派生类DoubleAnimation类对象必须放到时间线容器(又称演示图板)中,即Storyboard标记中,
6、其附加属性TargetName和TargetProperty分别为实现动画的控件对象名称和该控件被控制的属性。可控制时间线容器Storyboard开始工作、停止工作、暂停工作,重新工作等,这些动作分别用如下类表示:BeginStoryboard、StopStoryboard、PauseStoryboard、ResumeStoryboard。 【例6.2】本例实现例6.1的相同功能。在Grid标记中增加如下标记。编译运行后,鼠标右击矩形,矩形颜色逐渐变淡,直至消失,重复这个动作。, 如果不希望鼠标左击矩形后矩形立即开始动画,可以在DoubleAnimation 标记中增加如下属性:BeginTi
7、me=“0:0:5“,则在鼠标左击矩形后5秒,矩形开始动画,周期5秒不变。,【例6.3】本例用代码实现例6.2的相同功能。在Grid标记中增加标记:增加引用命名空间语句: using System.Windows.Media.Animation; 为MyRectangle的Load事件增加事件函数如下: private void MyRectangle_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) DoubleAnimation DA = new DoubleAnimation();DA.From = 1.0;DA.To
8、= 0.0;,DA.Duration = TimeSpan.FromSeconds(5);DA.AutoReverse = true;DA.RepeatBehavior = RepeatBehavior.Forever; MyRectangle.BeginAnimation(Rectangle.OpacityProperty, DA); 【例6.4】本例修改例6.3,当用鼠标左击矩形,矩形开始动画,右击动画停止当前动画重新开始。在标记Rectangle.Triggers中的EventTrigger标记的后边,增加如下标记。,6.1.4 动画类,Double类型动画类DoubleAnimatio
9、n仅能控制Double类型属性实现动画。为了控制其他不同类型的属性来完成属性动画,必须要有不同数据类型的动画类型,.Net3.5在命名空间System.Windows.Media.Animation中定义了多个不同类型动画类,例如DecimalAnimation、ColorAnimation、PointAnimation、ByteAnimation、Int16Animation等,一般称为属性动画类。 【例6.5】本例实现在正方形逐渐消失时,正方形颜色也发生变化。XAML标记如下,注意阴影部分定义了一个刷子以及在时间线容器中增加一个ColorAnimation类对象,,【例6.6】更简单实现方
10、法是仅在例6.2的DoubleAnimation标记后边增加如下标记:除了用DoubleAnimation类实现属性动画外,WPF还用DoubleAnimationUsingKeyFrames类实现关键帧动画,用DoubleAnimationUsingPath类实现在屏幕上使对象沿指定路径移动动画。同DoubleAnimation类似,后两个类也有不同数据类型的动画类型。,6.1.5 关键帧动画,关键帧动画是指在动画所有帧中仅人工生成一些帧,称为关键帧,其余帧由程序自动生成的动画技巧。该技术的核心是关键帧之间帧的计算,计算方法依赖于插值算法。关键帧技术可极大地减少人工计算的数据量。 关键帧动画
11、类也是用改变属性的值方法完成动画,WPF为关键帧动画类提供了3种插值方法:线形插值、样条插值和不插值。WPF提供了多个处理不同类型属性的关键帧动画类,为简单起见,这里仅以处理Double类型属性的DoubleAnimationUsingKeyFrames类为例说明关键帧动画类的插值方法,对应三个插值方法的3个类为:LinearDoubleKeyFrame、SplineDoubleKeyFrame和DiscreteDoubleKeyFrame。,【例6.7】本例使用DoubleAnimationUsingKeyFrames类实现关键帧线形插值动画。将如下标记替换新项目的Grid标记,编译运行后,
12、将在窗体左上角看到一个小球,每单击小球后,小球将按折线运动一次。标记中包括两个动画动作,控制小球的水平和垂直运动,第一个动画是属性动画,第二个是关键帧线形插值动画。,【例6.8】本例实现关键帧样条插值动画。修改上例中的关键帧线形插值动画标记如下。编译运行后看一下小球运动轨迹和上例有何不同。,【例6.9】本例实现不插值(离散值)动画。修改上例中的关键帧样条插值动画标记如下,编译运行后看一下小球运动轨迹和上例有何不同。,【例6.10】集合属性KeyFrames的元素可以是不同插值动画类。修改上例中的关键帧样条插值动画标记如下。编译运行后看一下小球运动轨迹和上例有何不同。,【例6.11】本例实现一个
13、行走的小人的动画,参见书上193-194,6.1.6 基于路径的动画,DoubleAnimationUsingPath类用来实现在屏幕上使对象沿指定路径移动动画。上节例子中的小球实际也是沿指定路径运动,不过其路径相对较简单,如果希望实现对象沿复杂路径运动,就必须使用DoubleAnimationUsingPath类,该类PathGeometry为被控制对象移动的路径,它应是一个PathGeometry类对象,属性Source=“X“(或Y)表示使用移动路径的X(或Y)坐标。在下例中用到ArcSegment类,它描述一段弧,属性Size为弧所在椭圆的X和Y轴半径,属性Point为弧终点在椭圆的坐
14、标,属性RotationAngle为椭圆围绕X轴旋转的量(以度为单位),属性IsLargeArc指示弧是否应大于180度,属性SweepDirection指定是以 Clockwise (顺时针)方向还是以Counterclockwise(逆时针)方向绘制弧。注意弧没有起点,决定弧所在容器,下例为Canvas。,【例6.12】本例使小球沿着一个椭圆弧旋转。用如下标记替换Grid标记,注意本例控制小圆沿资源指定的椭圆旋转,标记Storyboard.TargetProperty=“(Canvas.Left)“和Source=“X“意义是控制的属性是小圆距离窗体的X坐标。,6.2 音频支持,6.2.1
15、 SoundPlayer类 System.Media.SoundPlayer类提供了加载和播放指定文件路径wav声音文件或URL中包含wav 文件流(Stream)的功能。该类同时只能播放一个wav文件。其常用属性和方法如下: 构造函数: SoundPlayer(); public SoundPlayer(Stream stream); /参数为包含.wav文件的流 public SoundPlayer(string soundLocation); /参数为指定路径的.wav文件,【例6.13】本例使用第3个构造函数。建立新项目,增加按钮,其事件函数如下: private void butto
16、n1_Click(object sender, RoutedEventArgs e) System.Media.SoundPlayer sP = new System.Media.SoundPlayer(“E:应用程序设计教程(第二版)Exampletest2.wav“);sP.Play(); /在另一线程(参见第7章)播放该文件,如使用PlaySync方法则在同一线程播放 /如在同一线程播放,播放时将不能响应其他事件,属性SoundLocation:记录要加载的wav文件的文件路径或URL。 【例6.14】本例修改例6.13按钮的事件函数如下: private void button1_Cl
17、ick(object sender, RoutedEventArgs e) System.Media.SoundPlayer sP = new System.Media.SoundPlayer();sP.SoundLocation = “E:应用程序设计教程(第二版)Exampletest2.wav“;sP.Play(); ,方法LoadAsync():在新线程(参见第7章)中加载wav文件,在加载前必须首先指定属性SoundLocation。在从网络上加载wav文件时是必须的,以免在加载时影响当前工作。加载完成后,引发LoadCompleted 事件。使用System.Media.Syste
18、mSounds类还可以播放常见的系统声音,例如提示音。 SystemSounds.Beep.Play(); /播放蜂鸣声,还可播放其他系统声音,6.2.2 SoundPlayerAction类,SoundPlayer类是Net2.0中的类,不支持XAML,为了支持XAML,在Net3.5种提供了System.Windows.Controls.SoundPlayerAction类,该类也仅能同时播放一个wav文件。 【例6.15】本例实现单击按钮时发声。Grid标记中: Button,6.2.3 MediaPlayer类,System.Windows.Media.MediaPlayer类用于播放
19、音频、视频以及包含音频的视频,本节仅介绍播放音频的方法。使用MediaPlayer类,必须安装微软的Windows Media Player10及以上版本,MediaPlayer类支持Media Player10支持的所有播放文件格式。使用MediaPlayer类可以很容易创建一个媒体播放器。 【例6.16】使用MediaPlayer类播放音频文件最简单例子。在窗体增加按钮,其事件函数如下,单击按钮将播放指定文件的音乐,自动识别不同扩展名的文件。 private void button1_Click(object sender, RoutedEventArgs e) MediaPlayer p
20、layer = new MediaPlayer();player.Open(new Uri(“E:应用程序设计教程(第二版)Exampletest2.wav“);player.Play(); ,MediaPlayer类常用方法和属性如下,这些方法和属性原则上也适合视频。 方法public void Open(Uri source):将参数指定文件作为播放文件,根据文件扩展名选择播放方式。将播放媒体初始位置作为当前播放位置。 方法public void Pause():暂停播放,保留当前播放位置。 方法public void Play():从当前位置播放媒体。 方法public void Sto
21、p():停止媒体播放,将播放媒体初始位置作为当前播放位置。 属性Balance:左右扬声器音量之间的平衡,介于-1到1范围内的Double类型数据,-1表示100%的左侧扬声器,为1表示100%的右侧扬声器,默认值为 0。,属性Clock:为了控制音频或视频的播放节奏,MediaPlayer类需要一个播放时钟,MediaPlayer类对象默认内建时钟,称为内部时钟模式。从该属性可以得到内建时钟,该时钟是MediaClock类对象。也可以为MediaPlayer类制定一个外部播放时钟,称为外部时钟模式。如果指定了外部时钟,就不能使用MediaPlayer类的Play、Pause、Stop等方法及
22、属性Position控制媒体播放、暂停、停止等功能,必须使用MClock.Controller类中的方法。参见例6.18。 只读属性NaturalDuration:Duration类对象,播放文件所需总时间。 属性Position:TimeSpan类对象,表示已播放的持续时间。 属性Source:Uri 类表示的媒体文件位置。 属性Volume:音频输出音量,用Double类型0与1数据表示音量。默认值为 0.5。,一个音频播放器应有如下功能:暂停和播放键、停止从新开始、进度条并可以拖动、显示总时间和当前时间进度,控制音量、静音、循环以及如何显示歌词。 利用以上属性和方法可以实现音频播放器播放
23、大部分功能。其中进度条只要和属性Position关联即可。循环播放可在播放结束后的MediaEnded事件函数中重新从开始位置播放即可。显示歌词需要歌词文件,并和播放的音乐同步,也是可以实现的。有兴趣读者可以试验一下。 MediaPlayer类不能用XAML标记。,6.2.4 MediaElement类,System.Windows.Controls.MediaElement类克服了MediaPlayer类不能用XAML标记缺点,完全支持XAML,该类属性及方法和MediaPlayer类类似,也有方法Play、Pause和Stop,有属性Balance、NaturalDuration、Posi
24、tion、Clock、Source和Volume,只要将属性LoadedBehavior设置为Manual,表示装载播放的媒体文件后,采用手工控制,即使用Play、Pause和Stop等方法控制,就可以方便地象使用MediaPlayer类那样控制媒体文件播放。,【例6.17】用MediaElement播放音频文件,实现指定播放文件、暂停和重新播放功能。 (1)建立新项目,在Grid标记中放置MediaElement控件,标记如下:(2)MediaElement类MediaEnded事件函数如下: private void Element_MediaEnded(object sender, Ro
25、utedEventArgs e) p.Stop(); ,(3)增加三个按钮,标题分别是:指定文件、播放、暂停。事件函数如下: private void button1_Click(object sender, RoutedEventArgs e) p.Source = new Uri(“E:应用程序设计教程(第二版)Exampletest.wav“); private void button2_Click(object sender, RoutedEventArgs e) p.Play(); private void button3_Click(object sender, RoutedEve
26、ntArgs e) p.Pause(); (4)编译运行,单击播放按钮,可以播放XAML标记指定的文件,单击暂停按钮,暂停播放,再单击播放按钮,从暂停位置继续播放。单击指定文件按钮,可播放另一文件音频。,6.2.5 MediaTimeLine类,System.Windows.Media.MediaTimeline类是一个Timeline对象,不能单独使用,播放音频和视频就必须和MediaElement类或MediaPlayer类一起使用。该类具有一些MediaElement类没有的控制媒体播放的方式,例如属性Duration可以修改媒体播放的时间长度,属性BeginTime可以指定在装入播放文
27、件后延迟播放的时间,属性AutoReverse指示播放完成后是否反向播放,属性RepeatBehavior指定播放重复次数或连续播放。下边通过一个实例,说明MediaTimeline类用法。,【例6.18】使用MediaTimeline类播放音频文件最简单例子。首先在Window1.xaml.cs头部增加如下语句: using System.Windows.Media.Animation; 在窗体增加按钮,其事件函数如下,单击按钮将播放指定文件的音乐。 private void button1_Click(object sender, RoutedEventArgs e) MediaTimel
28、ine mTimeline = new MediaTimeline(new Uri(“E:应用程序设计教程(第二版)Exampletest.wav“);mTimeline.RepeatBehavior = RepeatBehavior.Forever; MediaClock mClock = mTimeline.CreateClock();MediaPlayer player = new MediaPlayer();player.Clock = mClock; mClock.Controller.Begin(); ,MediaClock类属性Controller是ClockController
29、类对象,用一些方法来控制时钟的开始、暂停、恢复、查找、停止和移除,这些方法包括:Begin()、Pause()、Resume()、Seek()、Stop()和Remove。音频是通过时钟进行播放的,对时钟控制实际就是对播放进行控制。 【例6.19】本例用MediaTimeline类实现例6.15的功能,即单击按钮时发声。将如下XAML标记放到Grid标记中。MediaTimeline标记中的属性Storyboard.TargetName是播放音频的MediaElement类对象名。标记的意义参见6.1.3节。 Button,6.3 视频支持,6.3.1 MediaElement类 【例6.20
30、】将如下标记放到Grid标记中。编译运行,可以看到一个时钟图像,时钟指针每秒移动一次指向下一时间,同时用数字显示当前时间,并响一下。6.2.4节已介绍了该类的一些属性,这些属性也可以控制视频。如将例6.17中打开的音频文件更改为视频文件,将打开视频文件播放,并能用按钮实现暂停播放和重新播放功能。该类是一个控件,因此也有控制控件大小、位置等属性,支持布局,由于视频在控件中播放,因此有Stretch属性,表示如何视频图像如填充控件,可以是:None、Fill、Uniform、UniformToFill。还支持Clip属性,用其指定的封闭图形裁剪已填充的视频图像。,【例6.21】设定MediaEle
31、ment控件的大小及填充方式,并用一个圆裁剪视频图像。将如下标记放到Grid标记中。,【例6.22】本例实现视频播放器的截图功能。将如下标记放到Grid标记中。,为Grid控件增加MouseLeftButtonDown事件函数Grid_MouseLeftButtonDown如下。编译运行后,播放时钟视频,单击时钟图像,将在Image控件显示截图。private void Grid_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) RenderTargetBitmap bit = new RenderTargetBitmap(i
32、nt)me.ActualWidth, (int)me.ActualHeight, 96, 96, PixelFormats.Pbgra32);bit.Render(me);image1.Source = BitmapFrame.Create(bit); ,6.3.2 MediaTimeLine类,【例6.23】用MediaTimeLine类播放视频文件,并实现暂停播放和重新播放功能。将如下标记放到Grid标记中。,PlayPauseResume上例MediaTimeLine使用MediaElement作为播放窗体。也可将播放内容放到VisualBrush画刷中,这样就可以在任何可以使用画刷的地
33、方播放视频,例如具有BackGround、Fill属性的控件。,【例6.24】MediaTimeLine用VisualBrush画刷播放。在Window1构造函数最后增加如下语句,编译运行可看到播放的视频。 MediaTimeline line = new MediaTimeline(); line.Source = new Uri(“E:应用程序设计教程(第二版)Examplebutterfly.wmv“); VideoDrawing v = new VideoDrawing(); v.Player = new MediaPlayer(); v.Rect = new Rect(0, 0, 3
34、00, 300); v.Player.Clock = line.CreateClock(); Background = new DrawingBrush(v);,6.3.3 MediaPlayer类,MediaPlayer类用于播放音频、视频以及包含音频内容的视频,如果打开视频文件,该类就播放视频,6.2.3节中介绍的控制音频的方法同样也可以控制视频,但前提是为播放的视频图像提供一个播放窗口,一般是将播放内容放到VisualBrush画刷中,这样就可以在任何可以使用画刷的地方播放视频,例如具有BackGround、Fill属性的控件。,【例6.25】使用MediaPlayer类播放视频文件。在
35、Window1构造函数最后增加如下语句,编译运行可看到播放的视频。MediaPlayer player = new MediaPlayer();player.Open(new Uri(“E:应用程序设计教程(第二版)Examplebutterfly.wmv“);VideoDrawing v = new VideoDrawing();v.Player = player ;v.Rect = new Rect(0, 0, 300, 300); Background = new DrawingBrush(v);player.Play();,6.4 语音功能介绍,语音功能包括语音合成和语音识别。语音合成主要用途是提供文本朗读功能,语音识别是将人类的语音变为文本。.Net 3.5包括一套新的语音API,位于System.Speech命名空间,该API和WPF没有任何关系,可以在任何.Net程序中使用。,