使用MCI接口播放音乐

时间:2022-07-30 10:55:35

      在C#中播放音乐主要有三种方式:1、System.Media.SoundPlay;2、MCI接口;3、MediaPlayer控件。SoundPlay是专门用来播放声音的,即.wav文件,使用方法比较简单。MediaPlayer控件是系统自带的播放器,关于它的介绍已经很多了。

      今天我想为大家介绍的MCI接口,关于MCI接口的介绍,大家可以参考MSDN,这里我们只是介绍具体的用法。首先,我们需要定义一个枚举类型来描述播放器的状态。

  public enum PlayState : byte
{
Playing = 1,
Puased = 2,
Stopped = 3,
}


      接下来,为了便于后面的继续,我们对MCI接口做了一个封装:

  class WAPI
{
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern int GetShortPathName(
string lpszLongPath,
string shortFile,
int cchBuffer
);
[DllImport("winmm.dll", EntryPoint = "mciSendString", CharSet = CharSet.Auto)]
public static extern int mciSendString(
string lpstrCommand,
string lpstrReturnString,
int uReturnLength,
int hwndCallback
);
}

      关于这两个API函数,大家可以在MSDN找到相关说明。接下来,我们来构建播放器的类:

 public class MPlayer
{
//定义歌曲地址
private string Url = string.Empty;
//定义歌曲结构的实例
private Media m = new Media();
//构造函数
public MPlayer()
{
m.Position = 0;
m.State = PlayState.Stopped;
m.Volume = 0;
m.Speed = 1000;
m.Duration = 0;
}


//FileName属性
public string FileName
{
set
{
Url = string.Empty;
string Name = value;
m.Position = 0;
Url = Url.PadLeft(260, ' ');
WAPI.GetShortPathName(Name, Url, Url.Length);
Url = GetFileUrl(Url);
InitDevice();
}
}

//设备初始化
private void InitDevice()
{
string DeviceID = GetDeviceID(Url);//返回类型
WAPI.mciSendString("Close All", null, 0, 0);//关闭所有设备
if (DeviceID != "RealPlay")
{
string MciCommand = String.Format("Open {0} type {1} Alias Media", Url, DeviceID);
WAPI.mciSendString(MciCommand, null, 0, 0);//初始化设备
m.State = PlayState.Stopped;
}
}

//获取设备ID
private string GetDeviceID(string Url)
{
string Result = string.Empty;
Url = Url.ToUpper().Trim();
if (Url.Length < 3)
{
return Url;
}
switch (Url.Substring(Url.Length - 3))
{
case "MID":
Result = "Sequencer";
break;
case "RMI":
Result = "Sequencer";
break;
case "IDI":
Result = "Sequencer";
break;
case "WAV":
Result = "Waveaudio";
break;
case "ASX":
Result = "MPEGVideo2";
break;
case "IVF":
Result = "MPEGVideo2";
break;
case "LSF":
Result = "MPEGVideo2";
break;
case "LSX":
Result = "MPEGVideo2";
break;
case "P2V":
Result = "MPEGVideo2";
break;
case "WAX":
Result = "MPEGVideo2";
break;
case "WVX":
Result = "MPEGVideo2";
break;
case ".WM":
Result = "MPEGVideo2";
break;
case "WMX":
Result = "MPEGVideo2";
break;
case "WMP":
Result = "MPEGVideo2";
break;
case ".RM":
Result = "RealPlay";
break;
case "RAM":
Result = "RealPlay";
break;
case ".RA":
Result = "RealPlay";
break;
case "MVB":
Result = "RealPlay";
break;
default:
Result = "MPEGVideo";
break;
}
return Result;
}

//得到当前路径
private string GetFileUrl(string FileName)
{
FileName = FileName.Trim();//去掉空格
if (FileName.Length > 1)//判断是否为空(name包含'\0')
{
FileName = FileName.Substring(0, FileName.Length - 1);//去掉'\0'
}
return FileName;
}

//判断初始化后设备是否准备好接受命令
public bool IsReady()
{
string Ready = new string(' ', 10);
WAPI.mciSendString("Status Media Ready", Ready, Ready.Length, 0);
Ready = Ready.Trim();
if (Ready.Contains("true"))
{
return true;
}
else
{
return false;
}
}

//播放
public void Play()
{
if (m.State != PlayState.Playing)
{
WAPI.mciSendString("Play Media", null, 0, 0);
m.State = PlayState.Playing;
}
}

//停止
public void Stop()
{
if (m.State != PlayState.Stopped)
{
WAPI.mciSendString("Stop Media", null, 0, 0);
m.State = PlayState.Stopped;
}
}

//暂停
public void Puase()
{
if (m.State == PlayState.Playing)
{
WAPI.mciSendString("Pause Media", null, 0, 0);
m.State = PlayState.Puased;
}
}

//恢复播放
public void Resume()
{
int RefInt = WAPI.mciSendString("Resume Media", null, 0, 0);
m.State = PlayState.Playing;
}

//属性Duration
public int Duration
{
get
{
WAPI.mciSendString("Set Media Time Format Milliseconds", null, 0, 0);//设置时间格式单位为毫秒
m.Duration = GetDuration();
return m.Duration;
}
}

private int GetDuration()
{
string Length = string.Empty;
Length = Length.PadLeft(20, ' ');//设置定长字符串long是19位,足够表示时间了
WAPI.mciSendString("Status Media Length", Length, Length.Length, 0);
Length = Length.Trim();
if (Length.Length > 1)
{
Length = Length.Substring(0, Length.Length - 1);
return (int)(long.Parse(Length) / 1000);
}
return 0;
}

//属性State
public PlayState State
{
get
{
return m.State;
}
}

public string PositionString
{
get
{
string mm = (this.Position / 60).ToString("00");
string ss = (this.Position % 60).ToString("00");
return mm + ":" + ss;
}
}

public string DurationString
{
get
{
string mm = (this.Duration / 60).ToString("00");
string ss = (this.Duration % 60).ToString("00");
return mm + ":" + ss;
}
}
//设置获取当前时间
public int Position
{
get
{
string Position = string.Empty;
Position = Position.PadLeft(20, ' ');//long表示范围是19位
WAPI.mciSendString("Status Media Position", Position, Position.Length, 0);
Position = Position.Trim();
if (Position.Length > 1)
{
m.Position = (int)(long.Parse(Position) / 1000);//以秒返回
}
return m.Position;
}
set
{
string Command = String.Format("Seek Media to {0}", value*1000);
WAPI.mciSendString(Command, null, 0, 0);//使播放停止
m.State = PlayState.Stopped;
m.Position = value*1000;
Play();
}
}

//设置静音
public void VolumeOff(bool IsOff)
{
string SetOnOff = string.Empty;
if (IsOff)
SetOnOff = "Off";
else
SetOnOff = "On";
string MciCommand = String.Format("Set Audio Media {0}", SetOnOff);
WAPI.mciSendString(MciCommand, null, 0, 0);
}

//Volume
public int Volume
{
get
{
return m.Volume;
}
set
{
if (value >= 0)
{
m.Volume = value;
string MciCommand = String.Format("Set Audio Media Volume To {0}", m.Volume);
WAPI.mciSendString(MciCommand, null, 0, 0);
}
}
}
//定义歌曲结构
private struct Media
{
public int Position;
public PlayState State;
public int Volume;
public int Speed;
public int Duration;
}
}

         关于这个类,我想说两点,第一:在设置Position属性即歌曲的进度时,我们对其赋值为value*1000.为什么要乘1000呢?因为在获取Position时为们做了单位转换,除了1000,所以这里要乘以1000,否则程序将不起作用。第二:使用MCI播放的时候,经常会发出嘶嘶的杂音,我的解决办法是,在播放前设置歌曲进度为1秒,即歌曲并不从头开始播放,这样就可以跳过去了,呵呵。好吧,就这样了,睡觉啦!