利用mciSendString播放音频

  最近在写音频播放器,不过有点懒散,开发进度很慢,一天只做了一点点东西。其实就是让程序能播放音频。这个在我大二学winform程序开发时书上有说,那是书上教的是用media player的COM组件,而且当时什么也不会,写出来的东西只能播放单个音频。要播放完整个播放表的所有歌曲,必须得在播放完一个音频时点击播放下一个音频,也就是不懂得自动切换音频。当时也有想过,如果能获取到一个音频的长度就好了,但是那时候不懂得百度,即使百度了也不懂得那些Thread啊什么的。

  现在对Thread有了一些认识,也用过系统的API,感觉写个播放器完完全全没问题,而且对一个单纯用于听歌的播放器有点自己的想法。于是上网搜搜相关资料。

  不出我的所料,播放音频能够通过系统API来实现。其实播放音频有两种方式,第一种就是我大二时看书说的用media player的COM组件;第二种就是网上找到的系统API。

  这篇文章呢就不是说我怎么怎么写播放器,而是说说我在使用这个系统API时的一些感想罢了。

  用到的API函数有两个一个是GetShortPathName,另一个是mciSendString,同时还有一些在调用这些函数时用到的字符串遍历,下面则是函数声明和字符串变量的声明

 

[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函数使用的字符串变量  
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
        public string Name = "";
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
        public string durLength = "";
        [MarshalAs(UnmanagedType.LPTStr, SizeConst = 128)]
        public string TemStr = "";
    

  GetShortPathName方法主要是在载入音频文件时用得到,其他地方没发现用得着它。主要是用mciSendString,这些函数在MSDN上都能找到详细的介绍,经发现其实用micSendString播放音乐就相当于发一系列的命令,由函数的第一个参数名就看出来了,可是MSDN上的那些指令的介绍我还没看得明白,我所用到的指令都是在网上查回来的,说起来挺笨拙的,开了一个音频播着,然后就弄个文本框输入各种各样的指令,看看这条指令对不对,这个很像我现在从事的工作里的有个操作——串口调试。

好了,既然说是通过指令的,那下面则把用到的指令分门别类地罗列一下

  • 载入文件

open "+ 文件名  + " alias media

这里的文件名并不是平时资源管理器中的文件名或者全文件名,而是通过调用GetShortPathName方法得出来的文件名。alias 后面跟着那个media 其实是对当前打开的音频作一个命名而已。这个命名是不唯一不能重复,但接着播放音乐,暂停、停止等操作都要用到它的。

  • 设置格式

set media time format milliseconds

这里就用到上面的那个命名了,这里设成milliseconds(毫秒)是干嘛的呢,我也没弄清楚,我试过设成seconds都是同样没变化的。

播放动作控制

play media                 //重头开始播放

pause media     //暂停播放

resume media   //继续播放

close media       //停止播放

close all              //关闭所有

play media FROM  N To M //从N毫秒处开始播放到M处毫秒结束,不过这条命令可以不要后面的To M

  • 关于时间

status media position        //当前音频的播放进度

status media length  //当前音频的长度

传这两个命令的时候,接收值就要用到micSendString方法的第二个参数了。

  • 关于音量

setaudio media volume to Number   //设置音量大小

这里的Number是0~1000的范围

setaudio media off                               //关闭声音

setaudio media on                                //开启声音

这个呢我只在我自己的系统Win7下试过,XP就没试过不知怎么,Win7的系统音频是一个合成器的模式,

每个进程都有它独立的音量设置,与系统的音量不同,我们平时设置的音量其实是扩音器的音量。因此这里只能设当前进程的音量。并不会影响系统的音量。而且调节了音量在系统音频合成器是看不到音量的滑块有变化的,包括静音。这一点我看了别的播放器,像我上面截图的KuGoo啊,QQ影音也是这样子的。其实还有另外的一个API函数可以设置音量的,那个函数就能改变上图的音量滑块了,但是仍然改变不了扬声器的音量大小。我还想到一点,就是QQ影音和有一些视频网站,它能把声音调到100%以上,我最初有想过做成那样子,不过现在没找到方法,那个估计要对音频的声音波形放大的。还有一个就是这个音频操作只对当前播放的音频起作用,切换到下一个音频的时候之前设的音量啊,开闭音量都没作用的。

       现在命令介绍完了,到说使用那个micSendString的状况了。

  我曾经尝试开多线程去播放音乐,就是一条线程就载入一个音频,播放这样子。结果呢,一首歌没播完,然后播另一首歌时,两首歌同时响起,用了close all,stop这些命令都没效果,后来发现了这个与调用micSendString方法时传进去的第二个参数有关系,也就是说播放一个音频的过程中发送的所有命令通通都用同一个lpstrReturnString对象做参数好了。

  上面一段说到播放一个音频就用同一个lpstrReturnString对象,要做到这个才能正常操作,而且也很节省资源,不用每次都构造一个新的对象。但也不能省过头,我试过播放多个音频都用了同一个lpstrReturnString对象,结果到有时候就发送命令失效了,要想得到音频的长度获取不到,要想播放音频,没播放。

  以上的两个问题我都找到了解决的办法。但是下面这个我就想不明白是什么回事了。用winform程序去调用micSendString能成功调用,能播放到,但是同样的代码放到一个控制台里面就不一定能调用成功了,会播放不了的。为什么说不一定呢,当我建项目时选控制台类型,生成的exe它是播不了的,当我建项目是winform类型,生成把它改成控制台类型,生成的控制台又能成功播放了。网上有种说法是说“那个micSendString是跟窗体关联的,控制台调用的话就播放不了的。”但我觉得还是解释不了我这个奇怪的现象。呵呵!这个还要等各位园友来指教啊!

  虽然对micSendString接触了几天,但我知道还是理解不透彻的,以上有什么说错的还得请各位园友批评指正。谢谢!

原文地址:https://www.cnblogs.com/HopeGi/p/3263850.html