Handmade Hero » Forums » Code » [Day 008] Problem with IDirectSound8::Lock not assigning the second region a pointer
undeadasimov
wesley
3 posts
#12188 [Day 008] Problem with IDirectSound8::Lock not assigning the second region a pointer
2 weeks ago

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);
                    }

Stahlherz
4 posts
#12189 [Day 008] Problem with IDirectSound8::Lock not assigning the second region a pointer
2 weeks ago

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.
undeadasimov
wesley
3 posts
#12190 [Day 008] Problem with IDirectSound8::Lock not assigning the second region a pointer
2 weeks ago Edited by wesley on June 11, 2017, 7:13 p.m. 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.
mmozeiko
Mārtiņš Možeiko
1349 posts
1 project
#12191 [Day 008] Problem with IDirectSound8::Lock not assigning the second region a pointer
2 weeks ago Edited by Mārtiņš Možeiko on June 11, 2017, 8:17 p.m.

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.
undeadasimov
wesley
3 posts
#12192 [Day 008] Problem with IDirectSound8::Lock not assigning the second region a pointer
2 weeks ago

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.