根据
Loveddy上的的资料和源码,写了一个可以播放WAVE文件的程序,
上传。
记得老爸说过:天下文人是一家,你抄我来,我抄他。现在来看,写程序亦是如此。
Loveddy的Blog很好,很值得去看,去抄,嘿嘿~
实际使用DirectSound时,发现对象必须基于一个“窗口”才来使用,即在创建DirectSoundBuffer时,其HWND是必须的,不然虽不会出错,但也没有声音,很奇怪,么找到原因。
下面是播放的主要部分代码:
1.对象的基类,因为还要为以后写其他播放对象预留。
1 #ifndef __DSOUNDOBJECT_H__
2 #define __DSOUNDOBJECT_H__
3
4 #include <dsound.h>
5
6 #include <string>
7
8
9 class CDSoundObject
10 {
11 public:
12 enum SoundType { ST_WAVE, ST_MP3 };
13 public:
14 CDSoundObject(SoundType type);
15 virtual ~CDSoundObject();
16
17 virtual int Init(HWND hwnd);
18
19 virtual int LoadFile(const std::string& file) = 0;
20
21 protected:
22 virtual void Release();
23
24 virtual int CreateDSound();
25 protected:
26 HWND _hWnd;
27 SoundType _eType;
28 IDirectSound * _pDS;
29 IDirectSoundBuffer * _pDSBuffer;
30 };
31
32 #endif
1 #include "DSoundObject.h"
2
3 CDSoundObject::CDSoundObject(CDSoundObject::SoundType type)
4 : _eType(type)
5 , _pDS(NULL), _pDSBuffer(NULL)
6 {
7 }
8
9 CDSoundObject::~CDSoundObject()
10 {
11 Release();
12 }
13
14 void CDSoundObject::Release()
15 {
16 if(_pDS != NULL)
17 _pDS->Release();
18 }
19
20 int CDSoundObject::Init(HWND hwnd)
21 {
22 _hWnd = hwnd;
23 return CreateDSound();
24 }
25
26 int CDSoundObject::CreateDSound()
27 {
28 HRESULT hr = DirectSoundCreate(NULL, &_pDS, NULL);
29 if(hr != DS_OK)
30 return -1;
31 _pDS->SetCooperativeLevel(_hWnd, DSSCL_NORMAL);
32 return 0;
33 }
2.Wave播放对象
1 #ifndef __DSWAVEOBJECT_H__
2 #define __DSWAVEOBJECT_H__
3
4 #include "DSoundObject.h"
5
6 class CDSWaveObject : public CDSoundObject
7 {
8 protected:
9 // .WAV file header
10 struct WAVE_HEADER
11 {
12 char riff_sig[4]; // 'RIFF'
13 long waveform_chunk_size; // 8
14 char wave_sig[4]; // 'WAVE'
15 char format_sig[4]; // 'fmt ' (notice space after)
16 long format_chunk_size; // 16;
17 short format_tag; // WAVE_FORMAT_PCM
18 short channels; // # of channels
19 long sample_rate; // sampling rate
20 long bytes_per_sec; // bytes per second
21 short block_align; // sample block alignment
22 short bits_per_sample; // bits per second
23 char data_sig[4]; // 'data'
24 long data_size; // size of waveform data
25 };
26 public:
27 CDSWaveObject();
28 virtual ~CDSWaveObject();
29
30 virtual int LoadFile(const std::string& file);
31 virtual int Play();
32 virtual int Pause();
33 virtual int Stop();
34 protected:
35 virtual void Release();
36 protected:
37 int ReadWaveHeader(std::ifstream& ifs, WAVE_HEADER& header) const;
38 int CreateDSBuffer(const WAVE_HEADER& header);
39 int ReadWaveData(std::ifstream& ifs, size_t start, size_t count);
40 };
41
42
43 #endif
1 #include <fstream>
2
3 #include "DSWaveObject.h"
4
5 CDSWaveObject::CDSWaveObject()
6 : CDSoundObject(CDSoundObject::ST_WAVE)
7 {
8 }
9
10 CDSWaveObject::~CDSWaveObject()
11 {
12 Release();
13 }
14
15 void CDSWaveObject::Release()
16 {
17 if(_pDSBuffer != NULL)
18 _pDSBuffer->Release();
19 }
20
21 int CDSWaveObject::LoadFile(const std::string &file)
22 {
23 std::ifstream ifs;
24 ifs.open(file.c_str(), std::ios::in | std::ios::binary);
25 if(!ifs.is_open())
26 return -1;
27
28 WAVE_HEADER header;
29 memset(&header, 0, sizeof(WAVE_HEADER));
30
31 if(ReadWaveHeader(ifs, header) != 0)
32 return -1;
33
34 if(CreateDSBuffer(header) != 0)
35 return -1;
36
37 if(ReadWaveData(ifs, 0, header.data_size) != 0)
38 return -1;
39
40 ifs.close();
41
42 return 0;
43 }
44
45 int CDSWaveObject::ReadWaveHeader(std::ifstream &ifs, CDSWaveObject::WAVE_HEADER &header) const
46 {
47 ifs.seekg(0, std::ios::beg);
48 ifs.read((char*)&header, sizeof(WAVE_HEADER));
49 if(!ifs.good())
50 return -1;
51 if(memcmp(header.riff_sig, "RIFF", 4) || memcmp(header.wave_sig, "WAVE", 4) ||
52 memcmp(header.format_sig, "fmt ", 4) || memcmp(header.data_sig, "data", 4))
53 {
54 return -1;
55 }
56 return 0;
57 }
58
59 int CDSWaveObject::CreateDSBuffer(const CDSWaveObject::WAVE_HEADER &header)
60 {
61 WAVEFORMATEX wformat;
62 memset(&wformat, 0, sizeof(WAVEFORMATEX));
63 wformat.wFormatTag = WAVE_FORMAT_PCM;
64 wformat.nChannels = header.channels;
65 wformat.nSamplesPerSec = header.sample_rate;
66 wformat.wBitsPerSample = header.bits_per_sample;
67 wformat.nBlockAlign = header.bits_per_sample/ 8 * header.channels;// header.block_align;
68 wformat.nAvgBytesPerSec = header.sample_rate * header.block_align;//header.
69 //wformat.cbSize = header.data_size;
70
71 DSBUFFERDESC desc;
72 memset(&desc, 0, sizeof(DSBUFFERDESC));
73 desc.dwSize = sizeof(DSBUFFERDESC);
74 desc.dwFlags = DSBCAPS_CTRLVOLUME;
75 desc.dwBufferBytes = header.data_size;
76 desc.lpwfxFormat = &wformat;
77
78 if(_pDSBuffer != NULL)
79 _pDSBuffer->Release();
80
81 HRESULT hr = _pDS->CreateSoundBuffer(&desc, &_pDSBuffer, NULL);
82 if(hr != DS_OK)
83 return -1;
84 return 0;
85 }
86
87 int CDSWaveObject::ReadWaveData(std::ifstream &ifs, size_t start, size_t count)
88 {
89 LPVOID aptr1 = NULL, aptr2 = NULL;
90 DWORD abyte1 = NULL, abyte2 = NULL;
91
92 HRESULT hr = _pDSBuffer->Lock(start, count, &aptr1, &abyte1, &aptr2, &abyte2, 0);
93 if(hr != DS_OK)
94 return -1;
95
96 ifs.read((char*)aptr1, abyte1);
97 if(aptr2 != NULL)
98 ifs.read((char*)aptr2, abyte2);
99 _pDSBuffer->Unlock(aptr1, abyte1, aptr2, abyte2);
100
101 return 0;
102 }
103
104 int CDSWaveObject::Play()
105 {
106 if(_pDSBuffer == NULL)
107 return -1;
108 _pDSBuffer->SetCurrentPosition(0);
109 _pDSBuffer->SetVolume(DSBVOLUME_MAX);
110 _pDSBuffer->Play(0, 0, DSBPLAY_LOOPING);
111
112 return 0;
113 }
114
115 int CDSWaveObject::Pause()
116 {
117 return 0;
118 }
119
120 int CDSWaveObject::Stop()
121 {
122 _pDSBuffer->Stop();
123 return 0;
124 }
源码工程在这里,写的仓促,仅供参考。使用了wxWidget库,编译是需要的。