欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
利用directsound播放PCM流的封裝類(lèi)
北京理工大學(xué) 20981 陳罡
終于可以用了,原本directsound就是來(lái)播放聲音的,怎么現在看來(lái)這么費勁呢?好多directsound的sample代碼都是播放 wav文件的,而我從一開(kāi)始就打算把音頻數據通過(guò)以太網(wǎng)以流的形式傳輸,這樣必然就需要一個(gè)循環(huán)緩沖區,從網(wǎng)絡(luò )接收數據,解碼后寫(xiě)入這個(gè)緩沖區,然后另外 一個(gè)線(xiàn)程,周期性的讀取這個(gè)緩沖區,來(lái)實(shí)現聲音播放。還是采用與directsound的抓取音頻數據的思路,編寫(xiě)了一個(gè)封裝類(lèi),很好用,目前也只是 8KHz,16Bits,Mono的PCM碼流,可以直接播放而已。
咱為人厚道,貼出代碼,希望對后來(lái)者有用:
這個(gè)是CStreamAudio類(lèi)的頭文件:
#pragma once
#include <mmsystem.h>
#include <dsound.h>
#define NUM_REC_NOTIFICATIONS  16
class CAudioStreamHandler {
public:
 virtual void AdoStreamData(unsigned char * pBuffer, int nBufferLen) = 0 ;
};
class CStreamAudio
{
protected:
 IDirectSound8 *   m_pDS;        // DirectSound component
 IDirectSoundBuffer8 * m_pDSBuf;   // Sound Buffer object
 IDirectSoundNotify8 * m_pDSNotify;  // Notification object
 WAVEFORMATEX   m_wfxOutput ; // Wave format of output
 
 // some codes from capture audio
 DSBPOSITIONNOTIFY     m_aPosNotify[NUM_REC_NOTIFICATIONS + 1]; //notify flag array
 DWORD        m_dwPlayBufSize;  //play loop buffer size
 DWORD        m_dwNextPlayOffset;//offset in loop buffer
 DWORD        m_dwNotifySize;  //notify pos when loop buffer need to emit the event
 CAudioStreamHandler* m_stream_handler ; // caller stream buffer filler
public:
 BOOL     m_bPlaying ;
 HANDLE     m_hNotifyEvent;   //notify event
 BOOL     LoadStreamData() ;
public:
 static UINT notify_stream_thd(LPVOID data) ;
protected:
 HRESULT InitDirectSound(HWND hWnd) ;
 HRESULT FreeDirectSound() ;
 IDirectSoundBuffer8 *CreateStreamBuffer(IDirectSound8* pDS, WAVEFORMATEX* wfx) ;
 BOOL SetWavFormat(WAVEFORMATEX * wfx) ;
public:
 CStreamAudio(void);
 ~CStreamAudio(void);
 BOOL Open(HWND hWnd, CAudioStreamHandler * stream_handler) ;
 BOOL Close() ;
 BOOL CtrlStream(BOOL bPlaying) ;
};
 
下面是CStreamAudio的源文件:
#include "StdAfx.h"
#include ".\streamaudio.h"
#ifndef SAFE_RELEASE
#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } }
#endif
#ifndef MAX
#define MAX(a,b)        ( (a) > (b) ? (a) : (b) )
#endif
CStreamAudio::CStreamAudio(void)
{
 if(FAILED(CoInitialize(NULL))) /*, COINIT_APARTMENTTHREADED)))*/
 {
  AfxMessageBox("CStreamAudio CoInitialize Failed!\r\n");
  return;
 }
 m_pDS = NULL ;        // DirectSound component
 m_pDSBuf = NULL ;   // Sound Buffer object
 m_pDSNotify = NULL ;  // Notification object
 m_hNotifyEvent = NULL ;
 ZeroMemory(&m_wfxOutput, sizeof(m_wfxOutput)) ; // Wave format of output
 m_wfxOutput.wFormatTag = WAVE_FORMAT_PCM ;
 m_dwPlayBufSize = 0 ;  //play loop buffer size
 m_dwNextPlayOffset = 0 ; //offset in loop buffer
 m_dwNotifySize = 0 ;  //notify pos when loop buffer need to emit the event
 m_bPlaying = FALSE ;
}
CStreamAudio::~CStreamAudio(void)
{
 FreeDirectSound() ;
 CoUninitialize() ;
}
HRESULT CStreamAudio::InitDirectSound(HWND hWnd)
{
 if(FAILED(DirectSoundCreate8(NULL, &m_pDS, NULL))) {
  MessageBox(NULL, "Unable to create DirectSound object", "Error", MB_OK);
  return S_FALSE;
 }
 // sets the cooperative level of the application for this sound device
 m_pDS->SetCooperativeLevel(hWnd, DSSCL_PRIORITY);
 // use preset output wave format
 SetWavFormat(&m_wfxOutput) ;
 return S_OK ;
}
HRESULT CStreamAudio::FreeDirectSound()
{
 // make sure the thread gone
 m_bPlaying = FALSE ;
 Sleep(500) ;
 // stop sound play
 if(m_pDSBuf) m_pDSBuf->Stop();
 
 // Release the notify event handles
 if(m_hNotifyEvent) {
  CloseHandle(m_hNotifyEvent) ;
  m_hNotifyEvent = NULL ;
 }
 // Release DirectSound objects
 SAFE_RELEASE(m_pDSBuf) ;
 SAFE_RELEASE(m_pDS) ;
 return S_OK ;
}
BOOL CStreamAudio::Open(HWND hWnd, CAudioStreamHandler * stream_handler)
{
 HRESULT hr ;
 m_stream_handler = stream_handler ;
 hr = InitDirectSound(hWnd) ;
 return (FAILED(hr)) ? FALSE : TRUE ;
}
BOOL CStreamAudio::Close()
{
 HRESULT hr ;
 hr = FreeDirectSound() ;
 return (FAILED(hr)) ? FALSE : TRUE ;
}
UINT CStreamAudio::notify_stream_thd(LPVOID data)
{
 CStreamAudio * psmado = static_cast<CStreamAudio *>(data) ;
 DWORD dwResult = 0 ;
 DWORD Num = 0 ;
 while(psmado->m_bPlaying) {
  // Wait for a message
  dwResult = MsgWaitForMultipleObjects(1, &psmado->m_hNotifyEvent,
            FALSE, INFINITE, QS_ALLEVENTS);
  // Get notification
  switch(dwResult) {
   case WAIT_OBJECT_0:
    {
     psmado->LoadStreamData();
    }
    break ;
   default:
    break ;
  }
 }
 AfxEndThread(0, TRUE) ;
 return 0 ;
}
IDirectSoundBuffer8 * CStreamAudio::CreateStreamBuffer(IDirectSound8* pDS, WAVEFORMATEX * wfx)
{
 IDirectSoundBuffer *  pDSB = NULL ;
 IDirectSoundBuffer8 * pDSBuffer = NULL ;
 DSBUFFERDESC dsbd;
 // calculate play buffer size
 // Set the notification size
 m_dwNotifySize = MAX( 1024, wfx->nAvgBytesPerSec / 8 ) ;
 m_dwNotifySize -= m_dwNotifySize % wfx->nBlockAlign ;
 // Set the buffer sizes
 m_dwPlayBufSize = m_dwNotifySize * NUM_REC_NOTIFICATIONS;

 // create the sound buffer using the header data
 ZeroMemory(&dsbd, sizeof(DSBUFFERDESC));
 dsbd.dwSize = sizeof(DSBUFFERDESC);
 // set DSBCAPS_GLOBALFOCUS to make sure event if the software lose focus could still
 // play sound as well
 dsbd.dwFlags = DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLPOSITIONNOTIFY | DSBCAPS_LOCSOFTWARE | DSBCAPS_GLOBALFOCUS;
 dsbd.dwBufferBytes = m_dwPlayBufSize ;
 dsbd.lpwfxFormat = wfx ;
 if(FAILED(pDS->CreateSoundBuffer(&dsbd, &pDSB, NULL))) return NULL;
 // get newer interface
 if(FAILED(pDSB->QueryInterface(IID_IDirectSoundBuffer8, (void**)(&pDSBuffer)))) {
   SAFE_RELEASE(pDSB) ;
   return NULL;
 }
 // return the interface
 return pDSBuffer;
}
BOOL CStreamAudio::LoadStreamData()
{
 ///////////////////////
 HRESULT hr;
 VOID*   pvStreamData1    = NULL;
 DWORD   dwStreamLength1 = 0 ;
 VOID*   pvStreamData2   = NULL;
 DWORD   dwStreamLength2 = 0 ;
 DWORD   dwWritePos = 0 ;
 DWORD   dwPlayPos = 0 ;
 LONG lLockSize = 0 ;
 if( FAILED( hr = m_pDSBuf->GetCurrentPosition( &dwPlayPos, &dwWritePos ) ) )
  return S_FALSE;
 lLockSize = dwWritePos - m_dwNextPlayOffset;
 if( lLockSize < 0 )
  lLockSize += m_dwPlayBufSize;
 // Block align lock size so that we are always write on a boundary
 lLockSize -= (lLockSize % m_dwNotifySize);
 if( lLockSize == 0 ) return S_FALSE;
 // lock the sound buffer at position specified
 if(FAILED(m_pDSBuf->Lock( m_dwNextPlayOffset, lLockSize,
  &pvStreamData1, &dwStreamLength1,
  &pvStreamData2, &dwStreamLength2, 0L)))
  return FALSE;
 // read in the data
 if(m_stream_handler) m_stream_handler->AdoStreamData((BYTE *)pvStreamData1, dwStreamLength1) ;
 // Move the capture offset along
 m_dwNextPlayOffset += dwStreamLength1;
 m_dwNextPlayOffset %= m_dwPlayBufSize; // Circular buffer
 if(pvStreamData2 != NULL) {
  if(m_stream_handler) m_stream_handler->AdoStreamData((BYTE *)pvStreamData2, dwStreamLength2) ;
  // Move the capture offset along
  m_dwNextPlayOffset += dwStreamLength2;
  m_dwNextPlayOffset %= m_dwPlayBufSize; // Circular buffer
 }
 // unlock it
 m_pDSBuf->Unlock(pvStreamData1, dwStreamLength1, pvStreamData2, dwStreamLength2) ;
 // return a success
 return TRUE;
}
BOOL CStreamAudio::CtrlStream(BOOL bPlaying)
{
 HRESULT hr ;
 int i;
 m_bPlaying = bPlaying ;
 if(m_bPlaying) {
  // Create a 2 second buffer to stream in wave
  m_pDSBuf = CreateStreamBuffer(m_pDS, &m_wfxOutput) ;
  if(m_pDSBuf == NULL) return FALSE ;
  // Create the notification interface
  if(FAILED(m_pDSBuf->QueryInterface(IID_IDirectSoundNotify8, (void**)(&m_pDSNotify))))
   return FALSE ;
  // create auto notify event
  m_hNotifyEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
  // Setup the notification positions
  for( i = 0; i < NUM_REC_NOTIFICATIONS; i++ ) {
   m_aPosNotify[i].dwOffset = (m_dwNotifySize * i) + m_dwNotifySize - 1;
   m_aPosNotify[i].hEventNotify = m_hNotifyEvent;            
  }
  // Tell DirectSound when to notify us. the notification will come in the from
  // of signaled events that are handled in WinMain()
  if( FAILED( hr = m_pDSNotify->SetNotificationPositions( NUM_REC_NOTIFICATIONS, m_aPosNotify ) ) )
   return S_FALSE ;
  m_dwNextPlayOffset = 0 ;
  
  // Fill buffer with some sound
  LoadStreamData() ;
  // Play sound looping
  m_pDSBuf->SetCurrentPosition(0);
  m_pDSBuf->SetVolume(DSBVOLUME_MAX);
  m_pDSBuf->Play(0,0,DSBPLAY_LOOPING);
  // create notify event recv thread
  AfxBeginThread(CStreamAudio::notify_stream_thd, (LPVOID)(this)) ;
 } else {
  // stop play
  // make sure the thread gone
  Sleep(500) ;
  // stop sound play
  if(m_pDSBuf) m_pDSBuf->Stop();
  // Release the notify event handles
  if(m_hNotifyEvent) {
   CloseHandle(m_hNotifyEvent) ;
   m_hNotifyEvent = NULL ;
  }
  // Release DirectSound objects
  SAFE_RELEASE(m_pDSBuf) ;  
 }
 return TRUE ;
}
BOOL CStreamAudio::SetWavFormat(WAVEFORMATEX * wfx)
{
 // get the default capture wave formate
 ZeroMemory(wfx, sizeof(WAVEFORMATEX)) ;
 wfx->wFormatTag = WAVE_FORMAT_PCM;
 // 8KHz, 16 bits PCM, Mono
 wfx->nSamplesPerSec = 8000 ;
 wfx->wBitsPerSample = 16 ;
 wfx->nChannels  = 1 ;
 wfx->nBlockAlign = wfx->nChannels * ( wfx->wBitsPerSample / 8 ) ;
 wfx->nAvgBytesPerSec = wfx->nBlockAlign * wfx->nSamplesPerSec;
 return TRUE ;
}
我想這些應該可以解決相當一部分人對于voip技術(shù)的神秘感吧。
調用方式:
(1)添加派生類(lèi)
class CCapSvrDlg : public CDialog, 
public CAudioStreamHandler // audio stream play handler
 
(2)重載純虛函數
public: // override the CAudioStreamHandler
 void AdoStreamData(unsigned char * pBuffer, int nBufferLen) ;
這里的pBuffer與前幾篇博客的數據抓取類(lèi)有所不同,這個(gè)pBuffer是需要寫(xiě)入的,畢竟這個(gè)類(lèi)是用來(lái)播放流音頻數據的嘛。
 
(3)聲明播放對象
CStreamAudio    m_strm_ado ;
 
(4)在OnInitDialog中初始化對象:
 // create stream audio play
 m_strm_ado.Open(GetSafeHwnd(), this) ;
 
(5)再某個(gè)按鈕或是什么東西里面開(kāi)始流數據播放:
m_strm_ado.CtrlStream(TRUE) ;
 
(6)停止流播放
m_strm_ado.CtrlStream(FALSE) ;
 
(7)關(guān)閉播放對象
m_strm_ado.Close() ;
 
好了這個(gè)樣就一切ok了,在它需要周期性讀取pcm碼流的時(shí)候,會(huì )自動(dòng)調用AdoStreamData函數的,在nBufferLen形參里面會(huì )指明需要讀取多少個(gè)字節的pcm碼流。直接把數據寫(xiě)入pBuffer即可。
呵呵,只要搞個(gè)循環(huán)的接收緩沖區就可以了。
原本是OpenGL的鐵桿追隨者,這段時(shí)間看看directx, direct3d,呵呵,到底是微軟啊。還是懷念用OpenGL寫(xiě)視頻模塊的日子。。。
 
具體的依賴(lài)庫,查查directx的help吧,懶得寫(xiě)了,整個(gè)工程文件太大,浪費偶的博客空間,暫時(shí)先不上傳了。
 
 



本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
使用waveOut接口在Windows中播放聲音
DirectSound播放音頻應用程序開(kāi)發(fā)快速入門(mén)
H264視頻編碼成MP4文件
C# SerialPort串口通信發(fā)送接收,處理接收數據完整
深入淺出Win32多線(xiàn)程程序設計之綜合實(shí)例
InternetOpen\InternetOpenUrl\InternetReadFile 等相關(guān)Win32 網(wǎng)絡(luò )API 使用詳細說(shuō)明
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久