EGE专栏:EGE专栏

目录

  • 音乐播放
    • 一、winmm.lib 库的链接检查
    • 二、 MUSIC类
    • 三、让音乐播放起来
      • 先把文件扩展名显示设置打开
      • 进入当前目录
      • 把音乐文件放到源文件旁边
      • 播放音乐的程序
        • 测试程序
        • 如果音乐文件名正确,但是还是无法打开音乐文件
          • 解决方案
          • 具体操作
    • 四、音乐播放器控制
      • 1. 使用 OpenFile() 打开音乐文件
      • 2. 使用 IsOpen() 检测音乐文件是否成功打开
      • GetPlayStatus() 获取播放状态
      • 3. 使用 Play() 播放音乐
      • Pause() 暂停播放
      • Seek() 调节播放进度
      • Stop() 停止播放
      • GetLength() 获取音乐时长
      • GetPosition() 获取音乐播放进度
      • SetVolume() 调节音量
      • Close() 关闭音乐文件
    • 五、音乐播放状态切换示例
    • 六、注意事项
      • 音乐重复播放
    • 音乐播放示例程序

音乐播放

一、winmm.lib 库的链接检查

  音乐播放需要使用到 winmm.lib 库,如果你是使用的VC编译器,因为源代码中加了 #pragma 编译指令,会自动链接用到的一些库,所以你使用VC的编译器话,那么就不用手动添加链接库了。
  但是用 #pragma链接库只对VC编译器有效,所以使用CodeBlocksDevC++ 的需要手动添加链接库
  音乐播放相关需要用到 winmm.lib 库, 所以必须加到链接库里,否则会出现链接错误(undefined reference to)
CodeBlocks 是加上libwinmm.a,如下图(配置时已经添加)

DevC++ 是加上 -lwinmm 的编译参数(有些教程的配置里没加上,自己检查一下)

64位链接库的编译参数是

-lgraphics64 -luuid -lmsimg32 -lgdi32 -limm32 -lole32 -loleaut32 -lwinmm -lgdiplus

32位链接库的编译参数是

-lgraphics -luuid -lmsimg32 -lgdi32 -limm32 -lole32 -loleaut32 -lwinmm -lgdiplus

二、 MUSIC类

  EGE有用于控制音乐播放的 MUSIC类, 是对 windowsAPI的一个封装,调用了 <mmsystem.h> 中的函数。
  类定义如下:

typedef unsigned long DWORD;class MUSIC
{public:MUSIC();virtual ~MUSIC();operator HWND()const{ return (HWND)m_dwCallBack; }
public:int   IsOpen() { return (m_DID != MUSIC_ERROR) ? 1 : 0; }DWORD OpenFile(LPCSTR  filepath);DWORD OpenFile(LPCWSTR filepath);DWORD Play(DWORD dwFrom = MUSIC_ERROR, DWORD dwTo = MUSIC_ERROR);DWORD Pause();DWORD Seek(DWORD dwTo); //播放位置定位,单位为msDWORD SetVolume(float value);DWORD Close();DWORD Stop();DWORD GetPosition();DWORD GetLength();// 以下函数GetPlayStatus的返回值为以下之一(意义看后缀):// MUSIC_MODE_NOT_OPEN   //没有正确打开// MUSIC_MODE_NOT_READY  //设备没准备好 (较少使用)// MUSIC_MODE_PAUSE  //暂停中// MUSIC_MODE_PLAY   //正在播放// MUSIC_MODE_STOP   //成功打开后,或者播放完是这个状态// MUSIC_MODE_OPEN   //打开中 (较少使用)// MUSIC_MODE_SEEK   //定位中 (较少使用)DWORD GetPlayStatus();
private:DWORD       m_DID;PVOID       m_dwCallBack;
};

三、让音乐播放起来

先把文件扩展名显示设置打开

打开 文件资源管理器, 勾选上文件扩展名。这样就能看到完整的文件名。

进入当前目录

  如果你的源文件是新建的,那么就是源文件所在的目录。
  源文件就是你的代码文件, 建项目的时候创建有 .cpp 文件,懂吧?

把音乐文件放到源文件旁边

  东西比较多,显得凌乱,为了简单方便,就直接把音乐文件放在源文件旁边。

播放音乐的程序

  • 先定义一个MUSIC类变量
 MUSIC music;
  • 使用music.OpenFile( )打开音乐文件
    还可以使用 music.IsOpen() 检查是否打开了文件,打开成功返回true, 失败则返回false;
music.OpenFile("音乐文件名(带扩展名)");
if (music.IsOpen())
{//文件已被成功打开
}
  • 使用music.Play()播放音乐
music.Play();

所以想要打开音乐播放,使用如下代码便可

MUSIC music;
music.OpenFile("音乐文件名");
music.Play();           //当然,如果没打开成功,是播放不出来的

测试程序

  下面这个是音乐播放测试

  改成自己的音乐文件名, 带扩展名, 比如上面这首,就写成:(因为之前文件是放在源文件旁边的,所以在相对路径里可以省去文件前面的路径,只写文件名就可以了)

music.OpenFile("马步谣-双笙.mp3");
  • 先调节一下电脑的音量大小,以免放不出声音是因为没开声音


  如果无法播放,请检查一下 文件名 是否写正确了。 (是否带了文件扩展名,路径是否正确,可以用绝对路径试试)
  如果文件名写对了还是无法播放,往后看,有解决办法。

#include <graphics.h>int main()
{initgraph(640, 480, 0);setbkcolor(WHITE);setcolor(BLACK);setfont(40, 0, "楷体");MUSIC music;music.OpenFile("音乐名文件名(带扩展名)");//检查是否打开if (music.IsOpen()){xyprintf(200, 220, "%s\n", "音乐打开成功");music.Play();}else{xyprintf(200, 220, "%s\n", "音乐打开失败");}getch();music.Close();closegraph();return 0;
}

如果音乐文件名正确,但是还是无法打开音乐文件

  可能是音乐文件的格式不兼容,所以打不开。

解决方案

  对音乐文件使用格式转换软件进行转码。比如常用的QQ音乐播放器,里面就有音频转码功能。把音乐放进去转码一次,转换完成后应该就能打开了。

具体操作
  1. 打开QQ音乐播放器,点击右上角选项按钮,选择 音频转码
  2. 点击添加歌曲,选择转换的音乐文件(可以在文件夹里先按住Ctrl,再分别点击要选的音乐文件,可以多选),然后选择保存位置的位置,最后点击开始转换,转换完成后,点击打开文件夹就能看到转化后的音乐文件了,此时就可以使用了。

四、音乐播放器控制

MUSIC类使用方法:

1. 使用 OpenFile() 打开音乐文件

  打开音乐文件用的是 OpenFile() 函数, 参数是带扩展名的音乐文件名。
  比如我有个文件名为 musicFile.mp3的文件,在当前工作目录下(当前工作目录,一般是与新建的源文件同一个目录)。或者你直接使用带全路径的文件名
  那么打开文件方法如下:

 music.OpenFile("musicFile.mp3");

2. 使用 IsOpen() 检测音乐文件是否成功打开

  • 成功打开返回 true,否则返回false

播放之前最好先判断一下文件是否已经打开,否则可能会出现意外的结果

if (music.IsOpen()) {音乐文件已经成功打开
}

GetPlayStatus() 获取播放状态

  下面可以获取播放状态

DWORD playStatus = music.GetPlayStatus();

  返回值是以下枚举值之一, 可以根据状态来判断。
  比如,播放完毕自动重放,可以检查状态是否为 MUSIC_MODE_STOP, 是的话就 Play(0)

enum music_state_flag {MUSIC_MODE_NOT_OPEN = 0x0,           未打开文件MUSIC_MODE_NOT_READY = 0x20C,     没准备好MUSIC_MODE_PAUSE = 0x211,          暂停播放状态MUSIC_MODE_PLAY = 0x20E,             正在播放MUSIC_MODE_STOP = 0x20D,               停止播放状态MUSIC_MODE_OPEN = 0x212,             已打开文件MUSIC_MODE_SEEK = 0x210,              播放进度条调整(未播放)
};

  音乐打开加载完成后,播放状态为 MUSIC_MODE_STOP

3. 使用 Play() 播放音乐

  播放之前最好先判断一下文件是否已经打开,否则可能会出现意外的结果

  检测到音乐文件已经成功打开后,便可以播放音乐。
  函数声明如下:
  下面的时间指的是音乐的时间,单位是毫秒

DWORD Play(DWORD dwFrom = MUSIC_ERROR, DWORD dwTo = MUSIC_ERROR);

Play(开始时间, 结束时间)

  • 继续播放使用
music.Play();
  • 从音乐某个时间开始播放至音乐结束
music.Play(开始时间);

  而且 music.Play(开始时间) 还可以调整播放进度,而且是立即播放
  播放时状态是MUSIC_MODE_PLAY

  • 从音乐某个时间开始播放,播放到指定时间停止
music.Play(开始时间, 结束时间);

Pause() 暂停播放

  暂停后状态是 MUSIC_MODE_PAUSE

music.Pause();

Seek() 调节播放进度

  但是我实验了好像Seek() 不能用,可以用 Play(时间) 代替

 music.Seek( 毫秒数);

  换成下面这个

   music.Play(毫秒数);

Stop() 停止播放

停止是调用Stop()
调用后,播放状态是MUSIC_MODE_STOP
调用 Stop(), 仅仅是将播放状态设为MUSIC_MODE_STOP, 并且暂停播放
但是播放进度并没有变,将停留在刚才的进度,你使用Play() 会从刚才停的地方继续播放。所以如果是处于停止状态,应该使用Play(0) , 而不是Play(),否则和暂停没区别

如果想要进度马上调整到开始处,可以使用

   music.Play(0);music.Stop();

停止后的播放应该是

if (music.GetPlayStatus() == MUSIC_MODE_STOP) {music.play(0);
}

GetLength() 获取音乐时长

返回音乐的总时长,单位是毫秒。

int musicDuration = music.GetLength();

GetPosition() 获取音乐播放进度

(已播放的时间,单位是毫秒)

int playTime = music.GetPosition();

SetVolume() 调节音量

参数是float 型的,范围是0.0 ~ 1.0, 0表示没有声音,大于1和1无差别
默认是1.0
(这个音量是基于电脑的扬声器大小调节的,不会改变电脑的扬声器大小)

music.SetVolume(volume);

Close() 关闭音乐文件

不使用当前音乐后,可以关闭当前音乐文件,同时音乐播放也就停止了。
如果想要用同一个 MUSIC 对象打开另一个音乐文件,需要先关闭再打开。
MUSIC类对象被销毁时自动调用Close()进行关闭

music.Close();

五、音乐播放状态切换示例

控制的时候先获取一下播放状态

  • 播放
    第一次播放直接 Play() 就可, 如果是在播放时候切换状态,可以先检测一下,避免多余操作。
    方法: 如果是暂停,那么调用 Play() 继续播放,如果是停止,那么调用 Play(0) 重新播放(如果你停止的时候已经调用Play(0)将进度调整到了开头,那么直接用Play()就行)
DWORD status = music.GetPlayStatus();
if (status == MUSIC_MODE_PAUSE)music.Play();
else if (status == MUSIC_MODE_STOP)music.Play(0);
  • 暂停
    如果正在播放,那么就暂停
DWORD status = music.GetPlayStatus();
if (status == MUSIC_MODE_PLAY)music.Pause();
  • 停止
    如果处于播放或暂停,那么先调用 Play(0) 将进度调至开头,再调用 Stop() 停止(因为单单调用Stop()并不会改变播放进度)
DWORD status = music.GetPlayStatus();
if (status != MUSIC_MODE_STOP) {   music.Play(0);music.Stop();
}
  • 播放暂停切换
DWORD status = music.GetPlayStatus();
if (status == MUSIC_MODE_PLAY)music.Pause();
else if (status == MUSIC_MODE_PAUSE)music.Play();
else if (status == MUSIC_MODE_STOP)music.Play(0);
  • 调整播放进度
    直接调用Play(播放时间), 单位是毫秒

六、注意事项

音乐重复播放

  音乐自动播放完毕后,状态为 MUSIC_MODE_STOP = 0x20D,可以通过这个状态判断音乐是否播放结束,结束后从头开始播放即可。
  此时调用 Play() 是无法继续播放的, 需要使用 Play(0) ,设置播放进度到开始位置。
  播放结束判断及从头播放处理如下:
  需要注意,这需要周期检测,可以放到帧循环了。

//如果音乐已经播放完毕
if (music.GetPlayStatus() == MUSIC_MODE_STOP ) {//从头开始播放music.Play(0);
}

音乐播放示例程序

音乐文件名替换成自己的

如果遇到音乐不能播放,音乐文件名写成绝对路径形式试试,再不行就把音乐用QQ音乐音频转码过一遍,转mp3再试试

#include <graphics.h>
#include <string.h>
#include <math.h>class ProgressBar
{private://进度条样式参数int x, y, width, height;   //位置,尺寸color_t progressBkcolor;  //进度条背景色color_t progressColor;      //进度条进度颜色float progress;                //进度public:ProgressBar(int x, int y, int width, int height) : x(x), y(y), width(width), height(height) {progressBkcolor = LIGHTGRAY;progressColor = LIGHTBLUE;progress = 0.0f;}void setProgress(float progress) {this->progress = progress;draw();}private:void draw() {int cur = (int)(x + width * progress);setfillcolor(progressColor);bar(x, y, cur, y + height);setfillcolor(progressBkcolor);bar(cur, y, x + width, y + height);}
};int main()
{initgraph(640, 480, INIT_RENDERMANUAL);            //初始化窗口setcaption("EGE音乐播放");     //设置窗口标题setbkcolor(WHITE);setcolor(BLACK);setfont(16, 0, "楷体");xyprintf(20, 20, "按空格键播放/暂停, S 键停止");xyprintf(20, 40, "P键增大音量,M键减小音量");xyprintf(20, 60, "N键前进,B键后退");xyprintf(20, 80, "Q键退出");setcolor(LIGHTBLUE);//手动渲染模式,先刷新一下窗口,让背景色先出来//因为音乐加载需要时间,这段时间窗口是黑色的delay_ms(0);MUSIC music;//音乐文件名,改成自己的音乐const char* musicFile = "resource/music/薛之谦 - 花儿和少年.mp3";//找歌名位置int len = strlen(musicFile);while (len >= 0 && musicFile[len] != '/' && musicFile[len] != '\\') {--len;}const char* musicName = musicFile + len + 1;music.OpenFile(musicFile);if (music.IsOpen()) {ProgressBar progressBar(20, 200, 500, 20);progressBar.setProgress(0.0f);music.Play(0);int playTime = 0;              int totalTime = music.GetLength();     //获取音乐总时长(单位:毫秒)float volume = 0.8f;                 //音量    music.SetVolume(volume);xyprintf(20, 160, "音乐名:%s", musicName);xyprintf(400, 240, "音乐总时长:%02d:%02d",totalTime / 1000 / 60, totalTime / 1000 % 60);bool exit = false;//上次调节进度时间double lastAdjustTime = fclock(), curtime = lastAdjustTime;//检测键盘,控制音乐播放for (; is_run(); delay_fps(20)) {if (exit)break;while (kbmsg()) {key_msg keyMsg = getkey();if (keyMsg.msg != key_msg_down)continue;DWORD status = music.GetPlayStatus();int key = keyMsg.key;switch (key) {case 'Q':       //退出exit = true;break;case ' ':      //播放暂停切换if (status == MUSIC_MODE_PLAY)music.Pause();else if (status == MUSIC_MODE_PAUSE)music.Play();else if (status == MUSIC_MODE_STOP)music.Play(0);break;case 'S':       //停止if (status != MUSIC_MODE_STOP) {   music.Play(0);music.Stop();}break;case 'P':       //增加音量if ((volume += 0.1f) >= 1)volume = 1;music.SetVolume(volume);break;case 'M':     //减小音量if ((volume -= 0.1f) < 0)volume = 0;music.SetVolume(volume);break;case 'N':        //快进//no-break;case 'B':      //快退curtime= fclock();if (curtime- lastAdjustTime < 0.3)break;lastAdjustTime = curtime;if (key == 'N') {playTime += 10 * 1000;if (playTime > totalTime)playTime = totalTime;}else {playTime -= 10 * 1000;if (playTime < 0)playTime = 0;}music.Play(playTime);break;}}//获取播放时间(毫秒)int pos = music.GetPosition();//更新进度条if (pos != playTime) {playTime = pos;progressBar.setProgress(playTime * 1.0f / totalTime);}xyprintf(20, 240, "播放进度%02d:%02d", playTime / 1000 / 60, playTime / 1000 % 60);xyprintf(20, 280, "音量%3.0f%%", (volume * 100));}//关闭音乐music.Close();}else {xyprintf(50, 200, "打开音乐失败,请检查音乐文件名");getch();}closegraph();return 0;
}


  播放、暂停、停止,前进后退,显示音乐时长和播放进度,调节音量都已实现。


EGE专栏:EGE专栏

EGE基础:音乐播放篇相关推荐

  1. EGE基础入门篇(二):开始使用EGE

    EGE专栏:EGE专栏 上一篇:EGE基础入门篇(一):绘图基础知识 下一篇:EGE基础入门篇(三):开场动画 EGE基础入门篇(二) 文章最后修改时间:2021年6月23日19:30:47 文章目录 ...

  2. animation基础练习源码_用vue简单写一个音乐播放组件「附源码」

    作者:vipbic 转发链接:https://segmentfault.com/a/1190000022980992 前言 上次小编也分享一个关于Vue 开发过音乐播放对项目: 基于 electron ...

  3. 本地音乐播放器(一)——简介篇

    花了一段时间写了一个比较简单基础的音乐播放器,实现功能如下: 1. 获取SD卡中的音频文件 2. 后台播放音乐 3. 切换播放模式 4. 切换上一首,下一首 5. 播放进度条,快进快退 6. 拔出耳机 ...

  4. EGE基础入门篇(三):开场动画

    EGE专栏:EGE专栏 上一篇:EGE基础入门篇(二):开始使用EGE 下一篇:EGE基础入门篇(四):窗口简单操作 文章目录 开场动画 1. EGE开场动画的默认方式 2. 开场动画的开启 3. 开 ...

  5. vueJs开发音乐播放器第二篇(点击歌单跳出详情页)

    继上一篇开发音乐播放器歌单列表页 (1.使用router定义跳转链接,2. 使用axios得到音乐第三方数据,并渲染到页面上,3.组件之间传值(props)) 1.接下来使用了vue-router路由 ...

  6. HTML5移动端音乐播放器(启蒙篇)

    这段时间公司一直在做一个PC的教育类单页应用,庞大复杂,涉及非常多H5的知识,音频就是其中的一部分.前些天偷台风的闲暇时写了一个移动端音乐播放器,作为练手项目. 在线地址:请猛击这里 源码:请猛击这里 ...

  7. iOS开发拓展篇—音频处理(音乐播放器3)

    iOS开发拓展篇-音频处理(音乐播放器3) 说明:这篇文章主要介绍音频工具类和播放工具类的封装. 一.控制器间数据传递 1.两个控制器之间数据的传递 第一种方法:self.parentViewCont ...

  8. 2020 零基础 Vue综合应用 教开发音乐播放器—悦听(激发编程乐趣)【整理+源码】

    文章目录 1.引言 2.音乐播放器完整版效果图如下: 3.接口引用 4.示例代码 5.结束语 点击进入Vue❤学习专栏~ 1.引言 这是Vue学习的综合应用篇,教你开发一个音乐播放器,能听歌,能看热门 ...

  9. EGE基础入门篇(六):基本图形

    EGE专栏:EGE专栏 上一篇:EGE基础入门篇(五):窗口简单操作 下一篇:EGE基础入门篇(七):组合图形 一.EGE提供的基本图形 EGE绘制图形相关库函数文档 https://xege.org ...

最新文章

  1. MySQL基于时间字段进行分区的方案总结
  2. Python 3 利用机器学习模型 进行手写体数字检测
  3. poj 3101 Astronomy (java 分数的最小公倍数 gcd)
  4. 微软修复Windows 10周年更新KB3194496累积更新安装问题
  5. windows 2008 R2下(AD RMS)无法检索证书层次结构的解决方法
  6. android view父级隐藏,Android指定的子级已经有父级。必须先对子级的父级调用removeView()...
  7. dft对称性 matlab实验,数字信号处理实验指导书(审)
  8. SpringMVC 原理及详细使用
  9. CSO安全手册中的七条守则
  10. wps表格里面计算机在哪里,“Excel表格软件在电脑上到哪里找?“电脑excle在哪里...
  11. Codeforces 510 E. Fox And Dinner
  12. 华为Mate10到底AI在哪?
  13. 数据库连接字符串的写法(参考)
  14. Android应用开发:Dialog使用及示例
  15. 28张高清数据分析全知识地图,强烈建议收藏
  16. @submit.native.prevent
  17. ArcGIS | 02小技巧-三调地类转换
  18. 货效,坪效,人效,这三效怎么理解?
  19. [Phonegap+Sencha Touch] 移动开发19 某些安卓手机上弹出消息框 点击后不消失的解决的方法...
  20. 安卓巴士精选Android开发教程

热门文章

  1. 如何高效学习英语?这个方法你一定要知道
  2. Postgresql快照优化Globalvis新体系分析(性能大幅增强)
  3. java编程捕鱼和分鱼_C_捕鱼和分鱼
  4. 快来直播:“东方甄选”火爆影射直播新趋势——为知识买单
  5. 【python练习题 03】高矮个子排队
  6. 解决高并发项目下的热点问题
  7. chrome打开6666端口的方式
  8. 用python画美国国旗
  9. MPLS LSP的建立
  10. u盘容量变小了怎么恢复