更新 - 使用DirectSound播放Wave文件
修改了一下DSound程序,增加播放Notify,支持播放Buffer。这样就可以连续播放一个比较大的Wave文件了。 源码在这里。下面是主要的代码:
DSoundObject.h
DSoundObject.cpp
DSWaveObject.h
DSWaveObject.cpp
DSoundObject.h
1
#ifndef __DSOUNDOBJECT_H__
2 #define __DSOUNDOBJECT_H__
3
4 #include < windows.h >
5 #include < dsound.h >
6
7 #include < string >
8
9 extern HANDLE _eventNotify[ 2 ];//这句很奇怪,如果改成CDSoundObject的static成员,VCExpress链接会出错,不明原因。
10
11 class CDSoundObject
12 {
13 public :
14 enum SoundType { ST_WAVE, ST_MP3 };
15 static const DWORD SIZE_DS_BUFFER = 32 * 1024 ;
16 public :
17 CDSoundObject(SoundType type);
18 virtual ~ CDSoundObject();
19
20 virtual int Init(HWND hwnd);
21 virtual int LoadFile( const std:: string & file) = 0 ;
22
23 virtual int Play() = 0 ;
24 virtual int Pause() = 0 ;
25 virtual int Stop() = 0 ;
26 virtual bool IsPlaying() const = 0 ;
27 virtual size_t Duration() const = 0 ;
28 protected :
29 virtual void Release();
30 virtual int CreateDSound();
31 virtual int CreateDSoundBuffer();
32
33 virtual int LoadData(DWORD start, DWORD count) = 0 ;
34 virtual int PlayOver() = 0 ;
35 protected :
36 HWND _hWnd;
37 SoundType _eType;
38 IDirectSound * _pDS;
39 IDirectSoundBuffer * _pDSBuffer;
40 IDirectSoundNotify8 * _pDSNotify;
41 protected :
42 int CreateNotifyThread();
43 void ReleaseNotifyThread();
44 static DWORD NotifyHandleProc(LPVOID param);
45 public :
46 DWORD _dwNotifyThreadID;
47 HANDLE _hNotifyThread;
48
49 DSBPOSITIONNOTIFY _notifyPos[ 2 ];
50 };
51
52 #endif
2 #define __DSOUNDOBJECT_H__
3
4 #include < windows.h >
5 #include < dsound.h >
6
7 #include < string >
8
9 extern HANDLE _eventNotify[ 2 ];//这句很奇怪,如果改成CDSoundObject的static成员,VCExpress链接会出错,不明原因。
10
11 class CDSoundObject
12 {
13 public :
14 enum SoundType { ST_WAVE, ST_MP3 };
15 static const DWORD SIZE_DS_BUFFER = 32 * 1024 ;
16 public :
17 CDSoundObject(SoundType type);
18 virtual ~ CDSoundObject();
19
20 virtual int Init(HWND hwnd);
21 virtual int LoadFile( const std:: string & file) = 0 ;
22
23 virtual int Play() = 0 ;
24 virtual int Pause() = 0 ;
25 virtual int Stop() = 0 ;
26 virtual bool IsPlaying() const = 0 ;
27 virtual size_t Duration() const = 0 ;
28 protected :
29 virtual void Release();
30 virtual int CreateDSound();
31 virtual int CreateDSoundBuffer();
32
33 virtual int LoadData(DWORD start, DWORD count) = 0 ;
34 virtual int PlayOver() = 0 ;
35 protected :
36 HWND _hWnd;
37 SoundType _eType;
38 IDirectSound * _pDS;
39 IDirectSoundBuffer * _pDSBuffer;
40 IDirectSoundNotify8 * _pDSNotify;
41 protected :
42 int CreateNotifyThread();
43 void ReleaseNotifyThread();
44 static DWORD NotifyHandleProc(LPVOID param);
45 public :
46 DWORD _dwNotifyThreadID;
47 HANDLE _hNotifyThread;
48
49 DSBPOSITIONNOTIFY _notifyPos[ 2 ];
50 };
51
52 #endif
DSoundObject.cpp
1
#include
"
DSoundObject.h
"
2
3 HANDLE _eventNotify[ 2 ];
4
5 CDSoundObject::CDSoundObject(CDSoundObject::SoundType type)
6 : _eType(type)
7 , _pDS(NULL), _pDSBuffer(NULL), _pDSNotify(NULL)
8 , _dwNotifyThreadID( 0 ), _hNotifyThread(NULL)
9 {
10 }
11
12 CDSoundObject:: ~ CDSoundObject()
13 {
14 Release();
15 }
16
17 void CDSoundObject::Release()
18 {
19 ReleaseNotifyThread();
20
21 if (_pDS != NULL)
22 _pDS -> Release();
23 }
24
25 int CDSoundObject::Init(HWND hwnd)
26 {
27 _hWnd = hwnd;
28
29 return CreateDSound();
30 }
31
32 int CDSoundObject::CreateDSound()
33 {
34 HRESULT hr = DirectSoundCreate(NULL, & _pDS, NULL);
35 if (hr != DS_OK)
36 return - 1 ;
37 _pDS -> SetCooperativeLevel(_hWnd, DSSCL_NORMAL);
38 return 0 ;
39 }
40
41 int CDSoundObject::CreateDSoundBuffer()
42 {
43 // if(CreateNotifyThread() != 0)
44 // return -1;
45 return 0 ;
46 }
47
48 int CDSoundObject::CreateNotifyThread()
49 {
50 // event
51 _eventNotify[ 0 ] = CreateEvent(NULL, FALSE, FALSE, NULL);
52 _eventNotify[ 1 ] = CreateEvent(NULL, FALSE, FALSE, NULL);
53
54 _hNotifyThread = CreateThread(NULL, 0 , (LPTHREAD_START_ROUTINE)NotifyHandleProc, (LPVOID) this , 0 , & _dwNotifyThreadID);
55 if (_hNotifyThread == NULL)
56 return - 1 ;
57
58 HRESULT hr = _pDSBuffer -> QueryInterface(IID_IDirectSoundNotify8, ( void ** ) & _pDSNotify);
59 if (hr != DS_OK)
60 return - 1 ;
61
62 _notifyPos[ 0 ].dwOffset = (SIZE_DS_BUFFER / 2 ) - 1 ;
63 _notifyPos[ 0 ].hEventNotify = _eventNotify[ 0 ];
64 _notifyPos[ 1 ].dwOffset = SIZE_DS_BUFFER - 1 ;
65 _notifyPos[ 1 ].hEventNotify = _eventNotify[ 1 ];
66
67 hr = _pDSNotify -> SetNotificationPositions( 2 , _notifyPos);
68 if (hr != DS_OK)
69 return - 1 ;
70
71 return 0 ;
72 }
73
74 void CDSoundObject::ReleaseNotifyThread()
75 {
76 if (_hNotifyThread != NULL)
77 {
78 TerminateThread(_hNotifyThread, 0 );
79 CloseHandle(_hNotifyThread);
80 _hNotifyThread = NULL;
81 }
82 for ( int i = 0 ; i < 2 ; ++ i)
83 {
84 if (_eventNotify[i] != NULL)
85 {
86 CloseHandle(_eventNotify[i]);
87 _eventNotify[i] = NULL;
88 }
89 }
90
91 if (_pDSNotify != NULL)
92 {
93 _pDSNotify -> Release();
94 _pDSNotify = NULL;
95 }
96 }
97
98 DWORD CDSoundObject::NotifyHandleProc(LPVOID param)
99 {
100 CDSoundObject * obj = (CDSoundObject * )(param);
101 if (obj == NULL)
102 return - 1 ;
103
104 while ( true )
105 {
106 DWORD ret = MsgWaitForMultipleObjects( 2 , _eventNotify, FALSE, INFINITE, QS_ALLEVENTS);
107 if (ret == WAIT_FAILED)
108 return - 1 ;
109
110 DWORD notify = ret - WAIT_OBJECT_0;
111 if (notify == 0 )
112 {
113 if (obj -> LoadData( 0 , SIZE_DS_BUFFER / 2 ) != 0 )
114 break ;
115 }
116 else if (notify == 1 )
117 {
118 if (obj -> LoadData(SIZE_DS_BUFFER / 2 , SIZE_DS_BUFFER / 2 ) != 0 )
119 break ;
120 }
121 else
122 {
123 continue ;
124 // return -1;
125 }
126 }
127
128 obj -> PlayOver();
129
130 return 0 ;
131 }
2
3 HANDLE _eventNotify[ 2 ];
4
5 CDSoundObject::CDSoundObject(CDSoundObject::SoundType type)
6 : _eType(type)
7 , _pDS(NULL), _pDSBuffer(NULL), _pDSNotify(NULL)
8 , _dwNotifyThreadID( 0 ), _hNotifyThread(NULL)
9 {
10 }
11
12 CDSoundObject:: ~ CDSoundObject()
13 {
14 Release();
15 }
16
17 void CDSoundObject::Release()
18 {
19 ReleaseNotifyThread();
20
21 if (_pDS != NULL)
22 _pDS -> Release();
23 }
24
25 int CDSoundObject::Init(HWND hwnd)
26 {
27 _hWnd = hwnd;
28
29 return CreateDSound();
30 }
31
32 int CDSoundObject::CreateDSound()
33 {
34 HRESULT hr = DirectSoundCreate(NULL, & _pDS, NULL);
35 if (hr != DS_OK)
36 return - 1 ;
37 _pDS -> SetCooperativeLevel(_hWnd, DSSCL_NORMAL);
38 return 0 ;
39 }
40
41 int CDSoundObject::CreateDSoundBuffer()
42 {
43 // if(CreateNotifyThread() != 0)
44 // return -1;
45 return 0 ;
46 }
47
48 int CDSoundObject::CreateNotifyThread()
49 {
50 // event
51 _eventNotify[ 0 ] = CreateEvent(NULL, FALSE, FALSE, NULL);
52 _eventNotify[ 1 ] = CreateEvent(NULL, FALSE, FALSE, NULL);
53
54 _hNotifyThread = CreateThread(NULL, 0 , (LPTHREAD_START_ROUTINE)NotifyHandleProc, (LPVOID) this , 0 , & _dwNotifyThreadID);
55 if (_hNotifyThread == NULL)
56 return - 1 ;
57
58 HRESULT hr = _pDSBuffer -> QueryInterface(IID_IDirectSoundNotify8, ( void ** ) & _pDSNotify);
59 if (hr != DS_OK)
60 return - 1 ;
61
62 _notifyPos[ 0 ].dwOffset = (SIZE_DS_BUFFER / 2 ) - 1 ;
63 _notifyPos[ 0 ].hEventNotify = _eventNotify[ 0 ];
64 _notifyPos[ 1 ].dwOffset = SIZE_DS_BUFFER - 1 ;
65 _notifyPos[ 1 ].hEventNotify = _eventNotify[ 1 ];
66
67 hr = _pDSNotify -> SetNotificationPositions( 2 , _notifyPos);
68 if (hr != DS_OK)
69 return - 1 ;
70
71 return 0 ;
72 }
73
74 void CDSoundObject::ReleaseNotifyThread()
75 {
76 if (_hNotifyThread != NULL)
77 {
78 TerminateThread(_hNotifyThread, 0 );
79 CloseHandle(_hNotifyThread);
80 _hNotifyThread = NULL;
81 }
82 for ( int i = 0 ; i < 2 ; ++ i)
83 {
84 if (_eventNotify[i] != NULL)
85 {
86 CloseHandle(_eventNotify[i]);
87 _eventNotify[i] = NULL;
88 }
89 }
90
91 if (_pDSNotify != NULL)
92 {
93 _pDSNotify -> Release();
94 _pDSNotify = NULL;
95 }
96 }
97
98 DWORD CDSoundObject::NotifyHandleProc(LPVOID param)
99 {
100 CDSoundObject * obj = (CDSoundObject * )(param);
101 if (obj == NULL)
102 return - 1 ;
103
104 while ( true )
105 {
106 DWORD ret = MsgWaitForMultipleObjects( 2 , _eventNotify, FALSE, INFINITE, QS_ALLEVENTS);
107 if (ret == WAIT_FAILED)
108 return - 1 ;
109
110 DWORD notify = ret - WAIT_OBJECT_0;
111 if (notify == 0 )
112 {
113 if (obj -> LoadData( 0 , SIZE_DS_BUFFER / 2 ) != 0 )
114 break ;
115 }
116 else if (notify == 1 )
117 {
118 if (obj -> LoadData(SIZE_DS_BUFFER / 2 , SIZE_DS_BUFFER / 2 ) != 0 )
119 break ;
120 }
121 else
122 {
123 continue ;
124 // return -1;
125 }
126 }
127
128 obj -> PlayOver();
129
130 return 0 ;
131 }
DSWaveObject.h
1
#ifndef __DSWAVEOBJECT_H__
2 #define __DSWAVEOBJECT_H__
3
4 #include < fstream >
5 #include < string >
6
7 #include " DSoundObject.h "
8
9 class CDSWaveObject : public CDSoundObject
10 {
11 protected :
12 // .WAV file header
13 struct WAVE_HEADER
14 {
15 char riff_sig[ 4 ]; // 'RIFF'
16 long waveform_chunk_size; // 8
17 char wave_sig[ 4 ]; // 'WAVE'
18 char format_sig[ 4 ]; // 'fmt ' (notice space after)
19 long format_chunk_size; // 16;
20 short format_tag; // WAVE_FORMAT_PCM
21 short channels; // # of channels
22 long sample_rate; // sampling rate
23 long bytes_per_sec; // bytes per second
24 short block_align; // sample block alignment
25 short bits_per_sample; // bits per second
26 char data_sig[ 4 ]; // 'data'
27 long data_size; // size of waveform data
28 };
29
30 public :
31 CDSWaveObject();
32 virtual ~ CDSWaveObject();
33
34 virtual int LoadFile( const std:: string & file);
35 virtual int Play();
36 virtual int Pause();
37 virtual int Stop();
38 virtual bool IsPlaying() const ;
39 virtual size_t Duration() const ;
40 protected :
41 virtual void Release();
42 protected :
43 int LoadWaveData();
44 int ReadWaveHeader(WAVE_HEADER & header);
45 int CreateDSBuffer( const WAVE_HEADER & header);
46
47 virtual int LoadData(DWORD start, DWORD count);
48 virtual int PlayOver();
49 private :
50 std:: string _strFileName;
51
52 WAVE_HEADER _headerWave;
53 WAVEFORMATEX _fmtWave;
54 std::ifstream _ifStream;
55 DWORD _dwReadSize;
56 DWORD _dwPlayPos;
57 };
58
59
60 #endif
2 #define __DSWAVEOBJECT_H__
3
4 #include < fstream >
5 #include < string >
6
7 #include " DSoundObject.h "
8
9 class CDSWaveObject : public CDSoundObject
10 {
11 protected :
12 // .WAV file header
13 struct WAVE_HEADER
14 {
15 char riff_sig[ 4 ]; // 'RIFF'
16 long waveform_chunk_size; // 8
17 char wave_sig[ 4 ]; // 'WAVE'
18 char format_sig[ 4 ]; // 'fmt ' (notice space after)
19 long format_chunk_size; // 16;
20 short format_tag; // WAVE_FORMAT_PCM
21 short channels; // # of channels
22 long sample_rate; // sampling rate
23 long bytes_per_sec; // bytes per second
24 short block_align; // sample block alignment
25 short bits_per_sample; // bits per second
26 char data_sig[ 4 ]; // 'data'
27 long data_size; // size of waveform data
28 };
29
30 public :
31 CDSWaveObject();
32 virtual ~ CDSWaveObject();
33
34 virtual int LoadFile( const std:: string & file);
35 virtual int Play();
36 virtual int Pause();
37 virtual int Stop();
38 virtual bool IsPlaying() const ;
39 virtual size_t Duration() const ;
40 protected :
41 virtual void Release();
42 protected :
43 int LoadWaveData();
44 int ReadWaveHeader(WAVE_HEADER & header);
45 int CreateDSBuffer( const WAVE_HEADER & header);
46
47 virtual int LoadData(DWORD start, DWORD count);
48 virtual int PlayOver();
49 private :
50 std:: string _strFileName;
51
52 WAVE_HEADER _headerWave;
53 WAVEFORMATEX _fmtWave;
54 std::ifstream _ifStream;
55 DWORD _dwReadSize;
56 DWORD _dwPlayPos;
57 };
58
59
60 #endif
DSWaveObject.cpp
1
#include
"
DSWaveObject.h
"
2
3 CDSWaveObject::CDSWaveObject()
4 : CDSoundObject(CDSoundObject::ST_WAVE)
5 , _dwReadSize( 0 )
6 , _dwPlayPos( 0 )
7 {
8 }
9
10 CDSWaveObject:: ~ CDSWaveObject()
11 {
12 Release();
13 }
14
15 void CDSWaveObject::Release()
16 {
17 ReleaseNotifyThread();
18
19 if (_pDSBuffer != NULL)
20 {
21 _pDSBuffer -> Stop();
22 _pDSBuffer -> Release();
23 _pDSBuffer = NULL;
24 }
25 if (_ifStream.is_open())
26 _ifStream.close();
27 }
28
29 int CDSWaveObject::LoadFile( const std:: string & file)
30 {
31 Release();
32
33 _ifStream.open(file.c_str(), std::ios:: in | std::ios::binary);
34 if ( ! _ifStream.is_open())
35 return - 1 ;
36
37 memset( & _headerWave, 0 , sizeof (WAVE_HEADER));
38
39 if (ReadWaveHeader(_headerWave) != 0 )
40 return - 1 ;
41
42 if (CreateDSBuffer(_headerWave) != 0 )
43 return - 1 ;
44
45 return 0 ;
46 }
47
48 int CDSWaveObject::LoadWaveData()
49 {
50 _dwPlayPos = 0 ;
51 _dwReadSize = 0 ;
52
53 _ifStream.clear();
54
55 _ifStream.seekg( sizeof (WAVE_HEADER), std::ios::beg);
56 if (LoadData( 0 , CDSoundObject::SIZE_DS_BUFFER) != 0 )
57 {
58 return - 1 ;
59 }
60
61 ReleaseNotifyThread();
62
63 if (CreateNotifyThread() != 0 )
64 return - 1 ;
65 return 0 ;
66 }
67
68 int CDSWaveObject::ReadWaveHeader(CDSWaveObject::WAVE_HEADER & header)
69 {
70 _ifStream.seekg( 0 , std::ios::beg);
71 _ifStream.read(( char * ) & header, sizeof (WAVE_HEADER));
72 if ( ! _ifStream.good())
73 return - 1 ;
74 if (memcmp(header.riff_sig, " RIFF " , 4 ) || memcmp(header.wave_sig, " WAVE " , 4 ) ||
75 memcmp(header.format_sig, " fmt " , 4 ) || memcmp(header.data_sig, " data " , 4 ))
76 {
77 return - 1 ;
78 }
79 return 0 ;
80 }
81
82 int CDSWaveObject::CreateDSBuffer( const CDSWaveObject::WAVE_HEADER & header)
83 {
84 // WAVEFORMATEX wformat;
85 memset( & _fmtWave, 0 , sizeof (WAVEFORMATEX));
86 _fmtWave.wFormatTag = WAVE_FORMAT_PCM;
87 _fmtWave.nChannels = header.channels;
88 _fmtWave.nSamplesPerSec = header.sample_rate;
89 _fmtWave.wBitsPerSample = header.bits_per_sample;
90 _fmtWave.nBlockAlign = header.bits_per_sample / 8 * header.channels; // header.block_align;
91 _fmtWave.nAvgBytesPerSec = header.sample_rate * header.block_align; // header.
92 // wformat.cbSize = header.data_size;
93
94 DSBUFFERDESC desc;
95 memset( & desc, 0 , sizeof (DSBUFFERDESC));
96 desc.dwSize = sizeof (DSBUFFERDESC);
97 desc.dwFlags = DSBCAPS_GLOBALFOCUS | DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLPOSITIONNOTIFY | DSBCAPS_LOCSOFTWARE;
98 desc.dwBufferBytes = CDSoundObject::SIZE_DS_BUFFER; // header.data_size;
99 desc.lpwfxFormat = & _fmtWave;
100
101 if (_pDSBuffer != NULL)
102 _pDSBuffer -> Release();
103
104 HRESULT hr = _pDS -> CreateSoundBuffer( & desc, & _pDSBuffer, NULL);
105 if (hr != DS_OK)
106 return - 1 ;
107
108 return 0 ;
109 }
110
111 int CDSWaveObject::LoadData(DWORD start, DWORD count)
112 {
113 if ( ! _ifStream.good())
114 return - 1 ;
115 if (_dwReadSize >= _headerWave.data_size)
116 return - 1 ;
117
118 LPVOID aptr1 = NULL, aptr2 = NULL;
119 DWORD abyte1 = NULL, abyte2 = NULL;
120
121 HRESULT hr = _pDSBuffer -> Lock(start, count, & aptr1, & abyte1, & aptr2, & abyte2, 0 );
122 if (hr != DS_OK)
123 return - 1 ;
124
125 _ifStream.read(( char * )aptr1, abyte1);
126 if (aptr2 != NULL)
127 _ifStream.read(( char * )aptr2, abyte2);
128
129 _pDSBuffer -> Unlock(aptr1, abyte1, aptr2, abyte2);
130
131 _dwReadSize += count;
132
133 return 0 ;
134 }
135
136 int CDSWaveObject::Play()
137 {
138 if (_dwPlayPos == 0 )
139 {
140 LoadWaveData();
141 }
142
143 _pDSBuffer -> SetCurrentPosition(_dwPlayPos);
144 _pDSBuffer -> SetVolume( - 2000 ); // DSBVOLUME_MAX);
145 _pDSBuffer -> Play( 0 , 0 , DSBPLAY_LOOPING);
146
147 return 0 ;
148 }
149
150 int CDSWaveObject::Pause()
151 {
152 if (_pDSBuffer == NULL)
153 return - 1 ;
154 HRESULT hr = _pDSBuffer -> GetCurrentPosition( & _dwPlayPos, NULL);
155 if (hr != DS_OK)
156 return - 1 ;
157 _pDSBuffer -> Stop();
158
159 return 0 ;
160 }
161
162 int CDSWaveObject::Stop()
163 {
164 if (_pDSBuffer == NULL)
165 return - 1 ;
166 _pDSBuffer -> Stop();
167 _dwPlayPos = 0 ;
168
169 return 0 ;
170 }
171
172 bool CDSWaveObject::IsPlaying() const
173 {
174 if (_pDSBuffer == NULL)
175 return false ;
176
177 DWORD status = 0 ;
178 HRESULT hr = _pDSBuffer -> GetStatus( & status);
179 if (hr != DS_OK)
180 return false ;
181 return ((status & DSBSTATUS_PLAYING) == DSBSTATUS_PLAYING ? true : false );
182 }
183
184 size_t CDSWaveObject::Duration() const
185 {
186 return (_headerWave.data_size * 1000 / _fmtWave.nAvgBytesPerSec);
187 // if(_pDSBuffer == NULL)
188 // return 0;
189 // WAVEFORMATEX wformat;
190 // HRESULT hr = _pDSBuffer->GetFormat(&wformat, sizeof(WAVEFORMATEX), NULL);
191 // if(hr != DS_OK)
192 // return 0;
193
194 // DSBCAPS caps;
195 // memset(&caps, 0, sizeof(DSBCAPS));
196 // caps.dwSize = sizeof(DSBCAPS);
197 // hr = _pDSBuffer->GetCaps(&caps);
198 // if(hr != DS_OK)
199 // return -1;
200
201 // return (caps.dwBufferBytes * 1000 / wformat.nAvgBytesPerSec);
202 }
203
204 int CDSWaveObject::PlayOver()
205 {
206 return Stop();
207 }
208
2
3 CDSWaveObject::CDSWaveObject()
4 : CDSoundObject(CDSoundObject::ST_WAVE)
5 , _dwReadSize( 0 )
6 , _dwPlayPos( 0 )
7 {
8 }
9
10 CDSWaveObject:: ~ CDSWaveObject()
11 {
12 Release();
13 }
14
15 void CDSWaveObject::Release()
16 {
17 ReleaseNotifyThread();
18
19 if (_pDSBuffer != NULL)
20 {
21 _pDSBuffer -> Stop();
22 _pDSBuffer -> Release();
23 _pDSBuffer = NULL;
24 }
25 if (_ifStream.is_open())
26 _ifStream.close();
27 }
28
29 int CDSWaveObject::LoadFile( const std:: string & file)
30 {
31 Release();
32
33 _ifStream.open(file.c_str(), std::ios:: in | std::ios::binary);
34 if ( ! _ifStream.is_open())
35 return - 1 ;
36
37 memset( & _headerWave, 0 , sizeof (WAVE_HEADER));
38
39 if (ReadWaveHeader(_headerWave) != 0 )
40 return - 1 ;
41
42 if (CreateDSBuffer(_headerWave) != 0 )
43 return - 1 ;
44
45 return 0 ;
46 }
47
48 int CDSWaveObject::LoadWaveData()
49 {
50 _dwPlayPos = 0 ;
51 _dwReadSize = 0 ;
52
53 _ifStream.clear();
54
55 _ifStream.seekg( sizeof (WAVE_HEADER), std::ios::beg);
56 if (LoadData( 0 , CDSoundObject::SIZE_DS_BUFFER) != 0 )
57 {
58 return - 1 ;
59 }
60
61 ReleaseNotifyThread();
62
63 if (CreateNotifyThread() != 0 )
64 return - 1 ;
65 return 0 ;
66 }
67
68 int CDSWaveObject::ReadWaveHeader(CDSWaveObject::WAVE_HEADER & header)
69 {
70 _ifStream.seekg( 0 , std::ios::beg);
71 _ifStream.read(( char * ) & header, sizeof (WAVE_HEADER));
72 if ( ! _ifStream.good())
73 return - 1 ;
74 if (memcmp(header.riff_sig, " RIFF " , 4 ) || memcmp(header.wave_sig, " WAVE " , 4 ) ||
75 memcmp(header.format_sig, " fmt " , 4 ) || memcmp(header.data_sig, " data " , 4 ))
76 {
77 return - 1 ;
78 }
79 return 0 ;
80 }
81
82 int CDSWaveObject::CreateDSBuffer( const CDSWaveObject::WAVE_HEADER & header)
83 {
84 // WAVEFORMATEX wformat;
85 memset( & _fmtWave, 0 , sizeof (WAVEFORMATEX));
86 _fmtWave.wFormatTag = WAVE_FORMAT_PCM;
87 _fmtWave.nChannels = header.channels;
88 _fmtWave.nSamplesPerSec = header.sample_rate;
89 _fmtWave.wBitsPerSample = header.bits_per_sample;
90 _fmtWave.nBlockAlign = header.bits_per_sample / 8 * header.channels; // header.block_align;
91 _fmtWave.nAvgBytesPerSec = header.sample_rate * header.block_align; // header.
92 // wformat.cbSize = header.data_size;
93
94 DSBUFFERDESC desc;
95 memset( & desc, 0 , sizeof (DSBUFFERDESC));
96 desc.dwSize = sizeof (DSBUFFERDESC);
97 desc.dwFlags = DSBCAPS_GLOBALFOCUS | DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLPOSITIONNOTIFY | DSBCAPS_LOCSOFTWARE;
98 desc.dwBufferBytes = CDSoundObject::SIZE_DS_BUFFER; // header.data_size;
99 desc.lpwfxFormat = & _fmtWave;
100
101 if (_pDSBuffer != NULL)
102 _pDSBuffer -> Release();
103
104 HRESULT hr = _pDS -> CreateSoundBuffer( & desc, & _pDSBuffer, NULL);
105 if (hr != DS_OK)
106 return - 1 ;
107
108 return 0 ;
109 }
110
111 int CDSWaveObject::LoadData(DWORD start, DWORD count)
112 {
113 if ( ! _ifStream.good())
114 return - 1 ;
115 if (_dwReadSize >= _headerWave.data_size)
116 return - 1 ;
117
118 LPVOID aptr1 = NULL, aptr2 = NULL;
119 DWORD abyte1 = NULL, abyte2 = NULL;
120
121 HRESULT hr = _pDSBuffer -> Lock(start, count, & aptr1, & abyte1, & aptr2, & abyte2, 0 );
122 if (hr != DS_OK)
123 return - 1 ;
124
125 _ifStream.read(( char * )aptr1, abyte1);
126 if (aptr2 != NULL)
127 _ifStream.read(( char * )aptr2, abyte2);
128
129 _pDSBuffer -> Unlock(aptr1, abyte1, aptr2, abyte2);
130
131 _dwReadSize += count;
132
133 return 0 ;
134 }
135
136 int CDSWaveObject::Play()
137 {
138 if (_dwPlayPos == 0 )
139 {
140 LoadWaveData();
141 }
142
143 _pDSBuffer -> SetCurrentPosition(_dwPlayPos);
144 _pDSBuffer -> SetVolume( - 2000 ); // DSBVOLUME_MAX);
145 _pDSBuffer -> Play( 0 , 0 , DSBPLAY_LOOPING);
146
147 return 0 ;
148 }
149
150 int CDSWaveObject::Pause()
151 {
152 if (_pDSBuffer == NULL)
153 return - 1 ;
154 HRESULT hr = _pDSBuffer -> GetCurrentPosition( & _dwPlayPos, NULL);
155 if (hr != DS_OK)
156 return - 1 ;
157 _pDSBuffer -> Stop();
158
159 return 0 ;
160 }
161
162 int CDSWaveObject::Stop()
163 {
164 if (_pDSBuffer == NULL)
165 return - 1 ;
166 _pDSBuffer -> Stop();
167 _dwPlayPos = 0 ;
168
169 return 0 ;
170 }
171
172 bool CDSWaveObject::IsPlaying() const
173 {
174 if (_pDSBuffer == NULL)
175 return false ;
176
177 DWORD status = 0 ;
178 HRESULT hr = _pDSBuffer -> GetStatus( & status);
179 if (hr != DS_OK)
180 return false ;
181 return ((status & DSBSTATUS_PLAYING) == DSBSTATUS_PLAYING ? true : false );
182 }
183
184 size_t CDSWaveObject::Duration() const
185 {
186 return (_headerWave.data_size * 1000 / _fmtWave.nAvgBytesPerSec);
187 // if(_pDSBuffer == NULL)
188 // return 0;
189 // WAVEFORMATEX wformat;
190 // HRESULT hr = _pDSBuffer->GetFormat(&wformat, sizeof(WAVEFORMATEX), NULL);
191 // if(hr != DS_OK)
192 // return 0;
193
194 // DSBCAPS caps;
195 // memset(&caps, 0, sizeof(DSBCAPS));
196 // caps.dwSize = sizeof(DSBCAPS);
197 // hr = _pDSBuffer->GetCaps(&caps);
198 // if(hr != DS_OK)
199 // return -1;
200
201 // return (caps.dwBufferBytes * 1000 / wformat.nAvgBytesPerSec);
202 }
203
204 int CDSWaveObject::PlayOver()
205 {
206 return Stop();
207 }
208