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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127 | internal void
fillSoundBuffer(Sound_output *soundOutput, Game_sound_output *sourceBuffer,DWORD byteToLock,DWORD bytesToWrite)
{
VOID *region1;
DWORD region1Size;
VOID *region2;
DWORD region2Size;
gSecondaryBuffer->Lock(
byteToLock,
bytesToWrite,
®ion1,®ion1Size,
®ion2,®ion2Size,
DSBLOCK_FROMWRITECURSOR
);
s16 *sampleSource = sourceBuffer->samples;
s16 *samplesDest = (s16*)region1;
DWORD region1SampleCount = region1Size / 4;
for(DWORD sampleIndex = 0; sampleIndex < region1SampleCount; sampleIndex++)
{
*samplesDest++ = *sampleSource++;
*samplesDest++ = *sampleSource++;
soundOutput->runningSampleIndex++;
}
DWORD region2SampleCount = region2Size / 4;
samplesDest = (s16*)region2;
for(DWORD sampleIndex = 0; sampleIndex < region2SampleCount; sampleIndex++)
{
*samplesDest++ = *sampleSource++;
*samplesDest++ = *sampleSource++;
soundOutput->runningSampleIndex++;
}
gSecondaryBuffer->Unlock(region1, region1Size, region2, region2Size);
}
main()
{
Sound_output soundOutput;
soundOutput.samplesPerSecond = 44100;
soundOutput.secondaryBufferSize = soundOutput.samplesPerSecond * (sizeof(s16)*2);
soundOutput.hz = 256;
soundOutput.runningSampleIndex = 0;
soundOutput.wavePeriod = soundOutput.samplesPerSecond / soundOutput.hz;
soundOutput.latencyCount = 4*(soundOutput.samplesPerSecond / 60);
s16 *soundBuffer = (s16*)VirtualAlloc(0, soundOutput.secondaryBufferSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
clearSoundBuffer(&soundOutput);
gSecondaryBuffer->Play(0, 0,DSBPLAY_LOOPING);
while(gameIsRunning)
{
DWORD targetCursor = 0;
DWORD byteToLock = 0;
DWORD bytesToWrite = 0;
if(soundIsValid)
{
byteToLock = ((soundOutput.runningSampleIndex*4) % soundOutput.secondaryBufferSize);
targetCursor = ((lastPlayCursor + (soundOutput.latencyCount*4))
% soundOutput.secondaryBufferSize);
if(byteToLock > targetCursor)
{
bytesToWrite = (soundOutput.secondaryBufferSize - byteToLock);
bytesToWrite += targetCursor;
}
else
{
bytesToWrite = targetCursor - byteToLock;
}
}
Game_sound_output gameSoundOutput = {};
gameSoundOutput.samplesPerSec = 44100;
gameSoundOutput.samplesToOutput = bytesToWrite / 4;
gameSoundOutput.samples = soundBuffer;
gameUpdateAndRender(&gameFramebuffer, newInput, &gameMemory, &gameSoundOutput);
#if 1
if(soundIsValid)
{
#if DEBUG
DWORD playCursor;
DWORD writeCursor;
gSecondaryBuffer->GetCurrentPosition(&playCursor, &writeCursor);
char buffer[256];
_snprintf_s(buffer, sizeof(buffer),"LPC:%u BTL:%u TC:%u: BTW:%u PC:%u WC:%u\n",
lastPlayCursor, byteToLock, targetCursor, bytesToWrite, playCursor, writeCursor);
OutputDebugStringA(buffer);
#endif
fillSoundBuffer(&soundOutput, &gameSoundOutput,byteToLock, bytesToWrite);
}
#endif
DWORD playCursor;
DWORD writeCursor;
if(SUCCEEDED(gSecondaryBuffer->GetCurrentPosition(&playCursor, &writeCursor)))
{
lastPlayCursor = playCursor;
if(!soundIsValid)
{
soundOutput.runningSampleIndex = writeCursor / 4;
soundIsValid = true;
}
}
else
{
soundIsValid = false;
}
}
}
|