vb directsound8 能否用vb做音乐播放器 mp3

刚好最近接触了一些DirectSound,就写了一个小程序练练手,可以用来添加播放基本的wav和mp3音频文件的播放器。界面只是简单的GDI,dxsdk只使用了DirectSound8相关的接口。DirectSound的使用步骤很简单
首先你要创建一个DirectSound8设备对象
1 HRESULT DirectSoundCreate8(
LPCGUID lpcGuidDevice,
LPDIRECTSOUND8 * ppDS8,
LPUNKNOWN pUnkOuter
& 当然要确保已安装了DXSDK,并在工程中设置了相关路径,包含dsound.lib。
lpcGuidDevice是声音设备对象GUID的地址,设置为NULL,表示默认设备;ppDS8是返回的IDirectSound8接口指针,接下来就通过它来调用相关接口了;pUnkOuter必须设置为NULL。
接下来是设置协作级别
1 HRESULT SetCooperativeLevel(
HWND hwnd,
DWORD dwLevel
hwnd是应用程序窗口句柄;dwLevel是请求的协作级别,可选的值包括DSSCL_NORMAL:正常级别,其他程序可共享设备;DSSCL_PRIORITY:优先级别,设备为当前程序独占;DSSCL_EXCLUSIVE:对于DX8.0及之后的版本,具有和DSSCL_PRIORITY相同的效果;DSSCL_WRITEPRIMARY:当前程序具有主缓冲区的写权限,同时副缓冲区不能进行播放。
接下来就可以创建缓冲区了
1 HRESULT CreateSoundBuffer(
LPCDSBUFFERDESC pcDSBufferDesc,
LPDIRECTSOUNDBUFFER * ppDSBuffer,
LPUNKNOWN pUnkOuter
pcDSBufferDesc是一个DSBUFFERDESC结构的指针,用来描述要创建的声音缓冲区的地址;ppDSBuffer是返回的IDirectSoundBuffer接口对象的指针;pUnkOuter必须设置为NULL。其中DSBUFFERDESC定义如下
1 typedef struct DSBUFFERDESC {
DWORD dwBufferB
LPWAVEFORMATEX lpwfxF
GUID guid3DA
8 } DSBUFFERDESC;
dwSize:结构的大小,用字节表示;dwFlags:指定缓冲区的功能标志,常用的有DSBCAPS_GLOBALFOCUS(缓冲区为全局)、DSBCAPS_CTRLVOLUME(缓冲区具有音量控制功能)、DSBCAPS_CTRLPOSITIONNOTIFY(缓冲区具有位置通知功能)等。dwBufferBytes:将要创建的缓冲区大小;dwReserved:保留参数,必须为0;lpwfxFormat:指向一个WAVEFORMATEX结构的指针,该结构用来指定缓冲区的波形格式。
然后是创建副缓冲区
通过使用IDirectSoundBuffer的QueryInterface方法,GUID设置为IID_IDirectSoundBuffer8,得到一个IDirectSoundBuffer8接口对象,用来控制播放等。
1 IDirectSoundBuffer8* m_pBuffer8 = NULL;
2 ppDSBuffer-&QueryInterface( IID_IDirectSoundBuffer8, (void**)&m_pBuffer8 );
到这里创建m_pBuffer8成功的话,就可以调用Play(),Stop()的方法控制基本的播放了。
创建缓冲区通知对象
为了更好的控制缓冲区播放,我们还可以创建缓冲区通知对象,通过IDirectSoundBuffer8的QueryInterface方法,GUID设置为IID_IDirectSoundNotify,得到一个IDirectSoundNotify8接口对象。
1 IDirectSoundNotify8* pNotify = NULL;
2 m_pBuffer8-&QueryInterface( IID_IDirectSoundNotify,(void**)&pNotify );
接口获取成功后,就可以设置通知位置了,也就是说当缓冲区播放到相应位置时,系统就会触发对应的事件,我们可以用来自己处理,填充数据、播放下一首或是停止等操作。
1 HRESULT SetNotificationPositions(
DWORD dwPositionNotifies,
LPCDSBPOSITIONNOTIFY pcPositionNotifies
dwPositionNotifies:DSBPOSITIONNOTIFY结构的数量;pcPositionNotifies:指向DSBPOSITIONNOTIFY结构的指针。其中DSBPOSITIONNOTIFY结构如下
1 typedef struct DSBPOSITIONNOTIFY {
HANDLE hEventN
4 } DSBPOSITIONNOTIFY;
dwOffset:触发位置,即缓冲区开始起的偏移量;hEventNotify:触发事件句柄。
填充缓冲区
另外,在填充缓冲区的操作,必须在IDirectSoundBuffer8的lock和unlock方法之间进行:
1 HRESULT Lock(
DWORD dwOffset,
DWORD dwBytes,
LPVOID * ppvAudioPtr1,
pdwAudioBytes1,
LPVOID * ppvAudioPtr2,
LPDWORD pdwAudioBytes2,
DWORD dwFlags
dwOffset:要锁定的缓冲区起始位置,即从缓冲区首地址起的偏移量,用字节表示;dwBytes:希望锁定的缓冲区内存大小,用字节表示;ppvAudioPtr1:返回指向该锁定缓冲区的第一部分指针;pdwAudioBytes1:ppvAudioPtr1指向地址的大小;ppvAudioPtr2:返回指向该锁定缓冲区的第二部分指针,如果传入NULL,则该锁定区域全部返回到ppvAudioPtr1;pdwAudioBytes2:ppvAudioPtr2指向地址的大小,如果ppvAudioPtr2传入NULL,该值则应传入0;dwFlags:修改锁定事件的标志,一般不使用设为0。
1 HRESULT Unlock(
LPVOID pvAudioPtr1,
DWORD dwAudioBytes1,
LPVOID pvAudioPtr2,
DWORD dwAudioBytes2
填充完锁定缓冲区内存后,用来取消该锁定区域,参数可以参看lock中的介绍。至此,IDirectSound8中主要用到的接口就这些了。
WAVEFORMATEX结构
使用DirectSound播放PCM的重点就在于解析相应的音频文件格式获取相应信息,来填充WAVEFORMATEX结构。
1 typedef struct tWAVEFORMATEX {
WORD wFormatT
DWORD nSamplesPerS
DWORD nAvgBytesPerS
WORD nBlockA
WORD wBitsPerS
9 } WAVEFORMATEX, *PWAVEFORMATEX, *LPWAVEFORMATEX;
下面详细介绍一下此结构:wFormatTag:波形音频格式类型,在这里都设置为WAVE_FORMAT_PCM;nChannels:音频声道数;nSamplesPerSec:采样率;nAvgBytesPerSec:平均传输率,如果音频格式设置为WAVE_FORMAT_PCM,该值则必须等于nSamplesPerSec和nBlockAlign的乘积;nBlockAlign:以字节为单位的块对齐,是wFormatTag对应的最小原子单位,如果是WAVE_FORMAT_PCM,该值必须等于nChannels和wBitsPerSample的乘积除以8;wBitsPerSample:每次采样的比特数,即量化位数;cbSize:需要附加的额外信息大小,以字节为单位,这里设置为0。关于DirectSound相关的内容就介绍到这里,接下来就该考虑怎么将wav和mp3文件信息解析并填充WAVEFORMATEX结构了。
WAV音频文件格式的解析
1、解析wav文件,这就需要稍微了解一下基本的wav文件格式,wav文件相应的非数据信息存储在文件头部分,常见的几种文件头格式:&
8KHz采样、16比特量化的线性PCM语音信号的WAV文件头格式表(共44字节)
文件头定义为
char&riff_id[4]="RIFF"
文件总长-8
&long int&size0=文总长-8
"WAVEfmt&"
char&wave_fmt[8]
10&00&00&00H(PCM)
long&int&size1=0x10
int&fmttag=0x01
channel=1&或2
long&int&samplespersec
每秒播放字节数
long&int&bytepersec
采样一次占字节数&
int&blockalign=声道数*量化数/8
int&bitpersamples=8或16
char&data_id="data"
采样数据字节数
long&int&size2=文长-44
到文尾&char&采样数据
& & & & & & & & & &
8KHz采样、8比特A律量化的PCM语音信号的WAV文件头格式表(共58字节)
文件头定义为
char&riff_id[4]="RIFF"
文件总长-8&
long&int&size0=文总长-8
"WAVEfmt&"&
char&wave_fmt[8]
long&int&size1=0x12
int&fmttag=0x06
int&channel=1&或2
long&int&samplespersec
每秒播放字节数&
long&int&bytepersec
采样一次占字节数
int&blockalign=0x01
long&int&bitpersamples=8
char&wave_fact="fact"
char&wave_data="data"
采样数据字节数&
lont&int&size2=文长-58
只要构建字节对应的结构,然后从wav文件起始位置读取相应长度到结构即可,例如
1 struct WAVE_HEADER
riff_sig[4];
waveform_chunk_
wave_sig[4];
format_sig[4];
format_chunk_
bytes_per_
data_sig[4];
19 struct WAVE_HEADER_FACT
riff_sig[4];
waveform_chunk_
wave_sig[4];
format_sig[4];
format_chunk_
bytes_per_
bits_per_sample2;
fact_sig[4];
fact_size2;
fact_data[4];
data_sig[4];
这里构建了两种类型的wav格式头,从文件中读取信息到结构,然后直接赋值给WAVEFORMATEX即可
1 WAVEFORMATEX
wave_format;
2 WAVE_HEADER
wave_header;
3 fread( &wave_header, 1, sizeof(WAVE_HEADER), fp);
4 wave_format.wFormatTag
= WAVE_FORMAT_PCM;
5 wave_format.nChannels
= wave_header.
6 wave_format.nSamplesPerSec
= wave_header.sample_
7 wave_format.wBitsPerSample
= wave_header.bits_per_
8 wave_format.nBlockAlign
= wave_header.bits_per_sample / 8 * wave_header.
9 wave_format.nAvgBytesPerSec = wave_header.sample_rate * wave_format.nBlockA
mp3音频文件格式的解析
2、解析mp3文件选择使用了libmpg123库中提供的方法,mpg123解码器是全部开源的,可以在 下载获得。在编译libmpg123的过程中可能会遇到若干问题,这里大致罗列一下,进入ports\MSVC++选择对应的vs版本工程,这里选择了2010版。由于工程中在预链接事件中使用了yasm汇编器,所以需要下载配置yasm到vs工程中,在 有32位和64位系统对应的vs2010版本。下载后解压,根据readme文档添加配置:将yasm.exe放置vs主目录bin中;将yasm.props、yasm.targets、yasm.xml三个规则文件添加至MSBuild\Microsoft.Cpp\v4.0\BuildCustomizations目录中。选择Debug_X86或Release_x86配置,编译中可能会提示link无法打开输入文件xxx.o,将附加依赖和预链接命令中的.o全部替换为.obj。将生成的libmpg123.lib添加到工程中,并将ports\MSVC++下的mpg123.h也引入到自己的工程中,接下来就可以使用libmpg123相关的方法来解析mp3文件了。首先需要创建一个mpg123_handle句柄指针,过程如下
1 mpg123_handle* m_mpghandle = NULL;
2 int ret = MPG123_OK;
3 if( (ret = mpg123_init()) != MPG123_OK || (m_mpghandle = mpg123_new(NULL, &ret)) == NULL )
return -1;
之后打开mp3文件并获取相关信息
//编码格式
4 if( mpg123_open(m_mpghandle, "youfile.mp3") != MPG123_OK || mpg123_getformat(m_mpghandle, &rate, &channels, &encoding) != MPG123_OK )
return -1;
通过判断encoding来设置量化数,并赋值WAVEFORMATEX结构,代码如下
1 WAVEFORMATEX
perbits = 16;
3 if((encoding & MPG123_ENC_16) == MPG123_ENC_16)
perbits = 16;
5 else if((encoding & MPG123_ENC_32) == MPG123_ENC_32)
perbits = 32;
perbits = 8;
10 wave_format.wFormatTag
= WAVE_FORMAT_PCM;
11 wave_format.nChannels
12 wave_format.nSamplesPerSec
13 wave_format.wBitsPerSample
14 wave_format.nBlockAlign
= perbits / 8 *
15 wave_format.nAvgBytesPerSec = rate * perbits / 8 *
另外再说一下如何获取mp3文件的时长和比特率,mp3文件是由帧所构成的,想要知道播放时长,就可以通过总帧数 * 每一帧的时长来推算获得。总帧数可通过mpg123_tellframe获取,而每一帧时长 = 每一帧的采样个数 * 每一采样的时长 = 每一帧的采样个数 * (1/每一帧的采样频率),而无论哪种编码的mp3文件每一帧的采样个数都是1152,所以计算时长代码如下:
3 mpg123_seek( m_mpghandle, 0, SEEK_END );
4 frameNum = mpg123_tellframe( m_mpghandle ); //获取总帧数
5 fTime = (long)( frameNum * 1152/ rate );
而计算比特率,需要区别编码格式,如果是CBR,则比特率是固定的;如果是VBR,由于比特率不固定,所以只能大概取一个平均比特率,计算公式为 平均比特率 = 文件大小(字节)*8 / 总时长 /1000,计算比特率代码如下:
4 FILE* tmpfp = NULL;
5 if( mpg123_info( m_mpghandle, &mpginfo) != MPG123_OK )
return -1;
7 if(mpginfo.layer != 3)
return -1;
9 if( mpginfo.vbr == MPG123_CBR )
bitrate = mpginfo.
11 else if( mpginfo.vbr == MPG123_VBR )
if( fopen_s( &tmpfp, "youfile.mp3", "rb" ) == 0 )
fseek( tmpfp, 0, SEEK_END );
filesize = ftell( tmpfp );
fclose( tmpfp );
tmpfp = NULL;
bitrate = (filesize * 8)/(fTime*1000);
将mp3文件解析并创建好缓冲区之后,就可以通过mpg123_read方法将文件数据填充至缓冲区了,代码如下
1 void* buf = NULL;
2 DWORD buf_len = 0;
3 unsigned char* _
5 _buffer = (unsigned char*)malloc( lock_size * sizeof(unsigned char) );
6 if( SUCCEEDED( m_pBuffer8-&Lock(lock_pos, lock_size, &buf, &buf_len, NULL, NULL, 0 ) ) )
mpg123_read( m_mpghandle, _buffer, lock_size, &outsize);
memcpy(buf, _buffer, outsize);
m_pBuffer8-&Unlock( buf, buf_len, NULL, 0 );
其中lock_pos和lock_size 分别是缓冲区的偏移量和锁定大小。mpg13_read的第2个参数返回实际读取到的数据指针,第3个参数是希望读取的数据长度,第4个参数返回实际读取的数据长度。&
以下是全部代码:D3DPlayer.h
__D3D_PLAYER__
__D3D_PLAYER__
5 #include "resource.h"
7 #define SAFE_RELEASE(p) { if(p) { (p)-&Release(); (p)=NULL; } }
8 #define SAFE_DELETE(p) { if(p) {delete (p); (p)=NULL; } }
D3DPlayer.h
D3DPlayer.cpp
1 #include "stdafx.h"
2 #include "D3DPlayer.h"
3 #include "D3DSound.h"
5 #define MAX_LOADSTRING
6 #define WS_MYPLAYERWINDOW
(WS_OVERLAPPED
WS_CAPTION
WS_SYSMENU
WS_MINIMIZEBOX
WS_MAXIMIZEBOX)
11 #define MYWINWIDTH
12 #define MYWINHEIGHT
14 HINSTANCE hI
// 当前实例
15 TCHAR szTitle[MAX_LOADSTRING];
// 标题栏文本
16 TCHAR szWindowClass[MAX_LOADSTRING];
// 主窗口类名
17 extern myD3DSound*
PreTranslateMessage(LPMSG pMsg);
MyRegisterClass(HINSTANCE hInstance);
InitInstance(HINSTANCE, int);
22 LRESULT CALLBACK
WndProc(HWND, UINT, WPARAM, LPARAM);
23 INT_PTR CALLBACK
About(HWND, UINT, WPARAM, LPARAM);
25 int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
lpCmdLine,
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
HACCEL hAccelT
myD3DSound* pDXSound = new myD3DS
LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadString(hInstance, IDC_D3DPLAYER, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
if (!InitInstance (hInstance, nCmdShow))
return FALSE;
hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_D3DPLAYER));
while (GetMessage(&msg, NULL, 0, 0))
if(!PreTranslateMessage(&msg))
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
TranslateMessage(&msg);
DispatchMessage(&msg);
SAFE_DELETE(g_pmySound);
return (int) msg.wP
64 ATOM MyRegisterClass(HINSTANCE hInstance)
WNDCLASSEX
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style
= CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc
wcex.cbClsExtra
wcex.cbWndExtra
wcex.hInstance
wcex.hIcon
= LoadIcon(hInstance, MAKEINTRESOURCE(IDI_MYPLAYER));
wcex.hCursor
= LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground
= (HBRUSH)( COLOR_WINDOW - 1 );
wcex.lpszMenuName
= MAKEINTRESOURCE(IDC_D3DPLAYER);
wcex.lpszClassName
= szWindowC
wcex.hIconSm
= LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_MYSMALL));
return RegisterClassEx(&wcex);
85 BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
hInst = hI // 将实例句柄存储在全局变量中
iWidth=GetSystemMetrics(SM_CXSCREEN);
iHeight=GetSystemMetrics(SM_CYSCREEN);
hWnd = CreateWindow(szWindowClass, szTitle, WS_MYPLAYERWINDOW, (iWidth-MYWINWIDTH)/2,
(iHeight-MYWINHEIGHT)/2, MYWINWIDTH, MYWINHEIGHT, NULL, NULL, hInstance, NULL);
if (!hWnd)
return FALSE;
g_pmySound-&myInit( hWnd );
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
110 LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
int wmId, wmE
PAINTSTRUCT
UINT CtrlId;
DRAWITEMSTRUCT *
NMHDR *pNMHDR;
switch (message)
case WM_NOTIFY:
pNMHDR = (LPNMHDR)lP
switch( pNMHDR-&code )
case NM_DBLCLK:
if( pNMHDR-&idFrom == IDB_SONGLIST )
int i = SendMessage(g_pmySound-&m_listview, LVM_GETNEXTITEM, -1, LVNI_SELECTED);
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
if(pNMListView && pNMListView-&iItem &= 0 && pNMListView-&iItem & g_pmySound-&mySongNum() )
g_pmySound-&mySetPlayInfo(pNMListView,TRUE);
g_pmySound-&myPlay();
GetClientRect( hWnd, &rect );
InvalidateRect(hWnd,&rect,TRUE);
case NM_CLICK:
if( pNMHDR-&idFrom == IDB_SONGLIST )
SendMessage(g_pmySound-&m_listview, LVM_GETNEXTITEM, -1, LVNI_SELECTED);
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
if(pNMListView && pNMListView-&iItem &= 0 && pNMListView-&iItem & g_pmySound-&mySongNum() )
g_pmySound-&mySetPlayInfo(pNMListView,FALSE);
DWORD PID;
GetWindowThreadProcessId(hWnd, &PID);
hProcess=OpenProcess(PROCESS_ALL_ACCESS,false,PID);
vitem.iItem = pNMListView-&iI
vitem.state =
LVIS_SELECTED|LVIS_FOCUSED;
vitem.stateMask = LVIS_SELECTED|LVIS_FOCUSED;
pvitem=(LVITEM*)VirtualAllocEx(hProcess, NULL, sizeof(LVITEM),MEM_COMMIT, PAGE_READWRITE);
WriteProcessMemory(hProcess, pvitem, &vitem, sizeof(LVITEM), NULL);
SendMessage(g_pmySound-&m_listview, LVM_SETITEMSTATE, (WPARAM)pNMListView-&iItem, (LPARAM)pvitem);
GetClientRect( hWnd, &rect );
InvalidateRect(hWnd,&rect,TRUE);
else if( pNMHDR-&idFrom == 12 )
int i = 0;
case WM_COMMAND:
= LOWORD(wParam);
wmEvent = HIWORD(wParam);
// 分析菜单选择:
switch (wmId)
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
case IDM_EXIT:
res = MessageBox( hWnd, TEXT("是否关闭"), TEXT("退出"), MB_YESNO );
if( res == IDYES )
DestroyWindow( hWnd );
case IDB_OPEN:
g_pmySound-&myOpenFile();
GetClientRect( hWnd, &rect );
InvalidateRect(hWnd,&rect,TRUE);
case IDB_CLOSE:
g_pmySound-&myCloseFile();
GetClientRect( hWnd, &rect );
InvalidateRect(hWnd,&rect,TRUE);
case IDB_PLAY:
g_pmySound-&myPlay();
GetClientRect( hWnd, &rect );
InvalidateRect(hWnd,&rect,TRUE);
case IDB_STOP:
g_pmySound-&myStop();
GetClientRect( hWnd, &rect );
InvalidateRect(hWnd,&rect,TRUE);
case IDB_PAUSE:
g_pmySound-&myPause();
return DefWindowProc(hWnd, message, wParam, lParam);
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
// TODO: 在此添加任意绘图代码...
EndPaint(hWnd, &ps);
case WM_DRAWITEM:
CtrlId = (UINT)wP
dis = (LPDRAWITEMSTRUCT)lP
int lw,lh,fw,fh,
//ctrl width,ctrl height,font w,font h,font size
WCHAR txt[MAX_PATH];
lw=(dis-&rcItem.right)-(dis-&rcItem.left);
lh=(dis-&rcItem.bottom)-(dis-&rcItem.top);
len=GetWindowText(dis-&hwndItem,txt,MAX_PATH);
txt[len] = 0;
fw=lw/(len+1);
if( IDB_SONGTEXT == CtrlId || IDB_PLAYING == CtrlId )
else if( IDB_SONGINFO == CtrlId
else if( IDB_SONGTIME == CtrlId || IDB_TIMESHOW == CtrlId )
hfont=CreateFont( fh, fw, 0, 0, 500, FALSE, FALSE, FALSE,
GB2312_CHARSET, OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
DEFAULT_PITCH, TEXT("宋体") );
switch( CtrlId )
case IDB_PLAYING:
case IDB_SONGTEXT:
hfont = (HFONT)SelectObject( dis-&hDC, hfont );
SetBkMode( dis-&hDC, TRANSPARENT );
SetTextColor( dis-&hDC, RGB(0,0,0) );
TextOut( dis-&hDC, 0, 0, txt,len+1 );
hfont = (HFONT)SelectObject(dis-&hDC, hfont );
DeleteObject(hfont);
case IDB_TIMESHOW:
SetTimer( hWnd, 200, 1000, NULL );
hfont = (HFONT)SelectObject( dis-&hDC, hfont );
SetBkMode( dis-&hDC, TRANSPARENT );
SetTextColor( dis-&hDC, RGB(0,0,0) );
TextOut( dis-&hDC, 0, 0, txt,len+1 );
hfont = (HFONT)SelectObject(dis-&hDC, hfont );
DeleteObject(hfont);
case IDB_SONGINFO:
hfont = (HFONT)SelectObject( dis-&hDC, hfont );
SetBkMode( dis-&hDC, TRANSPARENT );
SetTextColor( dis-&hDC, RGB(0,0,0) );
TextOut( dis-&hDC, 0, 0, txt,len+1 );
hfont = (HFONT)SelectObject(dis-&hDC, hfont );
DeleteObject(hfont);
case IDB_SONGTIME:
hfont = (HFONT)SelectObject( dis-&hDC, hfont );
SetBkMode( dis-&hDC, TRANSPARENT );
SetTextColor( dis-&hDC, RGB(0,0,0) );
TextOut( dis-&hDC, 0, 0, txt,len+1 );
hfont = (HFONT)SelectObject(dis-&hDC, hfont );
DeleteObject(hfont);
//GetClientRect( hWnd, &rect );
//InvalidateRect(hWnd,&rect,TRUE);
case WM_DESTROY:
PostQuitMessage(0);
case WM_CREATE:
g_pmySound-&myCreateWin(hWnd);
g_pmySound-&myInitList();
case WM_SIZE:
g_pmySound-&myChangeSize( hWnd );
case WM_TIMER:
GetClientRect( hWnd, &rect );
InvalidateRect(hWnd,&rect,TRUE);
SYSTEMTIME
if( wParam == 200 )
if( ! g_pmySound-&isPlay() )
GetLocalTime( &time );
g_pmySound-&mySetTimer( time );
SetWindowText( g_pmySound-&m_timeshow, g_pmySound-&myGetTimer() );
case WM_CLOSE:
res = MessageBox( hWnd, TEXT("是否关闭"), TEXT("退出"), MB_YESNO );
if( res == IDYES )
DestroyWindow( hWnd );
case WM_INITDIALOG:
case WM_HSCROLL:
case WM_LBUTTONUP:
return DefWindowProc(hWnd, message, wParam, lParam);
368 INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
UNREFERENCED_PARAMETER(lParam);
switch (message)
case WM_INITDIALOG:
return (INT_PTR)TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
EndDialog(hDlg, LOWORD(wParam));
return (INT_PTR)TRUE;
return (INT_PTR)FALSE;
388 BOOL PreTranslateMessage(LPMSG pMsg)
if( pMsg-&message == WM_LBUTTONUP )
if( (HWND)pMsg-&hwnd == g_pmySound-&m_scrollbar )
g_pmySound-&mySetScrollPos( TRUE, 0 );
//return TRUE;
else if( (HWND)pMsg-&hwnd == g_pmySound-&m_volumebar )
g_pmySound-&mySetVolumePos( TRUE, 0 );
//return TRUE;
return FALSE;
return FALSE;
D3DPlayer.cpp
D3DSound.h
__D3D_SOUND__
__D3D_SOUND__
4 #include "D3DPlayer.h"
5 #include "stdafx.h"
6 #include "mpg123.h"
8 #define MAX_AUDIO_BUF
9 #define BUFFERNOTIFYSIZE
10 #define IDB_OPEN
11 #define IDB_CLOSE
12 #define IDB_PLAY
13 #define IDB_PAUSE
14 #define IDB_STOP
15 #define IDB_PLAYING
16 #define IDB_TIMESHOW
17 #define IDB_SONGINFO
18 #define IDB_SONGTEXT
19 #define IDB_SONGTIME
20 #define IDB_SONGLIST
22 struct WAVE_HEADER
riff_sig[4];
waveform_chunk_
wave_sig[4];
format_sig[4];
format_chunk_
bytes_per_
data_sig[4];
39 struct WAVE_HEADER_FACT
riff_sig[4];
waveform_chunk_
wave_sig[4];
format_sig[4];
format_chunk_
bytes_per_
bits_per_sample2;
fact_sig[4];
fact_size2;
fact_data[4];
data_sig[4];
61 struct myListMember
m_name[100];
m_time[10];
m_type[10];
m_bits[20];
m_path[MAX_PATH];
71 static DWORD ThreadNotifyEvent( LPVOID thread_data );
72 static DWORD ThreadNotifyEvent2( LPVOID thread_data );
73 static DWORD ThreadNotifyEvent3( LPVOID thread_data );
74 void ChartoWCHAR( const char*, WCHAR* );
75 void WCHARtoChar( const WCHAR*, char* );
77 class myD3DSound
79 private:
OPENFILENAME
m_ds_dwBuffS
//dxsound缓冲区大小
//控制buffer
m_hThread2;
//滚动条显示
m_thread_id2;
m_hThread3;
//剩余时间显示
m_thread_id3;
mpg123_handle* m_
WCHAR m_wstrTime[60];
WCHAR m_wSongTime[30];
WCHAR m_wSongLeave[30];
//剩余时长
typedef std::vector&myListMember& MY_SONG_LIST;
MY_SONG_LIST m_
WCHAR m_wSongPath[MAX_PATH];
//正在播放歌曲
WCHAR m_wSongName[MAX_PATH];
WCHAR m_wSongPathPre[MAX_PATH];
//单击选中歌曲
WCHAR m_wSongNamePre[MAX_PATH];
104 public:
LPDIRECTSOUND8
m_pDirectS
//playing file info
LPDIRECTSOUNDBUFFER8
m_pBuffer8;
m_hEvents[MAX_AUDIO_BUF];
128 #ifdef __MAX_BUFFER__
m_ds_dwFileS
//文件大小
130 #endif
m_ds_dwFileT
//文件时长(s)
//文件传输率
//文件偏移量
//文件剩余量
m_iScrollP
//进度条位置
m_iVolumeP
//音量条位置
enum eFAIL_CODE{
EFAIL_NOFILE = 1,
EFAIL_NOTSUPPORT,
EFAIL_PCMBUFFERERR,
EFAIL_MPGBUFFERERR,
EFAIL_OPENFILEERR,
EFAIL_FORMATERR,
147 private:
int mySetSoundType();
int myGetWAVFormat( DWORD* dwSize, DWORD* dwCycle, FILE* fp, WAVEFORMATEX** wfx );
int myGetMP3Format( char* filestr, DWORD* dwSize, DWORD* dwCycle, int* bitrate, WAVEFORMATEX** wfx, bool isClose = TRUE );
HRESULT myCreatePCMBuffer( WAVEFORMATEX* wfx, DWORD* dwBuffSize );
HRESULT myCreateMPGBuffer( WAVEFORMATEX* wfx, DWORD* dwBuffSize );
void myUpdateList();
void myCleanBuffer();
void cleanup();
//clear mpg123 handle
156 public:
myD3DSound();
~myD3DSound();
HRESULT myInit( HWND );
void myCreateWin( HWND );
void myChangeSize( HWND );
void mySetList( WCHAR* );
void myInitList();
void mySetPlayInfo( NM_LISTVIEW* pNMListView, bool DBClick );
void mySetTimer( SYSTEMTIME );
bool myReadBuffer( long lock_pos, long lock_size );
bool myReadMPGBuffer( long lock_pos, long lock_size );
void mySetScrollPos( bool isUp, DWORD dPos );
void mySetVolumePos( bool isUp, DWORD dPos );
void myOpenFile();
void myCloseFile();
int myPlay();
int myStop();
int myPause();
int mySongNum();
WCHAR* myGetTimer();
bool isPlay(){ return isP }
void SetPlaying( bool flags ){ isPlaying = }
int GetBufferValue( FILE** fp, mpg123_handle** mpghandle, DWORD* BuffSize );
bool IsMPG3(){return m_}
187 #endif
D3DSound.h
D3DSound.cpp
1 #include "D3DSound.h"
3 const WCHAR* g_cwErrorMsg[7] = {
TEXT("Pelase choose a file!"),
TEXT("Only supports .mp3 and .wav file!"),
TEXT("Create PCM buffer fail!"),
TEXT("Create MPG buffer fail!"),
TEXT("Cannot play the file!"),
TEXT("File format error!")
12 WCHAR* g_cwSongList[6] = {
TEXT("序号"),
TEXT("名称"),
TEXT("持续时间"),
TEXT("扩展名"),
TEXT("比特率"),
TEXT("文件路径")
23 myD3DSound*
g_pmySound = NULL;
26 ///////////////////////
27 //public function
28 ///////////////////////
30 HRESULT myD3DSound::myInit( HWND hWnd )
m_father = hW
if( FAILED( DirectSoundCreate8(NULL, &m_pDirectSound, NULL) ) )
return E_FAIL;
if( FAILED( m_pDirectSound-&SetCooperativeLevel( hWnd, DSSCL_PRIORITY ) ) )
return E_FAIL;
return S_OK;
42 myD3DSound::myD3DSound():
43 m_pDirectSound(NULL),
44 m_pBuffer8(NULL),
45 m_father(NULL),
46 m_openbtn(NULL),
47 m_closebtn(NULL),
48 m_playbtn(NULL),
49 m_pausebtn(NULL),
50 m_stopbtn(NULL),
51 m_txtplaying(NULL),
52 m_songtxt(NULL),
53 m_timeshow(NULL),
54 m_songinfo(NULL),
55 m_songtime(NULL),
56 m_scrollbar(NULL),
57 m_volumebar(NULL),
58 m_listview(NULL),
59 m_fp(NULL),
60 isPlaying(FALSE),
61 m_bmpg(FALSE),
62 m_factwav(FALSE),
63 m_hThread(NULL),
64 m_hThread2(NULL),
65 m_mpghandle(NULL)
m_ds_dwBuffSize = 0;
69 #ifdef __MAX_BUFFER__
m_ds_dwFileSize = 0;
m_ds_dwFileTime = 0;
m_ds_dwFilebps = 0;
m_ds_dwPos = 0;
m_ds_dwLeave = 0;
m_iScrollPos = 0;
m_iVolumePos = 50;
m_thread_id = 0;
m_dwPlayPos = 0;
ZeroMemory(&opfn, sizeof(OPENFILENAME));
memset( m_wstrTime, 0, sizeof(m_wstrTime) );
memset( m_wSongTime, 0, sizeof(m_wSongTime) );
memset( m_wSongLeave, 0, sizeof(m_wSongLeave) );
memset( m_wSongPath, 0, sizeof(m_wSongPath) );
memset( m_wSongName, 0, sizeof(m_wSongName) );
memset( m_wSongPathPre, 0, sizeof(m_wSongPathPre) );
memset( m_wSongNamePre, 0, sizeof(m_wSongNamePre) );
m_list.clear();
g_pmySound = this;
93 myD3DSound::~myD3DSound()
SAFE_RELEASE(m_pBuffer8);
SAFE_RELEASE(m_pDirectSound);
ZeroMemory(&opfn, sizeof(OPENFILENAME));
memset( m_wstrTime, 0, sizeof(m_wstrTime) );
memset( m_wSongTime, 0, sizeof(m_wSongTime) );
memset( m_wSongLeave, 0, sizeof(m_wSongLeave) );
memset( m_wSongPath, 0, sizeof(m_wSongPath) );
memset( m_wSongName, 0, sizeof(m_wSongName) );
memset( m_wSongPathPre, 0, sizeof(m_wSongPathPre) );
memset( m_wSongNamePre, 0, sizeof(m_wSongNamePre) );
if( m_fp )
fclose( m_fp );
m_fp = NULL;
m_list.clear();
cleanup();
116 void myD3DSound::myCreateWin( HWND hWnd )
RECT dynamic_
RECT button_
RECT static_
RECT list_
GetClientRect( hWnd, &dynamic_rc );
LONG Width
= dynamic_rc.right - dynamic_rc.
LONG Height = dynamic_rc.bottom
- dynamic_rc.
button_rc.left = 15;
button_rc.top = 15;
m_openbtn = CreateWindow( TEXT("BUTTON"), TEXT("Add"),WS_VISIBLE|WS_CHILD|BS_PUSHBUTTON,
button_rc.left, button_rc.top, 50, 20, hWnd, (HMENU)IDB_OPEN, (HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE), NULL
button_rc.left += 60;
m_closebtn = CreateWindow( TEXT("BUTTON"), TEXT("Del"),WS_VISIBLE|WS_CHILD|BS_PUSHBUTTON,
button_rc.left, button_rc.top, 50, 20, hWnd, (HMENU)IDB_CLOSE, (HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE), NULL
button_rc.left += 60;
m_playbtn = CreateWindow( TEXT("BUTTON"), TEXT("Play"),WS_VISIBLE|WS_CHILD|BS_PUSHBUTTON,
button_rc.left, button_rc.top, 50, 20, hWnd, (HMENU)IDB_PLAY, (HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE), NULL );
button_rc.left += 60;
m_pausebtn = CreateWindow( TEXT("BUTTON"), TEXT("Pause"),WS_VISIBLE|WS_CHILD|BS_PUSHBUTTON,
button_rc.left, button_rc.top, 50, 20, hWnd, (HMENU)IDB_PAUSE, (HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE), NULL );
button_rc.left += 60;
m_stopbtn = CreateWindow( TEXT("BUTTON"), TEXT("Stop"),WS_VISIBLE|WS_CHILD|BS_PUSHBUTTON,
button_rc.left, button_rc.top, 50, 20, hWnd, (HMENU)IDB_STOP, (HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE), NULL );
button_rc.left += 60;
m_scrollbar = CreateWindow( TRACKBAR_CLASS, TEXT(""), WS_VISIBLE|WS_CHILD|WS_BORDER|TBS_HORZ|TBS_TOOLTIPS,
button_rc.left, button_rc.top, 275, 20, hWnd, (HMENU)12, (HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE), NULL
static_rc.left = 15;
static_rc.top = 50;
m_txtplaying = CreateWindow(TEXT("STATIC"), TEXT("playing now:"), WS_VISIBLE|WS_CHILD|SS_CENTER|SS_OWNERDRAW,
static_rc.left, static_rc.top, 90, 20, hWnd, (HMENU)IDB_PLAYING, (HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE), NULL
static_rc.left += ( 90 + 10 );
m_songtxt = CreateWindow( TEXT("STATIC"), TEXT("无文件"), WS_VISIBLE|WS_CHILD|WS_BORDER|SS_LEFT|SS_OWNERDRAW,
static_rc.left, static_rc.top, 560, 20, hWnd, (HMENU)IDB_SONGTEXT, (HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE), NULL
static_rc.left = 15;
static_rc.top = Height - 5 - 16;
m_songinfo = CreateWindow( TEXT("STATIC"), TEXT("请选择wav文件进行播放。"), WS_VISIBLE|WS_CHILD|SS_CENTER|WS_BORDER|SS_OWNERDRAW,
static_rc.left, static_rc.top, 350, 16, hWnd, (HMENU)IDB_SONGINFO, (HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE), NULL
static_rc.left += (350 + 10);
m_songtime = CreateWindow( TEXT("STATIC"), TEXT("00:00 / 00:00"), WS_VISIBLE|WS_CHILD|SS_CENTER|WS_BORDER|SS_OWNERDRAW,
static_rc.left, static_rc.top, 140, 16, hWnd, (HMENU)IDB_SONGTIME, (HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE), NULL
static_rc.left = Width - 15 - 150;
m_timeshow = CreateWindow( TEXT("STATIC"), TEXT(""), WS_VISIBLE|WS_CHILD|SS_CENTER|SS_OWNERDRAW,
static_rc.left, static_rc.top, 150, 16, hWnd, (HMENU)IDB_TIMESHOW, (HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE), NULL
static_rc.left = Width - 90;
static_rc.top = 15;
m_volumebar = CreateWindow( TRACKBAR_CLASS, TEXT(""), WS_VISIBLE|WS_CHILD|WS_BORDER|TBS_HORZ|TBS_TOOLTIPS,
static_rc.left, static_rc.top, 80, 20, hWnd, (HMENU)13, (HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE), NULL
SendMessage( m_volumebar, TBM_SETPOS, TRUE, (LPARAM)50 );
list_rc.left = 30;
list_rc.top = 80;
m_listview = CreateWindowEx( LVS_EX_GRIDLINES|LVS_EX_FULLROWSELECT, WC_LISTVIEW, TEXT(""),
WS_VISIBLE|WS_CHILD|WS_BORDER|WS_VSCROLL|WS_HSCROLL|LVS_REPORT|LVS_SHOWSELALWAYS|LVS_SINGLESEL,
list_rc.left, list_rc.top, 640, 145, hWnd, (HMENU)IDB_SONGLIST, (HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE), NULL
188 void myD3DSound::myChangeSize( HWND hWnd )
RECT dynamic_
GetClientRect( hWnd, &dynamic_rc );
LONG Width
= dynamic_rc.right - dynamic_rc.
LONG Height = dynamic_rc.bottom
- dynamic_rc.
MoveWindow( m_songinfo, 15, Height - 5 - 16, 350, 16, TRUE );
MoveWindow( m_songtime, 15 + 350 + 10, Height - 5 - 16, 140, 16, TRUE );
MoveWindow( m_timeshow, Width - 15 - 150, Height - 5 - 16, 150, 16, TRUE );
MoveWindow( m_songtxt, 115, 50, Width - 115 - 15, 20, TRUE );
MoveWindow( m_scrollbar, 315, 15, Width - 315 - 15 - 90, 20, TRUE );
MoveWindow(
m_volumebar, Width - 90, 15, 80, 20, TRUE );
MoveWindow( m_listview, 30, 80, Width - 60, Height - 80 - 10 - 21, TRUE );
212 void myD3DSound::mySetList( WCHAR* wcFilename )
StrCpyW( tmplist.m_path, wcFilename );
cName[100];
tmpstr[MAX_PATH];
memset(cName,0,100);
memset(tmpstr,0,MAX_PATH);
WCHARtoChar( wcFilename, tmpstr );
int len = strlen(tmpstr);
char* p = &tmpstr[len];
int len_name = 0;
bool isname = 0;
bool bk = 0;
while( !bk )
if( !isname && (*p == '.') )
isname = true;
if( isname )
if(*p == '\\' )
bk = true;
len_name++;
memcpy( cName, p, len_name );
ChartoWCHAR( cName, tmplist.m_name );
ctmpType[5];
lwType = PathFindExtension( wcFilename );
WCHARtoChar( lwType, ctmpType);
sprintf_s( cType, "%s", ctmpType+1);
ChartoWCHAR( cType, tmplist.m_type );
if( StrCmpW( lwType, TEXT(".wav") ) == 0 || StrCmpW( lwType, TEXT(".WAV") ) == 0 )
FILE* tmpfp = NULL;
cBits[20];
WAVEFORMATEX* pwfx = NULL;
memset(cBits,0,20);
if( fopen_s( &tmpfp, tmpstr, "rb" ) == 0 )
myGetWAVFormat( &tmpSize, &tmpCycle, tmpfp, &pwfx );
if(pwfx != NULL)
sprintf_s( cBits, 20, "%d kbps", (pwfx-&wBitsPerSample * pwfx-&nChannels * pwfx-&nSamplesPerSec)/1000 );
fclose(tmpfp);
ChartoWCHAR( cBits, tmplist.m_bits );
char cTime[10];
memset(cTime,0,10);
sprintf_s( cTime, "%02d:%02d", tmpCycle/60, tmpCycle%60 );
ChartoWCHAR( cTime, tmplist.m_time );
else if( StrCmpW( lwType, TEXT(".mp3") ) == 0 || StrCmpW( lwType, TEXT(".MP3") ) == 0 )
cBits[20];
FILE* tmpfp = NULL;
WAVEFORMATEX* pwfx = NULL;
memset(cBits,0,20);
if( myGetMP3Format( tmpstr, &tmpSize, &tmpCycle, &bits, &pwfx ) == 0 )
sprintf_s( cBits, 20, "%d kbps", bits);
ChartoWCHAR( cBits, tmplist.m_bits );
char cTime[10];
memset(cTime,0,10);
sprintf_s( cTime, "%02d:%02d", tmpCycle/60, tmpCycle%60 );
ChartoWCHAR( cTime, tmplist.m_time );
m_list.push_back( tmplist );
myUpdateList();
314 void myD3DSound::myUpdateList()
ListView_DeleteAllItems(m_listview);
int iSize = m_list.size();
vitem.mask = LVIF_TEXT;
for( int i = 0; i& iS i++ )
cIdx[100];
wIdx[100];
memset(cIdx,0,100);
memset(wIdx,0,100);
vitem.iItem =
m_list[i].m_idx = i+1;
sprintf_s( cIdx, "%d", i+1 );
ChartoWCHAR( cIdx, wIdx );
vitem.pszText = wI
vitem.iSubItem = 0;
ListView_InsertItem(m_listview, &vitem);
vitem.iSubItem = 1;
vitem.pszText = m_list[i].m_
ListView_SetItem( m_listview, &vitem);
vitem.iSubItem = 2;
vitem.pszText = m_list[i].m_
ListView_SetItem(m_listview, &vitem);
vitem.iSubItem = 3;
vitem.pszText = m_list[i].m_
ListView_SetItem(m_listview, &vitem);
vitem.iSubItem = 4;
vitem.pszText = m_list[i].m_
ListView_SetItem(m_listview, &vitem);
vitem.iSubItem = 5;
vitem.pszText = m_list[i].m_
ListView_SetItem(m_listview, &vitem);
356 int myD3DSound::mySongNum()
return m_list.size();
363 void myD3DSound::myInitList()
vcl.mask = LVCF_SUBITEM | LVCF_WIDTH | LVCF_TEXT | LVCF_FMT;
vcl.fmt = LVCFMT_LEFT;
for( int i = 0; i & 6; i++ )
vcl.pszText = g_cwSongList[i];
vcl.cx = 80;
if( i == 5 )
vcl.cx = 800;
vcl.iSubItem =
ListView_InsertColumn( m_listview, i, &vcl );
381 void myD3DSound::mySetTimer( SYSTEMTIME time )
char strtime[60];
memset( strtime, 0, 60 );
sprintf_s(strtime,"%04d-%02d-%02d %02d:%02d:%02d",
time.wYear,time.wMonth,time.wDay,time.wHour,time.wMinute,time.wSecond);
ChartoWCHAR(strtime,m_wstrTime);
392 WCHAR* myD3DSound::myGetTimer()
return m_wstrT
399 void myD3DSound::mySetScrollPos( bool isUp, DWORD dPos )
iPos = SendMessage( m_scrollbar, TBM_GETPOS, 0, 0 );
if( g_pmySound-&isPlay() &&
g_pmySound-&m_ds_dwFileSize &= DSBSIZE_MAX )
DWORD dNewP
dNewPos = iPos * (g_pmySound-&m_ds_dwFileSize / 100);
g_pmySound-&m_pBuffer8-&SetCurrentPosition( dNewPos );
g_pmySound-&m_pBuffer8-&Play(0, 0, DSBPLAY_LOOPING);
iPos = SendMessage( m_scrollbar, TBM_SETPOS, TRUE, (LPARAM)0 );
427 void myD3DSound::mySetVolumePos( bool isUp, DWORD dPos )
LONG vol = 0;
double dbV
if( isUp && m_pBuffer8 != NULL )
iPos = SendMessage( m_volumebar, TBM_GETPOS, 0, 0 );
if( iPos & 0 && iPos &= 100 )
dbValue = 20.0f * log10( (double)(iPos / 100.0f) );
vol = (LONG)(dbValue * 100.0f);
else if( iPos == 0 )
vol = DSBVOLUME_MIN;
vol = DSBVOLUME_MAX;
m_pBuffer8-&SetVolume( vol );
455 void myD3DSound::myOpenFile()
WCHAR strFilename[MAX_PATH];
ZeroMemory(&opfn, sizeof(OPENFILENAME));
opfn.lStructSize = sizeof(OPENFILENAME);
//结构体大小
opfn.lpstrFilter = L"所有文件\0*.*\0wav文件\0*.wav\0MP3文件\0*.mp3\0";
opfn.nFilterIndex = 1;
//过滤索引
opfn.lpstrFile = strF
//文件名的缓冲,不需要初始化则必须为null
opfn.lpstrFile[0] = '\0';
opfn.nMaxFile = sizeof(strFilename);
opfn.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY;
if( GetOpenFileName(&opfn) )
mySetList(strFilename);
474 void myD3DSound::myCloseFile()
ZeroMemory(&opfn, sizeof(OPENFILENAME));
if( StrCmpW(m_wSongPath, m_wSongPathPre) == 0 )
SetWindowText(m_songtxt, TEXT(""));
if( m_fp )
fclose( m_fp );
m_fp = NULL;
MY_SONG_LIST::iterator S
for( Songit = m_list.begin(); Songit != m_list.end(); Songit++ )
if( StrCmpW(Songit-&m_path, m_wSongPathPre) == 0 )
m_list.erase( Songit );
memset( m_wSongPathPre, 0, MAX_PATH );
memset( m_wSongPath, 0, MAX_PATH );
myUpdateList();
504 void myD3DSound::mySetPlayInfo( NM_LISTVIEW* pNMListView, bool DBClick )
if( DBClick )
if( StrCmpW(m_list[pNMListView-&iItem].m_path, m_wSongPath) )
{//双击新歌则停止当前播放
StrCpyW( m_wSongPath, m_list[pNMListView-&iItem].m_path );
StrCpyW( m_wSongName, m_list[pNMListView-&iItem].m_name );
StrCpyW( m_wSongPathPre, m_list[pNMListView-&iItem].m_path );
StrCpyW( m_wSongNamePre, m_list[pNMListView-&iItem].m_name );
StrCpyW( m_wSongPathPre, m_list[pNMListView-&iItem].m_path );
StrCpyW( m_wSongNamePre, m_list[pNMListView-&iItem].m_name );
if( ! isPlay() )
StrCpyW( m_wSongPath, m_list[pNMListView-&iItem].m_path );
StrCpyW( m_wSongName, m_list[pNMListView-&iItem].m_name );
531 int myD3DSound::myPlay()
if( isPlay() )
if( StrCmpW( m_wSongPath, m_wSongPathPre ) )
StrCpyW( m_wSongName, m_wSongNamePre );
StrCpyW( m_wSongPath, m_wSongPathPre );
if( m_pBuffer8 == NULL )
int res = 0;
res = mySetSoundType();
if( res != 0 )
MessageBox( m_father, g_cwErrorMsg[res], TEXT("ERROR"), MB_OK );
//create notification thread
m_hThread = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)ThreadNotifyEvent, NULL, 0, &m_thread_id );
m_hThread2 = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)ThreadNotifyEvent2, NULL, 0, &m_thread_id2 );
m_hThread3 = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)ThreadNotifyEvent3, NULL, 0, &m_thread_id3 );
SetWindowText( m_songtxt, m_wSongName );
SetPlaying( TRUE );
mySetVolumePos(TRUE,0);
m_pBuffer8-&SetCurrentPosition( m_dwPlayPos );
m_pBuffer8-&Play(0, 0, DSBPLAY_LOOPING);
570 int myD3DSound::myStop()
myCleanBuffer();
if( isPlay() )
CloseHandle( m_hEvents[0] );
if( m_hThread != NULL )
TerminateThread( m_hThread, 0 );
CloseHandle( m_hThread );
if( IsMPG3() )
cleanup();
SetWindowText( m_songinfo, TEXT("请选择wav文件进行播放。") );
StrCpyW( m_wSongName, TEXT(""));
StrCpyW( m_wSongPath, TEXT(""));
SetWindowText( m_songtxt, m_wSongName );
SendMessage( g_pmySound-&m_scrollbar, TBM_SETPOS, TRUE, (LPARAM)0 );
SetWindowText( g_pmySound-&m_songtime, TEXT("00:00 / 00:00") );
598 int myD3DSound::myPause()
if( m_pBuffer8 == NULL )
return -1;
if( isPlay() )
m_pBuffer8-&GetCurrentPosition( &m_dwPlayPos, NULL );
SetPlaying( FALSE );
m_pBuffer8-&Stop();
SetPlaying( TRUE );
m_pBuffer8-&SetCurrentPosition( m_dwPlayPos );
m_pBuffer8-&Play(0, 0, DSBPLAY_LOOPING);
619 int myD3DSound::GetBufferValue( FILE** fp, mpg123_handle** mpghandle, DWORD* BuffSize )
*mpghandle = m_
*BuffSize = m_ds_dwBuffS
628 ///////////////////////
629 //private
630 ///////////////////////
632 int myD3DSound::mySetSoundType()
WCHAR cNameStr[MAX_PATH];
LPWSTR lpNameT
char cType[4];
char cTmpStr[5];
memset( cNameStr, 0, MAX_PATH );
memset( cType, 0, 4 );
memset( cTmpStr, 0, 5 );
StrCpyW( cNameStr, m_wSongPath );
if( cNameStr[0] == '\0' )
return EFAIL_NOFILE;
lpNameType = PathFindExtension( cNameStr );
WCHARtoChar( lpNameType, cTmpStr);
sprintf_s( cType, "%s", cTmpStr+1);
if( StrCmpW( lpNameType, TEXT(".mp3") ) == 0 || StrCmpW( lpNameType, TEXT(".MP3") ) == 0 )
//stream size
DWORD dwBuffS
WAVEFORMATEX
WAVEFORMATEX* pTmpWfx = NULL;
char filepath[MAX_PATH];
memset( filepath, 0, MAX_PATH );
WCHARtoChar( cNameStr, filepath );
if( myGetMP3Format( filepath, &dwSize, &dwCycle, &bitrate, &pTmpWfx, FALSE ) != 0 )
return EFAIL_FORMATERR;
m_ds_dwFileSize = dwS
m_ds_dwFileTime = dwC
m_ds_dwFilebps = pTmpWfx-&nAvgBytesPerS
m_ds_dwPos
//offset position
m_ds_dwLeave
//leave data size
wfx.wFormatTag
= pTmpWfx-&wFormatT
wfx.nChannels
= pTmpWfx-&nC
wfx.nSamplesPerSec
= pTmpWfx-&nSamplesPerS
wfx.wBitsPerSample
= pTmpWfx-&wBitsPerS
wfx.nBlockAlign
= pTmpWfx-&nBlockA
wfx.nAvgBytesPerSec = pTmpWfx-&nAvgBytesPerS
pTmpWfx = NULL;
if( FAILED( myCreateMPGBuffer( &wfx, &dwBuffSize ) ) )
return EFAIL_MPGBUFFERERR;
m_ds_dwBuffSize = dwBuffS
//song info
wcStr_info[100];
cStr_info[100];
cStr_type[5];
memset( wcStr_info,0,100 );
memset( cStr_info,0,100 );
memset( cStr_type,0,5 );
WCHARtoChar( lpNameType, cStr_type );
sprintf_s( cStr_info, "%s | %d kbps | %d Hz", cStr_type+1, bitrate, wfx.nSamplesPerSec);
ChartoWCHAR( cStr_info, wcStr_info );
SetWindowText( m_songinfo, wcStr_info );
m_bmpg = TRUE;
else if( StrCmpW( lpNameType, TEXT(".wav") ) == 0 || StrCmpW( lpNameType, TEXT(".WAV") ) == 0 )
WAVEFORMATEX
//声音文件总大小
DWORD dwBuffS
//创建的缓冲区总大小
int inum=WideCharToMultiByte(CP_ACP,0,cNameStr,-1,NULL,0,NULL,0);
char* cfilename = NULL;
cfilename = (char*)malloc( inum * sizeof(char) );
if( cfilename == NULL )
free(cfilename);
memset( cfilename, 0, inum * sizeof(char) );
WideCharToMultiByte(CP_ACP,0,cNameStr,-1,cfilename,inum,NULL,0);
if( fopen_s( &m_fp, cfilename, "rb" ) )
return EFAIL_OPENFILEERR;
WAVEFORMATEX* pTmpWfx = NULL;
myGetWAVFormat( &dwSize, &dwCycle, m_fp, &pTmpWfx );
if( pTmpWfx == NULL )
return EFAIL_FORMATERR;
m_ds_dwFileSize = dwS
m_ds_dwFileTime = dwC
m_ds_dwFilebps = pTmpWfx-&nAvgBytesPerS
if(m_factwav)
m_ds_dwPos = sizeof(WAVE_HEADER_FACT);
//offset position
m_ds_dwPos = sizeof(WAVE_HEADER);
m_ds_dwLeave = dwS
//leave data size
wfx.wFormatTag
= pTmpWfx-&wFormatT
wfx.nChannels
= pTmpWfx-&nC
wfx.nSamplesPerSec
= pTmpWfx-&nSamplesPerS
wfx.wBitsPerSample
= pTmpWfx-&wBitsPerS
wfx.nBlockAlign
= pTmpWfx-&nBlockA
wfx.nAvgBytesPerSec = pTmpWfx-&nAvgBytesPerS
pTmpWfx = NULL;
if( FAILED( myCreatePCMBuffer( &wfx, &dwBuffSize ) ) )
return EFAIL_PCMBUFFERERR;
m_ds_dwBuffSize = dwBuffS
//返回缓冲区大小
//songinfo
wcStr_info[100];
//output info
cStr_info[100];
cStr_type[5];
memset( wcStr_info,0,100 );
memset( cStr_info,0,100 );
memset( cStr_type,0,5 );
WCHARtoChar( lpNameType, cStr_type );
sprintf_s( cStr_info, "%s | %d kbps | %d Hz", cStr_type+1,
(wfx.wBitsPerSample * wfx.nChannels * wfx.nSamplesPerSec)/1000, wfx.nSamplesPerSec);
//类型|比特率|频率
ChartoWCHAR( cStr_info, wcStr_info );
SetWindowText( m_songinfo, wcStr_info );
m_bmpg = FALSE;
return EFAIL_NOTSUPPORT;
773 int myD3DSound::myGetWAVFormat( DWORD* dwSize, DWORD* dwCycle, FILE* fp, WAVEFORMATEX** wfx )
WAVE_HEADER
WAVE_HEADER_FACT
wave_header2;
777 #ifndef _DEBUG
volatile WAVEFORMATEX
WAVEFORMATEX
781 #endif
char fact[4];
fseek( fp, 38, SEEK_SET );
fread( fact, 1, 4, fp );
fseek( fp, 0, SEEK_SET );
if( memcmp(fact,"fact",4) == 0 )
fread( &wave_header2, 1, sizeof(WAVE_HEADER_FACT), fp);
m_factwav = TRUE;
if(memcmp(wave_header2.riff_sig, "RIFF", 4) ||
memcmp(wave_header2.wave_sig, "WAVE", 4) ||
memcmp(wave_header2.format_sig, "fmt ", 4) )
return -1;
wave_format.wFormatTag
= WAVE_FORMAT_PCM;
wave_format.nChannels
= wave_header2.
wave_format.nSamplesPerSec
= wave_header2.sample_
wave_format.wBitsPerSample
= wave_header2.bits_per_
wave_format.nBlockAlign
= wave_header2.bits_per_sample / 8 * wave_header2.
wave_format.nAvgBytesPerSec = wave_header2.sample_rate * wave_format.nBlockA
*dwSize = wave_header2.data_
*dwCycle = wave_header2.data_size / wave_format.nAvgBytesPerS
fread( &wave_header, 1, sizeof(WAVE_HEADER), fp);
m_factwav = FALSE;
if(memcmp(wave_header.riff_sig, "RIFF", 4) ||
memcmp(wave_header.wave_sig, "WAVE", 4) ||
memcmp(wave_header.format_sig, "fmt ", 4) )
return -1;
wave_format.wFormatTag
= WAVE_FORMAT_PCM;
wave_format.nChannels
= wave_header.
wave_format.nSamplesPerSec
= wave_header.sample_
wave_format.wBitsPerSample
= wave_header.bits_per_
wave_format.nBlockAlign
= wave_header.bits_per_sample / 8 * wave_header.
wave_format.nAvgBytesPerSec = wave_header.sample_rate * wave_format.nBlockA
*dwSize = wave_header.data_
*dwCycle = wave_header.data_size / wave_format.nAvgBytesPerS
*wfx = (WAVEFORMATEX*)&wave_
832 int myD3DSound::myGetMP3Format( char* filestr, DWORD* dwSize, DWORD* dwCycle, int* bitrate, WAVEFORMATEX** wfx, bool isClose )
ret = MPG123_OK;
channels = 0;
encoding = 0;
//编码格式
perbits = 16;
//bits per second
fTime = 0;
fSize = 0;
simpleNum = 1152;
streamSize1;
streamSize2;
streamSize3;
tmpfp = NULL;
848 #ifndef _DEBUG
volatile WAVEFORMATEX
WAVEFORMATEX
852 #endif
cleanup();
ret = mpg123_init();
if(ret != MPG123_OK || ( m_mpghandle = mpg123_new(NULL, &ret) ) == NULL)
cleanup();
return -1;
if( mpg123_open(m_mpghandle, filestr) != MPG123_OK || mpg123_getformat(m_mpghandle, &rate, &channels, &encoding) != MPG123_OK )
cleanup();
return -1;
if((encoding & MPG123_ENC_16) == MPG123_ENC_16)
perbits = 16;
else if((encoding & MPG123_ENC_32) == MPG123_ENC_32)
perbits = 32;
perbits = 8;
wave_format.wFormatTag
= WAVE_FORMAT_PCM;
wave_format.nChannels
wave_format.nSamplesPerSec
wave_format.wBitsPerSample
wave_format.nBlockAlign
= perbits / 8 *
wave_format.nAvgBytesPerSec = rate * perbits / 8 *
*wfx = (WAVEFORMATEX*)&wave_
mpg123_seek( m_mpghandle, 0, SEEK_END );
frameNum = mpg123_tellframe( m_mpghandle );
//总帧数法:Total_Time = Total_Frame_Number * (Sample_Number * (1 / Frame_Sample_Rate))
fTime = (long)( frameNum * simpleNum / rate );
//time and buffer size
*dwCycle = fT
//data size = ftime * nAvgBytesPerSec = (frameNum*simpleNum/rate)*(rate*perbits/8*channels)
*dwSize = frameNum * simpleNum * perbits * channels / 8;
if( mpg123_info( m_mpghandle, &mpginfo) != MPG123_OK )
cleanup();
return -1;
if(mpginfo.layer != 3)
cleanup();
return -1;
//bit rate
if( mpginfo.vbr == MPG123_CBR )
*bitrate = mpginfo.
else if( mpginfo.vbr == MPG123_VBR )
if( fopen_s( &tmpfp, filestr, "rb" ) == 0 )
fseek( tmpfp, 0, SEEK_END );
fSize = ftell( tmpfp );
//文件大小
fclose( tmpfp );
tmpfp = NULL;
*bitrate = (fSize * 8)/(fTime*1000);
//(kbits/s) : filesize(bytes)*8(bits)/filetime(s)/1000
//平均比特率 = 文件大小/总时间/1000
if(isClose)
cleanup();
933 HRESULT myD3DSound::myCreatePCMBuffer( WAVEFORMATEX* wfx, DWORD* dwBuffSize )
DSBUFFERDESC
WAVEFORMATEX
IDirectSound8* lpDS8;
LPDIRECTSOUNDBUFFER
LPDIRECTSOUNDNOTIFY8
DSBPOSITIONNOTIFY
if( m_pDirectSound == NULL )
return E_FAIL;
lpDS8 = m_pDirectS
ZeroMemory(&dsbd, sizeof(dsbd));
wave.wFormatTag = WAVE_FORMAT_PCM;
wave.nChannels = wfx-&nC
//音频文件的通道数量
wave.nSamplesPerSec = wfx-&nSamplesPerS
//采样频率
wave.wBitsPerSample = wfx-&wBitsPerS
//每次采样样本的大小
wave.nChannels = 2;
wave.nSamplesPerSec = 44100;
wave.wBitsPerSample = 16;
wave.nBlockAlign = wave.nChannels * wave.wBitsPerSample / 8;
wave.nAvgBytesPerSec = wave.nSamplesPerSec * wave.nBlockA
wave.cbSize = 0;
dsbd.dwSize = sizeof(dsbd);
dsbd.dwFlags = DSBCAPS_GLOBALFOCUS | DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLPOSITIONNOTIFY;
if( m_ds_dwFileSize & DSBSIZE_MAX )
dsbd.dwBufferBytes = DSBSIZE_MAX;
dsbd.dwBufferBytes = m_ds_dwFileS
*dwBuffSize = dsbd.dwBufferB
//返回缓冲区大小
dsbd.lpwfxFormat = &
caps.dwSize = sizeof(DSCAPS);
if( SUCCEEDED( lpDS8-&GetCaps(&caps) ) )
if( caps.dwMaxHwMixingStreamingBuffers & 0 )
dsbd.dwFlags |= DSBCAPS_LOCDEFER;
dsbd.dwFlags |= DSBCAPS_STATIC;
if( FAILED( lpDS8-&CreateSoundBuffer( &dsbd, &pTmpBuffer, NULL ) ) )
return E_FAIL;
if( FAILED( pTmpBuffer-&QueryInterface( IID_IDirectSoundBuffer8, (void**)&m_pBuffer8 ) ) )
return E_FAIL;
pTmpBuffer-&Release();
if( FAILED( m_pBuffer8-&QueryInterface( IID_IDirectSoundNotify,(void**)&pNotify ) ) )
return E_FAIL;
dspNotify.dwOffset = dsbd.dwBufferBytes - 1;
m_hEvents[0] = CreateEvent(NULL,FALSE,FALSE,NULL);
dspNotify.hEventNotify = m_hEvents[0];
pNotify-&SetNotificationPositions( 1, &dspNotify);
pNotify-&Release();
fseek( m_fp, m_ds_dwPos, SEEK_SET );
if( myReadBuffer( 0, dsbd.dwBufferBytes ) )
m_ds_dwPos
+= dsbd.dwBufferB
//if(m_ds_dwFileSize &= DSBSIZE_MAX), this m_ds_dwLeave will be 0
m_ds_dwLeave
-= dsbd.dwBufferB
return S_OK;
return E_FAIL;
1025 HRESULT myD3DSound::myCreateMPGBuffer( WAVEFORMATEX* wfx, DWORD* dwBuffSize )
DSBUFFERDESC
WAVEFORMATEX
IDirectSound8* lpDS8;
LPDIRECTSOUNDBUFFER
LPDIRECTSOUNDNOTIFY8
DSBPOSITIONNOTIFY
if( m_pDirectSound == NULL )
return E_FAIL;
lpDS8 = m_pDirectS
ZeroMemory(&dsbd, sizeof(dsbd));
wave.wFormatTag = WAVE_FORMAT_PCM;
wave.nChannels = wfx-&nC
wave.nSamplesPerSec = wfx-&nSamplesPerS
wave.wBitsPerSample = wfx-&wBitsPerS
wave.nChannels = 2;
wave.nSamplesPerSec = 44100;
wave.wBitsPerSample = 16;
wave.nBlockAlign = wave.nChannels * wave.wBitsPerSample / 8;
wave.nAvgBytesPerSec = wave.nSamplesPerSec * wave.nBlockA
wave.cbSize = 0;
dsbd.dwSize = sizeof(dsbd);
dsbd.dwFlags = DSBCAPS_GLOBALFOCUS | DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLPOSITIONNOTIFY;
if( m_ds_dwFileSize & DSBSIZE_MAX )
dsbd.dwBufferBytes = DSBSIZE_MAX;
dsbd.dwBufferBytes = m_ds_dwFileS
*dwBuffSize = dsbd.dwBufferB
//返回缓冲区大小
dsbd.lpwfxFormat = &
caps.dwSize = sizeof(DSCAPS);
if( SUCCEEDED( lpDS8-&GetCaps(&caps) ) )
if( caps.dwMaxHwMixingStreamingBuffers & 0 )
dsbd.dwFlags |= DSBCAPS_LOCDEFER;
dsbd.dwFlags |= DSBCAPS_STATIC;
if( FAILED( lpDS8-&CreateSoundBuffer( &dsbd, &pTmpBuffer, NULL ) ) )
return E_FAIL;
if( FAILED( pTmpBuffer-&QueryInterface( IID_IDirectSoundBuffer8, (void**)&m_pBuffer8 ) ) )
return E_FAIL;
pTmpBuffer-&Release();
if( FAILED( m_pBuffer8-&QueryInterface( IID_IDirectSoundNotify,(void**)&pNotify ) ) )
return E_FAIL;
dspNotify.dwOffset = dsbd.dwBufferBytes - 1;
m_hEvents[0] = CreateEvent(NULL,FALSE,FALSE,NULL);
dspNotify.hEventNotify = m_hEvents[0];
pNotify-&SetNotificationPositions( 1, &dspNotify);
pNotify-&Release();
if( m_mpghandle == NULL )
return E_FAIL;
mpg123_seek( m_mpghandle, 0, SEEK_SET );
if( myReadMPGBuffer( 0, dsbd.dwBufferBytes ) )
m_ds_dwPos
+= dsbd.dwBufferB
//if(m_ds_dwFileSize &= DSBSIZE_MAX), this m_ds_dwLeave will be 0
m_ds_dwLeave
-= dsbd.dwBufferB
return S_OK;
return E_FAIL;
1120 bool myD3DSound::myReadBuffer( long lock_pos, long lock_size )
if( m_pBuffer8 == NULL || m_fp == NULL )
LPVOID buf = NULL;
buf_len = 0;
if( SUCCEEDED( m_pBuffer8-&Lock(lock_pos, lock_size, &buf, &buf_len, NULL, NULL, 0 ) ) )
fread( buf, 1, buf_len, m_fp );
m_pBuffer8-&Unlock( buf, buf_len, NULL, 0 );
1137 bool myD3DSound::myReadMPGBuffer( long lock_pos, long lock_size )
if( m_pBuffer8 == NULL || m_mpghandle == NULL )
LPVOID buf = NULL;
buf_len = 0;
unsigned char* _
_buffer = (unsigned char*)malloc( lock_size * sizeof(unsigned char) );
if( SUCCEEDED( m_pBuffer8-&Lock(lock_pos, lock_size, &buf, &buf_len, NULL, NULL, 0 ) ) )
mpg123_read( m_mpghandle, _buffer, lock_size, &outsize);
memcpy(buf, _buffer, outsize);
m_pBuffer8-&Unlock( buf, buf_len, NULL, 0 );
1159 void myD3DSound::myCleanBuffer()
if( m_pBuffer8 )
m_pBuffer8-&Stop();
SetPlaying( FALSE );
m_ds_dwPos = 0;
m_ds_dwLeave = 0;
m_ds_dwBuffSize =0;
m_dwPlayPos = 0;
SAFE_RELEASE( m_pBuffer8 );
1171 #ifdef __MAX_BUFFER__
m_ds_dwFileSize = 0;
1173 #endif
m_ds_dwFileTime = 0;
m_ds_dwFilebps = 0;
m_iScrollPos = 0;
1180 void myD3DSound::cleanup()
if( m_mpghandle != NULL )
mpg123_close(m_mpghandle);
mpg123_delete(m_mpghandle);
m_mpghandle = NULL;
mpg123_exit();
1191 ///////////////////////
1192 //global function
1193 ///////////////////////
1196 DWORD ThreadNotifyEvent( LPVOID thread_data )
DWORD res_msg = 0;
DWORD dwBuffsize = 0;
FILE* fp = NULL;
mpg123_handle* mpghandle = NULL;
if( g_pmySound == NULL )
g_pmySound-&GetBufferValue( &fp, &mpghandle, &dwBuffsize );
if( (!g_pmySound-&IsMPG3() && fp == NULL) || dwBuffsize == 0 || (g_pmySound-&IsMPG3() && mpghandle == 0) )
while( 1 )
res_msg = WaitForSingleObject( g_pmySound-&m_hEvents[0], INFINITE );
if( res_msg == WAIT_OBJECT_0 )
//update buffer
if( g_pmySound-&m_ds_dwLeave == 0 )
g_pmySound-&myStop();
ExitThread( 0 );
if( g_pmySound-&IsMPG3() )
mpg123_seek( mpghandle, g_pmySound-&m_ds_dwPos, SEEK_SET );
if( g_pmySound-&m_ds_dwLeave &= dwBuffsize )
g_pmySound-&myReadMPGBuffer( 0, g_pmySound-&m_ds_dwLeave );
g_pmySound-&m_ds_dwLeave = 0;
g_pmySound-&myReadMPGBuffer( 0, dwBuffsize
g_pmySound-&m_ds_dwPos
g_pmySound-&m_ds_dwLeave
fseek(fp, g_pmySound-&m_ds_dwPos, SEEK_SET);
if( g_pmySound-&m_ds_dwLeave &= dwBuffsize )
g_pmySound-&myReadBuffer( 0, g_pmySound-&m_ds_dwLeave );
g_pmySound-&m_ds_dwLeave = 0;
g_pmySound-&myReadBuffer( 0, dwBuffsize
g_pmySound-&m_ds_dwPos
g_pmySound-&m_ds_dwLeave
1256 DWORD ThreadNotifyEvent2( LPVOID thread_data )
DWORD d_FileSize = g_pmySound-&m_ds_dwFileS
if( d_FileSize &= DSBSIZE_MAX )
while( 1 )
//update slider
if( g_pmySound-&m_pBuffer8 == NULL )
SendMessage( g_pmySound-&m_scrollbar, TBM_SETPOS, TRUE, (LPARAM)0 );
ExitThread(0);
if( FAILED( g_pmySound-&m_pBuffer8-&GetCurrentPosition( &d_PosFile, NULL ) ) )
SendMessage( g_pmySound-&m_scrollbar, TBM_SETPOS, TRUE, (LPARAM)0 );
ExitThread(0);
if( d_PosFile &= (d_FileSize/100)* icut )
SendMessage( g_pmySound-&m_scrollbar, TBM_SETPOS, TRUE, (LPARAM)icut );
if( icut &= 100 )
ExitThread(0);
1290 DWORD ThreadNotifyEvent3( LPVOID thread_data )
d_FileTime = g_pmySound-&m_ds_dwFileT
d_Filebps = g_pmySound-&m_ds_dwF
//每秒传输字节
ctmpTime[20];
wtmpTime[20];
memset(ctmpTime,0,20 );
memset(wtmpTime,0,20 );
d_Nowtime = 0;
sprintf_s( ctmpTime, "%02d:%02d / %02d:%02d", d_Nowtime/60, d_Nowtime%60, d_FileTime/60, d_FileTime%60 );
ChartoWCHAR( ctmpTime, wtmpTime );
SetWindowText( g_pmySound-&m_songtime, wtmpTime );
SYSTEMTIME
memset(ctmpTime,0,20 );
memset(wtmpTime,0,20 );
if( g_pmySound-&m_pBuffer8 == NULL )
SetWindowText( g_pmySound-&m_songtime, TEXT("00:00 / 00:00") );
ExitThread(0);
if( FAILED( g_pmySound-&m_pBuffer8-&GetCurrentPosition( &d_PosFile, NULL ) ) )
SetWindowText( g_pmySound-&m_songtime, TEXT("00:00 / 00:00") );
ExitThread(0);
if( d_PosFile &= d_Filebps *(d_Nowtime+1) )
d_Nowtime++;
sprintf_s( ctmpTime, "%02d:%02d / %02d:%02d", d_Nowtime/60, d_Nowtime%60, d_FileTime/60, d_FileTime%60 );
ChartoWCHAR( ctmpTime, wtmpTime );
SetWindowText( g_pmySound-&m_songtime, wtmpTime );
GetLocalTime( &time );
g_pmySound-&mySetTimer( time );
SetWindowText( g_pmySound-&m_timeshow, g_pmySound-&myGetTimer() );
GetClientRect( g_pmySound-&m_father, &rect );
InvalidateRect(g_pmySound-&m_father,&rect,TRUE);
if( d_Nowtime == d_FileTime )
ExitThread(0);
1338 void ChartoWCHAR( const char* dsc, WCHAR* dst)
int len_c;
len_c = MultiByteToWideChar( CP_ACP,0,dsc,-1,NULL,0 );
MultiByteToWideChar( CP_ACP,0,dsc,-1,dst,len_c );
1344 void WCHARtoChar( const WCHAR* dsc, char* dst )
int len_w;
len_w = WideCharToMultiByte(CP_ACP,0,dsc,-1,NULL,0,NULL,0);
WideCharToMultiByte(CP_ACP,0,dsc,-1,dst,len_w,NULL,0);
D3DSound.cpp
阅读(...) 评论()

我要回帖

更多关于 cdirectsound 的文章

 

随机推荐