Day 9 - Directsound clicking issue - help!

Hi all,

After watching Day 9 I decided to modify Casey's sine wave generator so that it plays a tone continuously as long as the F key is held down. Like a synthesizer, the sound will stop playing when F is released. I got it working, however there is a weird issue. When F is first pressed it makes a brief click sound after about 0.5 secs, but after that there is no more clicking. The click occurs only the first time F is pressed, on successive presses there is no click! I have no idea how to troubleshoot this but I'd love to know what might be causing the click!

I have posted the entire win32handmade.cpp file to gist.github.com:

https://gist.github.com/mrennix/60384f0e86a655ba8180fa8a6c7cb3ca

If someone could download and compile the file and test it, that would be awesome. It compiles cleanly on /W4.
I have also made these other changes to Casey's code in case you are wondering:

1. I use Unicode (defines at top of file, so some lib calls use W instead of A versions).

2. For Directsound I don't stream, I just fill the buffer with 1 second of sine wave data and then play from the beginning each time F is pressed. The buffer is not modified during the game loop. I did this to simplify my understanding of how Directsound works.

3. I added a simple log file that logs to a file in the current directory, showing if Xinput and Directsound initialized ok.

Thanks guys!



Edited by 20thCB on
The problem is that holding a key down will continuously send a WM_KEYDOWN message and you end up restarting the sound. The first time you press the key, a message is sent, then there is a short wait, then the key down message will repeat. It's like when you hold a key down in a text editor.

So in your case you need to know if the sound is already playing to avoid setting the play cursor to zero on every key down message. Here is an example.
 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
static bool playing = false;

...

case WM_SYSKEYDOWN:
case WM_SYSKEYUP:
case WM_KEYDOWN:
{
    uint64 vk_code = wParam;
    if ( !playing && vk_code == 'F')
    {
        playing = true;
        GlobalSecondaryBuffer->SetCurrentPosition(0);
                
        if ( GlobalSecondaryBuffer->Play(0, 0, DSBPLAY_LOOPING) == DS_OK)
        {      
            OutputDebugStringA( "play\n" );
        }
    }
    if (vk_code == 'G')
    {
        GlobalSecondaryBuffer->Stop();
        playing = false;
    }
} break;

case WM_KEYUP:
{
    uint64 vk_code = wParam;
    if (vk_code == 'F')
    {
        GlobalSecondaryBuffer->Stop();
        playing = false;
    }
} break;


Note that on my machine, each time the sound starts and stops (except the first time) I ear a small click. Removing the GlobalSecondaryBuffer->SetCurrentPosition(0); line seems to fix the problem.
You can also check if key was down previously to detect repeated key messages. If I remember correctly that is what HH is doing:
1
2
3
4
5
6
7
8
9
case WM_SYSKEYDOWN:
case WM_SYSKEYUP:
case WM_KEYDOWN:
{
    uint64 vk_code = wParam;
    bool was_down = ((lparam >> 30) & 1) != 0;
    if ( !was_down && vk_code == 'F')
    {
        ...
mrmixer - thank you so much, that's perfect! I wonder why removing SetCurrentPosition(0) removed the clicks after the first play?
I don't know. What follows is a complete guess, don't assume it's correct:

Setting the cursor just before playing may not leave enough time for the primary buffer to synchronize with the secondary buffer. Depending on when you do the SetCurrentPosition call, the clicking can be heard or not. If I place the call just before the Stop call then there is no clicking, if I put it just after there is a click. So maybe the position is only updated when the buffer is playing. So it sounds like (again it's a guess) that DirectSound plays the last byte it was playing before it stopped and then play from the new position.

Note that since Windows Vista DirectSound is emulated. You can look at mmozeiko's example for using WASAPI for a better sound system.

Edited by Simon Anciaux on Reason: Typo