多多色-多人伦交性欧美在线观看-多人伦精品一区二区三区视频-多色视频-免费黄色视屏网站-免费黄色在线

國(guó)內(nèi)最全I(xiàn)T社區(qū)平臺(tái) 聯(lián)系我們 | 收藏本站
阿里云優(yōu)惠2
您當(dāng)前位置:首頁(yè) > php開(kāi)源 > php教程 > [C#] 控制系統(tǒng)音量-第二章

[C#] 控制系統(tǒng)音量-第二章

來(lái)源:程序員人生   發(fā)布時(shí)間:2014-12-23 08:50:09 閱讀次數(shù):3272次

========================================================
作者:qiujuer
博客:blog.csdn.net/qiujuer
網(wǎng)站:www.qiujuer.net
開(kāi)源庫(kù):Genius-Android
轉(zhuǎn)載請(qǐng)注明出處:http://blog.csdn.net/qiujuer/article/details/41575517

========================================================

引入

在很久之前寫(xiě)了1篇 [C#] 控制系統(tǒng)音量-第1章 ,忘記是甚么時(shí)候?qū)懙牧耍徊贿^(guò)并沒(méi)有忘記有這回事兒,不過(guò)看見(jiàn)沒(méi)有甚么人需要所以就沒(méi)有出后面的文章了。前天突然看見(jiàn)評(píng)論有人需要,所以覺(jué)得有必要完善1下;總結(jié)了1下這是第2章,同時(shí)也是終章;之前準(zhǔn)備寫(xiě)多章仔細(xì)分析1下的,現(xiàn)在看來(lái)就介紹1下如何使用吧。

問(wèn)題

在第1章中,控制電腦音量是能夠?qū)崿F(xiàn)的,但是只支持XP系統(tǒng);這無(wú)疑是糟的;現(xiàn)在這個(gè)階段使用XP的還有多少?本篇為支持Win7及其以上版本音量控制而生。

兼容性(C#)

Win7、Win8、Win8.1

前戲

在開(kāi)始之前有必要介紹1下 Core Audio APIs ,甚么是 Core Audio APIsCore Audio APIs 是微軟在WIn7以后提供的1套用于控制系統(tǒng)音量的Api,其具有以下特點(diǎn):

  1. 低延時(shí),幾近無(wú)故障的音頻流。
  2. 提高可靠性 ( 很多音頻函數(shù)從核心態(tài)移到了用戶態(tài) )
  3. 提高了安全性 (在安全的,低優(yōu)先級(jí)別的線程處理被保護(hù)的音頻內(nèi)容)
  4. 分配了特定的系統(tǒng)級(jí)別的規(guī)則 (console, multimedia, communications) 給單獨(dú)的音頻裝備。
  5. 用戶可以直接操作,相應(yīng) endpoint 裝備的軟件抽象 ( 如:擴(kuò)音器,耳麥及麥克風(fēng) ) 以下的高層 API 是以 Core Audio APIs 來(lái)工作的。

相干介紹:

http://msdn.microsoft.com/en-us/library/dd370802(VS.85).aspx

http://msdn.microsoft.com/en-us/library/dd370784(v=vs.85).aspx

固然這里我們其實(shí)不是直接使用此API,由于其是C++的調(diào)用接口,在這里對(duì)其進(jìn)行了封裝,封裝成C#下能直接調(diào)用的dll文件;后面添加。

CoreAudioApi.dll 包結(jié)構(gòu):


在這里就不詳細(xì)介紹其中代碼,打包時(shí)會(huì)同時(shí)把 CoreAudioApi.pdb 文件打包,在調(diào)試時(shí)能進(jìn)入其中查看代碼。

至于導(dǎo)入 DLL 到項(xiàng)目中,這個(gè)也無(wú)需說(shuō)了吧。

CodeTime

在這里還要進(jìn)行1次簡(jiǎn)單的調(diào)用簡(jiǎn)化封裝,封裝為 VolumeControl class.

VolumeControl.cs

namespace Volume { public class VolumeControl { private static VolumeControl _VolumeControl; private MMDevice device; public event AudioNotificationDelegate OnAudioNotification; public bool InitializeSucceed; public static VolumeControl Instance { get { if (_VolumeControl == null) _VolumeControl = new VolumeControl(); return _VolumeControl; } } private VolumeControl() { MMDeviceEnumerator DevEnum = new MMDeviceEnumerator(); try { device = DevEnum.GetDefaultAudioEndpoint(EDataFlow.eRender, ERole.eMultimedia); device.AudioEndpointVolume.OnVolumeNotification += new AudioEndpointVolumeNotificationDelegate(AudioEndpointVolume_OnVolumeNotification); InitializeSucceed = true; } catch { InitializeSucceed = false; } } private void AudioEndpointVolume_OnVolumeNotification(AudioVolumeNotificationData data) { if (InitializeSucceed && this.OnAudioNotification != null) { this.OnAudioNotification(null, new AudioNotificationEventArgs() { MasterVolume = data.MasterVolume * 100, Muted = data.Muted }); } } public double MasterVolume { get { return InitializeSucceed ? device.AudioEndpointVolume.MasterVolumeLevelScalar * 100 : 0; } set { if (InitializeSucceed) { device.AudioEndpointVolume.MasterVolumeLevelScalar = (float)(value / 100.0f); if (this.IsMute) this.IsMute = false; } } } public bool IsMute { get { return InitializeSucceed ? device.AudioEndpointVolume.Mute : true; } set { if (InitializeSucceed)device.AudioEndpointVolume.Mute = value; } } public double[] AudioMeterInformation { get { if (InitializeSucceed) { try { return new double[3]{ device.AudioMeterInformation.MasterPeakValue * 100.00, device.AudioMeterInformation.PeakValues[0] * 100, device.AudioMeterInformation.PeakValues[1] * 100 }; } catch { return new double[3] { 0, 0, 0 }; } } else return new double[3] { 0, 0, 0 }; } } } public delegate void AudioNotificationDelegate(object sender, AudioNotificationEventArgs e); public class AudioNotificationEventArgs : EventArgs { public double MasterVolume { get; set; } public bool Muted { get; set; } } }
可以看到,在代碼中為了外面調(diào)用的方便性,我們采取了單列模式,固然這里沒(méi)有單獨(dú)對(duì)多線程添加鎖的機(jī)制。可自行添加其  Instance 部份。

其中有4個(gè)變量:

  • VolumeControl 固然是為了單列而生的
  • MMDevice 實(shí)際的音量操作,來(lái)自于封裝了1次的 CoreAudioApi.dll 庫(kù)
  • AudioNotificationDelegate 可以看見(jiàn)最后面的地方實(shí)際上是1個(gè)事件拜托,用于事件的通知,主要作用是當(dāng)系統(tǒng)音量改變時(shí)通知主界面進(jìn)行刷新界面
  • InitializeSucceed 這個(gè)是用于記錄是不是初始化成功的參數(shù);固然可以去掉

static VolumeControl Instance 用于保證單列的運(yùn)行

在類的構(gòu)造函數(shù)中,可以看到:

MMDeviceEnumerator DevEnum = new MMDeviceEnumerator(); device = DevEnum.GetDefaultAudioEndpoint(EDataFlow.eRender, ERole.eMultimedia); device.AudioEndpointVolume.OnVolumeNotification += new AudioEndpointVolumeNotificationDelegate(AudioEndpointVolume_OnVolumeNotification);
其中 實(shí)例化了1個(gè) MMDeviceEnumerator 類,然后初始化了 MMDevice 屬性;同時(shí)在這里進(jìn)行了注冊(cè)事件,讓音量改變時(shí)調(diào)用方法 AudioEndpointVolume_OnVolumeNotification()

而在方法 AudioEndpointVolume_OnVolumeNotification() 中又調(diào)用了當(dāng)前類的拜托事件,用于觸發(fā)事件刷新界面;同時(shí)對(duì)傳遞的參數(shù)進(jìn)行了封裝;封裝為了類:AudioNotificationEventArgs

在類 AudioNotificationEventArgs 中:

public class AudioNotificationEventArgs : EventArgs { public double MasterVolume { get; set; } public bool Muted { get; set; } }
包括兩個(gè)屬性,分別是當(dāng)前音量大小和是不是靜音。

繼續(xù)分析我們的主類:

public double MasterVolume { get { return InitializeSucceed ? device.AudioEndpointVolume.MasterVolumeLevelScalar * 100 : 0; } set { if (InitializeSucceed) { device.AudioEndpointVolume.MasterVolumeLevelScalar = (float)(value / 100.0f); if (this.IsMute) this.IsMute = false; } } } public bool IsMute { get { return InitializeSucceed ? device.AudioEndpointVolume.Mute : true; } set { if (InitializeSucceed)device.AudioEndpointVolume.Mute = value; } }
這兩個(gè)屬性,分別用于設(shè)置與獲得當(dāng)前主音量大小和是不是靜音操作的封裝。

public double[] AudioMeterInformation { get { if (InitializeSucceed) { try { return new double[3]{ device.AudioMeterInformation.MasterPeakValue * 100.00, device.AudioMeterInformation.PeakValues[0] * 100, device.AudioMeterInformation.PeakValues[1] * 100 }; } catch { return new double[3] { 0, 0, 0 }; } } else return new double[3] { 0, 0, 0 }; } }
該方法用于獲得當(dāng)前的音量信息,分別是主音量左聲道右聲道

ViewCode

在這里使用WPF作為示例,界面代碼:

<Grid Margin="10"> <Grid.ColumnDefinitions> <ColumnDefinition /> <ColumnDefinition /> </Grid.ColumnDefinitions> <StackPanel> <Label Content="音量" /> <Label Content="主聲道:" Margin="0,10,0,0"/> <ProgressBar x:Name="mMasterPBar" Minimum="0" Maximum="100" Width="170" HorizontalAlignment="Right" Margin="0,0,10,0"/> <Label Content="左聲道:" Margin="0,10,0,0"/> <ProgressBar x:Name="mLeftPBar" Minimum="0" Maximum="100" Width="170" HorizontalAlignment="Right" Margin="0,0,10,0"/> <Label Content="右聲道:" Margin="0,10,0,0"/> <ProgressBar x:Name="mRightPBar" Minimum="0" Maximum="100" Width="170" HorizontalAlignment="Right" Margin="0,0,10,0"/> <Label Content="操作:" Margin="0,20,0,0" HorizontalAlignment="Right" /> </StackPanel> <Slider Grid.Column="1" Name="mMasterVolumeSlider" Orientation="Vertical" Height="200" Maximum="100" ValueChanged="mMasterVolumeSlider_ValueChanged" /> </Grid>

對(duì)應(yīng)的界面:


界面代碼:

public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); InitializeAudioControl(); } private void Page_Loaded(object sender, RoutedEventArgs e) { volumeControlTimer.Start(); } private void Page_Unloaded(object sender, RoutedEventArgs e) { volumeControlTimer.Stop(); } private VolumeControl volumeControl; private bool isUserChangeVolume = true; private DispatcherTimer volumeControlTimer; private void InitializeAudioControl() { volumeControl = VolumeControl.Instance; volumeControl.OnAudioNotification += volumeControl_OnAudioNotification; volumeControl_OnAudioNotification(null, new AudioNotificationEventArgs() { MasterVolume = volumeControl.MasterVolume }); volumeControlTimer = new DispatcherTimer(); volumeControlTimer.Interval = TimeSpan.FromTicks(150); volumeControlTimer.Tick += volumeControlTimer_Tick; } void volumeControl_OnAudioNotification(object sender, AudioNotificationEventArgs e) { this.isUserChangeVolume = false; try { this.Dispatcher.Invoke(new Action(() => { mMasterVolumeSlider.Value = e.MasterVolume; })); } catch { } this.isUserChangeVolume = true; } void volumeControlTimer_Tick(object sender, EventArgs e) { double[] information = volumeControl.AudioMeterInformation; mMasterPBar.Value = information[0]; mLeftPBar.Value = information[1]; mRightPBar.Value = information[2]; } private void mMasterVolumeSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e) { if (isUserChangeVolume) { volumeControl.MasterVolume = mMasterVolumeSlider.Value; } } }

還是從屬性開(kāi)始,3個(gè)屬性:

VolumeControl 這個(gè)很簡(jiǎn)單了吧,就是上面封裝的成果

isUserChangeVolume 這個(gè)是用于排除系統(tǒng)回調(diào)時(shí)觸發(fā) Slider 控件的 ValueChanged() 事件,避免無(wú)窮循環(huán)

DispatcherTimer 用于刷新界面中的音量條

開(kāi)始說(shuō)說(shuō)方法:

InitializeAudioControl() 用于初始化 VolumeControl 同時(shí),添加事件回調(diào),和初始化 DispatcherTimer Timer 

volumeControl_OnAudioNotification() 回調(diào)方法

volumeControlTimer_Tick() 這個(gè)就是 DispatcherTimer 刷新界面的方法

mMasterVolumeSlider_ValueChanged() 這個(gè)就更加簡(jiǎn)單了,界面的事件觸發(fā)方法

必要說(shuō)明:

在用戶撥動(dòng)界面的屬性條的時(shí)候會(huì)觸發(fā) mMasterVolumeSlider_ValueChanged() 這時(shí)候 isUserChangeVolume True 所以能調(diào)用進(jìn)行音量改變;

而當(dāng)音量改變進(jìn)程中(也包括用戶使用系統(tǒng)的音量條時(shí))將會(huì)觸發(fā) volumeControl_OnAudioNotification() 方法進(jìn)行回調(diào),而在 volumeControl_OnAudioNotification() 方法中,我們首先 將isUserChangeVolume = false

然后使用拜托的封裝類進(jìn)行界面更改;這時(shí)候界面音量條更改必將會(huì)觸發(fā) mMasterVolumeSlider_ValueChanged()  方法,這時(shí)候 isUserChangeVolume False 狀態(tài),所以不會(huì)再次進(jìn)行音量的更改調(diào)用,故而避免死循環(huán)狀態(tài)出現(xiàn);

在最后事件觸發(fā)完后固然是把 isUserChangeVolume 重新設(shè)置為 True 了。


至于其他應(yīng)當(dāng)都是1看就懂了,界面加載完成時(shí)就 讓刷新線程工作,而界面 Unloaded 時(shí)自然就停止工作,避免過(guò)剩消耗。


END

附上本次的示例代碼,和 DLL 庫(kù),都打包在1個(gè)文件夾中了。

win7 win8 C# 音量控制 Volume

生活不易,碼農(nóng)辛苦
如果您覺(jué)得本網(wǎng)站對(duì)您的學(xué)習(xí)有所幫助,可以手機(jī)掃描二維碼進(jìn)行捐贈(zèng)
程序員人生
------分隔線----------------------------
分享到:
------分隔線----------------------------
關(guān)閉
程序員人生
主站蜘蛛池模板: 中文字幕第8页 | 欧美综合一区 | 亚洲精品一区专区 | 亚洲 日本 欧美 | 68久久久久欧美精品观看 | 99精品欧美一区二区三区 | 中午字幕在线观看 | 精品一区二区三区四区乱码90 | 免费网站在线观看高清版 | 国产一区二区三区日韩 | 日韩精品国产一区 | 另类天堂| 9丨精品国产高清自在线看 ⅹxx日本护土 | 欧美18videosex性欧美乱任 | 欧美 日韩 国产在线 | 最近最新中文字幕大全2019免费视频 | 自拍偷拍二区 | 国产成人综合亚洲一区 | 日本久久综合 | 亚洲国产欧美在线成人aaaa | 国产精品亚洲第一区在线28石 | 亚洲欧洲免费 | 精品日韩一区二区三区视频 | 最近免费中文字幕大全高清mv | 欧美日本一二三区 | 五月视频 | 欧美极品videosvideo激情 欧美极品video粗暴 | 亚洲日韩欧美综合 | 午夜影院免费看 | 国产不卡的一区二区三区四区 | 欧美激情精品久久久久久久 | 亚洲综合视频在线 | 精品久久中文字幕有码 | 看黄色免费网站 | 亚洲女人天堂 | 国产高清一区二区 | 日本大片免费一级 | 国产亚洲精品美女久久久久 | 日本一级毛片视频无遮挡免费 | 国产成人高清一区二区私人 | 免费中日高清无专码有限公司 |