Although this stream started in quite few years back, it's now only that I've discovered this gem and
started following along. I'm typing my own code following the instructions from Casey and I'm unable to completely
understand the circular buffer code for dsound.
So in the following code snippet from out WinMain function we're filling the complete buffer and playing it before calling the GetCurrentPosition(). My question is why do we have to calculate the play cursor/ write cursor and fill the buffer again if we filled full buffer previously and started playing?
Although if I comment the second win32FillSoundBuffer line inside the if condition, I notice the skip in the sound being played and I'm not able to understand why given that the buffer was filled completely before.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 | if(windowHandle) { //NOTE: Get one DC and use it forever HDC DeviceContext = GetDC(windowHandle); //Note: Graphics test int XOffset = 0; int YOffset = 0; SoundOutput.SamplesPerSecond = 48000; SoundOutput.ToneHz = 256; SoundOutput.ToneVol = 3000; SoundOutput.RunningSampleIndex=0; SoundOutput.WavePeriod = SoundOutput.SamplesPerSecond/SoundOutput.ToneHz; //SoundOutput.HalfWavePeriod = WavePeriod/2; SoundOutput.BytesPerSample = sizeof(int16)*2; SoundOutput.SecondaryBufferSize = SoundOutput.SamplesPerSecond*SoundOutput.BytesPerSample; SoundOutput.LatencySampleCount = SoundOutput.SamplesPerSecond / 15; //Want to be head of play cursor by 1/60th of a sec //TODO Enable win32InitDSound(windowHandle, SoundOutput.SamplesPerSecond, SoundOutput.SecondaryBufferSize); win32FillSoundBuffer(&SoundOutput, 0, SoundOutput.LatencySampleCount*SoundOutput.BytesPerSample); SecondaryBuffer->Play(0, 0, DSBPLAY_LOOPING); Running = true; while(Running) { MSG Message; while(PeekMessage(&Message, NULL, 0, 0, PM_REMOVE)) { if(Message.message == WM_QUIT) { Running = false; } TranslateMessage(&Message); DispatchMessageA(&Message); } //TODO: should we poll this more frequently? for (DWORD ControllerIndex=0; ControllerIndex< XUSER_MAX_COUNT; ControllerIndex++ ) { XINPUT_STATE ControllerState; if(XInputGetState(ControllerIndex, &ControllerState) == ERROR_SUCCESS) { //NOTE: this controller is plugged in XINPUT_GAMEPAD *Pad = &(ControllerState.Gamepad); bool Up = Pad->wButtons & XINPUT_GAMEPAD_DPAD_UP; bool Down = Pad->wButtons & XINPUT_GAMEPAD_DPAD_DOWN; bool Left = Pad->wButtons & XINPUT_GAMEPAD_DPAD_LEFT; bool Right = Pad->wButtons & XINPUT_GAMEPAD_DPAD_RIGHT; bool Start = Pad->wButtons & XINPUT_GAMEPAD_START; bool Back = Pad->wButtons & XINPUT_GAMEPAD_BACK; bool LeftShoulder = Pad->wButtons & XINPUT_GAMEPAD_LEFT_SHOULDER; bool RightShoulder = Pad->wButtons & XINPUT_GAMEPAD_RIGHT_SHOULDER; bool AButton = Pad->wButtons & XINPUT_GAMEPAD_A; bool BButton = Pad->wButtons & XINPUT_GAMEPAD_B; bool XButton = Pad->wButtons & XINPUT_GAMEPAD_X; bool YButton = Pad->wButtons & XINPUT_GAMEPAD_Y; int16 StickX = Pad->sThumbLX; int16 StickY = Pad->sThumbLY; if(AButton) { ++YOffset; } } else { //The controller is not available. } } RenderWeirdGradient(&BackBuffer, XOffset,YOffset); DWORD PlayCursor; DWORD WriteCursor; if(SUCCEEDED(SecondaryBuffer->GetCurrentPosition( &PlayCursor, &WriteCursor))) { //TODO: Change this to lower latency offset from play cursor when we have sound effects. DWORD ByteToLock = (SoundOutput.RunningSampleIndex*SoundOutput.BytesPerSample) % SoundOutput.SecondaryBufferSize; DWORD TargetCursor = ((PlayCursor + (SoundOutput.LatencySampleCount*SoundOutput.BytesPerSample)) % SoundOutput.SecondaryBufferSize); DWORD BytesToWrite; if(ByteToLock > TargetCursor) { BytesToWrite = SoundOutput.SecondaryBufferSize - ByteToLock; BytesToWrite += TargetCursor; } else { BytesToWrite = TargetCursor - ByteToLock; } win32FillSoundBuffer(&SoundOutput, ByteToLock, BytesToWrite); } win32_Window_Dimensions Dimensions = GetWindowDimension(windowHandle); Win32DisplayBufferInWindow (&BackBuffer, DeviceContext, Dimensions.Width, Dimensions.Height); ++XOffset; } } |