服务器项目——精选推荐

服务器项目——精选推荐

2023年7月29日发(作者:)

最近的项目中,要做这样一个功能,在服务器上可以通过播放器针对不同的音箱设备来播放不同的音乐,就像大学里英语角一样,校广播台对不同的活动中心播放的不同的英文广播。当然我们的项目功能类似,但是却也没校园广播那么复杂,校园广播使用了很好的音频设备,我们得控制成本,所以我们的解决方案是:在服务器上安装一块多通道的专业声卡(录音棚用来录音)或者是安装多块普通的声卡。这样我们在播放音乐的时候可以选择输出的声卡,播放界面如下:

如何去做这样一个播放器呢,.net framework中是不是有这个接口,网上找了一下资料,发现有两种方法:

第一种方法是调用win32下的的API函数去播放文件,代码:

using System;

using c;

using ;

using pServices;

namespace HardWaresOperation

{

public class SpeakerBeeper

{

//文件资源

private string SoundSource = @"C:Documents and SettingsAdministrator桌面";

private string SoundSource; public SpeakerBeeper(string _SoundSource)

{

SoundSource = _SoundSource;

}

///

/// 检查声卡,播放声音

///

/// 声音文件

/// 播放成功,返回true

public bool SpeakerBeep()

{

if (tGetNumDevs() != 0)

{

und(SoundSource, ,

_FILENAME | _ASYNC);

return true;

}

else

{

return false;

}

}

}

// 这是辅助的文件

public class SBHelper

{

public enum PlaySoundFlags : int

{

SND_SYNC = 0x0000,//同步

SND_ASYNC = 0x0001,//异步

SND_NODEFAULT = 0x0002,//未找到文件默认为静音

SND_MEMORY = 0x0004,//声音文件来自内存

SND_LOOP = 0x0008, //循环播放

SND_NOSTOP = 0x0010,//不停止目前的播放

SND_NOWAIT = 0x00002000,//当播放器忙碌时不等待

SND_ALIAS = 0x00010000, //为已注册的别名时

SND_ALIAS_ID = 0x00110000, //别名为ID

SND_FILENAME = 0x00020000, //文件名

SND_RESOURCE = 0x00040004 //资源名

}

[DllImport("", EntryPoint = "waveOutGetNumDevs")]

//waveOutGetNumdevs()方法

//当机器有声卡时返回1 //没有声卡返回0

public static extern int waveOutGetNumDevs();

[DllImport("")]

//SoundSource声音文件

//参数hmod是应用程序的实例句柄

//psFlag播放模式

public static extern bool PlaySound(string SoundSource, IntPtr hmod, PlaySoundFlags

psFlag);

}

}

但是发现waveOutGetNumDevs()函数只是用来返回机器是否有声卡,并没有得到机器的声卡设备的列表,知识对当前默认的设备进行播放,达不到要求。

第二种方法就是利用dirextx sdk开发包中的API来开发,这个开发包里面有个DierctSound可以用来开发,在网上找了好久他的中文开发文档,大致看了一遍,就决定动手做了。

一、首先是对DirectSound中的类我需要的调用的函数进行了封装,封装成两个结构体,一个枚举,一个静态类,一个播放类,类图如下:

其中DeviceInfo结构体是硬件信息也是就是声卡的硬件信息,DevId表示硬件的ID号,Description是对硬件的描述,这些信息都是通过DirectSound从声卡的驱动程序中读取出来的。

///

/// 设备信息 ///

public struct DeviceInfo

{

public Guid DevId;

public string Description;

}

DeviceStatus结构体记录播放器的状态,isLooping表示是否循环播放,isPlaying表示正处于播放还是停止,isTerminated表示播放终止。

///

/// 播放状态

///

public struct DeviceStatus

{

///

/// 是否播放

///

public bool isPlaying;

///

///是否循环播放

///

public bool isLooping;

///

/// 是否终止

///

public bool isTerminated;

}

PlayFlags枚举指定播放器是正常播放还是循环播放。

///

/// 设置播放的方式

///

public enum PlayFlags

{

///

/// 正常播放

///

Default,

///

/// 循环播放

///

Looping

};

静态类QBDeviceHelper中的方法GetDeviceList()用来获得机器的声卡列表。 public static class QBDeviceHelper

{

///

/// 获得设备列表(返回设备信息)

///

///

public static List GetDeviceList()

{

List devList = new List();

DevicesCollection myDevices = new DevicesCollection();//获得所有声卡列表

foreach (DeviceInformation dev in myDevices)

{

DeviceInfo dData = new DeviceInfo();

= Guid;

ption = ption;

(dData);

}

return devList;

}

}

播放器类QBAudioCtrl是用来控制播放器的播放,停止等动作。

public class QBAudioCtrl

{

SecondaryBuffer sbuffer = null;

public QBAudioCtrl(Guid DevId, string FileName)

{

try

{

//根据ID建立设备对象

Device dev = new Device(DevId);

//设置设备的优先级

perativeLevel((new ()),

ty);

//设置缓存的属性

BufferDescription bfDes = new BufferDescription();

lPan = true;

lVolume = true;

lFrequency = true;

Focus = true;

//创建二级缓存

sbuffer = new SecondaryBuffer(FileName, bfDes, dev);

= 0;//声音最大

= 0;//混合声道 ncy = sPerSecond;//以正常速度播放

}

catch (Exception e)

{

throw new Exception(e);

}

}

///

/// 播放

///

/// 播放方式(正常,循环)

public void Dev_Play(PlayFlags PlayStyle)

{

//开始播放

if (sbuffer != null)

{

if (g == true)

();

if (PlayStyle == t)

(0, t);//正常播放

else if (PlayStyle == g)

(0, g);//循环播放

}

}

//暂停

public void Dev_Stop()

{

if (sbuffer != null)

();

}

//关闭

public void Dev_Dispose()

{

e();

}

///

/// 获取播放状态

///

///

public DeviceStatus GetDeviceStatus()

{ DeviceStatus thisStatus = new DeviceStatus();

if (sbuffer != null)

{

BufferStatus devStates = ;

thisStatus = new DeviceStatus();

ing = g;//是否循环播放

ing = g;//是否播放

inated = ated;//是否终止

}

return thisStatus;

}

}

以上把基本的类写好了,下面就可以开始编写前台代码了。先来个截图

直接上代码吧

using System;

using c;

using entModel;

using ;

using g;

using ;

using ;

using ;

using QBAudioLib;

namespace QBAudio

{

public partial class Form2 : Form

{

QBAudioCtrl qbCtrl;

DeviceStatus devStauts;

PlayFlags thisFlags;

public Form2()

{

InitializeComponent();

}

private void Form2_Load(object sender, EventArgs e)//初始化

{

//获得所有的音频设备

List devInfo = iceList();

foreach (DeviceInfo dev in devInfo)

{

cBox_();

}

ags = t;

}

private void btn_play_Click(object sender, EventArgs e)//播放

{

try

{

_Play(ags);

devStauts = iceStatus();

lbl_ = "playing:" + ng() + "---looping:" +

ing + "---Terminated:" + inated;

}

catch (Exception ex)

{

(e);

}

}

private void btn_stop_Click(object sender, EventArgs e)//停止

{

try

{

_Stop();

devStauts = iceStatus();

lbl_ = "playing:" + ng() + "---looping:" +

ing + "---Terminated:" + inated;

}

catch (Exception ex)

{

(e);

}

}

private void btn_File_Click(object sender, EventArgs e)//选择播放文件

{

OpenFileDialog filedg = new OpenFileDialog();

= "音视频文件(*.wav)|*.wav";

if (alog() == )

{

if (me != "" || me != )

{

txt_ = me;

}

}

}

private void cBox_Devices_SelectedIndexChanged(object sender, EventArgs e)//选择声卡

{

try

{

//thisDev = (DeviceInfo)cBox_edItem;

Guid devID = (Guid)cBox_edItem;

string fileName = txt_();

if (fileName == null || fileName == )

{

("请选择播放的文件...");

return;

}

qbCtrl = new QBAudioCtrl(devID, fileName);

devStauts = iceStatus();

lbl_ = "playing:" + ng() + "---looping:" + ing + "---Terminated:" + inated;

}

catch (Exception ex)

{

(e);

}

}

private void btn_pause_Click(object sender, EventArgs e)//暂停

{

try

{

_Dispose();

}

catch (Exception ex)

{

(e);

}

}

private void radioButton1_CheckedChanged(object sender, EventArgs e)//设置正常播放

{

if (d)

{

thisFlags = t;

btn_play_Click(sender, e);

}

}

private void radioButton2_CheckedChanged(object sender, EventArgs e)//设置循环播放

{

if (d)

{

thisFlags = g;

btn_play_Click(sender, e);

}

}

}

}

但上面的例子中,只能播放单一文件,如果要是多个文件选择多个声卡同时播放呢?想到使用多线程来实现,再次封装多线程播放类

AudioPalyer类,有三个事件,当播放时触发OnAudioPlay事件,当循环播放时触发OnLoopingPlay事件,当正常播放时触发OnNormalPlay事件,代码如下:

using System;

using c;

using ;

using ;

using QBAudioLib;

using ing;

namespace QBAudioThread

{

public struct playInfo

{

public Guid devId;

public string fileName;

public PlayFlags thisFlag;

}

public class AudioEventArgs : EventArgs

{

public playInfo AudioPlayInfo;

}

public class AudioPlayer

{

QBAudioCtrl qbCtrl;

DeviceStatus devStauts;

playInfo thisInfo;

public delegate void DefEventHandler(object sender,AudioEventArgs args);

public event DefEventHandler OnAudioPlay;//开始播放事件 public event EventHandler OnNormalPaly;//默认正常播放时事件

public event EventHandler OnLoopingPaly;//循环播放时事件

public AudioPlayer(playInfo iPlay)

{

thisInfo = iPlay;

}

public void Audio_Play()

{

(this);

}

}

}

界面实现:qbCtrl = new QBAudioCtrl(, me);

_Play(ag);

devStauts = iceStatus();

//开始播放激发的事件

if (ing == true)

{

AudioEventArgs thisArgs = new AudioEventArgs();

layInfo = thisInfo;

OnAudioPlay(this, thisArgs);

}

if (ing == false)

{//默认播放激发的事件

OnNormalPaly(this, new EventArgs());

}

else

{//循环播放激发的事件

OnLoopingPaly(this, new EventArgs());

}

(this);

(1000);

代码:

using System;

using c;

using entModel;

using ;

using g;

using ;

using ;

using ;

using QBAudioLib;

using ing;

namespace QBAudioThread

{

public partial class Form2 : Form

{

PlayFlags thisFlags;

DataTable dt = new DataTable();

Thread threadPlay;

public Form2()

{

InitializeComponent();

}

private void Form2_Load(object sender, EventArgs e)

{

//获得所有的音频设备

List devInfo = iceList();

foreach (DeviceInfo dev in devInfo)

{

cBox_(new KeyValuePair(,

ption));

}

cBox_edIndex = 0;

ags = t;

("devId", typeof(Guid));

("fileName", typeof(string));

("thisFlag", typeof(PlayFlags));

urce = dt;

}

private void btn_play_Click(object sender, EventArgs e)//播放

{

try

{

int i = 0;

foreach (DataGridViewRow row in )

{

if ((bool)[0].FormattedValue == true)

{

playInfo thisPlay = new playInfo();

= (Guid)["devId"].Value;

me = ["fileName"].ng();

ag = (PlayFlags)["thisFlag"].Value;

AudioPlayer myPlayer = new AudioPlayer(thisPlay);

oPlay += new

ntHandler(myPlayer_OnAudioPlay); ingPaly += new

EventHandler(myPlayer_OnLoopingPaly);

alPaly += new

EventHandler(myPlayer_OnNormalPaly);

threadPlay = new Thread(new ThreadStart(_Play));

= "player_" + ng();

();

ground = true;

i++;

}

}

}

catch (Exception ex)

{

(e);

}

}

void myPlayer_OnAudioPlay(object sender,AudioEventArgs args)

{

playInfo myplay = (playInfo)layInfo;

string msg = ng() + "rn正在播放rn" + me +

"rn";

(msg);

}

void myPlayer_OnNormalPaly(object sender, EventArgs e)

{

("Normal");

}

void myPlayer_OnLoopingPaly(object sender, EventArgs e)

{

//播放一分钟后终止线程

("Looping");

}

private void btn_File_Click(object sender, EventArgs e)//选择播放文件

{

OpenFileDialog filedg = new OpenFileDialog();

= "音视频文件(*.wav)|*.wav";

if (alog() == )

{

if (me != "" || me != )

{

txt_ = me;

}

}

}

private void cBox_Devices_SelectedIndexChanged(object sender, EventArgs e)//选择声卡

{

}

private void radioButton1_CheckedChanged(object sender, EventArgs e)//选择默认播放

{

if (d)

{

thisFlags = t;

}

}

private void radioButton2_CheckedChanged(object sender, EventArgs e)//选择循环播放

{

if (d)

{

thisFlags = g;

}

}

private void btn_add_Click(object sender, EventArgs e)//添加进列表

{

DataRow dr = (); dr["devId"] = ((KeyValuePair)cBox_edItem).Key;

dr["fileName"] = txt_();

dr["thisFlag"] = thisFlags;

(dr);

urce = dt;

}

private void btn_clear_Click(object sender, EventArgs e)//清除列表

{

}

}

}

();

urce = dt;

发布者:admin,转转请注明出处:http://www.yc00.com/web/1690645168a384994.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信