Handmade Hero»Forums»Code
wesley
4 posts
[Day 008] Problem with IDirectSound8::Lock not assigning the second region a pointer
Just started these vids and I gotta say they're pretty dope. I'm running into issues in episode 8, where I think I forgot something or did something wrong. The issue being that the direct sound stuff where the IDirectSound8::Lock function is not returning a pointer into the second region and will give me a violation error. Been banging my head against it pretty hard and I don't know what I did wrong. If anybody could take a look I would much appreciate it.

My Init
 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
internal void win32InitDSound(HWND Window, int32_t BufferSize, int32_t SamplesPerSecond)
{
    // Load Library
    HMODULE DSoundLibrary = LoadLibrary("dsound.dll");
    if (DSoundLibrary){
        // Direct Sound Object
        direct_sound_create *DirectSoundCreate = (direct_sound_create *)
            GetProcAddress(DSoundLibrary, "DirectSoundCreate");
        LPDIRECTSOUND DirectSound;   
        if(DirectSoundCreate && SUCCEEDED(DirectSoundCreate(0, &DirectSound, 0)) )
        {
            WAVEFORMATEX WaveFormat = {};
            WaveFormat.wFormatTag = WAVE_FORMAT_PCM ;
            WaveFormat.nChannels = 2;
            WaveFormat.nSamplesPerSec = SamplesPerSecond;
            WaveFormat.wBitsPerSample = 16;
            WaveFormat.nBlockAlign = (WaveFormat.nChannels * WaveFormat.wBitsPerSample) / 8;
            WaveFormat.nAvgBytesPerSec = WaveFormat.nSamplesPerSec * WaveFormat.nBlockAlign; 
            WaveFormat.cbSize = 0;

            // create primary buffer
            if ( SUCCEEDED(DirectSound->SetCooperativeLevel(Window, DSSCL_PRIORITY)) )
            {
                DSBUFFERDESC BufferDescription = {};
                BufferDescription.dwSize = sizeof(BufferDescription);
                BufferDescription.dwFlags = DSBCAPS_PRIMARYBUFFER;

                LPDIRECTSOUNDBUFFER PrimaryBuffer;
                if(SUCCEEDED(DirectSound->CreateSoundBuffer(&BufferDescription, &PrimaryBuffer, 0)) )
                {
                    if(SUCCEEDED(PrimaryBuffer->SetFormat(&WaveFormat)))
                    {
                        OutputDebugStringA("Primary Buffer format set. \n");
                    }
                    else
                    {
                        // TODO: Logging
                    }
                }
                else
                {
                    // TODO: Logging
                }
            }
            else
            {
                // TODO: Logging
            }

            // create secondary buffer
            DSBUFFERDESC BufferDescription = {};
            BufferDescription.dwSize = sizeof(BufferDescription);
            BufferDescription.dwFlags = 0;
            BufferDescription.dwBufferBytes = BufferSize;
            BufferDescription.lpwfxFormat = &WaveFormat;

            HRESULT Err = DirectSound->CreateSoundBuffer(&BufferDescription, &GlobalSecondaryBuffer, 0);

            if(SUCCEEDED(Err) )
            {
                OutputDebugStringA("Secondary Buffer Created!\n");
            }
            
            
        }
        else
        {
            // TODO: Logging
        }
    }   
}


My Variables
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
 HDC DeviceContext = GetDC(Window);
           
            // graphics
            int XOffset = 0;
            int YOffset = 0;
            
            // sound
            int samplesPerSecond = 48000;
            int Hz = 256;
            uint32_t RunningSampleIndex = 0;
            int SquareWavePeriod = samplesPerSecond/Hz;
            int HalfSquareWavePeriod = SquareWavePeriod/2;
            int BytesPerSample = sizeof(int16_t)* 2;
            int SecondaryBufferSize = samplesPerSecond*BytesPerSample;


My Test Code
 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
                DWORD PlayCursor;
                DWORD WriteCursor;
                if(SUCCEEDED(GlobalSecondaryBuffer->GetCurrentPosition( &PlayCursor, &WriteCursor) ))
                {
                    DWORD ByteToLock = RunningSampleIndex*BytesPerSample % SecondaryBufferSize;
                    DWORD BytesToWrite;
                    if(ByteToLock > PlayCursor)
                    {
                        ByteToLock = (SecondaryBufferSize - ByteToLock);
                        BytesToWrite += PlayCursor;
                    }else
                    {
                        BytesToWrite = PlayCursor - ByteToLock;
                    }

                    VOID *Region1;
                    DWORD Region1Size;
                    VOID *Region2;
                    DWORD Region2Size;

                    if(SUCCEEDED( GlobalSecondaryBuffer->Lock(ByteToLock, BytesToWrite,
                                                         &Region1, &Region1Size,
                                                         &Region2, &Region2Size,
                                                         0)))
                    {

                        int16_t *SampleOut = (int16_t *)Region1;
                        DWORD Region1SampleCount = Region1Size/BytesPerSample;
                        for(DWORD SampleIndex = 0; SampleIndex < Region1SampleCount; ++SampleIndex)
                        {
                            
                            int16_t SampleValue = ( (RunningSampleIndex / HalfSquareWavePeriod) % 2 ) ? 6000 : -6000;
                            *SampleOut++ = SampleValue;
                            *SampleOut++ = SampleValue;
                            ++RunningSampleIndex;
                            
                        }

                        *SampleOut = (int16_t *)Region2;
                        DWORD Region2SampleCount = Region2Size/BytesPerSample;
                        for(DWORD SampleIndex = 0; SampleIndex < Region1SampleCount; ++SampleIndex)
                        {
                            
                            int16_t SampleValue = ( (RunningSampleIndex / HalfSquareWavePeriod) % 2 ) ? 6000 : -6000;
                            *SampleOut++ = SampleValue;
                            *SampleOut++ = SampleValue;
                            ++RunningSampleIndex;
                            
                        }
                        GlobalSecondaryBuffer->Unlock(Region1, Region1Size, Region2, Region2Size);
                    }

4 posts
[Day 008] Problem with IDirectSound8::Lock not assigning the second region a pointer
On line 39 of your Test Code your SampleOut is already initialized as a pointer, you only need to assign the Region2 value to it.

1
SampleOut = (int16_t *)Region2;


I think that should fix your problem.
wesley
4 posts
[Day 008] Problem with IDirectSound8::Lock not assigning the second region a pointer
Edited by wesley on Reason: Clarity
Thanks for the reply! Unfortunately this did not resolve my error. The error that I'm getting when running from Visual Studio's debugger :
Exception thrown at 0x000000013F4B6C15 in handmade.exe: 0xC0000005: Access violation writing location 0x0000000000000000.

Upon breaking from the info window the IDE goes to line 45 in the test code:
1
2
3
4
5
6
7
8
9
{
                            
                            int16_t SampleValue = ( (RunningSampleIndex / HalfSquareWavePeriod) % 2 ) ? 6000 : -6000;
                            // debugger stops here
                            *SampleOut++ = SampleValue;
                            *SampleOut++ = SampleValue;
                            ++RunningSampleIndex;
                            
                        }


The SampleOut variable has a memory code of 0x0000000000000000

I'm thoroughly stumped.
Mārtiņš Možeiko
2559 posts / 2 projects
[Day 008] Problem with IDirectSound8::Lock not assigning the second region a pointer
Edited by Mārtiņš Možeiko on
You need to change Region1SampleCount to Region2SampleCount in second for loop. I'm guessing that there is no second region and DirectSound simply returned NULL for Region2 and 0 for Region2SampleCount. But your loop is trying to write Region1SampleCount samples to region2.
wesley
4 posts
[Day 008] Problem with IDirectSound8::Lock not assigning the second region a pointer
Wow, such stupid over sights on my part! Thanks for catching my bugs people. This indeed fixed my issue. 10/10 would buy you both coffee.