Wing Commander
Reconstructed Win32 source (1996)
Toggle main menu visibility
Loading...
Searching...
No Matches
mixer.cpp
Go to the documentation of this file.
1
/**
2
* @file
3
* @ingroup ixlib
4
* @brief DirectSound driver opening and the mixer service thread.
5
*
6
* Originally `D:\rnd\prj\ix\win95\dsp\mixer.cpp`, address range
7
* 445f60-44679f, recovered from the module's own assert `__FILE__` anchors.
8
*/
9
#include "
ix.h
"
10
#include <dsound.h>
11
#include <stdlib.h>
12
#include <string.h>
13
14
#pragma function(memset)
15
16
#define IX_MIXER_FILE "D:\\rnd\\prj\\ix\\win95\\dsp\\mixer.cpp"
17
18
extern
unsigned
int
dwSoundBufferSize
;
19
extern
unsigned
int
dwMixerWriteOffset
;
20
extern
HANDLE
hIxPlaybackThread
;
21
extern
HWND
hPlaybackWindow
;
22
extern
HANDLE
hAudioWakeEvent
;
23
extern
LPDIRECTSOUND
pDspDevice
;
24
extern
unsigned
int
dwDspFlags
;
25
extern
LPDIRECTSOUNDBUFFER
pMixerBuffer
;
26
extern
unsigned
int
dwDspTick
;
27
extern
LPDIRECTSOUNDBUFFER
pDspPrimaryBuffer
;
28
29
BOOL CALLBACK
ix_dsp_open_driver
(LPGUID guid, LPSTR description,
30
LPSTR module, LPVOID context);
31
32
/* Function start: 0x00445F60 */
/* source lines 46, 50, 60, 63, 81, 84, 96 */
33
DWORD WINAPI
ix_mixer_thread_proc
(
void
*parameter)
34
{
35
DSCAPS soundCaps;
36
PCMWAVEFORMAT outputFormat;
37
DSBUFFERDESC bufferDescriptor;
38
HRESULT resultCode;
39
DSBCAPS primaryCaps;
40
41
dwDspFlags
|= 4;
42
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
43
DirectSoundEnumerateA(
ix_dsp_open_driver
, 0);
44
if
((
dwDspFlags
& 0x10) == 0 &&
45
pDspDevice
== 0) {
46
ix_log_printf
(
"Warning [%s - %d]:\n"
,
IX_MIXER_FILE
, 46);
47
ix_log_printf
(
"Failed to find write primary driver, using secondary buffer"
);
48
dwDspFlags
|= 0x10;
49
DirectSoundEnumerateA(
ix_dsp_open_driver
, 0);
50
}
51
if
(
pDspDevice
== 0) {
52
ix_log_printf
(
"Fatal [%s - %d]:\n"
,
IX_MIXER_FILE
, 50);
53
ix_log_printf
(
"Failed to init directsound"
);
54
exit(-1);
55
}
56
57
memset(&soundCaps, 0, 0x60);
58
soundCaps.dwSize = 0x60;
59
pDspDevice
->GetCaps(&soundCaps);
60
if
((
dwDspFlags
& 0x10) == 0 &&
61
(soundCaps.dwFlags &
62
(DSCAPS_PRIMARY16BIT | DSCAPS_PRIMARYSTEREO)) !=
63
(DSCAPS_PRIMARY16BIT | DSCAPS_PRIMARYSTEREO)) {
64
ix_log_printf
(
"Warning [%s - %d]:\n"
,
IX_MIXER_FILE
, 60);
65
ix_log_printf
(
"sound driver doesn't support our primary buffer format, using secondary buffer"
);
66
dwDspFlags
|= 0x10;
67
DirectSoundEnumerateA(
ix_dsp_open_driver
, 0);
68
if
(
pDspDevice
== 0) {
69
ix_log_printf
(
"Fatal [%s - %d]:\n"
,
IX_MIXER_FILE
, 63);
70
ix_log_printf
(
"Failed to init directsound"
);
71
exit(-1);
72
}
73
}
74
75
memset(&outputFormat, 0, 0x10);
76
outputFormat.wf.wFormatTag = WAVE_FORMAT_PCM;
77
outputFormat.wf.nChannels = 2;
78
outputFormat.wf.nSamplesPerSec = 22050;
79
outputFormat.wf.nBlockAlign = 4;
80
outputFormat.wf.nAvgBytesPerSec = 88200;
81
outputFormat.wBitsPerSample = 16;
82
83
memset(&bufferDescriptor, 0, 0x14);
84
bufferDescriptor.dwSize = 0x14;
85
bufferDescriptor.dwFlags = DSBCAPS_PRIMARYBUFFER | DSBCAPS_CTRLVOLUME;
86
resultCode =
pDspDevice
->CreateSoundBuffer(
87
&bufferDescriptor, &
pDspPrimaryBuffer
, 0);
88
if
(resultCode != DS_OK) {
89
ix_log_printf
(
"Fatal [%s - %d]:\n"
,
IX_MIXER_FILE
, 81);
90
ix_log_printf
(
"Failed to create primary buffer"
);
91
exit(-1);
92
}
93
94
resultCode =
pDspPrimaryBuffer
->SetFormat(
95
(LPWAVEFORMATEX)&outputFormat);
96
if
(resultCode != DS_OK) {
97
ix_log_printf
(
"Warning [%s - %d]:\n"
,
IX_MIXER_FILE
, 84);
98
ix_log_printf
(
"Failed to SetFormat, %s"
,
99
ix_dsp_result_to_text
(resultCode));
100
}
101
if
((
dwDspFlags
& 0x10) != 0) {
102
memset(&bufferDescriptor, 0, 0x14);
103
bufferDescriptor.dwSize = 0x14;
104
bufferDescriptor.dwFlags = DSBCAPS_CTRLVOLUME;
105
bufferDescriptor.dwBufferBytes = 0x8000;
106
bufferDescriptor.lpwfxFormat = (LPWAVEFORMATEX)&outputFormat;
107
resultCode =
pDspDevice
->CreateSoundBuffer(
108
&bufferDescriptor, &
pMixerBuffer
, 0);
109
if
(resultCode != DS_OK) {
110
ix_log_printf
(
"Warning [%s - %d]:\n"
,
IX_MIXER_FILE
, 96);
111
ix_log_printf
(
"Failed to CreateSoundBuffer, %s"
,
112
ix_dsp_result_to_text
(resultCode));
113
return
(DWORD)-1;
114
}
115
dwSoundBufferSize
= 0x8000;
116
ix_log_printf
(
"secondary buffer, size = %d\n"
,
117
dwSoundBufferSize
);
118
}
else
{
119
memset(&primaryCaps, 0, 0x14);
120
primaryCaps.dwSize = 0x14;
121
pDspPrimaryBuffer
->GetCaps(&primaryCaps);
122
pMixerBuffer
=
pDspPrimaryBuffer
;
123
dwSoundBufferSize
= primaryCaps.dwBufferBytes;
124
ix_log_printf
(
"primary buffer, size = %d\n"
,
125
dwSoundBufferSize
);
126
}
127
128
pDspPrimaryBuffer
->SetVolume(
129
10000 - (
nMasterVolume
* 10000) / 0xffff);
130
while
((
dwDspFlags
& 4) != 0) {
131
ix_mixer_service
();
132
if
((
dwDspFlags
& 4) != 0) {
133
WaitForSingleObject(
hAudioWakeEvent
, 1000);
134
ResetEvent(
hAudioWakeEvent
);
135
pMixerBuffer
->Restore();
136
}
137
}
138
139
if
(
pMixerBuffer
==
pDspPrimaryBuffer
) {
140
pDspPrimaryBuffer
= 0;
141
}
else
if
(
pDspPrimaryBuffer
!= 0) {
142
pDspPrimaryBuffer
->Release();
143
pDspPrimaryBuffer
= 0;
144
}
145
if
(
pMixerBuffer
!= 0) {
146
pMixerBuffer
->Release();
147
pMixerBuffer
= 0;
148
}
149
if
(
pDspDevice
!= 0) {
150
pDspDevice
->Release();
151
pDspDevice
= 0;
152
}
153
return
0;
154
}
155
156
/* Function start: 0x004463FC */
/* source line(s) 150;157;161;176;186;196: Failed to Lock, %s | Failed to Unlock, %s | Failed to Play, %s | Failed to get current pos */
157
int
ix_mixer_service
(
void
)
158
{
159
DWORD delay;
160
HRESULT startupResult;
161
void
*initialBuffer;
162
DWORD startupBytes;
163
164
delay = 0x42;
165
startupResult =
pMixerBuffer
->Lock(
166
0, 0x2df0, &initialBuffer, &startupBytes, 0, 0, 0);
167
if
(startupResult != DS_OK) {
168
ix_log_printf
(
"Warning [%s - %d]:\n"
,
IX_MIXER_FILE
, 150);
169
ix_log_printf
(
"Failed to Lock, %s"
,
ix_dsp_result_to_text
(startupResult));
170
return
-1;
171
}
172
EnterCriticalSection(&
csMixer
);
173
ix_dspv_mix
(initialBuffer, startupBytes);
174
LeaveCriticalSection(&
csMixer
);
175
startupResult =
pMixerBuffer
->Unlock(initialBuffer, startupBytes, 0, 0);
176
if
(startupResult != DS_OK) {
177
ix_log_printf
(
"Warning [%s - %d]:\n"
,
IX_MIXER_FILE
, 157);
178
ix_log_printf
(
"Failed to Unlock, %s"
,
ix_dsp_result_to_text
(startupResult));
179
return
-1;
180
}
181
startupResult =
pMixerBuffer
->Play(0, 0, DSBPLAY_LOOPING);
182
if
(startupResult != DS_OK) {
183
ix_log_printf
(
"Warning [%s - %d]:\n"
,
IX_MIXER_FILE
, 161);
184
ix_log_printf
(
"Failed to Play, %s"
,
ix_dsp_result_to_text
(startupResult));
185
return
-1;
186
}
187
188
dwMixerWriteOffset
= 0x2df0;
189
while
((
dwDspFlags
& 4) != 0) {
190
/* Separate scopes preserve the original refill stack slots. */
191
DWORD secondBytes;
192
DWORD playCursor;
193
{
194
HRESULT result;
195
DWORD hardwareWriteCursor;
196
int
bufferedBytes;
197
198
Sleep(delay);
199
dwDspTick
++;
200
result =
pMixerBuffer
->GetCurrentPosition(
201
&playCursor, &hardwareWriteCursor);
202
if
(result != DS_OK) {
203
ix_log_printf
(
"Warning [%s - %d]:\n"
,
IX_MIXER_FILE
, 176);
204
ix_log_printf
(
"Failed to get current position, %s"
,
205
ix_dsp_result_to_text
(result));
206
return
-1;
207
}
208
if
(playCursor >
dwMixerWriteOffset
)
209
playCursor -=
dwSoundBufferSize
;
210
bufferedBytes =
dwMixerWriteOffset
- playCursor;
211
delay = (
unsigned
int)(bufferedBytes * 0x42) / 0x16f8;
212
213
{
214
DWORD firstBytes;
215
void
*firstBuffer;
216
{
217
void
*secondBuffer;
218
DWORD requestedBytes;
219
220
requestedBytes = 0x16f8;
221
result =
pMixerBuffer
->Lock(
222
dwMixerWriteOffset
, requestedBytes,
223
&firstBuffer, &firstBytes,
224
&secondBuffer, &secondBytes, 0);
225
if
(result != DS_OK) {
226
ix_log_printf
(
"Warning [%s - %d]:\n"
,
IX_MIXER_FILE
, 186);
227
ix_log_printf
(
"Failed to Lock, %s"
,
228
ix_dsp_result_to_text
(result));
229
return
-1;
230
}
231
EnterCriticalSection(&
csMixer
);
232
ix_dspv_mix
(firstBuffer, firstBytes);
233
if
(secondBuffer != 0)
234
ix_dspv_mix
(secondBuffer, secondBytes);
235
LeaveCriticalSection(&
csMixer
);
236
result =
pMixerBuffer
->Unlock(
237
firstBuffer, firstBytes, secondBuffer, secondBytes);
238
if
(result != DS_OK) {
239
ix_log_printf
(
"Warning [%s - %d]:\n"
,
IX_MIXER_FILE
, 196);
240
ix_log_printf
(
"Failed to Unlock, %s"
,
241
ix_dsp_result_to_text
(result));
242
return
-1;
243
}
244
dwMixerWriteOffset
+= firstBytes;
245
if
(secondBuffer != 0) {
246
dwMixerWriteOffset
= secondBytes;
247
}
else
{
248
if
(
dwMixerWriteOffset
>=
dwSoundBufferSize
)
249
dwMixerWriteOffset
= 0;
250
}
251
}
252
}
253
}
254
}
255
return
0;
256
}
hIxPlaybackThread
HANDLE hIxPlaybackThread
Definition
dsp.cpp:21
dwDspTick
unsigned int dwDspTick
Definition
dsp.cpp:31
pDspDevice
LPDIRECTSOUND pDspDevice
Definition
dsp.cpp:25
pDspPrimaryBuffer
LPDIRECTSOUNDBUFFER pDspPrimaryBuffer
Definition
dsp.cpp:32
dwDspFlags
unsigned int dwDspFlags
Definition
dsp.cpp:27
hAudioWakeEvent
HANDLE hAudioWakeEvent
Definition
dsp.cpp:23
ix_dsp_open_driver
BOOL CALLBACK ix_dsp_open_driver(LPGUID guid, LPSTR description, LPSTR module, LPVOID context)
Definition
dsp.cpp:106
nMasterVolume
unsigned short nMasterVolume
Definition
dsp.cpp:17
pMixerBuffer
LPDIRECTSOUNDBUFFER pMixerBuffer
Definition
dsp.cpp:29
hPlaybackWindow
HWND hPlaybackWindow
Definition
dsp.cpp:22
dwMixerWriteOffset
unsigned int dwMixerWriteOffset
Definition
dsp.cpp:24
ix_dsp_result_to_text
const char * ix_dsp_result_to_text(int result)
Definition
dsp.cpp:263
dwSoundBufferSize
unsigned int dwSoundBufferSize
Definition
dsp.cpp:26
csMixer
CRITICAL_SECTION csMixer
Definition
dspv.cpp:20
ix.h
The library's classes and shared declarations.
ix_mixer_service
int ix_mixer_service(void)
Definition
mixer.cpp:157
ix_log_printf
void ix_log_printf(const char *fmt,...)
Definition
ixlog.cpp:32
ix_dspv_mix
void ix_dspv_mix(void *outputBuffer, unsigned int outputBytes)
ix_mixer_thread_proc
DWORD WINAPI ix_mixer_thread_proc(void *parameter)
Definition
mixer.cpp:33
IX_MIXER_FILE
#define IX_MIXER_FILE
Definition
mixer.cpp:16
src
ix
mixer.cpp
Generated by
1.18.0