使用DirectSound播放MP3文件

使用DirectSound播放MP3文件

    将对MP3的支持代码加入到DSound程序中,以供wxDeMPQ使用,随便调整了一下代码,使基类作更多的事情。下面修改后的代码, 源码在这里。

    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[ 3 ];
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();
24       virtual   int  Pause();
25       virtual   int  Stop();
26       virtual   bool  IsPlaying()  const ;
27       virtual   double  Duration()  =   0 ;
28  protected :
29       virtual   int  CreateDSound();
30       virtual   void  ReleaseDSound();
31       virtual   int  CreateDSoundBuffer();
32       virtual   void  ReleaseDSoundBuffer();
33 
34       virtual   int  InitDSData()  =   0 ;
35       virtual   int  LoadDSData(DWORD start, DWORD count)  =   0 ;
36       virtual   int  PlayOver();
37  protected :
38      HWND _hWnd;
39      SoundType _eType;
40      IDirectSound  *  _pDS;
41      IDirectSoundBuffer  *  _pDSBuffer;
42      IDirectSoundNotify8 *  _pDSNotify;
43  protected :
44       int  CreateNotifyThread();
45       void  ReleaseNotifyThread();
46       static  DWORD NotifyHandleProc(LPVOID param);
47  protected :
48      DWORD _dwNotifyThreadID;
49      HANDLE _hNotifyThread;
50 
51      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()
 14  {
 15      ReleaseNotifyThread();
 16      ReleaseDSoundBuffer();
 17      ReleaseDSound();
 18  }
 19 
 20 
 21  int  CDSoundObject::Init(HWND hwnd)
 22  {
 23      _hWnd  =  hwnd;
 24 
 25       return  CreateDSound();
 26  }
 27 
 28  int  CDSoundObject::CreateDSound()
 29  {
 30      HRESULT hr  =  DirectSoundCreate(NULL,  & _pDS, NULL);
 31       if (hr  !=  DS_OK)
 32           return   - 1 ;
 33      _pDS -> SetCooperativeLevel(_hWnd, DSSCL_NORMAL);
 34       return   0 ;
 35  }
 36 
 37 
 38  void  CDSoundObject::ReleaseDSound()
 39  {
 40       if (_pDS  !=  NULL)
 41          _pDS -> Release(), _pDS  =  NULL;
 42  }
 43 
 44  int  CDSoundObject::CreateDSoundBuffer()
 45  {
 46      ReleaseDSoundBuffer();
 47 
 48       return   0 ;
 49  }
 50 
 51  void  CDSoundObject::ReleaseDSoundBuffer()
 52  {
 53       if (_pDSBuffer  !=  NULL)
 54      {
 55          _pDSBuffer -> Stop();
 56          _pDSBuffer -> Release();
 57          _pDSBuffer  =  NULL;
 58      }
 59  }
 60 
 61  int  CDSoundObject::CreateNotifyThread()
 62  {
 63      ReleaseNotifyThread();
 64 
 65       // event
 66      _eventNotify[ 0 =  CreateEvent(NULL, FALSE, FALSE, NULL);
 67      _eventNotify[ 1 =  CreateEvent(NULL, FALSE, FALSE, NULL);
 68      _eventNotify[ 2 =  CreateEvent(NULL, FALSE, FALSE, NULL);
 69 
 70 
 71      _hNotifyThread  =  CreateThread(NULL,  0 , (LPTHREAD_START_ROUTINE)NotifyHandleProc, (LPVOID) this 0 & _dwNotifyThreadID);
 72       if (_hNotifyThread  ==  NULL)
 73           return   - 1 ;
 74 
 75      HRESULT hr  =  _pDSBuffer -> QueryInterface(IID_IDirectSoundNotify8, ( void ** ) & _pDSNotify);
 76       if (hr  !=  DS_OK)
 77           return   - 1 ;
 78 
 79      _notifyPos[ 0 ].dwOffset  =  (SIZE_DS_BUFFER  /   2 -   1 ;
 80      _notifyPos[ 0 ].hEventNotify  =  _eventNotify[ 0 ];
 81      _notifyPos[ 1 ].dwOffset  =  SIZE_DS_BUFFER  -   1 ;
 82      _notifyPos[ 1 ].hEventNotify  =  _eventNotify[ 1 ];
 83 
 84      hr  =  _pDSNotify -> SetNotificationPositions( 2 , _notifyPos);
 85       if (hr  !=  DS_OK)
 86           return   - 1 ;
 87 
 88       return   0 ;
 89  }
 90 
 91  void  CDSoundObject::ReleaseNotifyThread()
 92  {
 93       if (_hNotifyThread  !=  NULL)
 94      {
 95           // TerminateThread(_hNotifyThread, 0);
 96          SetEvent(_eventNotify[ 2 ]);
 97          CloseHandle(_hNotifyThread);
 98          _hNotifyThread  =  NULL;
 99      }
100       for ( int  i  =   0 ; i  <   2 ++  i)
101      {
102           if (_eventNotify[i]  !=  NULL)
103          {
104              CloseHandle(_eventNotify[i]);
105              _eventNotify[i]  =  NULL;
106          }
107      }
108 
109       if (_pDSNotify  !=  NULL)
110      {
111          _pDSNotify -> Release();
112          _pDSNotify  =  NULL;
113      }
114  }
115 
116  DWORD CDSoundObject::NotifyHandleProc(LPVOID param)
117  {
118      CDSoundObject *  obj  =  (CDSoundObject * )(param);
119       if (obj  ==  NULL)
120           return   - 1 ;
121 
122       while ( true )
123      {
124          DWORD ret  =  MsgWaitForMultipleObjects( 3 , _eventNotify, FALSE, INFINITE, QS_ALLEVENTS);
125           if (ret  ==  WAIT_FAILED)
126               return   - 1 ;
127          
128          DWORD notify  =  ret  -  WAIT_OBJECT_0;
129           if (notify  ==   0 )
130          {
131               if (obj -> LoadDSData( 0 , SIZE_DS_BUFFER  /   2 !=   0 )
132                   break ;
133          }
134           else   if (notify  ==   1 )
135          {
136               if (obj -> LoadDSData(SIZE_DS_BUFFER  /   2  , SIZE_DS_BUFFER  /   2 !=   0 )
137                   break ;
138          }
139           else   if (notify  ==   2 )
140          {
141               break ;
142          }
143           else
144          {
145               continue ;
146          }
147      }
148 
149      obj -> PlayOver();
150 
151       return   0 ;
152  }
153 
154  int  CDSoundObject::Play()
155  {
156       if (_dwPlayPos  ==   0 )
157      {
158          InitDSData();
159      }
160 
161      _pDSBuffer -> SetCurrentPosition(_dwPlayPos);
162      _pDSBuffer -> SetVolume( - 2000 ); // DSBVOLUME_MAX);
163      _pDSBuffer -> Play( 0 0 , DSBPLAY_LOOPING);
164 
165       return   0 ;
166  }
167 
168  int  CDSoundObject::Pause()
169  {
170       if (_pDSBuffer  ==  NULL)
171           return   - 1 ;
172      HRESULT hr  =  _pDSBuffer -> GetCurrentPosition( & _dwPlayPos, NULL);
173       if (hr  !=  DS_OK)
174           return   - 1 ;
175      _pDSBuffer -> Stop();
176 
177       return   0 ;
178  }
179 
180  int  CDSoundObject::Stop()
181  {
182       if (_pDSBuffer  ==  NULL)
183           return   - 1 ;
184      _pDSBuffer -> Stop();
185      _dwPlayPos  =   0 ;
186 
187       return   0 ;
188  }
189 
190  bool  CDSoundObject::IsPlaying()  const
191  {
192       if (_pDSBuffer  ==  NULL)
193           return   false ;
194 
195      DWORD status  =   0 ;
196      HRESULT hr  =  _pDSBuffer -> GetStatus( & status);
197       if (hr  !=  DS_OK)
198           return   false ;
199       return  ((status  &  DSBSTATUS_PLAYING)  ==  DSBSTATUS_PLAYING  ?   true  :  false );
200  }
201 
202  int  CDSoundObject::PlayOver()
203  {
204       return  Stop();
205  }
206 
207 
    DSMP3Object.h
 1  #ifndef __DSMP3OBJECT_H__
 2  #define  __DSMP3OBJECT_H__
 3 
 4  #include  < fstream >
 5  #include  < string >
 6 
 7  #include  " mpg123.h "
 8 
 9  #include  " DSoundObject.h "
10 
11  class  CDSMP3Object :  public  CDSoundObject
12  {
13  public :
14      CDSMP3Object();
15       virtual   ~ CDSMP3Object();
16      
17       virtual   int  LoadFile( const  std:: string &  file);
18       virtual   double  Duration();
19  protected :
20       virtual   void  Release();
21       virtual   int  CreateDSoundBuffer();
22 
23       virtual   int  InitDSData();
24       virtual   int  LoadDSData(DWORD start, DWORD count);
25  private :
26      mpg123_handle *  _handle;
27      unsigned  char  _buffer[SIZE_DS_BUFFER  /   2 ];
28      WAVEFORMATEX _fmtWave;
29  };
30 
31  #endif
32 
    DSMP3Object.cpp
  1  #include  " DSMP3Object.h "
  2 
  3  CDSMP3Object::CDSMP3Object()
  4  : CDSoundObject(CDSoundObject::ST_MP3)
  5  , _handle(NULL)
  6  {
  7  }
  8 
  9  CDSMP3Object:: ~ CDSMP3Object()
 10  {
 11      Release();
 12  }
 13 
 14  void  CDSMP3Object::Release()
 15  {
 16       if (_handle  !=  NULL)
 17      {
 18          mpg123_close(_handle);
 19          mpg123_delete(_handle);
 20          _handle  =  NULL;
 21          mpg123_exit();
 22      }
 23  }
 24 
 25  int  CDSMP3Object::LoadFile( const  std:: string   & file)
 26  {
 27      Release();
 28 
 29       if (mpg123_init()  !=  MPG123_OK)
 30           return   - 1 ;
 31       int  ret  =   - 1 ;
 32      _handle  =  mpg123_new(NULL,  & ret);
 33       if (_handle  ==  NULL  ||  ret  !=  MPG123_OK)
 34           return   - 1 ;
 35 
 36       if (mpg123_open(_handle, file.c_str())  !=  MPG123_OK)
 37           return   - 1 ;
 38 
 39       if (CreateDSoundBuffer()  !=   0 )
 40           return   - 1 ;
 41 
 42       return   0 ;
 43  }
 44 
 45  int  CDSMP3Object::CreateDSoundBuffer()
 46  {
 47      CDSoundObject::CreateDSoundBuffer();
 48 
 49       long  rate  =   0 ;
 50       int  channel  =   0 ;
 51       int  encoding  =   0 ;
 52 
 53       if (mpg123_getformat(_handle,  & rate,  & channel,  & encoding)  !=  MPG123_OK)
 54           return   - 1 ;
 55       if ((encoding  &  MPG123_ENC_16)  ==  MPG123_ENC_16)
 56          encoding  =   16 ;
 57       else   if ((encoding  &  MPG123_ENC_32)  ==  MPG123_ENC_32)
 58          encoding  =   32 ;
 59       else
 60          encoding  =   8 ;
 61 
 62      memset( & _fmtWave,  0 sizeof (WAVEFORMATEX));
 63      _fmtWave.wFormatTag  =  WAVE_FORMAT_PCM;
 64      _fmtWave.nChannels  =  channel;
 65      _fmtWave.nSamplesPerSec  =  rate;
 66      _fmtWave.wBitsPerSample  =  encoding;
 67      _fmtWave.nBlockAlign  =  encoding  /   8   *  channel;
 68      _fmtWave.nAvgBytesPerSec  =  rate  *  (encoding  /   8 *  channel;
 69      
 70      DSBUFFERDESC desc;
 71      memset( & desc,  0 sizeof (DSBUFFERDESC));
 72      desc.dwSize  =   sizeof (DSBUFFERDESC);
 73      desc.dwFlags  =  DSBCAPS_GLOBALFOCUS  |  DSBCAPS_CTRLVOLUME  |  DSBCAPS_CTRLPOSITIONNOTIFY  |  DSBCAPS_LOCSOFTWARE;
 74      desc.dwBufferBytes  =  CDSoundObject::SIZE_DS_BUFFER;
 75      desc.lpwfxFormat  =   & _fmtWave;
 76 
 77       if (_pDSBuffer  !=  NULL)
 78          _pDSBuffer -> Release();
 79 
 80      HRESULT hr  =  _pDS -> CreateSoundBuffer( & desc,  & _pDSBuffer, NULL);
 81       if (hr  !=  DS_OK)
 82           return   - 1 ;
 83      
 84       return   0 ;
 85  }
 86 
 87  int  CDSMP3Object::InitDSData()
 88  {
 89       // if(mpg123_seek(_handle, 0, SEEK_SET) < 0)
 90       //     return -1;
 91      off_t s  =  mpg123_seek(_handle,  0 , SEEK_SET);
 92       if (s  <   0 )
 93           return   - 1 ;
 94 
 95       if (LoadDSData( 0 , CDSoundObject::SIZE_DS_BUFFER)  !=   0 )
 96           return   - 1 ;
 97 
 98       if (CreateNotifyThread()  !=   0 )
 99           return   - 1 ;
100 
101  //     _dwPlayPos = 0;
102 
103       return   0 ;
104  }
105 
106  int  CDSMP3Object::LoadDSData(DWORD start, DWORD count)
107  {
108      LPVOID aptr1  =  NULL, aptr2  =  NULL;
109      DWORD abyte1  =  NULL, abyte2  =  NULL;
110 
111      HRESULT hr  =  _pDSBuffer -> Lock(start, count,  & aptr1,  & abyte1,  & aptr2,  & abyte2,  0 );
112       if (hr  !=  DS_OK)
113           return   - 1 ;
114 
115      size_t outsize  =   0 ;
116       if (mpg123_read(_handle, _buffer, SIZE_DS_BUFFER  /   2 & outsize)  !=  MPG123_OK)
117           return   - 1 ;
118 
119      memcpy(aptr1, _buffer, outsize);
120       if (aptr2  !=   0 )
121      {
122           if (mpg123_read(_handle, _buffer, SIZE_DS_BUFFER  /   2 & outsize)  !=  MPG123_OK)
123               return   - 1 ;
124          memcpy(aptr2, _buffer, outsize);
125      }
126 
127      _pDSBuffer -> Unlock(aptr1, abyte1, aptr2, abyte2);
128 
129       return   0 ;
130  }
131 
132  double  CDSMP3Object::Duration()
133  {
134      off_t len  =  mpg123_length(_handle);
135       return  (len  /  _fmtWave.nSamplesPerSec);
136  }



你可能感兴趣的:(使用DirectSound播放MP3文件)