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

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

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

開(kāi)通VIP
DirectSound播放音頻應用程序開(kāi)發(fā)快速入門(mén)
摘要:DirectSound編程的入門(mén)介紹,通過(guò)實(shí)例講解了如何利用DirectSound最基本的功能-----播放音頻,并提供了DirectSound播放音頻文件的兩種方式(Static buffer 和Streaming buffer ),

  關(guān)鍵詞: Directsound stream buffer ,static buffer wave 文件播放

  一、配置DirectDounf的開(kāi)發(fā)環(huán)境

在進(jìn)行DirectSound開(kāi)發(fā)之前,一定要設置好開(kāi)發(fā)環(huán)境,否則編譯時(shí)會(huì )提示你很多東西都找不到定義,DirectSound的開(kāi)發(fā)環(huán)境很好設置,簡(jiǎn)單的說(shuō)就是包含一些頭文件,將lib文件添加要工程中。僅僅包含dsound.h肯定是不夠的,一般來(lái)說(shuō),在你的工程中包含下面兩個(gè)文件就夠了。

#include <mmsystem.h>
#include <dsound.h>

  如果你還想使用Dsound的API的話(huà),那么你就要在你的vc開(kāi)發(fā)環(huán)境中添加Dsound..lib庫,如果你的程序還提示有很多的外部鏈接找不到,那么我建議你可以將下面的庫都添加到你的工程中comctl32.lib dxerr9.lib winmm.lib dsound.libdxguid.lib odbc32.lib odbccp32.lib,這些是我從Dsound提供的例子中得到的,肯定夠你用的,如下圖

 

  開(kāi)發(fā)環(huán)境配置好了。你可以在你的工程中任意使用DirectSound提供的接口和函數了。下面簡(jiǎn)單介紹DirectSound開(kāi)發(fā)中要用到的對象。

  二、DiectDound幾個(gè)對象

  我們首先學(xué)習一下Directsound中常用的幾個(gè)對象,簡(jiǎn)單學(xué)習一下哦DirectSound其實(shí)很簡(jiǎn)單的,主要有下面常用的幾個(gè)對象。

對象 數量 作用 主要接口
設備對象 每個(gè)應用程序只有一個(gè)設備對象 用來(lái)管理設備,創(chuàng )建輔助緩沖區 IDirectSound8
輔助緩沖區對象 每一個(gè)聲音對應一個(gè)輔助緩沖區,可以有多個(gè)輔助緩沖區 用來(lái)管理一個(gè)靜態(tài)的或者動(dòng)態(tài)的聲音流,然后在主緩沖區中混音 IDirectSoundBuffer8,
IDirectSound3DBuffer8,
IDirectSoundNotify8
主緩沖區對象 一個(gè)應用程序只有一個(gè)主緩沖區 將輔助緩沖區的數據進(jìn)行混音,并且控制3D參數. IDirectSoundBuffer, IDirectSound3DListener8
特技對象 沒(méi)有 來(lái)輔助緩沖的聲音數據進(jìn)行處理 8個(gè)特技接口IDirectSoundFXChorus8

  首先,要創(chuàng )建一個(gè)設備對象,然后通過(guò)設備對象創(chuàng )建緩沖區對象。輔助緩沖區由應用程序創(chuàng )建和管理,DirectSound會(huì )自動(dòng)地創(chuàng )建和管理主緩沖區,一般來(lái)說(shuō),應用程序即使沒(méi)有獲取這個(gè)主緩沖區對象的接口也可以播放音頻數據,但是,如果應用程序要想得到IDirectSound3DListener8接口,就必須要自己創(chuàng )建一個(gè)主緩沖區。

  三、播放音頻文件開(kāi)發(fā)的基本流程

  下面我們簡(jiǎn)單的來(lái)學(xué)習一下如果通過(guò)Directsound的API播放聲音,既然是breif overview,那么詳細的內容你可以參考下面的一節內容,這里只是簡(jiǎn)單的介紹一下播放聲音的步驟。
 
 

第一步,創(chuàng )建一個(gè)設備對象,設置設備對象的協(xié)作度。

  在你的代碼中你可以通過(guò)調用DirectSoundCreat8函數來(lái)創(chuàng )建一個(gè)支持IDirectSound8接口的對象,這個(gè)對象通常代表缺省的播放設備。當然你可以枚舉可用的設備,然后將設備的GUID傳遞給DirectSoundCreat8函數。

  如果沒(méi)有聲音輸出設備,這個(gè)函數就返回error,或者,在VXD驅動(dòng)程序下,如果聲音輸出設備正被某個(gè)應用程序通過(guò)waveform格式的api函數所控制,該函數也返回error。

  下面是創(chuàng )建對象的代碼,及其簡(jiǎn)單

LPDIRECTSOUND8 lpDirectSound;
HRESULT hr = DirectSoundCreate8(NULL, & lpDirectSound, NULL));

  注意,Directsound雖然基于COM,但是你并不需要初始化com庫,這些Directsound都幫你做好了,當然,如果你使用DMOs特技,你就要自己初始化com庫了,切記。

因為Windows是一個(gè)多任務(wù)操作環(huán)境,在同一個(gè)時(shí)刻有可能多個(gè)應用程序共用同一個(gè)設備,通過(guò)協(xié)作水平,DirectX就可以保證這些應用程序在訪(fǎng)問(wèn)設備的時(shí)候不會(huì )沖突,每個(gè)Directsound應用程序都有一個(gè)協(xié)作度,用來(lái)確定來(lái)接近設備的程度,當你創(chuàng )建完設備對象后,一定要調用IDirectSound8::SetCooperativeLevel來(lái)設置協(xié)作度,否則,你不會(huì )聽(tīng)到聲音的。

HRESULT hr = lpDirectSound->SetCooperativeLevel(hwnd, DSSCL_PRIORITY);
if (FAILED(hr))
{
 ErrorHandler(hr); // Add error-handling here.
}

  第二步,創(chuàng )建一個(gè)輔助Buffer,也叫后備緩沖區

  你可以通過(guò)IDirectSound8::CreateSoundBuffer來(lái)創(chuàng )建buffer對象,這個(gè)對象主要用來(lái)獲取處理數據,這種buffer稱(chēng)作輔助緩沖區,以和主緩沖區區別開(kāi)來(lái),Direcsound通過(guò)把幾個(gè)后備緩沖區的聲音混合到主緩沖區中,然后輸出到聲音輸出設備上,達到混音的效果。

  第三步,獲取PCM類(lèi)型的數據

  將WAV文件或者其他資源的數據讀取到緩沖區中。

  第四步,將數據讀取到緩沖區

  你可以通過(guò) IDirectSoundBuffer8::Lock.方法來(lái)準備一個(gè)輔助緩沖區來(lái)進(jìn)行寫(xiě)操作,通常這個(gè)方法返回一個(gè)內存地址,見(jiàn)數據從你的私人buffer中復制到這個(gè)地址中,然后調用IDirectSoundBuffer8::Unlock.

  第五步,播放緩沖區中的數據

你可以通過(guò)IDirectSoundBuffer8::Play方法來(lái)播放緩沖區中的音頻數據,你可以通過(guò)IDirectSoundBuffer8::Stop來(lái)暫停播放數據,你可以反復的萊停止,播放,音頻數據,如果你同時(shí)創(chuàng )建了幾個(gè)buffer,那么你就可以同時(shí)來(lái)播放這些數據,這些聲音會(huì )自動(dòng)進(jìn)行混音的。

  你可以通過(guò)IDirectSoundBuffer8::GetVolume and IDirectSoundBuffer8::SetVolume函數來(lái)獲取或者設置正在播放的音頻的音量的大小。

  如果設置主緩沖區的音量就會(huì )改變聲卡的音頻的聲量大小。音量的大小,用分貝來(lái)表示,一般沒(méi)法來(lái)增強缺省的音量,這里要提示一下,分貝的增減不是線(xiàn)形的,減少3分貝相當于減少1/2的能量。最大值衰減100分貝幾乎聽(tīng)不到了。

通過(guò)IDirectSoundBuffer8::GetFrequency andIDirectSoundBuffer8::SetFrequency方法可以獲取設置音頻播放的頻率,主緩沖區的頻率不允許改動(dòng),通過(guò)IDirectSoundBuffer8::GetPan andIDirectSoundBuffer8::SetPan函數可以設置音頻在左右聲道播放的位置,具有3D特性的緩沖區沒(méi)法調整聲道。
四、使用靜態(tài)的緩沖區

  如果我們的wave文件不是很大,那么我們就可以使用靜態(tài)的緩沖區了。

  包含全部音頻數據的緩沖區我們稱(chēng)為靜態(tài)的緩沖區,盡管,不同的聲音可能會(huì )反復使用同一個(gè)內存buffer,但嚴格來(lái)說(shuō),靜態(tài)緩沖區的數據只寫(xiě)入一次。
< classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="350" height="250" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=7,0,0,0">
 


  靜態(tài)緩沖區的創(chuàng )建和管理和流緩沖區很相似,唯一的區別就是它們使用的方式不一樣,靜態(tài)緩沖區只填充一次數據,然后就可以play,然而,流緩沖區是一邊play,一邊填充數據。

  給靜態(tài)緩沖區加載數據分下面幾個(gè)步驟

  1、調用IDirectSoundBuffer8::Lock函數來(lái)鎖定所有的內存,你要指定你鎖定內存中你開(kāi)始寫(xiě)入數據的偏移位置,并且取回該偏移位置的地址。

  2、采用標準的數據copy方法,將音頻數據復制到返回的地址。

  3、調用IDirectSoundBuffer8::Unlock.,解鎖該地址。

  下面我給出使用static buffer 播放wav文件的完整代碼,首先定義我們需要的一些對象:

LPDIRECTSOUNDBUFFER8 g_pDSBuffer8 = NULL; //buffer
LPDIRECTSOUND8 g_pDsd = NULL; //dsound
CWaveFile *g_pWaveFile= NULL;
//下面初始化DirectSound工作。
HRESULT hr;
if(FAILED(hr = DirectSoundCreate8(NULL,&g_pDsd,NULL)))
 return FALSE;
 //設置設備的協(xié)作度
if(FAILED(hr = g_pDsd->SetCooperativeLevel(m_hWnd,DSSCL_PRIORITY)))
 return FALSE;

g_pWaveFile = new CWaveFile;
g_pWaveFile->Open(_T("d:\\test.wav"),NULL,WAVEFILE_READ);
DSBUFFERDESC dsbd;
ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) );
dsbd.dwSize = sizeof(DSBUFFERDESC);
dsbd.dwFlags = DSBCAPS_GLOBALFOCUS | DSBCAPS_CTRLFX| DSBCAPS_CTRLPOSITIONNOTIFY |DSBCAPS_GETCURRENTPOSITION2;
dsbd.dwBufferBytes = g_pWaveFile->GetSize();//MAX_AUDIO_BUF * BUFFERNOTIFYSIZE ;
dsbd.lpwfxFormat = g_pWaveFile->m_pwfx;
LPDIRECTSOUNDBUFFER lpbuffer;
//創(chuàng )建輔助緩沖區對象
if(FAILED(hr = g_pDsd->CreateSoundBuffer(&dsbd,&lpbuffer,NULL)))
 return ;
if( FAILED( hr = lpbuffer->QueryInterface( IID_IDirectSoundBuffer8, (LPVOID*) &g_pDSBuffer8) ) )
 return ;
lpbuffer->Release();
//準備工作做完了,下面就開(kāi)始播放了
LPVOID lplockbuf;
DWORD len;
DWORD dwWrite;

g_pDSBuffer8->Lock(0,0,&lplockbuf,&len,NULL,NULL,DSBLOCK_ENTIREBUFFER);
g_pWaveFile->Read((BYTE*)lplockbuf,len,&dwWrite);
g_pDSBuffer8->Unlock(lplockbuf,len,NULL,0);
g_pDSBuffer8->SetCurrentPosition(0);
g_pDSBuffer8->Play(0,0,DSBPLAY_LOOPING);

  五、使用流緩沖區播放超大型的wave文件

  流緩沖區用來(lái)播放那些比較長(cháng)的音頻文件,因為數據比較長(cháng),沒(méi)法一次填充到緩沖區中,一邊播放,一邊將新的數據填充到DirectSound的緩沖區中。

  可以通過(guò)IDirectSoundBuffer8::Play函授來(lái)播放緩沖區中的內容,注意在該函數的參數中一定要設置DSBPLAY_LOOPING標志。

  通過(guò)IDirectSoundBuffer8::Stop方法中斷播放,該方法會(huì )立即停止緩沖區播放,因此你要確保所有的數據都被播放,你可以通過(guò)拖動(dòng)播放位置或者設置通知位置來(lái)實(shí)現。

  將音頻流倒入緩沖區需要下面三個(gè)步驟

  1、確保你的緩沖區已經(jīng)做好接收新數據的準備。你可以拖放播放的光標位置或者等待通知

  2、調用IDirectSoundBuffer8::Lock.函數鎖住緩沖區的位置,這個(gè)函數返回一個(gè)或者兩個(gè)可以寫(xiě)入數據的地址

  3、使用標準的copy數據的方法將音頻數據寫(xiě)入緩沖區中

  4、IDirectSoundBuffer8::Unlock.,解鎖

這里我要講一下DirectSound的通知機制。因為Stream buffer大小只夠容納一部分數據,因此,在播放完緩沖區中的數據后,DirectSound就會(huì )通知應用程序,將新的數據填充到DirectSound的緩沖區中。假如我們設置DirectSound的buffersize 為1920*4,如下圖


  我們可以給DirectSound設置一個(gè)事件,并且設置buffer通知大小,如下:

HANDLE g_event[MAX_AUDIO_BUF];
for(int i =0; i< MAX_AUDIO_BUF;i++)
{
 g_aPosNotify[i].dwOffset = i* BUFFERNOTIFYSIZE ;
 g_aPosNotify[i].hEventNotify = g_event[i];
}
if(FAILED(hr = g_pDSBuffer8->QueryInterface(IID_IDirectSoundNotify,(LPVOID *) &g_pDSNotify )))
 return ;
g_pDSNotify->SetNotificationPositions(MAX_AUDIO_BUF,g_aPosNotify);
g_pDSNotify->Release();

  當DirectSound播放到buffer的1920,3840,5760,7680等位置時(shí),Directsound就會(huì )通知應用程序,將g_ event,設置為通知態(tài),應用程序就可以通過(guò)WaitForMultipleObjects函數等待DirectSound的通知,將數據填充到DirectSoun的輔助緩沖區。

  下面我給出Stream buffer 播放wave文件的代碼。

#define MAX_AUDIO_BUF 4
#define BUFFERNOTIFYSIZE 1920
LPDIRECTSOUNDBUFFER8 g_pDSBuffer8 = NULL; //buffer
LPDIRECTSOUND8 g_pDsd = NULL; //dsound
CWaveFile *g_pWaveFile= NULL;
BOOL g_bPlaying = FALSE; //是否正在播放
LPDIRECTSOUNDNOTIFY8 g_pDSNotify = NULL;
DSBPOSITIONNOTIFY g_aPosNotify[MAX_AUDIO_BUF];//設置通知標志的數組
HANDLE g_event[MAX_AUDIO_BUF];
DWORD g_dwNextWriteOffset = 0;

//初始化DirectSound
HRESULT hr;
if(FAILED(hr = DirectSoundCreate8(NULL,&g_pDsd,NULL)))
return FALSE;
if(FAILED(hr = g_pDsd->SetCooperativeLevel(m_hWnd,DSSCL_PRIORITY)))
return FALSE;

g_pWaveFile = new CWaveFile;
g_pWaveFile->Open(_T("d:\\test.wav"),NULL,WAVEFILE_READ);

DSBUFFERDESC dsbd;
ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) );
dsbd.dwSize = sizeof(DSBUFFERDESC);
dsbd.dwFlags = DSBCAPS_GLOBALFOCUS | DSBCAPS_CTRLPOSITIONNOTIFY |DSBCAPS_GETCURRENTPOSITION2;
dsbd.dwBufferBytes = MAX_AUDIO_BUF * BUFFERNOTIFYSIZE ;
dsbd.lpwfxFormat = g_pWaveFile->m_pwfx;
LPDIRECTSOUNDBUFFER lpbuffer;
//創(chuàng )建DirectSound輔助緩沖區
if(FAILED(hr = g_pDsd->CreateSoundBuffer(&dsbd,&lpbuffer,NULL)))
 return FALSE;
if( FAILED( hr = lpbuffer->QueryInterface( IID_IDirectSoundBuffer8, (LPVOID*) &g_pDSBuffer8) ) )
 return FALSE;
lpbuffer->Release();
//設置DirectSound通知 機制
for(int i =0; i< MAX_AUDIO_BUF;i++)
{
 g_aPosNotify[i].dwOffset = i* BUFFERNOTIFYSIZE ;
 g_aPosNotify[i].hEventNotify = g_event[i];
}
if(FAILED(hr=g_pDSBuffer8->QueryInterface(IID_IDirectSoundNotify,(LPVOID*) g_pDSNotify )))
 return ;
g_pDSNotify->SetNotificationPositions(MAX_AUDIO_BUF,g_aPosNotify);
g_pDSNotify->Release();
ok,在下面的play函數中,我們就要單獨啟動(dòng)一個(gè)線(xiàn)程,來(lái)播放了
void OnBnClickedButtonPlay()
{
 g_bPlaying =TRUE;
 g_pWaveFile->ResetFile();
 CreateThread(0,0,PlayThread,this,NULL,NULL);
}
//停止播放音頻
void CDsoundEffectDemoDlg::OnBnClickedButtonStop()
{
 // TODO: 在此添加控件通知處理程序代碼
 g_bPlaying =FALSE;
 Sleep(500);
 g_pDSBuffer8->Stop();
}

  下面我們看看我們的播放線(xiàn)程,在線(xiàn)程里,我們首先將音頻數據填充到DirectSound的輔助緩沖區中,然后調用DirectSoundbuffer 的play方法,開(kāi)始播放,然后就在WaitForMultipleObjects等待DirectSound的通知吧,然后讀取wave文件將數據填充到DirectSound的空buffer中。

DWORD WINAPI PlayThread(LPVOID lpParame)
{
 DWORD res;
 LPVOID lplockbuf;
 DWORD len;
 DWORD dwWrite;

 g_pDSBuffer8->Lock(0,0,&lplockbuf,&len,NULL,NULL,DSBLOCK_ENTIREBUFFER);
 g_pWaveFile->Read((BYTE*)lplockbuf,len,&dwWrite);
 g_pDSBuffer8->Unlock(lplockbuf,len,NULL,0);
 g_pDSBuffer8->SetCurrentPosition(0);
 g_pDSBuffer8->Play(0,0,DSBPLAY_LOOPING);
 g_dwNextWriteOffset = 0;
 while(g_bPlaying)
 {
  res = WaitForMultipleObjects (MAX_AUDIO_BUF, g_event, FALSE, INFINITE);
  if(res > WAIT_OBJECT_0)
   ProcessBuffer();
 }

 return 0;
}

  下面的函數主要是給空的DirectSound緩沖區填充 音頻數據。

void ProcessBuffer()
{
 DWORD dwBytesWrittenToBuffer = 0;
 VOID* pDSLockedBuffer = NULL;
 VOID* pDSLockedBuffer2 = NULL;
 DWORD dwDSLockedBufferSize;
 DWORD dwDSLockedBufferSize2;
 HRESULT hr;
g_pDSBuffer8->Lock(g_dwNextWriteOffset,BUFFERNOTIFYSIZE,&pDSLockedBuffer,&dwDSLockedBufferSize, &pDSLockedBuffer2,&dwDSLockedBufferSize2,0);
 if(hr == DSERR_BUFFERLOST)
 {
  g_pDSBuffer8->Restore();
  g_pDSBuffer8->Lock(g_dwNextWriteOffset,BUFFERNOTIFYSIZE,&pDSLockedBuffer,&dwDSLockedBufferSize,
&pDSLockedBuffer2,&dwDSLockedBufferSize2,0);
 }
 if(SUCCEEDED(hr))
 {
  //write
  g_pWaveFile->Read((BYTE*)pDSLockedBuffer,dwDSLockedBufferSize,&dwBytesWrittenToBuffer);
  g_dwNextWriteOffset += dwBytesWrittenToBuffer;

  if (NULL != pDSLockedBuffer2)
  {
   g_pWaveFile->Read((BYTE*)pDSLockedBuffer2,dwDSLockedBufferSize2,&dwBytesWrittenToBuffer);
   g_dwNextWriteOffset += dwBytesWrittenToBuffer;
  }
  g_dwNextWriteOffset %= (BUFFERNOTIFYSIZE * MAX_AUDIO_BUF);

  if(dwBytesWrittenToBuffer <BUFFERNOTIFYSIZE )
  {
   FillMemory( (BYTE*) pDSLockedBuffer + dwBytesWrittenToBuffer,
   BUFFERNOTIFYSIZE - dwBytesWrittenToBuffer,
(BYTE)(g_pWaveFile->m_pwfx->wBitsPerSample == 8 ? 128 : 0 ) );

   g_bPlaying = FALSE;
  }
  hr = g_pDSBuffer8->Unlock(pDSLockedBuffer,dwDSLockedBufferSize,
  pDSLockedBuffer2,dwDSLockedBufferSize2);
 }
}
本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
DirectSoundFullDuplexCreate8
C#錄音
計算機科學(xué)論壇--利用DirectSound實(shí)現聲卡錄音
ArcGIS Engine+C#緩沖區分析文檔及完整源碼
Linux下的C編程入門(mén)之“線(xiàn)程”控制與“線(xiàn)程”通信編程
FVID的使用-FVID_control FVID_create
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

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