2016-01-19 116 views
0

我已經實現了基於tutorial的直接聲音類,但在測試時遇到問題。我已經將錯誤追溯到IDirectSound8 :: SetCooperativeLevel,它返回一個錯誤。IDirectSound8 SetCooperativeLevel返回不正確的參數

這裏是我的DirectSound的初始化方法的snipit

HRESULT r; 
DSBUFFERDESC bufferDesc; 
WAVEFORMATEX wavFormat; 

r = DirectSoundCreate8(NULL, &DSound, NULL); 
if (FAILED(r)) 
{ 
    _com_error error(r); 
    LPCTSTR errText = error.ErrorMessage(); 
    OutputDebugString(errText); 
    return false; 
} 
OutputDebugStringA("\nCOMPLETE: DSound Stage 1 "); 

r = DSound->SetCooperativeLevel(hwnd, DSSCL_PRIORITY); 
if (FAILED(r)) 
{ 
    _com_error error(r); 
    LPCTSTR errText = error.ErrorMessage(); 
    OutputDebugString(errText); 
    return false; 
} 
OutputDebugStringA("\nCOMPLETE: DSound Stage 2 "); 

的程序得到過去我的「DSOUND第1階段」,但在r = DSound->SetCooperativeLevel(hwnd, DSSCL_PRIORITY);聲明失敗「的參數不正確。」

在這一點上,我不知道爲什麼這個錯誤發生或如何解決它。我認爲問題在於我傳入的HWND參數,但是我不知道是否有問題。

這個問題可能是由運行時沒有創建物理窗口引起的嗎?我的意思是,當我編譯這個項目時,沒有生成窗口 - 雖然看起來好像應該有。

這裏是Main.cpp,我發送給我的音頻類的HWND被設置,值得注意的是我沒有寫這個文件,也沒有完全理解它是否應該創建一個窗口。

#include <windows.h> 
#include <windowsx.h> 

#include "RenderEngine.h" 
#include "Timer.h" 
#include "Audio.h" 

//WindowProc function prototype 
LRESULT CALLBACK WindowProc(HWND hWnd, 
         UINT message, 
         WPARAM wParam, 
         LPARAM lParam); 

int WINAPI WinMain(HINSTANCE hInstance,  //Handle to and Instance, This is how windows keeps track of which program is which. 
       HINSTANCE hPrevInstance, //Handle to the Previous Instance, this is a backwards compatibility requirement 
       LPSTR lpCmdLine,   //This is a Long Pointer to a string that contains the command line creating the application. 
       int nShowCmd)    //This determines what the window will look like. 
{ 
//First we create our Handle for the Window 
HWND hWnd; 
//Next we create our WindowClass Struct 
WNDCLASSEX wc; 
/////////////////////////////////////////////////////////////// 
//Create our Render Engine Class 
Timer GameTimer; 
RenderEngine Renderer; 
/////////////////////////////////////////////////////////////// 
//Create our Audio Class 
Audio* audio; 
/////////////////////////////////////////////////////////////// 

//Ensure the class is empty for use... 
ZeroMemory(&wc, sizeof(WNDCLASSEX)); 

//Initialize the Struct 
wc.cbSize = sizeof(WNDCLASSEX); 
wc.style = CS_HREDRAW | CS_VREDRAW; 
wc.lpfnWndProc = WindowProc; 
wc.hInstance = hInstance; 
wc.hCursor = LoadCursor(NULL, IDC_ARROW); 
wc.hbrBackground = (HBRUSH)COLOR_WINDOW; 
wc.lpszClassName = L"WIndowClass1"; 

//Regist the Window Class 
RegisterClassEx(&wc); 

//Create the windows and use the result as the handle 
hWnd = CreateWindowEx(NULL, 
         L"GSP420 WindowClass", //Name of the Window Class 
         L"GSP420 Project",  //Title of the Window 
         WS_OVERLAPPEDWINDOW,  //Window style 
         300,      //x-position of the Window 
         300,      //y-position of the Window 
         SCREENWIDTH,    //Width of the Window 
         SCREENHEIGHT,    //Heigt of the Window 
         NULL,      //There is no parent window 
         NULL,      //No menus are being used 
         hInstance,    //The application handle 
         NULL);     //We're not using Multiple-Windows 

//Display the Window 
ShowWindow(hWnd, nShowCmd); 

//////////////////////////////////////////////////////////////////// 
//Setup and Initialize Direct3D 
Renderer.initD3D(hWnd); 
//////////////////////////////////////////////////////////////////// 
//Setup and Initialize DirectSound 
OutputDebugStringA("BEGIN: AudioInit"); 
audio = new Audio; 
audio->AudioInit(hWnd); 
OutputDebugStringA("\nCOMPLETE: AudioInit\n"); 
//////////////////////////////////////////////////////////////////// 

//Enter the main loop 

//Windows Event Message Struct 
MSG msg; 

//Enter our Loop 
while (TRUE) 
{ 
    while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) 
    { 
     //Translate keystrokes into the correct format 
     TranslateMessage(&msg); 

     //Send the messages to WindowProc 
     DispatchMessage(&msg); 
    } 

    //If the message is WM_QUIT, exit the loop 
    if (msg.message == WM_QUIT) 
     break; 

    //////////////////////////////////// 
    ////////RUN OUR GAME CODE HERE////// 
    //////////////////////////////////// 
    GameTimer.calculateTime(); 

    Renderer.renderFrame(); 
    //////////////////////////////////// 
    ////////RUN OUR GAME CODE HERE////// 
    //////////////////////////////////// 
} 
//////////////////////////////////////////////////////// 
//Clean up DirectX and COM 
Renderer.cleanD3D(); 

//Return this part of the WM_QUIT message to Windows 
return msg.wParam; 
} 

//Main Message Handler for the Program 
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 
{ 
//Sort through and find the code to execute 
switch (message) 
{ 
    //This message is read when the window is closed 
    case WM_DESTROY: 
    { 
     //Close the application 
     PostQuitMessage(0); 
     return 0; 
    }break; 
} 

//Handle any messages the switch statement didn't 
return DefWindowProc(hWnd, message, wParam, lParam); 
} 

以供參考整個InitDSound方法

bool Audio::InitDSound(HWND hwnd) 
{ 
HRESULT r;             // Create result variable 
DSBUFFERDESC bufferDesc; 
WAVEFORMATEX wavFormat; 

r = DirectSoundCreate8(NULL, &DSound, NULL);    // Initialize DSound 
if (FAILED(r))            // Check result, break if initialization failed 
{ 
    _com_error error(r); 
    LPCTSTR errText = error.ErrorMessage(); 
    OutputDebugString(errText); 
    return false; 
} 
OutputDebugStringA("\nCOMPLETE: DSound Stage 1 "); 

r = DSound->SetCooperativeLevel(hwnd, DSSCL_PRIORITY);  // No idea, allows the format of the primary buffer to be modified 
if (FAILED(r))            // Check result, break if that thing didnt work 
{ 
    _com_error error(r); 
    LPCTSTR errText = error.ErrorMessage(); 
    OutputDebugString(errText); 
    return false; 
} 
OutputDebugStringA("\nCOMPLETE: DSound Stage 2 "); 

////////////////////////////////// 
// Primary Buffer Descritpion 
////////////////////////////////// 
bufferDesc.dwSize = sizeof(DSBUFFERDESC); 
bufferDesc.dwFlags = DSBCAPS_PRIMARYBUFFER | DSBCAPS_CTRLVOLUME; 
bufferDesc.dwBufferBytes = 0; 
bufferDesc.dwReserved = 0; 
bufferDesc.lpwfxFormat = NULL; 
bufferDesc.guid3DAlgorithm = GUID_NULL; 

r = DSound->CreateSoundBuffer(&bufferDesc, &pBuffer, NULL); // Get control of the primary sound buffer on the sounde device 
if (FAILED(r))            // Check result, break if that failed 
{ 
    _com_error error(r); 
    LPCTSTR errText = error.ErrorMessage(); 
    OutputDebugString(errText); 
    return false; 
} 
OutputDebugStringA("\nCOMPLETE: DSound Stage 3 "); 

////////////////////////////////// 
// Primary Buffer Format 
// (WAV @44,100 16bit stereo) 
////////////////////////////////// 
wavFormat.wFormatTag = WAVE_FORMAT_PCM; 
wavFormat.nSamplesPerSec = 44100; 
wavFormat.wBitsPerSample = 16; 
wavFormat.nChannels = 2; 
wavFormat.nBlockAlign = (wavFormat.wBitsPerSample/8) * wavFormat.nChannels; 
wavFormat.nAvgBytesPerSec = wavFormat.nSamplesPerSec * wavFormat.nBlockAlign; 
wavFormat.cbSize = 0; 

r = pBuffer->SetFormat(&wavFormat);       // Set the primary buffer format 
if (FAILED(r))            // Check result, break if that failed 
{ 
    _com_error error(r); 
    LPCTSTR errText = error.ErrorMessage(); 
    OutputDebugString(errText); 
    return false; 
} 
OutputDebugStringA("\nCOMPLETE: DSound Stage 4 "); 

return true; 
} 

回答

0

在Windows Vista或更高版本,有沒有無論如何主緩衝區,它的通過WASAPI所有效仿。無論如何,驅動程序會確定輸出速率,並始終將其轉換爲float值。你應該堅持使用DSSCL_NORMAL,因爲它並不意味着什麼,主緩衝區的格式是不相關的。

除非您的目標是Windows XP,否則您應該避免使用16年未更新的DirectSound。查看XAudio2或第三方音頻引擎,如FMOD,Wwise,MSS,OpenAL等,所有這些引擎都實現了自己的混音器,並使用WASAPI進行最終輸出。