獲取語音設備並創建Interface
DirectSound開發中常常需要獲取系統當前可用的語音設備列表,在SDK Samples中最先介紹了它。DirectX將它封裝成函數DirectSoundEnumerate/DirectSoundCaptureEnumerate,我們所要做的只是以DSEnumCallback作爲接口模板,添加一個自定義的回調函數,然後簡單的調用一下即可。
獲取設備列表後,創建DirectSound環境使用函數DirectSoundCreate8/DirectSoundCaptureCreate8。
下面是示例源代碼:
/*----------------------------------------------------------------------------------
* File: EnumDevices.cpp
*
* Desc: This sample shows how to enumerate DirectSound sound and capture devices.
*
* Copyright (c) Microsoft Corp. All rights reserved.
*
*
* DirectSoundEnumerate
* DirectSoundCaptureEnumerate
* DirectSoundCreate8
* DirectSoundCaptureCreate8
* DXTRACE_ERR_MSGBOX : 在DEBUG模式下用來顯示錯誤信息
* DSEnumCallback : 用來枚舉設備的回調函數
*-----------------------------------------------------------------------------------*/
#include <windows.h>
#include <dxerr9.h>
#include <dsound.h>
#include "resource.h"
#pragma comment( lib,"Dsound.lib" )
#ifdef _DEBUG
#pragma comment( lib,"dxerr9.lib" )
#endif
INT_PTR CALLBACK MainDlgProc( HWND,UINT,WPARAM,LPARAM );
INT_PTR CALLBACK DSoundEnumCallback( GUID*,LPSTR, LPSTR,VOID* );
HRESULT OnInitDialog( HWND );
HRESULT InitDirectSound( HWND );
HRESULT FreeDirectSound();
#define SAFE_DELETE(p) { if(p) { delete (p); (p)=NULL; } }
#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } }
LPDIRECTSOUND8 g_pDS = NULL; //用來存放IDirectSound8 interface地址
LPDIRECTSOUNDCAPTURE8 g_pDSCapture = NULL; //用來存放IDirectSoundCapture8 interface地址
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR pszCmdLine, int iCmdShow)
{
//初始化COM, 可參考DirectX開發文檔中創建COM對象部分(Creating a COM Object)
CoInitialize( NULL );
// Display the main dialog box.
DialogBox( hInstance, MAKEINTRESOURCE(IDD_MAIN), NULL, MainDlgProc );
//釋放COM
CoUninitialize();
return TRUE;
}
//主窗口回調函數
INT_PTR CALLBACK MainDlgProc( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam )
{
HRESULT hr;
switch( msg )
{
case WM_INITDIALOG:
if( FAILED( hr = OnInitDialog( hDlg ) ) )
{
DXTRACE_ERR_MSGBOX( TEXT("OnInitDialog"), hr );
MessageBox( hDlg, "枚舉DirectSound設備錯誤,程序退出.", "EnumDevices", MB_OK | MB_ICONERROR );
EndDialog( hDlg, IDABORT );
}
break;
case WM_COMMAND:
switch( LOWORD(wParam) )
{
case IDC_BUTTON_CREATE:
//嘗試創建
if( SUCCEEDED( hr = InitDirectSound( hDlg ) ) )
MessageBox( hDlg, TEXT("創建DirectSound interface成功."), TEXT("EnumDevices"), MB_OK );
else
{
DXTRACE_ERR_MSGBOX( TEXT("InitDirectSound"), hr );
MessageBox( hDlg, TEXT("創建DirectSound interface失敗."), TEXT("EnumDevices"), MB_OK | MB_ICONERROR );
}
break;
case IDOK:
EndDialog( hDlg, IDCANCEL );
break;
default:
return FALSE;
}
break;
case WM_DESTROY:
FreeDirectSound(); //不要忘記釋放設備
break;
default:
return FALSE;
}
return TRUE;
}
//初始化窗體
HRESULT OnInitDialog( HWND hDlg )
{
HRESULT hr;
//枚舉sound devices並添加到組合框中
HWND hSoundDeviceCombo = GetDlgItem( hDlg, IDC_COMBO_SOUND_DEVICE );
if( FAILED( hr = DirectSoundEnumerate( (LPDSENUMCALLBACK)DSoundEnumCallback, (VOID*)hSoundDeviceCombo ) ) )
return DXTRACE_ERR_MSGBOX( TEXT("DirectSoundEnumerate"), hr );
//枚舉capture devices並添加到組合框中
HWND hCaptureDeviceCombo = GetDlgItem( hDlg, IDC_COMBO_CAPTURE_DEVICE );
if( FAILED( hr = DirectSoundCaptureEnumerate( (LPDSENUMCALLBACK)DSoundEnumCallback, (VOID*)hCaptureDeviceCombo ) ) )
return DXTRACE_ERR_MSGBOX( TEXT("DirectSoundCaptureEnumerate"), hr );
//選中組合框中的第一個設備
SendMessage( hSoundDeviceCombo, CB_SETCURSEL, 0, 0 );
SendMessage( hCaptureDeviceCombo, CB_SETCURSEL, 0, 0 );
return S_OK;
}
//供枚舉函數使用的回調函數
INT_PTR CALLBACK DSoundEnumCallback( GUID* pGUID, LPSTR strDesc, LPSTR strDrvName, VOID* pContext )
{
//注意定義爲靜態變量
static GUID AudioDriverGUIDs[20]; //預留20個設備的存儲空間
static DWORD dwAudioDriverIndex = 0;
GUID* pTemp = NULL;
if( pGUID )
{
if( dwAudioDriverIndex >= 20 )
return TRUE;
pTemp = &AudioDriverGUIDs[dwAudioDriverIndex++];
memcpy( pTemp, pGUID, sizeof(GUID) );
}
HWND hSoundDeviceCombo = (HWND)pContext;
//把設備名稱添加到組合框中
SendMessage( hSoundDeviceCombo, CB_ADDSTRING, 0, (LPARAM)(LPCTSTR)strDesc );
//獲取當前設備名稱在組合框中的索引值
int nIndex = (int)SendMessage( hSoundDeviceCombo, CB_FINDSTRING, 0, (LPARAM) (LPCTSTR) strDesc );
//將存儲在AudioDriverGUIDs設備數組中的GUID保存到對應項中
SendMessage( hSoundDeviceCombo, CB_SETITEMDATA, nIndex, (LPARAM) pTemp );
return TRUE;
}
//創建IDirectSound
HRESULT InitDirectSound( HWND hDlg )
{
HRESULT hr;
//首先釋放當前可能使用的DirectSound對象
FreeDirectSound();
HWND hSoundDeviceCombo = GetDlgItem( hDlg, IDC_COMBO_SOUND_DEVICE );
HWND hCaptureDeviceCombo = GetDlgItem( hDlg, IDC_COMBO_CAPTURE_DEVICE );
int nSoundIndex = (int)SendMessage( hSoundDeviceCombo, CB_GETCURSEL, 0, 0 );
int nCaptureIndex = (int)SendMessage( hCaptureDeviceCombo, CB_GETCURSEL, 0, 0 );
//獲取當前選擇項所對應的GUID數據
GUID* pSoundGUID = (GUID*) SendMessage( hSoundDeviceCombo, CB_GETITEMDATA, nSoundIndex, 0 );
GUID* pCaptureGUID = (GUID*) SendMessage( hCaptureDeviceCombo, CB_GETITEMDATA, nCaptureIndex, 0 );
//使用所選設備創建IDirectSound
if( FAILED( hr = DirectSoundCreate8( pSoundGUID, &g_pDS, NULL ) ) )
return DXTRACE_ERR_MSGBOX( TEXT("DirectSoundCreate"), hr );
//作爲一個示例,我們嘗試創建後馬上釋放掉.
SAFE_RELEASE( g_pDS );
//使用所選設備創建IDirectSoundCapture
if( FAILED( hr = DirectSoundCaptureCreate8( pCaptureGUID, &g_pDSCapture, NULL ) ) )
return DXTRACE_ERR_MSGBOX( TEXT("DirectSoundCaptureCreate"), hr );
//釋放
SAFE_RELEASE( g_pDSCapture );
return S_OK;
}
//釋放對象
HRESULT FreeDirectSound()
{
SAFE_RELEASE( g_pDSCapture );
SAFE_RELEASE( g_pDS );
return S_OK;
}