日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) >

一个DirectSound的例子

發(fā)布時(shí)間:2025/3/15 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 一个DirectSound的例子 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

一個(gè)捕獲音頻并且播放的例子,可以用來唱歌^_^

寫了半天才發(fā)現(xiàn)Direct SDK有個(gè)類似的例子,所以到了最后幾乎都是照抄了。

聲音效果不太好,修改一下加上網(wǎng)絡(luò)傳送功能做成語(yǔ)音聊天工具。不過這樣肯定不行,真正的語(yǔ)音聊天可能都要音頻數(shù)據(jù)處理啊等功能的。

我是想試這做個(gè)東西來唱歌,不過效果不好!程序錯(cuò)誤很多,有很多地方可以改進(jìn)的,不過我一貫的作風(fēng)是淺嘗即止。

?

部分代碼
--------------------------------------------------------------------------
#include "sound.h"
LPDIRECTSOUND8 lpDirectSound =NULL;?????? //DirectSound 設(shè)備
LPDIRECTSOUNDBUFFER8 lpDSBuffer8 = NULL; //播放緩沖區(qū)(第二緩沖區(qū))
HANDLE soundEvent[3];??? //播放通知
LPDIRECTSOUNDCAPTURE8??????? lpDSCapture = NULL;//捕獲設(shè)備對(duì)象指針
LPDIRECTSOUNDCAPTUREBUFFER8?? lpDSBCapture = NULL;//捕獲緩沖區(qū)對(duì)象指針
HANDLE captureEvent[3];??? //播放通知
//int?? FreeBufferSectionNum =0;?? //第幾段的 播放緩沖可以寫了
int?? SoundBufferLength=0;???? //播放緩沖的總長(zhǎng)度, 一個(gè)緩沖設(shè)置分成3段,設(shè)置3個(gè)通知信號(hào)
int?? BufferSectionLength=0; //每一段的長(zhǎng)度 BYTE?? SwapBuffer[29400] ;//應(yīng)該是SwapBuffer[BufferSectionLength];?? ,
?????????????????????????????????????? //不過我懶的動(dòng)態(tài)申請(qǐng)了,所以固定了,用于把臨時(shí)保存捕獲的音頻數(shù)據(jù),
??????????????????????????????????????? //在從這里復(fù)制到播放緩存里面去。 其實(shí)直接復(fù)制也是可以的,不過加多一個(gè)緩存在這里,便于處理啊,網(wǎng)絡(luò)傳送等等。
??????????????????????????
//CWaveFile?? waveFile= NULL;??
bool SoundCreate(HWND hwnd )
{ HRESULT hr = DirectSoundCreate8(NULL, & lpDirectSound, NULL); if (FAILED(hr))
???? {????
?????????? MessageBox(hwnd,_T("創(chuàng)建DirectSound接口失敗。"),_T("widebright"),MB_OK);??? // Add error-handling here.
??????? return false;
???? } hr = lpDirectSound->SetCooperativeLevel(hwnd, DSSCL_PRIORITY?? ); //DSSCL_NORMAL if (FAILED(hr))
???? {????
???? MessageBox(hwnd,_T("設(shè)置DirectSound協(xié)作級(jí)別失敗。"),_T("widebright"),MB_OK);??? // Add error-handling here.
?????????? lpDirectSound->Release ();??? // Add error-handling here.
??????? return false;
???? } hr =?? CreateBasicBuffer(lpDirectSound ,& lpDSBuffer8); if (FAILED(hr))
???? {????
???? MessageBox(hwnd,_T("創(chuàng)建DirectSound聲音播放緩沖區(qū)失敗。"),_T("widebright"),MB_OK);??? // Add error-handling here.
?????????? lpDirectSound->Release ();??? // Add error-handling here.
??????? return false;
???? } //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);
?? return true;
} //創(chuàng)建 播放緩沖
//
//The example function creates a streaming buffer large enough to hold 3 seconds of streaming data. Nonstreaming buffers should be made just large enough to accommodate the entire sound.
//
//The DSBCAPS_GLOBALFOCUS flag in the example ensures that the buffer will continue playing even when the application window is not in the foreground. Without this flag, the buffer will be muted when another application or even a dialog box has the input focus.
//
//If the location of a buffer is not specified, DirectSound places it in hardware-controlled memory if possible. Because hardware buffers are mixed by the sound card processor, they have much less impact on application performance.
//
//If you wish to specify the location of a buffer rather than letting DirectSound decide where it belongs, set either the DSBCAPS_LOCHARDWARE or DSBCAPS_LOCSOFTWARE flag in the DSBUFFERDESC structure. If the DSBCAPS_LOCHARDWARE flag is set and there are insufficient hardware resources, the buffer creation request fails.
//
//To take advantage of the voice management features of DirectSound, specify the DSBCAPS_LOCDEFER flag when creating the buffer. This flag defers the allocation of resources for the buffer until it is played. For more information, see Dynamic Voice Management.
//
//You can ascertain the location of an existing buffer by using the IDirectSoundBuffer8::GetCaps method and checking the dwFlags member of the DSBCAPS structure for either the DSBCAPS_LOCHARDWARE or DSBCAPS_LOCSOFTWARE flags. One or the other is always specified.
//
//Buffer objects are owned by the device object that created them. When the device object is released, all buffers created by that object are also released and should not be referenced.
HRESULT CreateBasicBuffer(LPDIRECTSOUND8 lpDirectSound, LPDIRECTSOUNDBUFFER8* ppDsb8)
{
?? WAVEFORMATEX wfx;
?? DSBUFFERDESC dsbdesc;
?? LPDIRECTSOUNDBUFFER pDsb = NULL;
?? HRESULT hr;

?? // Set up WAV format structure. memset(&wfx, 0, sizeof(WAVEFORMATEX));
?? wfx.wFormatTag = WAVE_FORMAT_PCM;
?? wfx.nChannels = 2;
?? wfx.nSamplesPerSec = 22050;
?? wfx.nBlockAlign = 4;
?? wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
?? wfx.wBitsPerSample = 16;

?? // Set up DSBUFFERDESC structure.

?? memset(&dsbdesc, 0, sizeof(DSBUFFERDESC));
?? dsbdesc.dwSize = sizeof(DSBUFFERDESC);
?? dsbdesc.dwFlags =
????? DSBCAPS_CTRLPAN????? //聲源 是否可以左右移動(dòng)
//DSBCAPS_CTRL3D????? //聲源是否可以在?? 3D空移動(dòng)。
//DSBCAPS_CTRLFX????? //特效處理支持
| DSBCAPS_CTRLVOLUME?????????? //音量控制
//| DSBCAPS_CTRLFREQUENCY???? //頻率控制
| DSBCAPS_CTRLPOSITIONNOTIFY //可以設(shè)置播放位置通知
???? | DSBCAPS_GLOBALFOCUS;?? //在程序失去焦點(diǎn)的時(shí)候,依然播放聲音
?? dsbdesc.dwBufferBytes =?? wfx.nAvgBytesPerSec/2;?????? //設(shè)置緩沖區(qū)長(zhǎng)度 為多少秒,就設(shè)置這里為wfx.nAvgBytesPerSec 乘以多少,這里和捕獲的統(tǒng)一設(shè)置成一秒
?? dsbdesc.lpwfxFormat = &wfx;
SoundBufferLength=dsbdesc.dwBufferBytes ; //記錄緩沖的總長(zhǎng)度**************************************************
BufferSectionLength = SoundBufferLength/3?? ; //平均分成3段,每段的長(zhǎng)度
BufferSectionLength -=?? BufferSectionLength % wfx.nBlockAlign; //內(nèi)存對(duì)齊 // Create buffer.

?? hr = lpDirectSound->CreateSoundBuffer(&dsbdesc, &pDsb, NULL);
?? if (SUCCEEDED(hr))
?? {
????? hr = pDsb->QueryInterface(IID_IDirectSoundBuffer8, (LPVOID*) ppDsb8);
????? pDsb->Release();
?? }
?? return hr;
}
//設(shè)置通知對(duì)象
//The buffer must be stopped when this method is called. //dwOffset---Offset from the beginning of the buffer where the notify event is to be triggered, or DSBPN_OFFSETSTOP. 通知觸發(fā)時(shí)buffer的偏移
// hEventNotify ---Handle to the event to be signaled when the offset has been reached.?? 通知觸發(fā)的event HRESULT SetNotification(HANDLE?? *hEventNotify ,LPDIRECTSOUNDBUFFER8 lpDsbSecondary )
{ #define cEvents?? 3

?? LPDIRECTSOUNDNOTIFY8 lpDsNotify;
?? DSBPOSITIONNOTIFY PositionNotify[cEvents];
?? HRESULT hr;
??
?? if (FAILED( hr = lpDsbSecondary->QueryInterface(IID_IDirectSoundNotify8,
????????????? (LPVOID*)&lpDsNotify)))
?? {
???? return hr;
?? } // Create events.
?? for (int i = 0; i < cEvents; ++i)
?? {
???? hEventNotify[i] = CreateEvent(NULL, TRUE, FALSE, NULL);
???? if (NULL == hEventNotify[i])
???? {
?????? hr = GetLastError();
?????? return hr;
???? } PositionNotify[i].dwOffset =?? BufferSectionLength?? * (i+1)?? -1;?? ;??? //設(shè)置這里值 為DSBPN_OFFSETSTOP 時(shí),可以創(chuàng)建一個(gè)停止播放通知
????? PositionNotify[i].hEventNotify = hEventNotify[i];
???
?? }
??
?????
?? //注意沒調(diào)用一次SetNotificationPositions函數(shù)就清除以前的通知對(duì)象,所以要設(shè)置多個(gè)通知對(duì)象只能使用一個(gè)PositionNotify數(shù)組,而不能調(diào)用多次SetNotificationPositions函數(shù)
???? hr = lpDsNotify->SetNotificationPositions(3, PositionNotify);???
???? lpDsNotify->Release();
???? return hr;
}
BOOL AppWriteDataToBuffer(
???????? LPDIRECTSOUNDBUFFER8 lpDsb,?? // The buffer.
???????? DWORD dwOffset,?????????????? // Our own write cursor.
???????? LPBYTE lpbSoundData,????????? // Start of our data.
???????? DWORD dwSoundBytes)?????????? // Size of block to copy.
???? {
?????? LPVOID?? lpvPtr1;
?????? DWORD dwBytes1;
?????? LPVOID?? lpvPtr2;
?????? DWORD dwBytes2;
?????? HRESULT hr;
?????
?????? // Obtain memory address of write block. This will be in two parts
?????? // if the block wraps around.
?????
?????? hr = lpDsb->Lock(dwOffset, dwSoundBytes, &lpvPtr1,
?????????? &dwBytes1, &lpvPtr2, &dwBytes2, 0);
?????
?????? // If the buffer was lost, restore and retry lock.
?????
?????? if (DSERR_BUFFERLOST == hr)
?????? {
???????? lpDsb->Restore();
???????? hr = lpDsb->Lock(dwOffset, dwSoundBytes,
???????????? &lpvPtr1, &dwBytes1,
???????????? &lpvPtr2, &dwBytes2, 0);
?????? }
?????? if (SUCCEEDED(hr))
?????? {
???????? // Write to pointers.
?????
???????? CopyMemory(lpvPtr1, lpbSoundData, dwBytes1);
???????? if (NULL != lpvPtr2)?? //如果lpvPtr2不為NULL,說明要寫的超出了緩沖的長(zhǎng)度,這時(shí)lpvPtr2指向緩沖的開始部分,可以繼續(xù)寫進(jìn)去
???????? {
?????????? CopyMemory(lpvPtr2, lpbSoundData+dwBytes1, dwBytes2);
???????? }
?????
???????? // Release the data back to DirectSound.
?????
???????? hr = lpDsb->Unlock(lpvPtr1, dwBytes1, lpvPtr2,
???????? dwBytes2);
???????? if (SUCCEEDED(hr))
???????? {
?????????? // Success.
?????????? return TRUE;
???????? }
?????? }
?????
?????? // Lock, Unlock, or Restore failed.
?????
?????? return FALSE;
???? }
///
// 啟動(dòng) 播放聲音
bool?? SoundStart(HWND hwnd )
{
HRESULT hr; if( ! SoundCreate(hwnd)) exit(0);
????

//不采用 播放通知了,播放通知控制起來不方便,只需要的捕獲通知里面復(fù)制 到播放緩存的相應(yīng)位置好了
//????
//?? HRESULT?? hr = SetNotification(soundEvent,lpDSBuffer8);
//?? if (FAILED(hr))
//??? {????
//??? MessageBox(hwnd,_T("創(chuàng)建播放位置通知失敗"),_T("widebright"),MB_OK);??
//??? exit(0);
//}


ZeroMemory( SwapBuffer,29400);?? //無(wú)聲 AppWriteDataToBuffer (lpDSBuffer8,0,SwapBuffer,29400); lpDSBuffer8->SetVolume(DSBVOLUME_MAX);
lpDSBuffer8->SetCurrentPosition (0);
if (SUCCEEDED( hr = lpDSBuffer8->Play (0,0,DSBPLAY_LOOPING))) //開始播放
{
???? return true;
}else{ return false;
}
//不采用 播放通知了,播放通知控制起來不方便,只需要的捕獲通知里面復(fù)制 到播放緩存的相應(yīng)位置好了
//while (1)
//?? {
// //?????? DWORD?? notifyIndex =?? WaitForMultipleObjects(3,soundEvent,FALSE,INFINITE) ;???? //INFINITE 表示一直等待 ,除非hEvent產(chǎn)生了信號(hào)。 這里
// //??????
// //notifyIndex = notifyIndex - WAIT_OBJECT_0;??? //得到觸發(fā) 通知對(duì)象序號(hào)
// //?????? ResetEvent(soundEvent[ notifyIndex]);
//???????????????
//????? //FreeBufferSectionNum = notifyIndex;
//??? WaitForSingleObject(soundEvent[0], INFINITE);???????
//??? ResetEvent(soundEvent[ 0]);
//?????? FreeBufferSectionNum =0;
//??? WaitForSingleObject(soundEvent[1], INFINITE);???????
//??? ResetEvent(soundEvent[1]);
//??? FreeBufferSectionNum =1;
//??? WaitForSingleObject(soundEvent[2], INFINITE);???????
//??? ResetEvent(soundEvent[ 2]);
//?????? FreeBufferSectionNum =2;
//
//}?? }

//停止播放聲音
void SoundStop()
{ if ( ! lpDSBuffer8)?? {lpDSBuffer8->Stop(); lpDSBuffer8->Release ();}
???? if ( ! lpDirectSound) lpDirectSound->Release ();
????
} /
下面是錄音部分/
bool CaptureCreate(HWND hwnd )
{
?????????????????
???? HRESULT hr = DirectSoundCaptureCreate8 (&DSDEVID_DefaultCapture , &lpDSCapture,NULL);
if (FAILED(hr))
???? {????
?????????? MessageBox(hwnd,_T("創(chuàng)建DirectCapture接口失敗。"),_T("widebright"),MB_OK);??? // Add error-handling here.
??????? return false;
???? } hr =?? CreateCaptureBuffer(lpDSCapture , &lpDSBCapture); if (FAILED(hr))
???? {????
???? MessageBox(hwnd,_T("創(chuàng)建DirectCapture聲音播放緩沖區(qū)失敗。"),_T("widebright"),MB_OK);??? // Add error-handling here.
?????????? lpDSCapture->Release ();??? // Add error-handling here.
??????? return false;
???? } //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);
?? return true;
} HRESULT CreateCaptureBuffer(LPDIRECTSOUNDCAPTURE8 pDSC,
???????????????????????????? LPDIRECTSOUNDCAPTUREBUFFER8* ppDSCB8)
{
?? HRESULT hr;
?? DSCBUFFERDESC??????????????? dscbd;
?? LPDIRECTSOUNDCAPTUREBUFFER?? pDSCB;
?? WAVEFORMATEX???????????????? wfx =
????? {WAVE_FORMAT_PCM, 2, 22050, 88200, 4, 16, 0};
???? // {WAVE_FORMAT_PCM, 2, 44100, 176400, 4, 16, 0};
???? // wFormatTag, nChannels, nSamplesPerSec, mAvgBytesPerSec,
???? // nBlockAlign, wBitsPerSample, cbSize

?? if ((NULL == pDSC) || (NULL == ppDSCB8)) return E_INVALIDARG;
?? dscbd.dwSize = sizeof(DSCBUFFERDESC);
?? dscbd.dwFlags = 0;
?? dscbd.dwBufferBytes =?? wfx.nAvgBytesPerSec/2;????? //*******保存多少秒的數(shù)據(jù) 就設(shè)置這里為多少乘以 wfx.nAvgBytesPerSec*********
?? dscbd.dwReserved = 0;
?? dscbd.lpwfxFormat = &wfx;
?? dscbd.dwFXCount = 0;
?? dscbd.lpDSCFXDesc = NULL;

?? if (SUCCEEDED(hr = pDSC->CreateCaptureBuffer(&dscbd, &pDSCB, NULL)))
?? {
???? hr = pDSCB->QueryInterface(IID_IDirectSoundCaptureBuffer8, (LPVOID*)ppDSCB8);
???? pDSCB->Release();??
?? }
?? return hr;
} HRESULT SetCaptureNotifications(HANDLE?? *rghEvent, LPDIRECTSOUNDCAPTUREBUFFER8 pDSCB)
{
?? #define cEvents?? 3 LPDIRECTSOUNDNOTIFY8 pDSNotify;
?? WAVEFORMATEX????????? wfx;??
?? //HANDLE????? rghEvent[cEvents] = {0};
?? DSBPOSITIONNOTIFY?? rgdsbpn[cEvents];
?? HRESULT???? hr; if (NULL == pDSCB) return E_INVALIDARG;
?? if (FAILED(hr = pDSCB->QueryInterface(IID_IDirectSoundNotify, (LPVOID*)&pDSNotify)))
?? {
???? return hr;
?? }
?? if (FAILED(hr = pDSCB->GetFormat(&wfx, sizeof(WAVEFORMATEX), NULL)))
?? {
???? return hr;
?? } // Create events.
?? for (int i = 0; i < cEvents; ++i)
?? {
???? rghEvent[i] = CreateEvent(NULL, TRUE, FALSE, NULL);
???? if (NULL == rghEvent[i])
???? {
?????? hr = GetLastError();
?????? return hr;
???? } // Describe notifications.
???????? rgdsbpn[i].dwOffset =?? BufferSectionLength?? * (i+1)?? -1;
???????? rgdsbpn[i].hEventNotify = rghEvent[0];??? //rghEvent[i];?? 可以多個(gè)通知對(duì)象共用一個(gè)event的 }
// Create notifications.

?? hr = pDSNotify->SetNotificationPositions(cEvents, rgdsbpn);
?? pDSNotify->Release();
?? return hr;
} ///
// 啟動(dòng) 播放聲音
bool?? CaptureStart(HWND hwnd )
{
???? if( ! CaptureCreate(hwnd)) exit(0);
????
??
?? HRESULT?? hr = SetCaptureNotifications( captureEvent,lpDSBCapture );
????? if (FAILED(hr))
?? {????
???? MessageBox(hwnd,_T("創(chuàng)建捕獲位置通知失敗"),_T("widebright"),MB_OK);??
??????? exit(0);
?? }
??
????
lpDSBCapture->Start (DSCBSTART_LOOPING); //開始捕獲 int NextCaptureOffset =0;?? //捕獲緩存區(qū) 偏移
???? DWORD playCursor=0,writeCursor=0;
?? int NextSoundOffset = 0;?? //播放緩存區(qū) 的偏移,
???? lpDSBuffer8->GetCurrentPosition(&playCursor,&writeCursor);
???? NextSoundOffset = (writeCursor + 600 )% SoundBufferLength; while (1)
??? {
???? //??? DWORD?? notifyIndex =?? WaitForMultipleObjects(3,captureEvent,FALSE,INFINITE) ;???? //INFINITE 表示一直等待 ,除非hEvent產(chǎn)生了信號(hào)。 這里
???? //????
???? //notifyIndex = notifyIndex - WAIT_OBJECT_0;??? //得到觸發(fā) 通知對(duì)象序號(hào)
???? //??? ResetEvent(captureEvent[ notifyIndex]);
????? VOID* pDSCaptureLockedBuffer???? = NULL;
????? DWORD dwDSCaptureLockedBufferSize; WaitForSingleObject(captureEvent[0], INFINITE);???????
???? ResetEvent(captureEvent[ 0]);
???????? if( SUCCEEDED( hr = lpDSBCapture->Lock(NextCaptureOffset, BufferSectionLength,
?????????????????????????????????????????? &pDSCaptureLockedBuffer,
?????????????????????????????????????????? &dwDSCaptureLockedBufferSize,
?????????????????????????????????????????? NULL, NULL, 0L ) ) )
?? {
??????? CopyMemory( SwapBuffer,
???????????????? pDSCaptureLockedBuffer,
???????????????? dwDSCaptureLockedBufferSize );
????????????
??? lpDSBCapture->Unlock( pDSCaptureLockedBuffer, dwDSCaptureLockedBufferSize,
??????????????????????????? NULL, 0 );
???????????
??????????? lpDSBuffer8->GetCurrentPosition(&playCursor,&writeCursor);
//???? AppWriteDataToBuffer (lpDSBuffer8,writeCursor?? ,SwapBuffer,dwDSCaptureLockedBufferSize);
?? AppWriteDataToBuffer (lpDSBuffer8, NextSoundOffset ,SwapBuffer,dwDSCaptureLockedBufferSize);

?? }
??????? NextSoundOffset +=dwDSCaptureLockedBufferSize;
??????? NextSoundOffset %= SoundBufferLength; // Circular buffer
??????? NextCaptureOffset +=?? BufferSectionLength;
??????? NextCaptureOffset %= SoundBufferLength; // Circular buffer
????
???????
} }

//停止播放聲音
void CaptureStop()
{ if ( ! lpDSBCapture)?? {lpDSBuffer8->Stop (); lpDSBCapture->Release ();}
???? if ( ! lpDSCapture ) lpDSCapture ->Release ();
????
}

總結(jié)

以上是生活随笔為你收集整理的一个DirectSound的例子的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。