05 进阶音效控制与管理
来源:互联网 发布:三菱q系列plc编程实例 编辑:程序博客网 时间:2024/06/05 01:53
摘要
以 XNA 为基础的游戏程序可以利用 SoundEffect 类别的功能执行简单的音效播放,或是利用 SoundEffectInstance 类别进行进阶的音效播放控制,包括播放、暂停、恢复、结束、是否要播放 3D 的音效、控制声音从左边或右边的声道输出、控制音调高低、以及控制音量等等。在这一回的文章中,我们将介绍利用 SoundEffectInstance 类别进行进阶音效控制的做法,除此之外,我们也将会介绍支持组织和管理声音文件的 XACT(Cross-platform Audio Creation Tool) 工具。
有关 XNA Framework 提供的 SoundEffect 类别和 SoundEffectInstance 类别的基本功能和使用方法可以参考 [XNA 交互式游戏设计] 一文的说明。
进阶音效控制
Windows Phone 7 智能型手机并非只能播放一种音效,以 XNA 为基础的游戏程序可以同时播放 64 种声音,达成混合多种音效的效果。除此之外,XNA Framework 也支持动态播放音效,例如播放应用程序执行时期建立的音效,或是搭配麦克风播放由外界输入的音效。
[提示]
Windows Phone 7 智能型手机支持同时播放多达 64 种的音效,但是 Xbox 360 游戏机支持播放多达 300 种的音效,可以播放更丰富的声音效果,而 Windows 操作系统则是未限制可以同时播放的音效数目。
当游戏程序想要仿真环绕音效的时候,可以利用 SoundEffectInstance 类别的 Pan 属性控制音效要从左方发声,还是要从右方发声。Pan 属性是一个介于 -1.0 与 1.0 之间的数值,其值为 -1.0 表示要从左方发声,其值为 1.0 表示要从右方发声,而其值为 0 则表示要从中央发声,其默认值为 0。
当游戏程序需要控制所播放的音效的音调高低时,就可以利用 SoundEffectInstance 类别的 Pitch 属性进行控制。Pitch 属性是一个介于 -1.0 与 1.0 之间的数值,其值为 -1.0 表示音调最低,其值为 1.0 表示音调最高,其默认值为 0。
当游戏程序需要控制所播放的音效的音量时,就可以利用 SoundEffectInstance 类别的 Volume 属性进行控制。Volume 属性是一个介于 .0 与 1.0 之间的数值,其值为 0 表示音量最小 (静音),其值为 1 表示音量最大,其默认值为 1。请注意透过 SoundEffectInstance 类别控制的音量取决于 SoundEffect 类别的 MasterVolume 属性的内容值,换句话说将 SoundEffectInstance 类别的 Volume 属性的内容值设定为 1,所呈现的最大音量就是 SoundEffect 类别的 MasterVolume 属性设定的音量。
例如游戏程序想呈现环绕音效的效果,可以先把欲播放的声音文件加入到 Content Pipeline 项目中,然后于 Game1 类别宣告以下的变量,负责管理音效资源、SoundEffectInstance 类别的对象、以及记录音效移动的方向:
SoundEffect RingOut;//管理音效資源的變數SoundEffectInstance RingOutEffect;//管理 SoundEffectInstance 類別的物件的變數bool bPaneLeft = false;//記錄音效移動方向的變數
宣告妥变量之后请于 Game1 类别的 LoadContent 方法加入以下的程序代码,负责加载音效资源和建立 SoundEffectInstance 类别的对象:
RingOut = Content.Load<SoundEffect>("RingOut");//載入名稱為 RingOut 的音效資源RingOutEffect = RingOut.CreateInstance();//建立 SoundEffectInstance 類別的物件RingOutEffect.IsLooped = true;//設定音效要不斷地重覆播放
加载音效资源并建立妥 SoundEffectInstance 类别的对象之后,我们只要在 Game1 类别的 Update 方法中变更 SoundEffectInstance 类别的对象的 Pan 属性的内容值,就可以变更音效发声的位置,例如以下的程序:
if (bPaneLeft)//判斷音效發聲的位置是否為往左移動{ if (RingOutEffect.Pan - 0.1 <= -1)//如果已經無法往左移動 { RingOutEffect.Pan = -1f;//設定音效從左方發聲 bPaneLeft = true;//設定移動方向為往右移動 } else RingOutEffect.Pan -= 0.1f;//設定發聲位置往左移動 0,1}else//音效發聲的位置為往右移動{ if (RingOutEffect.Pan + 0.1 >= 1)//如果已經無法往右移動 { RingOutEffect.Pan = 1f;//設定音效從右方發聲 bPaneLeft = false;//設定移動方向為往左移動 } else RingOutEffect.Pan += 0.1f;//設定發聲位置往右移動 0,1}
做好之后请执行程序,游戏程序播放的音效就会从逐渐移至右方发声,移至最右方之后再逐渐移至左方进行发声,移至最左方之后再逐渐移至右方进行发声,周而复始,仿真音效环绕的效果。
[提示]
以 XNA 为基础的游戏程序可以使用类似的技巧控制所播放的音效的音调和音量,仿真音量由大变小,由小变大,或是音调由高变低,或是由低变高的效果。
动态音效支持
XNA Game Studio 4.0 在支持音效控制方面加入了一些新的控制功能,包括支持从 PCM 格式的音效数据流建立 SoundEffect 类别的对象,直接从 PCM 格式的音效数据流进行播放动态音效的功能,以及录制从麦克风输入的声音的功能,详细说明如下:
- XNA Game Studio 4.0 支持的 SoundEffect 类别的建构函式允许接受 PCM 格式的数据流型态的参数,建立能够从 PCM 格式的数据流播放音效的 SoundEffect 类别的对象。以下就是一个能够利用第一个参数指定 PCM 格式的音效数据流用来建立 SoundEffect 类别的对象的建构函式:
public SoundEffect ( byte[] buffer, int sampleRate, AudioChannels channels)
以下就是利用 TitleContainer 类别的 OpenStream 方法从扩展名为 .wav 格式的声音文件读入 PCM 格式的音效数据流,再据以建立 SoundEffect 类别的对象:
SoundEffect soundFromFile = SoundEffect.FromStream(TitleContainer.OpenStream(@"Content\Sample.wav")); //利用 WAV 格式音效檔案的內容建立 SoundEffect 類別的物件soundFromFile.Play();//播放 SoundEffect 類別的物件管理的音效資料
使用上述的方式播放音效数据流,以 XNA 为基础的游戏程序仍然需要将欲播放的 WAV 格式的声音文件预先加入到 Content Pipeline 项目,但是必须将 WAV 格式的声音文件的 [Build Action] 属性的内容值从默认的 Compile 改成 Content,再将 [Copy to Output Directory] 属性的内容值改成:Copy always,表示不要将 WAV 格式的声音文件建置成 XNB 格式的二进制数据,而要随着游戏程序一起部署到 Windows Phone 7 智能型手机,供游戏程序执行时期加载使用,并直接从 WAV 格式的声音文件加载欲播放的音效。
[注意]
第一个参数限制必须为 PCM 格式、频率为 8KHz 或 48KHz、单声道或立体声的音效数据。
- 除了 SoundEffect 类别能够支持播放格式为音效数据流的音效之外,XNA Game Studio 4.0 提供的 DynamicSoundEffectInstance 类别也支持游戏程序于运行时间建立音效数据,供游戏程序执行的时候播放。DynamicSoundEffectInstance 类别常用的属性请参考表1 的说明:
DynamicSoundEffectInstance 类别常用的方法请参考表2 的说明:
欲使用 DynamicSoundEffectInstance 类别执行动态音效播放,您可以于 Game1 类别宣告以下的变量:
DynamicSoundEffectInstance dynamicSound;//管理 DynamicSoundEffectInstance 類別//的物件的變數int position; //指定從第幾個位元組的音效資料開始播放int count;//指定欲播放的音效的位元組數byte[] byteArray;//存放音效資料的位元組陣列
然后于 Game1 类别的 LoadContent 方法加入以下的程序代码,从声音文件读入欲播放的音效数据:
Stream waveFileStream = TitleContainer.OpenStream(@"Content\RingOut.wav"); //依據欲播放的音效檔案建立 Stream 類別的物件BinaryReader reader = new BinaryReader(waveFileStream);//為 Stream 類別的物件建立 BinaryReader 類別的物件int chunkID = reader.ReadInt32();//讀取 Chunk IDint fileSize = reader.ReadInt32();//讀取檔案大小int riffType = reader.ReadInt32();//讀取 riff 型態int fmtID = reader.ReadInt32();//讀取 fmt IDint fmtSize = reader.ReadInt32();//讀取 fmt 大小int fmtCode = reader.ReadInt16();//讀取 fmt codeint channels = reader.ReadInt16(); //讀取 channel 數目int sampleRate = reader.ReadInt32();//讀取 Sample Rateint fmtAvgBPS = reader.ReadInt32(); //讀取 fmt 的平均 BPSint fmtBlockAlign = reader.ReadInt16();//讀取 fmt Block Align 數據int bitDepth = reader.ReadInt16();//讀取位元深度if (fmtSize == 18) //如果 fmt 大小為18{ int fmtExtraSize = reader.ReadInt16(); //讀取 fmt 額外的大小 reader.ReadBytes(fmtExtraSize); //讀入等同於 fmt 額外大小的資料}int dataID = reader.ReadInt32();//讀取音效資料 IDint dataSize = reader.ReadInt32(); //讀取音效資料大小byteArray = reader.ReadBytes(dataSize); //將音效資料大小的音效資料讀入到緩衝區dynamicSound = new DynamicSoundEffectInstance(sampleRate, (AudioChannels)channels);//依據 Sample Rate 和 Channel 建立 DynamicSoundEffectInstance 類別的物件count = dynamicSound.GetSampleSizeInBytes(TimeSpan.FromMilliseconds(100));//依據依據存放音效資料時間長度計算資料量dynamicSound.BufferNeeded += new EventHandler<EventArgs>(DynamicSound_BufferNeeded);//指定處理 BufferNeeded 事件的事件處理程序dynamicSound.Play();//播放 DynamicSoundEffectInstance 類別的物件管理的音效
接下来请为 Game1 类别加入以下的方法,负责处理 DynamicSoundEffectInstance 类别的对象的 BufferNeeded 事件:
void DynamicSound_BufferNeeded(object sender, EventArgs e){ dynamicSound.SubmitBuffer(byteArray, position, count);//從 byteArray 陣列第 position 位元組開始,取出 count 個位//元組供 DynamicSoundEffectInstance 類別的物件進行播放 position += count;//遞增 position 變數的內容值 if (position + count > byteArray.Length) //如果 byteArray 陣列的內容已全部播放完畢 { position = 0;//將 position 變數的內容值歸零 }}
[注意]
使用上述的方式播放音效数据流,以 XNA 为基础的游戏程序仍然需要将欲播放的 WAV 格式的声音文件预先加入到 Content Pipeline 项目,但是必须将 WAV 格式的声音文件的 [Build Action] 属性的内容值从默认的 Compile 改成 Content,再将 [Copy to Output Directory] 属性的内容值改成:Copy always,表示不要将 WAV 格式的声音文件建置成 XNB 格式的二进制数据,而要随着游戏程序一起部署到 Windows Phone 7 智能型手机,供游戏程序执行时期加载使用,并直接从 WAV 格式的声音文件加载欲播放的音效。
做好之后请按下 Ctrl+F5 组合键执行游戏程序,就可以听到 DynamicSoundEffectInstance 类别的对象播放的动态音效。
- XNA Game Studio (4.0) 提供的 Microphone 类别可以协助程序利用 Windows Phone 7 内建的麦克风录制外界输入的声音。有关 Microphone 类别常用的属性可以参考表4 的说明:
Microphone 类别常用的方法可以参考表5 的说明:
Microphone 类别常用的事件请参考表6的说明:
接下来我们就要利用 Microphone 类别提供的类别,录制透过 Windows Phone 7 内建的麦克风输入的声音,供程序进行播放。
首先请于 Game1 类别宣告以下的变量,负责管理 DynamicSoundEffectInstance 类别的对象:
DynamicSoundEffectInstance sound;
然后于 Game1 类别的 Initialize 方法加入以下的程序代码,负责启动录音的动作:
sound = new DynamicSoundEffectInstance(Microphone.Default.SampleRate, AudioChannels.Mono);//利用麥克風預設的 Sample Rate 錄製單聲道的聲音//處理錄製妥透過麥克風輸入的聲音引發的 BufferReady 事件Microphone.Default.BufferReady += (a, b) =>{ byte[] data = new byte[Microphone.Default.GetSampleSizeInBytes(Microphone.Default.BufferDuration)];//建立存放聲音資料的位元組陣列 Microphone.Default.GetData(data);//取得錄製的聲音,並儲存到 data 位元組陣列中 sound.SubmitBuffer(data);//將位元組陣列的內容交給 DynamicSoundEffectInstance 類//別的物件進行播放};Microphone.Default.Start();//啟動麥克風執行錄製聲音的工作
最后我们只要在 Game1 类别的 Update 方法中加入以下的程序代码,在录制5秒钟的声音之后停止录制的动作,并将录制妥的声音交由 DynamicSoundEffectInstance 类别的对象进行播放:
if (gameTime.TotalGameTime.TotalSeconds > 5)//如果錄製的時間是否超過 5 秒{ Microphone.Default.Stop();//關閉麥克風錄音的功能 sound.Play();//將錄製妥的聲音交由 DynamicSoundEffectInstance 類別的物件進行播放}
做好之后请执行程序,然后对麦克风讲话,5 秒钟之后,程序就会播放刚刚录制的声音。
范例下载:AdvSoundEffect.zip
- 05 进阶音效控制与管理
- 進階音效控制與管理
- Android 游戏音效控制
- RPG2.0音效控制
- 分布式进阶(六)之集群控制管理
- 游戏音乐音效添加管理
- 音效管理类
- Unity 音效管理
- Quota与进阶文件管理
- 项目风险管理与控制
- Cocos2d-x 3.0心得(05)-音效管理
- Unity3d 音效 音乐 大小控制
- Unity添加音效与音效衰减
- Java进阶---数组与内存控制
- 音乐与音效
- 音效与音乐
- 音效与音乐
- 音频引擎IrrKlang学习笔记01:播放控制与音效设置
- 2014华为招聘(武汉站)机试 2013年10月9日
- Area(poj1654多边形面积)
- 【Cocos2d-x】Win7+ vs2012,2010 + Cocos2d-x2.2 配置Cocos2d-X项目-环境
- [转]撞车之后,不要傻里傻气的!这里有绝招!
- nmon安装配置文档
- 05 进阶音效控制与管理
- 蓝牙核心技术
- 自动文本分类
- Java的泛型初窥
- 类成员函数指针的使用方式
- 2014斐讯通信校园招聘宣讲会+笔试
- Tomcat调优总结
- JavaServlet之http协议(二)
- jQuery 实例运用