Quake II RTX doxygen  1.0 dev
wave.c File Reference
#include "client.h"
#include "client/sound/dma.h"
#include <mmsystem.h>

Go to the source code of this file.

Macros

#define WAV_BUFFERS   64
 
#define WAV_MASK   (WAV_BUFFERS - 1)
 
#define WAV_BUFFER_SIZE   0x0400
 

Functions

static void WAVE_Shutdown (void)
 
static sndinitstat_t WAVE_Init (void)
 
static void WAVE_BeginPainting (void)
 
static void WAVE_Submit (void)
 
static void WAVE_Activate (qboolean active)
 
void WAVE_FillAPI (snddmaAPI_t *api)
 

Variables

static qboolean wav_init
 
static int sample16
 
static int snd_sent
 
static int snd_completed
 
static HANDLE hData
 
static HPSTR lpData
 
static HGLOBAL hWaveHdr
 
static LPWAVEHDR lpWaveHdr
 
static HWAVEOUT hWaveOut
 
static DWORD gSndBufSize
 

Macro Definition Documentation

◆ WAV_BUFFER_SIZE

#define WAV_BUFFER_SIZE   0x0400

Definition at line 26 of file wave.c.

◆ WAV_BUFFERS

#define WAV_BUFFERS   64

Definition at line 24 of file wave.c.

◆ WAV_MASK

#define WAV_MASK   (WAV_BUFFERS - 1)

Definition at line 25 of file wave.c.

Function Documentation

◆ WAVE_Activate()

static void WAVE_Activate ( qboolean  active)
static

Definition at line 321 of file wave.c.

322 {
323 }

Referenced by WAVE_FillAPI().

◆ WAVE_BeginPainting()

static void WAVE_BeginPainting ( void  )
static

Definition at line 241 of file wave.c.

242 {
243  int s;
244 
245  if (!wav_init) {
246  return;
247  }
248 
249  s = (snd_sent * WAV_BUFFER_SIZE) >> sample16;
250  dma.samplepos = s & (dma.samples - 1);
251 }

Referenced by WAVE_FillAPI().

◆ WAVE_FillAPI()

void WAVE_FillAPI ( snddmaAPI_t *  api)

Definition at line 325 of file wave.c.

326 {
327  api->Init = WAVE_Init;
328  api->Shutdown = WAVE_Shutdown;
329  api->BeginPainting = WAVE_BeginPainting;
330  api->Submit = WAVE_Submit;
331  api->Activate = WAVE_Activate;
332 }

Referenced by DMA_Init().

◆ WAVE_Init()

static sndinitstat_t WAVE_Init ( void  )
static

Definition at line 100 of file wave.c.

101 {
102  WAVEFORMATEX format;
103  int i;
104  HRESULT hr;
105 
106  Com_DPrintf("Initializing wave sound\n");
107 
108  snd_sent = 0;
109  snd_completed = 0;
110 
111  memset(&dma, 0, sizeof(dma));
112  dma.channels = 2;
113  dma.samplebits = 16;
114 
115  if (s_khz->integer == 44)
116  dma.speed = 44100;
117  else if (s_khz->integer == 22)
118  dma.speed = 22050;
119  else
120  dma.speed = 11025;
121 
122  memset(&format, 0, sizeof(format));
123  format.wFormatTag = WAVE_FORMAT_PCM;
124  format.nChannels = dma.channels;
125  format.wBitsPerSample = dma.samplebits;
126  format.nSamplesPerSec = dma.speed;
127  format.nBlockAlign = format.nChannels * format.wBitsPerSample / 8;
128  format.cbSize = 0;
129  format.nAvgBytesPerSec = format.nSamplesPerSec * format.nBlockAlign;
130 
131  /* Open a waveform device for output using window callback. */
132  Com_DPrintf("...opening waveform device: ");
133  while ((hr = waveOutOpen((LPHWAVEOUT)&hWaveOut, WAVE_MAPPER,
134  &format,
135  0, 0L, CALLBACK_NULL)) != MMSYSERR_NOERROR) {
136  if (hr != MMSYSERR_ALLOCATED) {
137  Com_DPrintf("failed\n");
138  return SIS_FAILURE;
139  }
140 
141  if (MessageBox(NULL,
142  _T("The sound hardware is in use by another app.\n\n")
143  _T("Select Retry to try to start sound again or Cancel to run ") _T("q2pro") _T(" with no sound."),
144  _T("Sound not available"),
145  MB_RETRYCANCEL | MB_SETFOREGROUND | MB_ICONEXCLAMATION) != IDRETRY) {
146  Com_DPrintf("hw in use\n");
147  return SIS_NOTAVAIL;
148  }
149  }
150  Com_DPrintf("ok\n");
151 
152  /*
153  * Allocate and lock memory for the waveform data. The memory
154  * for waveform data must be globally allocated with
155  * GMEM_MOVEABLE and GMEM_SHARE flags.
156 
157  */
158  Com_DPrintf("...allocating waveform buffer: ");
160  hData = GlobalAlloc(GMEM_MOVEABLE /*| GMEM_SHARE*/, gSndBufSize);
161  if (!hData) {
162  Com_DPrintf(" failed with error %#lx\n", GetLastError());
163  WAVE_Shutdown();
164  return SIS_FAILURE;
165  }
166  Com_DPrintf("ok\n");
167 
168  Com_DPrintf("...locking waveform buffer: ");
169  lpData = GlobalLock(hData);
170  if (!lpData) {
171  Com_DPrintf(" failed with error %#lx\n", GetLastError());
172  WAVE_Shutdown();
173  return SIS_FAILURE;
174  }
175  memset(lpData, 0, gSndBufSize);
176  Com_DPrintf("ok\n");
177 
178  /*
179  * Allocate and lock memory for the header. This memory must
180  * also be globally allocated with GMEM_MOVEABLE and
181  * GMEM_SHARE flags.
182  */
183  Com_DPrintf("...allocating waveform header: ");
184  hWaveHdr = GlobalAlloc(GMEM_MOVEABLE /*| GMEM_SHARE*/,
185  (DWORD) sizeof(WAVEHDR) * WAV_BUFFERS);
186  if (hWaveHdr == NULL) {
187  Com_DPrintf("failed with error %#lx\n", GetLastError());
188  WAVE_Shutdown();
189  return SIS_FAILURE;
190  }
191  Com_DPrintf("ok\n");
192 
193  Com_DPrintf("...locking waveform header: ");
194  lpWaveHdr = (LPWAVEHDR) GlobalLock(hWaveHdr);
195  if (lpWaveHdr == NULL) {
196  Com_DPrintf("failed with error %#lx\n", GetLastError());
197  WAVE_Shutdown();
198  return SIS_FAILURE;
199  }
200  memset(lpWaveHdr, 0, sizeof(WAVEHDR) * WAV_BUFFERS);
201  Com_DPrintf("ok\n");
202 
203  /* After allocation, set up and prepare headers. */
204  Com_DPrintf("...preparing headers: ");
205  for (i = 0; i < WAV_BUFFERS; i++) {
206  lpWaveHdr[i].dwBufferLength = WAV_BUFFER_SIZE;
207  lpWaveHdr[i].lpData = lpData + i * WAV_BUFFER_SIZE;
208 
209  if (waveOutPrepareHeader(hWaveOut, lpWaveHdr + i, sizeof(WAVEHDR)) !=
210  MMSYSERR_NOERROR) {
211  Com_DPrintf("failed\n");
212  WAVE_Shutdown();
213  return SIS_FAILURE;
214  }
215  }
216  Com_DPrintf("ok\n");
217 
218  dma.samples = gSndBufSize / (dma.samplebits / 8);
219  dma.samplepos = 0;
220  dma.submission_chunk = 512;
221  dma.buffer = (byte *) lpData;
222  sample16 = (dma.samplebits / 8) - 1;
223 
224  Com_Printf("Wave sound initialized\n");
225  wav_init = qtrue;
226 
227  return SIS_SUCCESS;
228 }

Referenced by WAVE_FillAPI().

◆ WAVE_Shutdown()

static void WAVE_Shutdown ( void  )
static

Definition at line 51 of file wave.c.

52 {
53  int i;
54 
55  Com_Printf("Shutting down wave sound\n");
56 
57  if (hWaveOut) {
58  Com_DPrintf("...resetting waveOut\n");
59  waveOutReset(hWaveOut);
60 
61  if (lpWaveHdr) {
62  Com_DPrintf("...unpreparing headers\n");
63  for (i = 0; i < WAV_BUFFERS; i++)
64  waveOutUnprepareHeader(hWaveOut, lpWaveHdr + i, sizeof(WAVEHDR));
65  }
66 
67  Com_DPrintf("...closing waveOut\n");
68  waveOutClose(hWaveOut);
69 
70  if (hWaveHdr) {
71  Com_DPrintf("...freeing WAV header\n");
72  GlobalUnlock(hWaveHdr);
73  GlobalFree(hWaveHdr);
74  }
75 
76  if (hData) {
77  Com_DPrintf("...freeing WAV buffer\n");
78  GlobalUnlock(hData);
79  GlobalFree(hData);
80  }
81 
82  }
83 
84  hWaveOut = 0;
85  hData = 0;
86  hWaveHdr = 0;
87  lpData = NULL;
88  lpWaveHdr = NULL;
89  wav_init = qfalse;
90 }

Referenced by WAVE_FillAPI(), WAVE_Init(), and WAVE_Submit().

◆ WAVE_Submit()

static void WAVE_Submit ( void  )
static

Definition at line 261 of file wave.c.

262 {
263  LPWAVEHDR h;
264  int wResult;
265 
266  if (!dma.buffer)
267  return;
268 
269  if (!wav_init)
270  return;
271 
272  //
273  // find which sound blocks have completed
274  //
275  while (1) {
276  if (snd_completed == snd_sent) {
277  Com_DPrintf("WAVE_Submit: Sound overrun\n");
278  break;
279  }
280 
281  if (!(lpWaveHdr[snd_completed & WAV_MASK].dwFlags & WHDR_DONE)) {
282  break;
283  }
284 
285  snd_completed++; // this buffer has been played
286  }
287 
288  //
289  // submit a few new sound blocks
290  //
291  while (((snd_sent - snd_completed) >> sample16) < 8) {
292  h = lpWaveHdr + (snd_sent & WAV_MASK);
293  if (paintedtime / 256 <= snd_sent)
294  break;
295  snd_sent++;
296  /*
297  * Now the data block can be sent to the output device. The
298  * waveOutWrite function returns immediately and waveform
299  * data is sent to the output device in the background.
300  */
301  wResult = waveOutWrite(hWaveOut, h, sizeof(WAVEHDR));
302 
303  if (wResult != MMSYSERR_NOERROR) {
304  Com_EPrintf("WAVE_Submit: Failed to write block to device\n");
305  WAVE_Shutdown();
306  return;
307  }
308  }
309 }

Referenced by WAVE_FillAPI().

Variable Documentation

◆ gSndBufSize

DWORD gSndBufSize
static

Definition at line 42 of file wave.c.

Referenced by WAVE_Init().

◆ hData

HANDLE hData
static

Definition at line 34 of file wave.c.

Referenced by WAVE_Init(), and WAVE_Shutdown().

◆ hWaveHdr

HGLOBAL hWaveHdr
static

Definition at line 37 of file wave.c.

Referenced by WAVE_Init(), and WAVE_Shutdown().

◆ hWaveOut

HWAVEOUT hWaveOut
static

Definition at line 40 of file wave.c.

Referenced by WAVE_Init(), WAVE_Shutdown(), and WAVE_Submit().

◆ lpData

HPSTR lpData
static

Definition at line 35 of file wave.c.

Referenced by WAVE_Init(), and WAVE_Shutdown().

◆ lpWaveHdr

LPWAVEHDR lpWaveHdr
static

Definition at line 38 of file wave.c.

Referenced by WAVE_Init(), WAVE_Shutdown(), and WAVE_Submit().

◆ sample16

int sample16
static

Definition at line 31 of file wave.c.

Referenced by WAVE_BeginPainting(), WAVE_Init(), and WAVE_Submit().

◆ snd_completed

int snd_completed
static

Definition at line 32 of file wave.c.

Referenced by WAVE_Init(), and WAVE_Submit().

◆ snd_sent

int snd_sent
static

Definition at line 32 of file wave.c.

Referenced by WAVE_BeginPainting(), WAVE_Init(), and WAVE_Submit().

◆ wav_init

qboolean wav_init
static

Definition at line 28 of file wave.c.

Referenced by WAVE_BeginPainting(), WAVE_Init(), WAVE_Shutdown(), and WAVE_Submit().

WAVE_BeginPainting
static void WAVE_BeginPainting(void)
Definition: wave.c:241
dma
dma_t dma
Definition: dma.c:22
s_khz
cvar_t * s_khz
Definition: dma.c:24
WAVE_Activate
static void WAVE_Activate(qboolean active)
Definition: wave.c:321
gSndBufSize
static DWORD gSndBufSize
Definition: wave.c:42
WAV_BUFFER_SIZE
#define WAV_BUFFER_SIZE
Definition: wave.c:26
lpData
static HPSTR lpData
Definition: wave.c:35
paintedtime
int paintedtime
Definition: main.c:43
snd_completed
static int snd_completed
Definition: wave.c:32
sample16
static int sample16
Definition: wave.c:31
snd_sent
static int snd_sent
Definition: wave.c:32
WAVE_Shutdown
static void WAVE_Shutdown(void)
Definition: wave.c:51
WAVE_Submit
static void WAVE_Submit(void)
Definition: wave.c:261
WAVE_Init
static sndinitstat_t WAVE_Init(void)
Definition: wave.c:100
hData
static HANDLE hData
Definition: wave.c:34
wav_init
static qboolean wav_init
Definition: wave.c:28
lpWaveHdr
static LPWAVEHDR lpWaveHdr
Definition: wave.c:38
L
#define L(name)
Definition: g_save.c:47
WAV_BUFFERS
#define WAV_BUFFERS
Definition: wave.c:24
hWaveOut
static HWAVEOUT hWaveOut
Definition: wave.c:40
WAV_MASK
#define WAV_MASK
Definition: wave.c:25
hWaveHdr
static HGLOBAL hWaveHdr
Definition: wave.c:37