Wing Commander
Reconstructed Win32 source (1996)
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
18extern unsigned int dwSoundBufferSize;
19extern unsigned int dwMixerWriteOffset;
20extern HANDLE hIxPlaybackThread;
21extern HWND hPlaybackWindow;
22extern HANDLE hAudioWakeEvent;
23extern LPDIRECTSOUND pDspDevice;
24extern unsigned int dwDspFlags;
25extern LPDIRECTSOUNDBUFFER pMixerBuffer;
26extern unsigned int dwDspTick;
27extern LPDIRECTSOUNDBUFFER pDspPrimaryBuffer;
28
29BOOL 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 */
33DWORD 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",
118 } else {
119 memset(&primaryCaps, 0, 0x14);
120 primaryCaps.dwSize = 0x14;
121 pDspPrimaryBuffer->GetCaps(&primaryCaps);
123 dwSoundBufferSize = primaryCaps.dwBufferBytes;
124 ix_log_printf("primary buffer, size = %d\n",
126 }
127
128 pDspPrimaryBuffer->SetVolume(
129 10000 - (nMasterVolume * 10000) / 0xffff);
130 while ((dwDspFlags & 4) != 0) {
132 if ((dwDspFlags & 4) != 0) {
133 WaitForSingleObject(hAudioWakeEvent, 1000);
134 ResetEvent(hAudioWakeEvent);
135 pMixerBuffer->Restore();
136 }
137 }
138
141 } else if (pDspPrimaryBuffer != 0) {
142 pDspPrimaryBuffer->Release();
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 */
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 {
250 }
251 }
252 }
253 }
254 }
255 return 0;
256}
HANDLE hIxPlaybackThread
Definition dsp.cpp:21
unsigned int dwDspTick
Definition dsp.cpp:31
LPDIRECTSOUND pDspDevice
Definition dsp.cpp:25
LPDIRECTSOUNDBUFFER pDspPrimaryBuffer
Definition dsp.cpp:32
unsigned int dwDspFlags
Definition dsp.cpp:27
HANDLE hAudioWakeEvent
Definition dsp.cpp:23
BOOL CALLBACK ix_dsp_open_driver(LPGUID guid, LPSTR description, LPSTR module, LPVOID context)
Definition dsp.cpp:106
unsigned short nMasterVolume
Definition dsp.cpp:17
LPDIRECTSOUNDBUFFER pMixerBuffer
Definition dsp.cpp:29
HWND hPlaybackWindow
Definition dsp.cpp:22
unsigned int dwMixerWriteOffset
Definition dsp.cpp:24
const char * ix_dsp_result_to_text(int result)
Definition dsp.cpp:263
unsigned int dwSoundBufferSize
Definition dsp.cpp:26
CRITICAL_SECTION csMixer
Definition dspv.cpp:20
The library's classes and shared declarations.
int ix_mixer_service(void)
Definition mixer.cpp:157
void ix_log_printf(const char *fmt,...)
Definition ixlog.cpp:32
void ix_dspv_mix(void *outputBuffer, unsigned int outputBytes)
DWORD WINAPI ix_mixer_thread_proc(void *parameter)
Definition mixer.cpp:33
#define IX_MIXER_FILE
Definition mixer.cpp:16