缘由:

  在改正俄罗斯方块程序的功能的时候,想给这个程序增加一个背景音乐。本想用PlayWave来做的,但想到这个功能十分常用,那还不如封装一个自己的CMusic

类,以备不时之需。本来以为很容易的,可是在真正操作的时候,却出现了一个问题,就是无法准确的知道什么时候音乐播放完成。问题的难道就在于,怎样将类的成员函数作为窗口的回调函数。

 原本用thunk来解决这个问题的,但是在解决的时候出现了一个问题,调试了好几天都没有解决。直到最近才解决。(也就是前一篇文章的由来)

代码:(前面定义的宏主要是解决Unicode问题)

cMusic.h

  1 #ifndef CMUSIC_H
2 #define CMUSIC_H
3
4 #ifdef _UNICODE
5 #define tstring wstring
6 #define tcout wcout
7 #define tcin wcin
8 #else
9 #define tstring string
10 #define tcout cout
11 #define tcin cin
12
13 #endif
14
15 #pragma warning(disable:4311)
16
17 #include "TCHAR.h"
18 #include<iostream>
19 #include<windows.h>
20 #include<string>
21 #include<vector>
22 #include<MMSystem.h>
23 #pragma comment(lib,"Winmm.lib")
24 using namespace std;
25
26 typedef LRESULT (*pfaCallBack)(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam);
27 #pragma pack(push,1)
28 struct Thunk
29 {
30 BYTE op_movecx;
31 DWORD_PTR val_ecx;
32 BYTE op_call;
33 DWORD_PTR val_address;
34 };
35 #pragma pack(pop)
36
37 #define MY_WM_PLAY WM_USER+1
38 #define MY_WM_PAUSE WM_USER+2
39 #define MY_WM_STOP WM_USER+3
40 #define MY_WM_CLOSE WM_USER+4
41 #define MY_WM_PLAYNEXT WM_USER+5
42 #define MY_WM_PLAYLAST WM_USER+6
43 #define MY_WM_REPLAY WM_USER+7
44 #define MY_WM_PLAY_LOOP WM_USER+8
45 #define MY_WM_RESUME WM_USER+9
46 #define MY_WM_TEST0 WM_USER+10
47
48 //类说明开始
49 //=========================================================//
50 // 功能:播放音乐以及进行相关的控制
51 // 设计思路:
52 // 这个类的实现应该会比较简单,主要是利用MCI开头的函数来进行控制
53 // 最主要实现一下功能:
54 // 播放一个音频文件
55 // 暂停播放
56 // 恢复播放
57 // 得到音频文件的信息
58 // 文件名
59 // 长度
60 // 当前播放的位置
61 // 显示播放列表//一个文件夹中的所有MP3或者是wav文件
62 // 播放上一首
63 // 播放下一首
64 //
65 // 作者:张敏
66 // 日期:2013-1-10 邮箱 zhang19min88@163.com
67 // 注意:实现这个类我的最大的感想就是不要想在一个类中封装所有的函数
68 // 在真正要用的时候再进行继承
69 //也许这样不会焦头乱额
70 //=========================================================//
71 class ZMCMusic
72 {
73 public:
74 friend DWORD WINAPI ThreadProc(LPVOID);
75 public:
76 ZMCMusic();//构造函数
77 ~ZMCMusic();//析构函数
78 public:
79 void Init();
80 void AddPlayList(tstring tstrDir);
81 BOOL Play();
82 BOOL Pause();
83 BOOL Resume();
84 BOOL Stop();
85 BOOL Close();
86 BOOL Replay();
87 BOOL PlayNext();//播放下一曲
88 BOOL playLast();//播放上一曲
89 BOOL GetFileInfo();
90 BOOL LoadMusicFile(tstring const tstrFileNmae);
91 static void ShowError();
92 private:
93 void GetCurPos();
94 void GetFileLenth();
95 int MakeWindow();//产生一个窗口
96 int CreateWindowInThread();//在线程中创建窗口
97 LRESULT ProcWindow(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam);//窗口过程的处理函数
98 private:
99 tstring m_tstrFileName;
100 vector<tstring> m_vcPlayList;//保存播放列表
101 int m_nCurPlayIndex;//当前正在播放文件夹的索引
102 int m_nFileLen;//文件的总长度
103 int m_nCurPos;//当前正播放的位置
104 int m_nSound;//播放的音量大小
105 private:
106 HWND m_hWnd;
107 HANDLE m_hThread;
108 HINSTANCE m_hInstance;
109 UINT m_uDeviceID;
110 DWORD m_dwThreadID;
111 tstring m_tstrWinClassName;
112 tstring m_tstrWinCaptionName;
113 private:
114 void InitThunk()
115 {
116 m_thunk.op_movecx=0xB9;// 0xb9 mov ecx,数值的 机器码
117 m_thunk.val_ecx=(DWORD_PTR)this;
118 m_thunk.op_call=0xE9;//0xe9是Jmp 相对地址的机器码
119 DWORD_PTR off=0;
120 _asm
121 {
122 mov eax,ZMCMusic::ProcWindow
123 mov DWORD PTR[off],eax
124 }
125 m_thunk.val_address=off-((DWORD_PTR)(&m_thunk.val_address)+sizeof(DWORD_PTR));
126 }
127 pfaCallBack GetStaticEntry()
128 {
129 return (pfaCallBack)&m_thunk;
130 }
131 private:
132 Thunk m_thunk;
133 };
134
135 #endif

cMusic.cpp

  1 #include "cMusic.h"
2 //程序说明开始
3 //=========================================================//
4 // 功能:类的构造函数,由于本类需要 创建一个隐藏的窗口,用来接收
5 // 播放完成之后的消息。所以在构造类的时候,很自然也需要构建一个
6 // 隐藏的窗口
7 // 参数:无
8 // 返回 :无
9 // 主要思路:
10 // 初始化一些变量 并且调用createThread函数创建一个线程,并且在线程中
11 // 创建一个窗口
12 // 调用方法:系统自动调用
13 // 作者:张敏
14 // 日期:2012-1-11 邮箱 zhang19min88@163.com
15 // 说明:
16 //=========================================================//
17 ZMCMusic::ZMCMusic()
18 {
19 m_uDeviceID=0;
20 m_tstrFileName=_T("");
21 m_tstrWinCaptionName=_T("MCI");
22 m_tstrWinClassName=_T("CMCI");
23 m_nSound=0;
24 m_nFileLen=0;
25 m_nCurPos=0;
26 m_dwThreadID=0;
27 m_nCurPlayIndex=0;
28 m_hInstance=(HINSTANCE)GetModuleHandle(NULL);
29 InitThunk();
30 }
31 void ZMCMusic::Init()
32 {
33 CreateWindowInThread();//在线程中创建一个窗口
34 }
35 ZMCMusic::~ZMCMusic()
36 {
37
38 }
39 //程序说明开始
40 //=========================================================//
41 // 功能:加载需要播放的文件
42 // 参数:tstrFileName 需要加载的文件名
43 // 返回 :成功执行返回真 否则返回假
44 // 主要思路:
45 // 调用MCISendCommand函数 发送MCI_OPEN命令
46 // 得到一个设备ID
47 // 调用方法:外部接口函数
48 // 作者:张敏
49 // 日期:2013-1-10 邮箱 zhang19min88@163.com
50 // 说明:
51 //=========================================================//
52 BOOL ZMCMusic::LoadMusicFile(tstring const tstrFileNmae)
53 {
54 m_tstrFileName=tstrFileNmae;
55 MCI_OPEN_PARMS mciOPenParms;
56 DWORD dwReturn=0;
57
58 mciOPenParms.lpstrDeviceType=_T("mpegvideo");//使用这种类型,可以播放MP3
59 mciOPenParms.lpstrElementName=m_tstrFileName.c_str();//也就是播放的音频文件的路径名
60 mciOPenParms.dwCallback=(DWORD_PTR)m_hWnd;//该命令成功执行后 想m_hWnd窗口发送一条消息
61
62 dwReturn=mciSendCommand(0,MCI_OPEN,MCI_OPEN_TYPE|MCI_OPEN_ELEMENT,(DWORD)(LPVOID)&mciOPenParms);
63 if(dwReturn!=0)
64 {
65 return FALSE;
66 }//成功打开这个设备
67 m_uDeviceID=mciOPenParms.wDeviceID; //得到一个设备的ID号
68
69 //MCI_STATUS_PARMS mciStatusParms;
70 //ZeroMemory(&mciStatusParms,sizeof(mciStatusParms));
71 //mciStatusParms.dwItem=MCI_STATUS_LENGTH;
72 //if(mciSendCommand( m_uDeviceID , MCI_STATUS , MCI_STATUS_ITEM , (DWORD)(LPMCI_STATUS_PARMS) &mciStatusParms )==0 )
73 //{
74 // m_nFileLen=mciStatusParms.dwReturn;
75 //}
76 return TRUE;
77 }
78
79 //程序说明开始
80 //=========================================================//
81 // 功能:播放加载了的音频文件
82 // 参数:
83 // 返回 :成功执行返回真 否则返回假
84 // 主要思路:
85 // 调用MCISendCommand函数 发送MCI_PLAY命令
86 // 调用方法:外部接口函数
87 // 作者:张敏
88 // 日期:2013-2-26 邮箱 zhang19min88@163.com
89 // 说明:
90 // 在这里并有处理MCI_NOTIFY消息,通过这个消息我们可以知道播放是否结束
91 // 当歌曲播放完成之后 我们会收到一个播放完成的消息
92 //=========================================================//
93 BOOL ZMCMusic::Play()
94 {
95 //LoadMusicFile(m_vcPlayList[ m_nCurPlayIndex]);
96 MCI_PLAY_PARMS mciPlayParms;
97 ZeroMemory(&mciPlayParms,sizeof(mciPlayParms));
98 mciPlayParms.dwCallback=(DWORD)m_hWnd;
99 return mciSendCommand(m_uDeviceID,MCI_PLAY,MCI_NOTIFY,(DWORD)(LPVOID)&mciPlayParms);
100 }
101 //程序说明开始
102 //=========================================================//
103 // 功能:暂停当前播放的文件
104 // 参数:无
105 // 返回 :成功执行返回真 否则返回假
106 // 主要思路:
107 // 调用MCISendCommand函数 发送MCI_PAUSE命令
108 // 调用方法:外部接口函数
109 // 作者:张敏
110 // 日期:2012-1-10 邮箱 zhang19min88@163.com
111 // 说明:
112 // 在这里并没有处理MCI_NOTIFY消息,通过这个消息我们可以知道播放是否结束
113 //=========================================================//
114 BOOL ZMCMusic::Pause()
115 {
116 MCI_GENERIC_PARMS mciGenericParms;
117 ZeroMemory(&mciGenericParms,sizeof(mciGenericParms));
118 mciGenericParms.dwCallback=(DWORD_PTR)m_hWnd;
119 return mciSendCommand(m_uDeviceID,MCI_PAUSE,MCI_WAIT,(DWORD)(LPVOID)&mciGenericParms);
120 }
121 //程序说明开始
122 //=========================================================//
123 // 功能:继续播放当前被暂停播放的文件
124 // 参数:无
125 // 返回 :成功执行返回真 否则返回假
126 // 主要思路:
127 // 调用MCISendCommand函数 发送MCI_RESUME命令
128 // 调用方法:外部接口函数
129 // 作者:张敏
130 // 日期:2012-1-10 邮箱 zhang19min88@163.com
131 // 说明:
132 //
133 //=========================================================//
134 BOOL ZMCMusic::Resume()
135 {
136 MCI_GENERIC_PARMS mciGenericParms;
137 ZeroMemory(&mciGenericParms,sizeof(mciGenericParms));
138 return mciSendCommand(m_uDeviceID,MCI_RESUME,MCI_NOTIFY,(DWORD)(LPVOID)&mciGenericParms);
139 }
140 //程序说明开始
141 //=========================================================//
142 // 功能:停止播放的文件
143 // 参数:无
144 // 返回 :成功执行返回真 否则返回假
145 // 主要思路:
146 // 调用MCISendCommand函数 发送MCI_STOP命令
147 // 调用方法:外部接口函数
148 // 作者:张敏
149 // 日期:2012-1-10 邮箱 zhang19min88@163.com
150 // 说明:
151 // 这个命令和PAUSE是不同的 pause只是暂停播放,但播放的内容依然在内存中,可以继续播放
152 // 而STOP则是该文件退出资源 不能继续播放
153 //对于这个命令的确切理解MSDN上说 它和Pause的区别是看不同的设备来说的
154 //=========================================================//
155 BOOL ZMCMusic::Stop()
156 {
157 return mciSendCommand(m_uDeviceID,MCI_STOP,NULL,NULL);
158 }
159 //程序说明开始
160 //=========================================================//
161 // 功能:关闭播放设备
162 // 参数:无
163 // 返回 :成功执行返回真 否则返回假
164 // 主要思路:
165 // 调用MCISendCommand函数 发送MCI_CLOSE命令
166 // 调用方法:外部接口函数
167 // 作者:张敏
168 // 日期:2013-1-11 邮箱 zhang19min88@163.com
169 // 说明:
170 // 这个命令和PAUSE是不同的 pause只是暂停播放,但播放的内容依然在内存中,可以继续播放
171 // 而STOP则是该文件退出资源 不能继续播放
172 //=========================================================//
173 BOOL ZMCMusic::Close()
174 {
175 return mciSendCommand(m_uDeviceID,MCI_CLOSE,NULL,NULL);
176 }
177 //程序说明开始
178 //=========================================================//
179 // 功能:重新播放
180 // 参数:无
181 // 返回 :成功执行返回真 否则返回假
182 // 主要思路:
183 // 调用CLose()函数 关闭设备 然后调用LoadMusicFile()函数打开设备 最后调用Play()函数进行播放
184 // 调用方法:外部接口函数
185 // 作者:张敏
186 // 日期:2013-2-27 邮箱 zhang19min88@163.com
187 // 说明:
188 //=========================================================//
189 BOOL ZMCMusic::Replay()
190 {
191 Close();
192 LoadMusicFile(m_tstrFileName);
193 return Play();
194 }
195
196
197
198 int ZMCMusic::MakeWindow()
199 {
200 MSG stMsg;
201 TCHAR szClassName[]=_T("MCI");
202
203 WNDCLASSEX stWC;
204 ZeroMemory(&stWC,sizeof(stWC));
205 stWC.hCursor=LoadCursor(NULL,IDC_ARROW);
206 stWC.cbSize=sizeof(stWC);
207 stWC.style=CS_HREDRAW|CS_VREDRAW;
208 stWC.lpfnWndProc=(WNDPROC)ZMCMusic::GetStaticEntry();//将类成员函数作为窗口过程函数
209 //stWC.lpfnWndProc=DefWindowProc;
210 stWC.lpszClassName=m_tstrWinClassName.c_str();
211 stWC.cbClsExtra=0;
212 stWC.hInstance=m_hInstance;
213
214 RegisterClassEx(&stWC);
215
216 m_hWnd=CreateWindowEx(WS_EX_CLIENTEDGE,m_tstrWinClassName.c_str(),m_tstrWinCaptionName.c_str(),WS_OVERLAPPEDWINDOW,100,100,600,700,NULL,NULL,m_hInstance,NULL);
217 if(m_hWnd==NULL)
218 {
219 ShowError();
220 }
221 ShowWindow(m_hWnd,SW_HIDE);
222 UpdateWindow(m_hWnd);
223 while(GetMessage(&stMsg,NULL,0,0))
224 {
225 TranslateMessage(&stMsg);
226 DispatchMessage(&stMsg);
227 }
228 return 0 ;
229 }
230
231 //程序说明开始
232 //=========================================================//
233 // 功能:窗口过程的处理函数
234 // 参数:hWNd uMsg wParam lParam 正常窗口回调函数
235 // 返回 :无
236 // 主要思路:
237 // 在这个回调函数中我们完成的就是处理MM_MCINOTIFY消息,主要是对MCI播放命令的执行结果进行响应
238 // 最关键的一个结果是通过这个消息的处理我们可以知道什么时候音乐播放完成
239 // 调用方法:系统自动调用
240 // 作者:张敏
241 // 日期:2012-1-11 邮箱 zhang19min88@163.com
242 // 说明:
243 //=========================================================//
244
245 //这个类该怎样利用还不是很清楚
246 LRESULT ZMCMusic::ProcWindow(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
247 {
248 switch(uMsg)
249 {
250 case WM_CREATE:
251 // MessageBox(NULL,_T("MCI"),_T("MCI"),MB_OK);
252 break;
253 case MM_MCINOTIFY://当播放完成之后
254 //在这里可以进行很多设置
255 //比喻说设定单曲循环
256 //设置自动播放下一首等等
257 //关键是如何用代码进行封装
258 //MessageBox(NULL,_T("MCI"),_T("Play End!"),MB_OK);
259 this->Replay();
260 break;
261 case MY_WM_PLAY: break;
262 case MY_WM_PAUSE:break;
263 case MY_WM_STOP:break;
264 case MY_WM_RESUME:break;
265 case MY_WM_REPLAY:break;
266 case MY_WM_PLAYNEXT:break;
267 case MY_WM_PLAYLAST:break;
268 case MY_WM_PLAY_LOOP:break;
269 default:
270 return DefWindowProc(hWnd,uMsg,wParam,lParam);
271 }
272 return 0;
273 }
274
275 //程序说明开始
276 //=========================================================//
277 // 功能:线程函数
278 //在这个函数中我们接受一个创建线程时的一个参数this 因为线程可以传递一个参数
279 // 在这个程序的处理过程中 我很好的解决了在内中调用线程的例子
280 // 以前遇到这种问题几次了,都是用一种不是很好的方式解决,今天算是搞清楚了
281 // 在类中创建线程,那么线程函数必须为全局函数,或者是静态函数,因为线程函数只能有一个参数,如果为成员函数,那么就会有一个默认的this
282 // 所以不行 我首先将它定义为友元函数,然后从线程函数中传递参数this这样就可以很好的解决这个问题了
283 // 参数:this指针
284 // 返回 :DWORD
285 // 主要思路:
286 // 调用类的方法创建一个隐藏的窗口
287 // 调用方法:系统自动调用
288 // 作者:张敏
289 // 日期:2012-1-11 邮箱 zhang19min88@163.com
290 // 说明:
291 //=========================================================//
292 DWORD WINAPI ThreadProc(LPVOID lParam)
293 {
294 ZMCMusic *pMusic=NULL;
295 pMusic=(ZMCMusic *)lParam;
296 return pMusic->MakeWindow();
297 }
298
299 //程序说明开始
300 //=========================================================//
301 // 功能:启动一个新的线程来创建一个窗口
302 // 参数:无
303 // 返回 :int
304 // 主要思路:
305 // 创建一个新的线程
306 // 调用方法:系统自动调用
307 // 作者:张敏
308 // 日期:2012-1-11 邮箱 zhang19min88@163.com
309 // 说明:
310 //=========================================================//
311 int ZMCMusic::CreateWindowInThread()
312 {
313 m_hThread=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)ThreadProc,(LPVOID)this,0,&m_dwThreadID);
314 WaitForSingleObject(m_hThread,500);
315 return 0;
316 }
317
318 //程序说明开始
319 //=========================================================//
320 // 功能:输出最近一次的错误信息
321 // 返回 :成功执行返回真 否则返回假
322 // 主要思路:
323 // 调用InternetReadFile函数
324 // 调用方法:
325 // 作者:张敏
326 // 日期:2012-1-7 邮箱 zhang19min88@163.com
327 // 说明:
328 //=========================================================//
329 void ZMCMusic::ShowError()
330 {
331 #define ERROR_BUF 256
332 TCHAR szBuf[ERROR_BUF];
333 LPVOID lpMsgBuf;
334 DWORD dw=GetLastError();
335 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,NULL,dw,MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),(LPTSTR)&lpMsgBuf,0,NULL);
336 wsprintf(szBuf,_T("执行失败!错误码为:%d. 错误原因为:%s\n"),dw,lpMsgBuf);
337 MessageBox(NULL,szBuf,_T("错误"),MB_OK);
338 }
339 //程序说明开始
340 //=========================================================//
341 // 功能:得到文件当前播放的位置
342 // 返回 :无
343 // 主要思路:
344 // 发送MCI_STATUS命令获得
345 // 主要是得到状态
346 // 调用方法:
347 // 作者:张敏
348 // 日期:2012-1-7 邮箱 zhang19min88@163.com
349 // 说明:
350 //=========================================================//
351 void ZMCMusic::GetCurPos()
352 {
353 MCI_STATUS_PARMS mciStatusParms;
354 mciStatusParms.dwItem=MCI_STATUS_POSITION;
355 if(mciSendCommand( m_uDeviceID , MCI_STATUS , MCI_STATUS_ITEM , (DWORD)(LPMCI_STATUS_PARMS) &mciStatusParms )==0 )
356 {
357 m_nCurPos=mciStatusParms.dwReturn;
358 }
359 }
360 //程序说明开始
361 //=========================================================//
362 // 功能:得到文件的长度
363 // 返回 :无
364 // 主要思路:
365 // 发送MCI_STATUS命令获得
366 // 主要是得到状态
367 // 调用方法:
368 // 作者:张敏
369 // 日期:2012-2-27 邮箱 zhang19min88@163.com
370 // 说明:
371 //=========================================================//
372 void ZMCMusic::GetFileLenth()
373 {
374 MCI_STATUS_PARMS mciStatusParms;
375 mciStatusParms.dwItem=MCI_STATUS_LENGTH;//获得文件的长度
376 if(mciSendCommand( m_uDeviceID , MCI_STATUS , MCI_STATUS_ITEM , (DWORD)(LPMCI_STATUS_PARMS) &mciStatusParms )==0 )
377 {
378 m_nFileLen=mciStatusParms.dwReturn;
379 }
380 }
381 //程序说明开始
382 //=========================================================//
383 // 功能:将文件夹中的*.MP3文件和*.wav文件读取出来按照顺序添加到播放列表
384 // 返回 :无
385 // 主要思路:
386 // 在文件夹中查找*.mp3和*.wav的文件,然后放在容器中
387 // 调用方法:
388 // 作者:张敏
389 // 日期:2012-1-7 邮箱 zhang19min88@163.com
390 // 说明:
391 //=========================================================//
392 void ZMCMusic::AddPlayList(tstring tstrDir)
393 {
394
395 }

main.cpp

 1 #include "cMusic.h"
2
3 void ShowMenu()
4 {
5 tcout<<"Press 0 to EXIT"<<endl;
6 tcout<<"Press 1 to PLAY"<<endl;
7 tcout<<"Press 2 to PAUSE"<<endl;
8 tcout<<"Press 3 to RESUSE"<<endl;
9 tcout<<"Press 4 to STOP"<<endl;
10 tcout<<"Press 5 to FULLSCAN"<<endl;
11 tcout<<"Press 6 to CLOSE"<<endl;
12 tcout<<"Press 7 to REPALY"<<endl;
13 tcout<<"Press 8 to SHOWPOS"<<endl;
14 tcout<<"Press 9 to STOP"<<endl;
15
16 }
17 int main()
18 {
19 tstring strFileName;
20 strFileName=_T("D:\\musicTest\\ifLove.mp3");
21 // strFileName=_T("D:\\musicTest\\msg.mp3");
22
23 ZMCMusic music;
24 music.Init();
25 //music.AddPlayList(strFileName);
26 music.LoadMusicFile(strFileName);
27
28 int nKey=0;
29 bool bExit=false;
30 while(!bExit)
31 {
32 ShowMenu();
33 tcout<<_T("You Command:");
34 tcin>>nKey;
35 switch(nKey)
36 {
37 case 0:bExit=true;break;
38 case 1:music.Play();break;
39 case 2:music.Pause();break;
40 case 3:music.Resume();break;
41 //case 4:music.Stop();break;
42 case 6:music.Close();break;
43 case 7:music.Replay();break;
44 //case 8:SendMessage(g_hWnd,WM_CLOSE,NULL,NULL);break;
45 default:break;
46 }
47 Sleep(500);
48 }
49 return 0;
50 }

运行结果:

aaarticlea/png;base64,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" alt="" />

注意:

MCI音乐播放的更多相关文章

  1. SE Springer小组之《Spring音乐播放器》需求分析说明书二

    2.1 目标 Spring音乐播放器软件为课程<软件工程>所开发的课程作业,主要意图是为访问计算机中的mp3格式的音频文件,并使其能够完成访问,读取,添加,保存,播放,切换音频文件等功能. ...

  2. SE Springer小组之《Spring音乐播放器》可行性研究报告三、四

    3 对现有系统的分析 由于本次可行性分析主要是建立在团队自行实现一个音乐软件的目标上,并不是在一个现有系统的基础上开发改进的新系统.因此这里将分析一款市面上已经存在的音乐软件(以下称为W音乐),并为之 ...

  3. 卡拉OK效果的实现-iOS音乐播放器

    自己编写的音乐播放器偶然用到这个模块,发现没有思路,而且上网搜了搜,关于这方面的文章不是很多,没找到满意的结果,然后自己也是想了想,最终实现了这种效果,想通了发现其实很简单. 直接上原理: 第一种: ...

  4. 小菜学习Winform(二)WMPLib实现音乐播放器

    前言 现在网上有很多的音乐播放器,但好像都不是.net平台做的,在.net中实现音乐文件的播放功能很简单,下面就简单实现下. SoundPlayer类 在.net提供了音乐文件的类:SoundPlay ...

  5. 【大结局】《从案例中学习JavaScript》之酷炫音乐播放器(四)

    这是之前写的用H5制作的音乐播放器,前三节其实已经做得差不多了,音轨的制作原理已经在上一节说明,不过一直还没有和音乐对接. 本章作为该系列的一个完结篇,我会专门把动态音轨的实现代码贴出来,demo地址 ...

  6. Andriod小项目——在线音乐播放器

    转载自: http://blog.csdn.net/sunkes/article/details/51189189 Andriod小项目——在线音乐播放器 Android在线音乐播放器 从大一开始就已 ...

  7. Android开发6:Service的使用(简单音乐播放器的实现)

    前言 啦啦啦~各位好久不见啦~博主最近比较忙,而且最近一次实验也是刚刚结束~ 好了不废话了,直接进入我们这次的内容~ 在这篇博文里我们将学习Service(服务)的相关知识,学会使用 Service ...

  8. android 音乐播放器

    本章以音乐播放器为载体,介绍android开发中,通知模式Notification应用.主要涉及知识点Notification,seekbar,service. 1.功能需求 完善音乐播放器 有播放列 ...

  9. 音乐播放器 EasyMusic (一)

    EasyMusic 一. 代码获取 github 上链接为 https://github.com/VincentWYJ/EasyMusic, 感兴趣的朋友可以同步下来看, 欢迎提出宝贵意见或建议. 1 ...

随机推荐

  1. SQL 不同的数据类型

    SQL 不同的数据类型 1.SQL TEXT 2.SQL VARCHAR(SIZE) VARCHAR(X) Case: user name, email, country, subject, pass ...

  2. (poj)1502 MPI Maelstrom

    题目链接:http://poj.org/problem?id=1502 Description BIT has recently taken delivery of their processor A ...

  3. ASP.net后台弹出消息对话框的方法!【转】

          在winform后台,我们通过MessageBox.show(“消息")的方式来返回后台信息,在webform后台,我们通过Response.write(”消息")来返 ...

  4. Newtonsoft.Json.dll反序列化JSON字符串的方法

      1.直接反序列化JSON字符串 //引用序列化.反序列化JSON字符串用到的空间 using Newtonsoft.Json; using Newtonsoft.Json.Linq; //定义一个 ...

  5. CSS3之渐变效果

    在css3出来之前,想要出现渐变效果必须就要制作一张图片.不过css3的出现使得渐变效果变得简单.由于不是所有的浏览器都支持css3,所以不是所有的浏览器都能够呈现出css3的效果出来.因此目前大部分 ...

  6. HTML5 基础

    1.HTML5 简介 HTML5 是最新的 HTML 标准,他是万维网的核心语言.标准通用标记语言下的一个应用“超文本标记语言”. HTML 的上一个标准 HTML4.01 诞生于 1999年,他的第 ...

  7. CGAL 介绍

    CGAL组织 内核 数值健壮 基础库 扩展性 2.4 命名约定 Naming In order to make it easier to remember what kind of entity a ...

  8. sscanf用法简析

    1. 常见用法. char buf[512] = ; sscanf("123456 ", "%s", buf); printf("%s\n" ...

  9. 关于 hashCode() 你需要了解的 3 件事

    (点击上方公众号,可快速关注) 原文:eclipsesource 译文:ImportNew - 南半球 链接:http://www.importnew.com/16517.html 在 Java 中, ...

  10. AJax跨域请求百度音乐接口数据展示页面

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...