织梦CMS - 轻松建站从此开始!

罗索

利用directsound播放PCM流的封装类

jackyhwei 发布于 2010-11-01 10:32 点击:次 
还是采用与directsound的抓取音频数据的思路,编写了一个封装类,很好用,目前也只是8KHz,16Bits,Mono的PCM码流,可以直接播放而已。咱为人厚道,贴出代码,希望对后来者有用
TAG:

终于可以用了,原本directsound就是来播放声音的,怎么现在看来这么费劲呢?好多directsound的sample代码都是播放wav文件的,而我从一开始就打算把音频数据通过以太网以流的形式传输,这样必然就需要一个循环缓冲区,从网络接收数据,解码后写入这个缓冲区,然后另外一个线程,周期性的读取这个缓冲区,来实现声音播放。还是采用与directsound的抓取音频数据的思路,编写了一个封装类,很好用,目前也只是8KHz,16Bits,Mono的PCM码流,可以直接播放而已。
咱为人厚道,贴出代码,希望对后来者有用:
这个是CStreamAudio类的头文件:

 

  1. #pragma once 
  2. #include <mmsystem.h> 
  3. #include <dsound.h> 
  4. #define NUM_REC_NOTIFICATIONS  16 
  5. class CAudioStreamHandler { 
  6. public
  7.  virtual void AdoStreamData(unsigned char * pBuffer, int nBufferLen) = 0 ; 
  8. }; 
  9. class CStreamAudio 
  10. protected
  11.  IDirectSound8 *   m_pDS;        // DirectSound component 
  12.  IDirectSoundBuffer8 * m_pDSBuf;   // Sound Buffer object 
  13.  IDirectSoundNotify8 * m_pDSNotify;  // Notification object 
  14.  WAVEFORMATEX   m_wfxOutput ; // Wave format of output 
  15.   
  16.  // some codes from capture audio 
  17.  DSBPOSITIONNOTIFY     m_aPosNotify[NUM_REC_NOTIFICATIONS + 1]; //notify flag array 
  18.  DWORD        m_dwPlayBufSize;  //play loop buffer size 
  19.  DWORD        m_dwNextPlayOffset;//offset in loop buffer 
  20.  DWORD        m_dwNotifySize;  //notify pos when loop buffer need to emit the event 
  21.  CAudioStreamHandler* m_stream_handler ; // caller stream buffer filler 
  22. public
  23.  BOOL     m_bPlaying ; 
  24.  HANDLE     m_hNotifyEvent;   //notify event 
  25.  BOOL     LoadStreamData() ; 
  26. public
  27.  static UINT notify_stream_thd(LPVOID data) ; 
  28. protected
  29.  HRESULT InitDirectSound(HWND hWnd) ; 
  30.  HRESULT FreeDirectSound() ; 
  31.  IDirectSoundBuffer8 *CreateStreamBuffer(IDirectSound8* pDS, WAVEFORMATEX* wfx) ; 
  32.  BOOL SetWavFormat(WAVEFORMATEX * wfx) ; 
  33. public
  34.  CStreamAudio(void); 
  35.  ~CStreamAudio(void); 
  36.  BOOL Open(HWND hWnd, CAudioStreamHandler * stream_handler) ; 
  37.  BOOL Close() ; 
  38.  BOOL CtrlStream(BOOL bPlaying) ; 
  39. }; 
 
我想这些应该可以解决相当一部分人对于voip技术的神秘感吧。
调用方式:
(1)添加派生类
class CCapSvrDlg : public CDialog, 
public CAudioStreamHandler // audio stream play handler
 
(2)重载纯虚函数
public: // override the CAudioStreamHandler
 void AdoStreamData(unsigned char * pBuffer, int nBufferLen) ;
这里的pBuffer与前几篇博客的数据抓取类有所不同,这个pBuffer是需要写入的,毕竟这个类是用来播放流音频数据的嘛。
 
(3)声明播放对象
CStreamAudio    m_strm_ado ;
 
(4)在OnInitDialog中初始化对象:
 // create stream audio play
 m_strm_ado.Open(GetSafeHwnd(), this) ;
 
(5)再某个按钮或是什么东西里面开始流数据播放:
m_strm_ado.CtrlStream(TRUE) ;
 
(6)停止流播放
m_strm_ado.CtrlStream(FALSE) ;
 
(7)关闭播放对象
m_strm_ado.Close() ;
 
好了这个样就一切ok了,在它需要周期性读取pcm码流的时候,会自动调用AdoStreamData函数的,在nBufferLen形参里面会指明需要读取多少个字节的pcm码流。直接把数据写入pBuffer即可。
呵呵,只要搞个循环的接收缓冲区就可以了。
原本是OpenGL的铁杆追随者,这段时间看看directx, direct3d,呵呵,到底是微软啊。还是怀念用OpenGL写视频模块的日子。。。
 
具体的依赖库,查查directx的help吧,懒得写了,整个工程文件太大,浪费偶的博客空间,暂时先不上传了。

CPP源码见后一页。

(陈罡)
本站文章除注明转载外,均为本站原创或编译欢迎任何形式的转载,但请务必注明出处,尊重他人劳动,同学习共成长。转载请注明:文章转载自:罗索实验室 [http://www.rosoo.net/a/201011/10387.html]
本文出处:北京理工大学 20981 作者:陈罡
顶一下
(3)
37.5%
踩一下
(5)
62.5%
------分隔线----------------------------
发表评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
用户名: 验证码:点击我更换图片
栏目列表
将本文分享到微信
织梦二维码生成器
推荐内容