使用 DirectSound 播放 MP3 文件
将对 MP3 的支持代码加入到 DSound 程序中,以供 wxDeMPQ 使用,随便调整了一下代
码,使基类作更多的事情。下面修改后的代码,源码在这里。
DSoundObject.h
1 #ifndef __DSOUNDOBJECT_H__
2 #define __DSOUNDOBJECT_H__
3
4 #include
5 #include
6
7 #include
8
9 extern HANDLE _eventNotify[3];
10
11 class CDSoundObject
12 {
13 public:
14
15
enum SoundType { ST_WAVE, ST_MP3 };
static const DWORD SIZE_DS_BUFFER = 32 * 1024;
16 public:
17
18
19
20
21
22
23
24
CDSoundObject(SoundType type);
virtual ~CDSoundObject();
virtual int Init(HWND hwnd);
virtual int LoadFile(const std::string& file) = 0;
virtual int Play();
virtual int Pause();
25
26
27
virtual int Stop();
virtual bool IsPlaying() const;
virtual double Duration() = 0;
28 protected:
29
30
31
32
33
34
35
36
virtual int CreateDSound();
virtual void ReleaseDSound();
virtual int CreateDSoundBuffer();
virtual void ReleaseDSoundBuffer();
virtual int InitDSData() = 0;
virtual int LoadDSData(DWORD start, DWORD count) = 0;
virtual int PlayOver();
37 protected:
38
39
40
41
42
HWND _hWnd;
SoundType _eType;
IDirectSound * _pDS;
IDirectSoundBuffer * _pDSBuffer;
IDirectSoundNotify8* _pDSNotify;
43 protected:
44
45
46
int CreateNotifyThread();
void ReleaseNotifyThread();
static DWORD NotifyHandleProc(LPVOID param);
47 protected:
48
49
50
51
DWORD _dwNotifyThreadID;
HANDLE _hNotifyThread;
DSBPOSITIONNOTIFY _notifyPos[2];
52 protected:
53
DWORD _dwPlayPos;
54 };
55
56 #endif
DSoundObject.cpp
1 #include "DSoundObject.h"
2
3 HANDLE _eventNotify[3];
4
5 CDSoundObject::CDSoundObject(CDSoundObject::SoundType type)
6 : _eType(type)
7 , _pDS(NULL), _pDSBuffer(NULL), _pDSNotify(NULL)
8 , _dwNotifyThreadID(0), _hNotifyThread(NULL)
9 , _dwPlayPos(0)
10 {
11 }
12
13 CDSoundObject::~CDSoundObject()
ReleaseNotifyThread();
ReleaseDSoundBuffer();
ReleaseDSound();
14 {
15
16
17
18 }
19
20
21 int CDSoundObject::Init(HWND hwnd)
_hWnd = hwnd;
return CreateDSound();
22 {
23
24
25
26 }
27
28 int CDSoundObject::CreateDSound()
HRESULT hr = DirectSoundCreate(NULL, &_pDS, NULL);
if(hr != DS_OK)
return -1;
_pDS->SetCooperativeLevel(_hWnd, DSSCL_NORMAL);
return 0;
29 {
30
31
32
33
34
35 }
36
37
38 void CDSoundObject::ReleaseDSound()
if(_pDS != NULL)
_pDS->Release(), _pDS = NULL;
39 {
40
41
42 }
43
44 int CDSoundObject::CreateDSoundBuffer()
ReleaseDSoundBuffer();
return 0;
45 {
46
47
48
49 }
50
51 void CDSoundObject::ReleaseDSoundBuffer()
52 {
53
54
55
56
57
if(_pDSBuffer != NULL)
{
_pDSBuffer->Stop();
_pDSBuffer->Release();
_pDSBuffer = NULL;
58
}
59 }
60
61 int CDSoundObject::CreateNotifyThread()
62 {
63
64
65
66
67
68
69
70
71
ReleaseNotifyThread();
//event
_eventNotify[0] = CreateEvent(NULL, FALSE, FALSE, NULL);
_eventNotify[1] = CreateEvent(NULL, FALSE, FALSE, NULL);
_eventNotify[2] = CreateEvent(NULL, FALSE, FALSE, NULL);
_hNotifyThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)No
tifyHandleProc, (LPVOID)this, 0, &_dwNotifyThreadID);
72
73
74
75
if(_hNotifyThread == NULL)
return -1;
HRESULT hr = _pDSBuffer->QueryInterface(IID_IDirectSoundNotify8, (voi
d**)&_pDSNotify);
76
77
78
79
80
81
82
83
84
85
if(hr != DS_OK)
return -1;
_notifyPos[0].dwOffset = (SIZE_DS_BUFFER / 2) - 1;
_notifyPos[0].hEventNotify = _eventNotify[0];
_notifyPos[1].dwOffset = SIZE_DS_BUFFER - 1;
_notifyPos[1].hEventNotify = _eventNotify[1];
hr = _pDSNotify->SetNotificationPositions(2, _notifyPos);
if(hr != DS_OK)
return -1;
return 0;
86
87
88
89 }
90
91 void CDSoundObject::ReleaseNotifyThread()
if(_hNotifyThread != NULL)
{
}
//TerminateThread(_hNotifyThread, 0);
SetEvent(_eventNotify[2]);
CloseHandle(_hNotifyThread);
_hNotifyThread = NULL;
for(int i = 0; i < 2; ++ i)
{
}
if(_eventNotify[i] != NULL)
{
}
CloseHandle(_eventNotify[i]);
_eventNotify[i] = NULL;
if(_pDSNotify != NULL)
{
}
_pDSNotify->Release();
_pDSNotify = NULL;
92 {
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114 }
115
116 DWORD CDSoundObject::NotifyHandleProc(LPVOID param)
117 {
118
119
120
121
122
123
124
CDSoundObject* obj = (CDSoundObject*)(param);
if(obj == NULL)
return -1;
while(true)
{
DWORD ret = MsgWaitForMultipleObjects(3, _eventNotify, FALSE, INFI
NITE, QS_ALLEVENTS);
125
126
127
128
129
130
131
132
133
134
135
136
= 0)
137
138
139
140
141
142
143
if(ret == WAIT_FAILED)
return -1;
DWORD notify = ret - WAIT_OBJECT_0;
if(notify == 0)
{
}
if(obj->LoadDSData(0, SIZE_DS_BUFFER / 2) != 0)
break;
else if(notify == 1)
{
}
if(obj->LoadDSData(SIZE_DS_BUFFER / 2 , SIZE_DS_BUFFER / 2) !
break;
else if(notify == 2)
{
}
break;
else
continue;
{
}
}
obj->PlayOver();
return 0;
144
145
146
147
148
149
150
151
152 }
153
154 int CDSoundObject::Play()
if(_dwPlayPos == 0)
{
}
InitDSData();
_pDSBuffer->SetCurrentPosition(_dwPlayPos);
_pDSBuffer->SetVolume(-2000);//DSBVOLUME_MAX);
_pDSBuffer->Play(0, 0, DSBPLAY_LOOPING);
return 0;
155 {
156
157
158
159
160
161
162
163
164
165
166 }
167
168 int CDSoundObject::Pause()
169 {
170
171
172
173
if(_pDSBuffer == NULL)
return -1;
HRESULT hr = _pDSBuffer->GetCurrentPosition(&_dwPlayPos, NULL);
if(hr != DS_OK)