Codejie's C++ Space

Using C++

使用DirectSound播放WAVE文件

    根据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, 0sizeof(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, 0sizeof(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, 0sizeof(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(00, 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库,编译是需要的。
   

posted on 2009-03-19 23:21 codejie 阅读(515) 评论(0)  编辑 收藏 引用 所属分类: C++


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


公告

Using C++

导航

统计

留言簿(73)

随笔分类(513)

积分与排名

最新评论

阅读排行榜

评论排行榜