利用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 = )]
public string Name = "";
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = )]
public string durLength = "";
[MarshalAs(UnmanagedType.LPTStr, SizeConst = )]
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接触了几天,但我知道还是理解不透彻的,以上有什么说错的还得请各位园友批评指正。谢谢!
利用mciSendString播放音频的更多相关文章
- C#调用mciSendString播放音频文件
mciSendString函数是一个WinAPI,主要用来向MCI(Media Control Interface)设备发送字符串命令. 一.函数的声明如下: private static exter ...
- 【转】Android播放音频MediaPlayer的几种方式介绍
接下来笔者介绍一下Android中播放音频的几种方式,android.media包下面包含了Android开发中媒体类,当然笔者不会依次去介绍,下面介绍几个音频播放中常用的类: 1.使用MediaPl ...
- windows 自带winmm.dll播放音频问题
同事用的一个录音小程序在他机器上可以用,换了两个电脑不能用,获取音频长度时总是0,检查代码也没有发现具体问题.最后发现是电脑声卡驱动的问题.更新声卡驱动好了. 附上播放音频的代码: 首先,导入dll文 ...
- .NET winform播放音频文件
前提:最近要求做一个在winform端做一个音频文件播放的功能,至此,总结最近搜寻的相关资料. 一.微软提供了三种方式来播放音频文件 1.通过System.Media.SoundPlayer来播放 2 ...
- 【Android】播放音频的几种方式介绍
接下来笔者介绍一下Android中播放音频的几种方式,android.media包下面包含了Android开发中媒体类,当然笔者不会依次去介绍,下面介绍几个音频播放中常用的类: 1.使用MediaPl ...
- iOS 9音频应用播放音频之音量设置与声道设置
iOS 9音频应用播放音频之音量设置与声道设置 iOS 9音频应用音量设置 音量又称响度.音强,是指人耳对所听到的声音大小强弱的主观感受,其客观评价尺度是声音的振幅大小.在iOS 9音频应用的应用中, ...
- VC++中MCI播放音频文件 【转】
MCI播放mp3音频文件例程 源文件中需要包含头文件 Mmsystem.h,在Project->Settings->Link->Object/libray module中加入库 Wi ...
- python中的多线程编程与暂停、播放音频的结合
先给两个原文链接: https://blog.csdn.net/u013755307/article/details/19913655 https://www.cnblogs.com/scolia/p ...
- FFmpeg学习3:播放音频
参考dranger tutorial,本文将介绍如何使用FFmpeg解码音频数据,并使用SDL将解码后的数据输出. 本文主要包含以下几方面的内容: 关于播放音频的需要的一些基础知识介绍 使用SDL2播 ...
随机推荐
- ISO/IEC 9899 C语言标准(非官方翻译)
本系列博文将以ISO/IEC 9899最新的官方手册为准,然后再添加GCC以及Clang编译器对标准的扩展. 本系列博文将不仅仅是针对C编程语言(C Programming Language)标准的翻 ...
- CSV - 操作比较
在数据报表生成的时候,我们一般会用程序去生成CSV.其中有些需要注意的地方. log_file = open('delay.%s.csv' % s_end, 'w') log_file.write(' ...
- Linux(Centos)下jdbc连接oracle速度超慢的问题
最近在centos下写个java swing程序,发现在linux用jdbc连接oracle及其缓慢,还经常失败.但是同样的程序在windows下运行就连接的非常快.网上搜索了很长时间都和我这情况没关 ...
- ODAC (V9.5.15) 学习笔记(二十)大数据量获取处理
ODAC获取数据的效率比较高,在Web程序中希望能够更快获取第一页的数据时,可以有几种方式: 1.在数据库中进行分页处理: 2.获取所有数据,只是快速返回第一页数据. 第一种方案对应用服务器资源消耗最 ...
- java之内部类(InnerClass)----非静态内部类、静态内部类、局部内部类、匿名内部类
提起java内裤类(innerClass)很多人不太熟悉,实际上类似的概念在c++里面也有,那就是嵌套类(Nested Class),关于这俩者的区别,在下文中会有对比.内部类从表面上看,就是在类中定 ...
- 在ubuntu下配置apache运行python脚本
2008-12-05 常用的简单命令 sudo apt-get remove --purge apache apache2 (彻底删除) sudo /etc/init.d/apache2 r ...
- Using the Cordova Camera API
使用ionic开发一款android或ios应用,估计少不了使用到Camera API,这里记录下使用过程. 创建空的ionic应用 ionic start myTabs tabs 通过cd demo ...
- 【NS2仿真】UDP协议
# # cbr # \ # udp sink # \ / # n0--------5M 2ms---------n1 # # set ns [new Simulator] set f [open ou ...
- SNF开发平台WinForm之七-单据打印和使用说明-SNF快速开发平台3.3-Spring.Net.Framework
8.1运行效果: 8.2开发实现: 1. 先要创建.grf报表模版,指定数据列.存储位置:Reports\Template文件夹下 2. 之后在程序当中查出数据,之后把数据和打印模版 传入方法进行 ...
- Linux内核Makefile文件(翻译自内核手册)
--译自Linux3.9.5 Kernel Makefiles(内核目录documention/kbuild/makefiles.txt) kbuild(kernel build) 内核编译器 Thi ...