#include #include #include /* —vƒŠƒ“ƒN dsound.lib dxguid.lib */ #define RELEASE(x) if(x){x->Release();x=NULL;} #define SCREEN_WIDTH 640 #define SCREEN_HEIGHT 480 HINSTANCE g_Inst; HWND g_hWnd; LPCSTR szAppName = "DirectSound"; LRESULT CALLBACK WndProc(HWND hWnd,UINT msg,UINT wParam,LONG lParam); DWORD g_dwBufferSize = 0; DWORD g_dwNotifyThreadID = 0; HANDLE g_hNotifyThread = NULL; HANDLE g_hNotificationEvent = NULL; LPDIRECTSOUND8 pDS = NULL; LPDIRECTSOUNDBUFFER pDSBPrimary = NULL; LPDIRECTSOUNDBUFFER pDSBSecondry = NULL; LPDIRECTSOUNDNOTIFY pDSNotify = NULL; DWORD ReadWave(LPDIRECTSOUNDBUFFER pDSBuffer, DWORD dwSize){ static int pos = 0; HANDLE hFile; VOID *lpBuffer; DWORD buffersize; DWORD filesize; hFile = CreateFile("sample.nms", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); int end_pos = (GetFileSize(hFile, NULL) - sizeof(DWORD)) / dwSize; if(end_pos - pos < 0){ CloseHandle(hFile); return 0; } SetFilePointer(hFile, sizeof(DWORD) + pos * dwSize, NULL, FILE_BEGIN); if(pos % 2 == 0){ pDSBuffer->Lock(0, dwSize, &lpBuffer, &buffersize, NULL, NULL, 0L); } else{ pDSBuffer->Lock(dwSize, dwSize, &lpBuffer, &buffersize, NULL, NULL, 0L); } ReadFile(hFile, lpBuffer, dwSize, &filesize, NULL); pDSBuffer->Unlock(lpBuffer, buffersize, NULL, 0); CloseHandle(hFile); pos++; return 1; } DWORD WINAPI NotificationProc(LPVOID lpParameter){ MSG msg; HWND hWnd = (HWND)lpParameter; BOOL bDone = FALSE; DWORD dwResult; while(!bDone){ dwResult = MsgWaitForMultipleObjects(1, &g_hNotificationEvent, FALSE, INFINITE, QS_ALLEVENTS); switch(dwResult) { case WAIT_OBJECT_0 + 0: dwResult = ReadWave(pDSBSecondry, g_dwBufferSize >> 1); if(dwResult == 0)bDone = TRUE; break; case WAIT_OBJECT_0 + 1: while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)){ if(msg.message == WM_QUIT){ bDone = TRUE; } } break; } } pDSBSecondry->Stop(); return 0; } int initDs(HWND hWnd){ HRESULT hr; hr = DirectSoundCreate8(NULL, &pDS, NULL); if(hr != DS_OK)return 0; hr = pDS->SetCooperativeLevel(hWnd, DSSCL_PRIORITY); if(hr != DS_OK)return 0; DSBUFFERDESC dsbd; ZeroMemory(&dsbd, sizeof(DSBUFFERDESC)); dsbd.dwSize = sizeof(DSBUFFERDESC); dsbd.dwFlags = DSBCAPS_PRIMARYBUFFER; dsbd.dwBufferBytes = 0; hr = pDS->CreateSoundBuffer(&dsbd, &pDSBPrimary, NULL); if(hr != DS_OK)return 0; WAVEFORMATEX wfx; ZeroMemory(&wfx, sizeof(WAVEFORMATEX)); wfx.wFormatTag = (WORD)WAVE_FORMAT_PCM; wfx.nChannels = (WORD)2; wfx.nSamplesPerSec = (DWORD)44100; wfx.wBitsPerSample = (WORD)16; wfx.nBlockAlign = (WORD)(wfx.wBitsPerSample / 8 * wfx.nChannels); wfx.nAvgBytesPerSec = (DWORD)(wfx.nSamplesPerSec * wfx.nBlockAlign); hr = pDSBPrimary->SetFormat(&wfx); if(hr != DS_OK)return 0; WAVEFORMATEX wfx2; ZeroMemory(&wfx2, sizeof(WAVEFORMATEX)); wfx2.wFormatTag = (WORD)WAVE_FORMAT_PCM; wfx2.nChannels = (WORD)2; wfx2.nSamplesPerSec = (DWORD)44100; wfx2.wBitsPerSample = (WORD)16; wfx2.nBlockAlign = (WORD)(wfx2.wBitsPerSample / 8 * wfx2.nChannels); wfx2.nAvgBytesPerSec = (DWORD)(wfx2.nSamplesPerSec * wfx2.nBlockAlign); DSBUFFERDESC dsbd2; ZeroMemory(&dsbd2, sizeof(DSBUFFERDESC)); dsbd2.dwSize = sizeof(DSBUFFERDESC); dsbd2.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRLPOSITIONNOTIFY | DSBCAPS_GLOBALFOCUS; dsbd2.dwBufferBytes = wfx2.nAvgBytesPerSec * 2; // 2 sec dsbd2.lpwfxFormat = &wfx2; hr = pDS->CreateSoundBuffer(&dsbd2, &pDSBSecondry, NULL); if(hr != DS_OK)return 0; g_hNotificationEvent = CreateEvent(NULL, FALSE, FALSE, NULL); if(g_hNotificationEvent == NULL)return 0; g_hNotifyThread = CreateThread(NULL, 0, NotificationProc, hWnd, 0, &g_dwNotifyThreadID); if(g_hNotifyThread == NULL)return 0; g_dwBufferSize = dsbd2.dwBufferBytes; DSBPOSITIONNOTIFY aPosNotify[2]; aPosNotify[0].dwOffset = g_dwBufferSize / 2 - 1; aPosNotify[0].hEventNotify = g_hNotificationEvent; aPosNotify[1].dwOffset = g_dwBufferSize - 1; aPosNotify[1].hEventNotify = g_hNotificationEvent; hr = pDSBSecondry->QueryInterface(IID_IDirectSoundNotify, (VOID**)&pDSNotify); if(hr != DS_OK)return 0; hr = pDSNotify->SetNotificationPositions(2, aPosNotify); if(hr != DS_OK)return 0; ReadWave(pDSBSecondry, g_dwBufferSize >> 1); ReadWave(pDSBSecondry, g_dwBufferSize >> 1); pDSBSecondry->Play(0, 0, DSBPLAY_LOOPING); return 1; } void deinitDs(void){ pDSBSecondry->Stop(); RELEASE(pDSNotify); RELEASE(pDSBSecondry); RELEASE(pDSBPrimary); RELEASE(pDS); } LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, UINT wParam, LONG lParam){ switch(msg){ case WM_KEYDOWN: switch(wParam){ case VK_ESCAPE: PostMessage(hWnd, WM_CLOSE, 0, 0); break; default: break; } break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hWnd, msg, wParam, lParam); } return 0L; } int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nCmdShow){ int result; int cx, cy; WNDCLASS wc; MSG msg; g_Inst=hInst; if(!hPrevInst){ wc.lpszClassName = "DirectSound"; wc.lpfnWndProc = WndProc; wc.style = CS_HREDRAW | CS_VREDRAW; wc.hInstance = hInst; wc.hIcon = NULL; wc.hCursor = LoadCursor(NULL,IDC_ARROW); wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); wc.lpszMenuName = NULL; wc.cbClsExtra = 0; wc.cbWndExtra = 0; if(!RegisterClass(&wc)){ return 0; } } cx = SCREEN_WIDTH + GetSystemMetrics(SM_CXDLGFRAME) * 2; cy = SCREEN_HEIGHT + GetSystemMetrics(SM_CYDLGFRAME) * 2 + GetSystemMetrics(SM_CYCAPTION); g_hWnd = CreateWindowEx(0, szAppName, szAppName, WS_OVERLAPPED | WS_SYSMENU | WS_MINIMIZEBOX, CW_USEDEFAULT, CW_USEDEFAULT, cx, cy, (HWND)NULL, (HMENU)NULL, hInst, (LPSTR)NULL); ShowWindow(g_hWnd, nCmdShow); UpdateWindow(g_hWnd); result = initDs(g_hWnd); if(result == 0){ goto fin; } while(GetMessage(&msg, (HWND)NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } fin: deinitDs(); return msg.wParam; }