FS2_Open
Open source remastering of the Freespace 2 engine
ds.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) Volition, Inc. 1999. All rights reserved.
3  *
4  * All source code herein is the property of Volition, Inc. You may not sell
5  * or otherwise commercially exploit the source or things you created based on the
6  * source.
7  *
8 */
9 
10 
11 
12 #include "cfile/cfile.h"
13 #include "cmdline/cmdline.h"
14 #include "globalincs/pstypes.h"
15 #include "osapi/osapi.h"
16 #include "sound/acm.h"
17 #include "sound/audiostr.h"
18 #include "sound/channel.h"
19 #include "sound/ds.h"
20 #include "sound/ds3d.h"
21 #include "sound/dscap.h"
22 #include "sound/openal.h"
23 #include "sound/sound.h" // jg18 - for enhanced sound
24 
25 
26 typedef struct sound_buffer
27 {
28  ALuint buf_id; // OpenAL buffer id
29  int channel_id; // Channel[] index this buffer is currently bound to
30 
31  int frequency;
33  int nchannels;
34  int nseconds;
35  int nbytes;
36 
38  buf_id(0), channel_id(-1), frequency(0), bits_per_sample(0),
39  nchannels(0), nseconds(0), nbytes(0)
40  {
41  }
42 } sound_buffer;
43 
44 
45 static int MAX_CHANNELS; // initialized properly in ds_init_channels()
46 channel *Channels = NULL;
47 static int channel_next_sig = 1;
48 
49 const int BUFFER_BUMP = 50;
51 
52 extern int Snd_sram; // mem (in bytes) used up by storing sounds in system memory
53 
54 static int Ds_use_eax = 0;
55 
56 static int Ds_eax_inited = 0;
57 
58 static int AL_play_position = 0;
59 
60 // NOTE: these can't be static
63 
64 
65 // this is so stupid - required to get VC6 to use the following array initializer
67 {
68  name = list.name;
69  flDensity = list.flDensity;
70  flDiffusion = list.flDiffusion;
71  flGain = list.flGain;
72  flGainHF = list.flGainHF;
73  flGainLF = list.flGainLF;
74  flDecayTime = list.flDecayTime;
84  flLateReverbPan[0] = list.flLateReverbPan[0];
85  flLateReverbPan[1] = list.flLateReverbPan[1];
86  flLateReverbPan[2] = list.flLateReverbPan[2];
87  flEchoTime = list.flEchoTime;
88  flEchoDepth = list.flEchoDepth;
96 }
97 
98 static const EFXREVERBPROPERTIES_list EFX_Reverb_Defaults[EAX_ENVIRONMENT_COUNT] =
99 {
100  { "Generic", 1.0f, 1.0f, 0.316228f, 0.891251f, 1.0f, 1.49f, 0.83f, 1.0f, 0.050003f, 0.007f, {0.0f, 0.0f, 0.0f}, 1.258925f, 0.011f, {0.0f, 0.0f, 0.0f}, 0.25f, 0.0f, 0.25f, 0.0f, 0.994260f, 5000.0f, 250.0f, 0.0f, 1 },
101  { "Padded cell", 0.171500f, 1.0f, 0.316228f, 0.001f, 1.0f, 0.17f, 0.10f, 1.0f, 0.250035f, 0.001f, {0.0f, 0.0f, 0.0f}, 1.269112f, 0.002f, {0.0f, 0.0f, 0.0f}, 0.25f, 0.0f, 0.25f, 0.0f, 0.994260f, 5000.0f, 250.0f, 0.0f, 1 },
102  { "Room", 0.428687f, 1.0f, 0.316228f, 0.592925f, 1.0f, 0.40f, 0.83f, 1.0f, 0.150314f, 0.002f, {0.0f, 0.0f, 0.0f}, 1.062919f, 0.003f, {0.0f, 0.0f, 0.0f}, 0.25f, 0.0f, 0.25f, 0.0f, 0.994260f, 5000.0f, 250.0f, 0.0f, 1 },
103  { "Bathroom", 0.171500f, 1.0f, 0.316228f, 0.251189f, 1.0f, 1.49f, 0.54f, 1.0f, 0.653131f, 0.007f, {0.0f, 0.0f, 0.0f}, 3.273407f, 0.011f, {0.0f, 0.0f, 0.0f}, 0.25f, 0.0f, 0.25f, 0.0f, 0.994260f, 5000.0f, 250.0f, 0.0f, 1 },
104  { "Living room", 0.976563f, 1.0f, 0.316228f, 0.001f, 1.0f, 0.50f, 0.10f, 1.0f, 0.205116f, 0.003f, {0.0f, 0.0f, 0.0f}, 0.280543f, 0.004f, {0.0f, 0.0f, 0.0f}, 0.25f, 0.0f, 0.25f, 0.0f, 0.994260f, 5000.0f, 250.0f, 0.0f, 1 },
105  { "Stone room", 1.0f, 1.0f, 0.316228f, 0.707946f, 1.0f, 2.31f, 0.64f, 1.0f, 0.441062f, 0.012f, {0.0f, 0.0f, 0.0f}, 1.100272f, 0.017f, {0.0f, 0.0f, 0.0f}, 0.25f, 0.0f, 0.25f, 0.0f, 0.994260f, 5000.0f, 250.0f, 0.0f, 1 },
106  { "Auditorium", 1.0f, 1.0f, 0.316228f, 0.578096f, 1.0f, 4.32f, 0.59f, 1.0f, 0.403181f, 0.02f, {0.0f, 0.0f, 0.0f}, 0.716968f, 0.03f, {0.0f, 0.0f, 0.0f}, 0.25f, 0.0f, 0.25f, 0.0f, 0.994260f, 5000.0f, 250.0f, 0.0f, 1 },
107  { "Concert hall", 1.0f, 1.0f, 0.316228f, 0.562341f, 1.0f, 3.92f, 0.70f, 1.0f, 0.242661f, 0.02f, {0.0f, 0.0f, 0.0f}, 0.997700f, 0.029f, {0.0f, 0.0f, 0.0f}, 0.25f, 0.0f, 0.25f, 0.0f, 0.994260f, 5000.0f, 250.0f, 0.0f, 1 },
108  { "Cave", 1.0f, 1.0f, 0.316228f, 1.0f, 1.0f, 2.91f, 1.30f, 1.0f, 0.500035f, 0.015f, {0.0f, 0.0f, 0.0f}, 0.706318f, 0.022f, {0.0f, 0.0f, 0.0f}, 0.25f, 0.0f, 0.25f, 0.0f, 0.994260f, 5000.0f, 250.0f, 0.0f, 0 },
109  { "Arena", 1.0f, 1.0f, 0.316228f, 0.447713f, 1.0f, 7.24f, 0.33f, 1.0f, 0.261216f, 0.02f, {0.0f, 0.0f, 0.0f}, 1.018591f, 0.03f, {0.0f, 0.0f, 0.0f}, 0.25f, 0.0f, 0.25f, 0.0f, 0.994260f, 5000.0f, 250.0f, 0.0f, 1 },
110  { "Hangar", 1.0f, 1.0f, 0.316228f, 0.316228f, 1.0f, 10.05f, 0.23f, 1.0f, 0.500035f, 0.02f, {0.0f, 0.0f, 0.0f}, 1.256030f, 0.03f, {0.0f, 0.0f, 0.0f}, 0.25f, 0.0f, 0.25f, 0.0f, 0.994260f, 5000.0f, 250.0f, 0.0f, 1 },
111  { "Carpeted hallway", 0.428687f, 1.0f, 0.316228f, 0.01f, 1.0f, 0.30f, 0.10f, 1.0f, 0.121479f, 0.002f, {0.0f, 0.0f, 0.0f}, 0.153109f, 0.03f, {0.0f, 0.0f, 0.0f}, 0.25f, 0.0f, 0.25f, 0.0f, 0.994260f, 5000.0f, 250.0f, 0.0f, 1 },
112  { "Hallway", 0.364500f, 1.0f, 0.316228f, 0.707946f, 1.0f, 1.49f, 0.59f, 1.0f, 0.245754f, 0.007f, {0.0f, 0.0f, 0.0f}, 1.661499f, 0.011f, {0.0f, 0.0f, 0.0f}, 0.25f, 0.0f, 0.25f, 0.0f, 0.994260f, 5000.0f, 250.0f, 0.0f, 1 },
113  { "Stone corridor", 1.0f, 1.0f, 0.316228f, 0.761202f, 1.0f, 2.70f, 0.79f, 1.0f, 0.247172f, 0.013f, {0.0f, 0.0f, 0.0f}, 1.575796f, 0.02f, {0.0f, 0.0f, 0.0f}, 0.25f, 0.0f, 0.25f, 0.0f, 0.994260f, 5000.0f, 250.0f, 0.0f, 1 },
114  { "Alley", 1.0f, 0.30f, 0.316228f, 0.732825f, 1.0f, 1.49f, 0.86f, 1.0f, 0.250035f, 0.007f, {0.0f, 0.0f, 0.0f}, 0.995405f, 0.011f, {0.0f, 0.0f, 0.0f}, 0.125f, 0.95f, 0.25f, 0.0f, 0.994260f, 5000.0f, 250.0f, 0.0f, 1 },
115  { "Forest", 1.0f, 0.30f, 0.316228f, 0.022387f, 1.0f, 1.49f, 0.54f, 1.0f, 0.052481f, 0.162f, {0.0f, 0.0f, 0.0f}, 0.768245f, 0.088f, {0.0f, 0.0f, 0.0f}, 0.125f, 1.0f, 0.25f, 0.0f, 0.994260f, 5000.0f, 250.0f, 0.0f, 1 },
116  { "City", 1.0f, 0.50f, 0.316228f, 0.398107f, 1.0f, 1.49f, 0.67f, 1.0f, 0.073030f, 0.007f, {0.0f, 0.0f, 0.0f}, 0.142725f, 0.011f, {0.0f, 0.0f, 0.0f}, 0.25f, 0.0f, 0.25f, 0.0f, 0.994260f, 5000.0f, 250.0f, 0.0f, 1 },
117  { "Mountains", 1.0f, 0.27f, 0.316228f, 0.056234f, 1.0f, 1.49f, 0.21f, 1.0f, 0.040738f, 0.30f, {0.0f, 0.0f, 0.0f}, 0.191867f, 0.10f, {0.0f, 0.0f, 0.0f}, 0.25f, 1.0f, 0.25f, 0.0f, 0.994260f, 5000.0f, 250.0f, 0.0f, 0 },
118  { "Quarry", 1.0f, 1.0f, 0.316228f, 0.316228f, 1.0f, 1.49f, 0.83f, 1.0f, 0.0f, 0.061f, {0.0f, 0.0f, 0.0f}, 1.778279f, 0.025f, {0.0f, 0.0f, 0.0f}, 0.125f, 0.70f, 0.25f, 0.0f, 0.994260f, 5000.0f, 250.0f, 0.0f, 1 },
119  { "Plain", 1.0f, 0.21f, 0.316228f, 0.10f, 1.0f, 1.49f, 0.50f, 1.0f, 0.058479f, 0.179f, {0.0f, 0.0f, 0.0f}, 0.108893f, 0.10f, {0.0f, 0.0f, 0.0f}, 0.25f, 1.0f, 0.25f, 0.0f, 0.994260f, 5000.0f, 250.0f, 0.0f, 1 },
120  { "Parking lot", 1.0f, 1.0f, 0.316228f, 1.0f, 1.0f, 1.65f, 1.50f, 1.0f, 0.208209f, 0.008f, {0.0f, 0.0f, 0.0f}, 0.265155f, 0.012f, {0.0f, 0.0f, 0.0f}, 0.25f, 0.0f, 0.25f, 0.0f, 0.994260f, 5000.0f, 250.0f, 0.0f, 0 },
121  { "Sewer pipe", 0.307063f, 0.80f, 0.316228f, 0.316228f, 1.0f, 2.81f, 0.14f, 1.0f, 1.638702f, 0.014f, {0.0f, 0.0f, 0.0f}, 3.247133f, 0.021f, {0.0f, 0.0f, 0.0f}, 0.25f, 0.0f, 0.25f, 0.0f, 0.994260f, 5000.0f, 250.0f, 0.0f, 1 },
122  { "Underwater", 0.364500f, 1.0f, 0.316228f, 0.01f, 1.0f, 1.49f, 0.10f, 1.0f, 0.596348f, 0.007f, {0.0f, 0.0f, 0.0f}, 7.079458f, 0.011f, {0.0f, 0.0f, 0.0f}, 0.25f, 0.0f, 1.18f, 0.348f, 0.994260f, 5000.0f, 250.0f, 0.0f, 1 },
123  { "Drugged", 0.428687f, 0.50f, 0.316228f, 1.0f, 1.0f, 8.39f, 1.39f, 1.0f, 0.875992f, 0.002f, {0.0f, 0.0f, 0.0f}, 3.108136f, 0.03f, {0.0f, 0.0f, 0.0f}, 0.25f, 0.0f, 0.25f, 1.0f, 0.994260f, 5000.0f, 250.0f, 0.0f, 0 },
124  { "Dizzy", 0.364500f, 0.60f, 0.316228f, 0.630957f, 1.0f, 17.23f, 0.56f, 1.0f, 0.139155f, 0.02f, {0.0f, 0.0f, 0.0f}, 0.493742f, 0.03f, {0.0f, 0.0f, 0.0f}, 0.25f, 1.0f, 0.81f, 0.31f, 0.994260f, 5000.0f, 250.0f, 0.0f, 0 },
125  { "Psychotic", 0.062500f, 0.50f, 0.316228f, 0.840427f, 1.0f, 7.56f, 0.91f, 1.0f, 0.486407f, 0.02f, {0.0f, 0.0f, 0.0f}, 2.437811f, 0.03f, {0.0f, 0.0f, 0.0f}, 0.25f, 0.0f, 4.00f, 1.0f, 0.994260f, 5000.0f, 250.0f, 0.0f, 0 }
126 };
127 
129 
130 
131 typedef ALvoid (AL_APIENTRY * ALGENFILTERS) (ALsizei, ALuint*);
132 typedef ALvoid (AL_APIENTRY * ALDELETEFILTERS) (ALsizei, ALuint*);
133 typedef ALvoid (AL_APIENTRY * ALFILTERI) (ALuint, ALenum, ALint);
134 typedef ALvoid (AL_APIENTRY * ALGENEFFECTS) (ALsizei, ALuint*);
135 typedef ALvoid (AL_APIENTRY * ALDELETEEFFECTS) (ALsizei, ALuint*);
136 typedef ALvoid (AL_APIENTRY * ALEFFECTI) (ALuint, ALenum, ALint);
137 typedef ALvoid (AL_APIENTRY * ALEFFECTF) (ALuint, ALenum, ALfloat);
138 typedef ALvoid (AL_APIENTRY * ALEFFECTFV) (ALuint, ALenum, ALfloat*);
139 typedef ALvoid (AL_APIENTRY * ALGETEFFECTF) (ALuint, ALenum, ALfloat*);
140 typedef ALvoid (AL_APIENTRY * ALGENAUXILIARYEFFECTSLOTS) (ALsizei, ALuint*);
141 typedef ALvoid (AL_APIENTRY * ALDELETEAUXILIARYEFFECTSLOTS) (ALsizei, ALuint*);
142 typedef ALboolean (AL_APIENTRY * ALISAUXILIARYEFFECTSLOT) (ALuint);
143 typedef ALvoid (AL_APIENTRY * ALAUXILIARYEFFECTSLOTI) (ALuint, ALenum, ALint);
144 typedef ALvoid (AL_APIENTRY * ALAUXILIARYEFFECTSLOTIV) (ALuint, ALenum, ALint*);
145 typedef ALvoid (AL_APIENTRY * ALAUXILIARYEFFECTSLOTF) (ALuint, ALenum, ALfloat);
146 typedef ALvoid (AL_APIENTRY * ALAUXILIARYEFFECTSLOTFV) (ALuint, ALenum, ALfloat*);
147 
148 
149 ALGENFILTERS v_alGenFilters = NULL;
150 ALDELETEFILTERS v_alDeleteFilters = NULL;
151 
152 ALFILTERI v_alFilteri = NULL;
153 
154 ALGENEFFECTS v_alGenEffecs = NULL;
155 ALDELETEEFFECTS v_alDeleteEffects = NULL;
156 
157 ALEFFECTI v_alEffecti = NULL;
158 ALEFFECTF v_alEffectf = NULL;
159 ALEFFECTFV v_alEffectfv = NULL;
160 ALGETEFFECTF v_alGetEffectf = NULL;
161 
162 ALGENAUXILIARYEFFECTSLOTS v_alGenAuxiliaryEffectSlots = NULL;
163 ALDELETEAUXILIARYEFFECTSLOTS v_alDeleteAuxiliaryEffectSlots = NULL;
164 
165 ALISAUXILIARYEFFECTSLOT v_alIsAuxiliaryEffectSlot = NULL;
166 ALAUXILIARYEFFECTSLOTI v_alAuxiliaryEffectSloti = NULL;
167 ALAUXILIARYEFFECTSLOTIV v_alAuxiliaryEffectSlotiv = NULL;
168 ALAUXILIARYEFFECTSLOTF v_alAuxiliaryEffectSlotf = NULL;
169 ALAUXILIARYEFFECTSLOTFV v_alAuxiliaryEffectSlotfv = NULL;
170 
171 ALCdevice *ds_sound_device = NULL;
172 ALCcontext *ds_sound_context = NULL;
173 
174 ALuint AL_EFX_aux_id = 0;
175 
176 static ALuint AL_EFX_effect_id = 0;
177 static int Ds_active_env = -1;
178 
179 
180 static void *al_load_function(const char *func_name)
181 {
182  void *func = alGetProcAddress(func_name);
183  if ( !func ) {
184  throw func_name;
185  }
186  return func;
187 }
188 
189 static void al_efx_load_preset(size_t presetid)
190 {
191  if ( !Ds_eax_inited ) {
192  return;
193  }
194 
195  if (presetid >= EFX_presets.size()) {
196  return;
197  }
198 
199  EFXREVERBPROPERTIES *prop = &EFX_presets[presetid];
200 
201  OpenAL_ErrorPrint( v_alEffectf(AL_EFX_effect_id, AL_EAXREVERB_DENSITY, prop->flDensity) );
203  OpenAL_ErrorPrint( v_alEffectf(AL_EFX_effect_id, AL_EAXREVERB_GAIN, prop->flGain) );
204  OpenAL_ErrorPrint( v_alEffectf(AL_EFX_effect_id, AL_EAXREVERB_GAINHF, prop->flGainHF) );
205  OpenAL_ErrorPrint( v_alEffectf(AL_EFX_effect_id, AL_EAXREVERB_GAINLF, prop->flGainLF) );
215  OpenAL_ErrorPrint( v_alEffectf(AL_EFX_effect_id, AL_EAXREVERB_ECHO_TIME, prop->flEchoTime) );
224 
225  Ds_active_env = presetid;
226 }
227 
228 
230 
246 int ds_parse_sound(CFILE* fp, ubyte **dest, uint *dest_size, WAVEFORMATEX **header, bool ogg, OggVorbis_File *ovf)
247 {
248  PCMWAVEFORMAT PCM_header;
249  ushort cbExtra = 0;
250  unsigned int tag, size, next_chunk;
251  bool got_fmt = false, got_data = false;
252 
253  // some preinit stuff, could be done from calling function but this should guarantee it's right
254  *dest = NULL;
255  *dest_size = 0;
256 
257  if (fp == NULL) {
258  return -1;
259  }
260 
261  // if we should have a Vorbis file then try for it
262  if (ogg) {
263  if (ovf == NULL) {
264  Int3();
265  return -1;
266  }
267 
268  // Check for OGG Vorbis first
269  if ( !ov_open_callbacks(fp, ovf, NULL, 0, cfile_callbacks) ) {
270  // got one, now read all of the needed header info
271  ov_info(ovf, -1);
272 
273  // we only support one logical bitstream
274  if ( ov_streams(ovf) != 1 ) {
275  nprintf(( "Sound", "SOUND ==> OGG reading error: We don't support bitstream changes!\n" ));
276  return -1;
277  }
278 
279  if ( (*header = (WAVEFORMATEX *) vm_malloc ( sizeof(WAVEFORMATEX) )) != NULL ) {
280  (*header)->wFormatTag = OGG_FORMAT_VORBIS;
281  (*header)->nChannels = (ushort)ovf->vi->channels;
282  (*header)->nSamplesPerSec = ovf->vi->rate;
283 
285  case DS_SQ_HIGH:
286  (*header)->wBitsPerSample = Ds_float_supported ? 32 : 16;
287  break;
288 
289  case DS_SQ_MEDIUM:
290  (*header)->wBitsPerSample = 16;
291  break;
292 
293  default:
294  (*header)->wBitsPerSample = 8;
295  break;
296  }
297 
298  (*header)->nBlockAlign = (ushort)(((*header)->wBitsPerSample / 8) * ovf->vi->channels);
299  (*header)->nAvgBytesPerSec = ovf->vi->rate * (*header)->nBlockAlign;
300 
301  // WMC - Total samples * channels * bits/sample
302 
303  ogg_int64_t pcm_total_size = ov_pcm_total(ovf, -1);
304  if (pcm_total_size > 0) {
305  *dest_size = (uint)(pcm_total_size * (*header)->nBlockAlign);
306  } else {
307  nprintf(("Sound", "SOUND ==> Size returned for this file is invalid. Please re-encode the file, as it will not work correctly.\n"));
308  return -1;
309  }
310  } else {
311  Assert( 0 );
312  return -1;
313  }
314 
315  // we're all good, can leave now
316  return 0;
317  }
318  } else {
319  // Otherwise we assime Wave format
320  // Skip the "RIFF" tag and file size (8 bytes)
321  // Skip the "WAVE" tag (4 bytes)
322  // IMPORTANT!! Look at snd_load before even THINKING about changing this.
323  cfseek( fp, 12, CF_SEEK_SET );
324 
325  // Now read RIFF tags until the end of file
326  while (1) {
327  if ( cfread( &tag, sizeof(uint), 1, fp ) != 1 ) {
328  break;
329  }
330 
331  tag = INTEL_INT( tag );
332 
333  if ( cfread( &size, sizeof(uint), 1, fp ) != 1 ) {
334  break;
335  }
336 
337  size = INTEL_INT( size );
338 
339  next_chunk = cftell(fp) + size;
340 
341  switch (tag) {
342  case 0x20746d66: { // The 'fmt ' tag
343  PCM_header.wf.wFormatTag = cfread_ushort(fp);
344  PCM_header.wf.nChannels = cfread_ushort(fp);
345  PCM_header.wf.nSamplesPerSec = cfread_uint(fp);
346  PCM_header.wf.nAvgBytesPerSec = cfread_uint(fp);
347  PCM_header.wf.nBlockAlign = cfread_ushort(fp);
348  PCM_header.wBitsPerSample = cfread_ushort(fp);
349 
350  // should be either: WAVE_FORMAT_PCM, WAVE_FORMAT_ADPCM, WAVE_FORMAT_IEEE_FLOAT
351  switch (PCM_header.wf.wFormatTag) {
352  case WAVE_FORMAT_PCM: {
353  if ( (PCM_header.wBitsPerSample != 8) && (PCM_header.wBitsPerSample != 16) ) {
354  nprintf(("Sound", "SOUND ==> %d-bit PCM is not supported!\n", PCM_header.wBitsPerSample));
355  return -1;
356  }
357  // fix block align
358  PCM_header.wf.nBlockAlign = (PCM_header.wBitsPerSample / 8) * PCM_header.wf.nChannels;
359  break;
360  }
361 
362  case WAVE_FORMAT_IEEE_FLOAT: {
363  if (PCM_header.wBitsPerSample != 32) {
364  nprintf(("Sound", "SOUND ==> %d-bit FLOAT PCM is not supported!\n", PCM_header.wBitsPerSample));
365  return -1;
366  }
367 
368  switch (Ds_sound_quality) {
369  case DS_SQ_HIGH:
370  PCM_header.wBitsPerSample = Ds_float_supported ? 32 : 16;
371  break;
372 
373  case DS_SQ_MEDIUM:
374  PCM_header.wBitsPerSample = 16;
375  break;
376 
377  default:
378  PCM_header.wBitsPerSample = 8;
379  break;
380  }
381  // fix block align
382  PCM_header.wf.nBlockAlign = (PCM_header.wBitsPerSample / 8) * PCM_header.wf.nChannels;
383  break;
384  }
385 
386  case WAVE_FORMAT_ADPCM:
387  // block align doesn't get fixed here
388  break;
389 
390  default: {
391  nprintf(("Sound", "SOUND ==> Format '%d' is not supported!\n", PCM_header.wf.wFormatTag));
392  return -1;
393  }
394  }
395 
396  if (PCM_header.wf.wFormatTag == WAVE_FORMAT_ADPCM) {
397  cbExtra = cfread_ushort(fp);
398  }
399 
400  // Allocate memory for WAVEFORMATEX structure + extra bytes
401  if ( (*header = (WAVEFORMATEX *) vm_malloc ( sizeof(WAVEFORMATEX)+cbExtra )) != NULL ) {
402  // Copy bytes from temporary format structure
403  memcpy (*header, &PCM_header, sizeof(PCM_header));
404  (*header)->cbSize = cbExtra;
405 
406  // Read those extra bytes, append to WAVEFORMATEX structure
407  if (cbExtra != 0) {
408  cfread( ((ubyte *)(*header) + sizeof(WAVEFORMATEX)), cbExtra, 1, fp);
409  }
410  } else {
411  // malloc failed
412  return -1;
413  }
414  got_fmt = true;
415  break;
416  }
417 
418  case 0x61746164: { // the 'data' tag
419  *dest_size = size;
420 
421  (*dest) = (ubyte *)vm_malloc(size);
422  Assert( *dest != NULL );
423 
424  cfread( *dest, size, 1, fp );
425 
426  got_data = true;
427 
428  break;
429  }
430 
431  default: // unknown, skip it
432  break;
433  }
434 
435  // This is here so that we can avoid reading data that we don't understand or properly handle.
436  // We could do this just as well by checking the RIFF size, but this is easier - taylor
437  if (got_fmt && got_data) {
438  break;
439  }
440 
441  cfseek( fp, next_chunk, CF_SEEK_SET );
442  }
443 
444  // we're all good, can leave now
445  return 0;
446  }
447 
448  return -1;
449 }
450 
457 int ds_parse_sound_info(char *real_filename, sound_info *s_info)
458 {
459  PCMWAVEFORMAT PCM_header;
460  uint tag, size, next_chunk;
461  bool got_fmt = false, got_data = false;
462  OggVorbis_File ovf;
463  int rc, FileSize, FileOffset;
464  char fullpath[MAX_PATH];
466  int rval = -1;
467 
468  if ( (real_filename == NULL) || (s_info == NULL) ) {
469  return -1;
470  }
471 
472  // remove extension
473  strcpy_s( filename, real_filename );
474  char *p = strrchr(filename, '.');
475  if ( p ) *p = 0;
476 
477  rc = cf_find_file_location_ext(filename, NUM_AUDIO_EXT, audio_ext_list, CF_TYPE_ANY, sizeof(fullpath) - 1, fullpath, &FileSize, &FileOffset);
478 
479  if (rc < 0) {
480  return -1;
481  }
482 
483  // open the file
484  CFILE *fp = cfopen_special(fullpath, "rb", FileSize, FileOffset);
485 
486  if (fp == NULL) {
487  return -1;
488  }
489 
490  // Ogg Vorbis
491  if (rc == 0) {
492  if ( !ov_open_callbacks(fp, &ovf, NULL, 0, cfile_callbacks) ) {
493  // got one, now read all of the needed header info
494  ov_info(&ovf, -1);
495 
496  // we only support one logical bitstream
497  if ( ov_streams(&ovf) != 1 ) {
498  nprintf(( "Sound", "SOUND ==> OGG reading error: We don't support bitstream changes!\n" ));
499  ov_clear(&ovf);
500  goto Done;
501  }
502 
503  s_info->format = OGG_FORMAT_VORBIS;
504  s_info->n_channels = (ushort)ovf.vi->channels;
505  s_info->sample_rate = ovf.vi->rate;
506 
508  case DS_SQ_HIGH:
509  s_info->bits = Ds_float_supported ? 32 : 16;
510  break;
511 
512  case DS_SQ_MEDIUM:
513  s_info->bits = 16;
514  break;
515 
516  default:
517  s_info->bits = 8;
518  break;
519  }
520 
521  s_info->n_block_align = (ushort)((s_info->bits / 8) * s_info->n_channels);
522  s_info->avg_bytes_per_sec = s_info->sample_rate * s_info->n_block_align;
523 
524  s_info->size = (uint)(ov_pcm_total(&ovf, -1) * s_info->n_block_align);
525 
526  ov_clear(&ovf);
527 
528  // we're all good, can leave now
529  rval = 0;
530  goto Done;
531  }
532  }
533  // PCM Wave
534  else if (rc == 1) {
535  // Skip the "RIFF" tag and file size (8 bytes)
536  // Skip the "WAVE" tag (4 bytes)
537  // IMPORTANT!! Look at snd_load before even THINKING about changing this.
538  cfseek( fp, 12, CF_SEEK_SET );
539 
540  // Now read RIFF tags until the end of file
541  while (1) {
542  if ( cfread( &tag, sizeof(uint), 1, fp ) != 1 ) {
543  break;
544  }
545 
546  tag = INTEL_INT( tag );
547 
548  if ( cfread( &size, sizeof(uint), 1, fp ) != 1 ) {
549  break;
550  }
551 
552  size = INTEL_INT( size );
553  next_chunk = cftell(fp) + size;
554 
555  switch (tag) {
556  case 0x20746d66: // The 'fmt ' tag
557  PCM_header.wf.wFormatTag = cfread_ushort(fp);
558  PCM_header.wf.nChannels = cfread_ushort(fp);
559  PCM_header.wf.nSamplesPerSec = cfread_uint(fp);
560  PCM_header.wf.nAvgBytesPerSec = cfread_uint(fp);
561  PCM_header.wf.nBlockAlign = cfread_ushort(fp);
562  PCM_header.wBitsPerSample = cfread_ushort(fp);
563 
564  // should be either: WAVE_FORMAT_PCM, WAVE_FORMAT_ADPCM, WAVE_FORMAT_IEEE_FLOAT
565  switch (PCM_header.wf.wFormatTag) {
566  case WAVE_FORMAT_PCM: {
567  if ( (PCM_header.wBitsPerSample != 8) && (PCM_header.wBitsPerSample != 16) ) {
568  nprintf(("Sound", "SOUND ==> %d-bit PCM is not supported!\n", PCM_header.wBitsPerSample));
569  goto Done;
570  }
571  // fix block align
572  PCM_header.wf.nBlockAlign = (PCM_header.wBitsPerSample / 8) * PCM_header.wf.nChannels;
573  break;
574  }
575 
576  case WAVE_FORMAT_IEEE_FLOAT: {
577  if (PCM_header.wBitsPerSample != 32) {
578  nprintf(("Sound", "SOUND ==> %d-bit FLOAT PCM is not supported!\n", PCM_header.wBitsPerSample));
579  goto Done;
580  }
581 
582  switch (Ds_sound_quality) {
583  case DS_SQ_HIGH:
584  PCM_header.wBitsPerSample = Ds_float_supported ? 32 : 16;
585  break;
586 
587  case DS_SQ_MEDIUM:
588  PCM_header.wBitsPerSample = 16;
589  break;
590 
591  default:
592  PCM_header.wBitsPerSample = 8;
593  break;
594  }
595  // fix block align
596  PCM_header.wf.nBlockAlign = (PCM_header.wBitsPerSample / 8) * PCM_header.wf.nChannels;
597  break;
598  }
599 
600  case WAVE_FORMAT_ADPCM:
601  // block align doesn't get fixed here
602  break;
603 
604  default: {
605  nprintf(("Sound", "SOUND ==> Format '%d' is not supported!\n", PCM_header.wf.wFormatTag));
606  goto Done;
607  }
608  }
609 
610  s_info->format = PCM_header.wf.wFormatTag;
611  s_info->n_channels = PCM_header.wf.nChannels;
612  s_info->sample_rate = PCM_header.wf.nSamplesPerSec;
613  s_info->bits = PCM_header.wBitsPerSample;
614  s_info->avg_bytes_per_sec = PCM_header.wf.nAvgBytesPerSec;
615  s_info->n_block_align = PCM_header.wf.nBlockAlign;
616 
617  got_fmt = true;
618  break;
619 
620  case 0x61746164: // the 'data' tag
621  s_info->size = size;
622  got_data = true;
623  break;
624 
625  default:
626  break;
627  }
628 
629  if (got_fmt && got_data) {
630  rval = 0;
631  goto Done;
632  }
633  cfseek( fp, next_chunk, CF_SEEK_SET );
634  }
635  }
636 Done:
637  cfclose(fp);
638  return rval;
639 }
640 
645 {
646  sound_buffer new_buffer;
647  uint i;
648 
649  for (i = 0; i < sound_buffers.size(); i++) {
650  if (sound_buffers[i].buf_id == 0) {
651  return (int)i;
652  }
653  }
654 
655  sound_buffers.push_back( new_buffer );
656 
657  return (int)(sound_buffers.size() - 1);
658 }
659 
676 int ds_load_buffer(int *sid, int *final_size, void *header, sound_info *si, int flags)
677 {
678  Assert( final_size != NULL );
679  Assert( header != NULL );
680 
681  if (si == NULL) {
682  Int3();
683  return -1;
684  }
685 
686  // All sounds are required to have a software buffer
687  *sid = ds_get_sid();
688  if ( *sid == -1 ) {
689  nprintf(("Sound","SOUND ==> No more sound buffers available\n"));
690  return -1;
691  }
692 
693  ALuint pi;
694  OpenAL_ErrorCheck( alGenBuffers (1, &pi), return -1 );
695 
696  ALenum format;
697  ALsizei size;
698  ALint bits, bps, n_channels = si->n_channels;
699  ALuint frequency;
700  ALvoid *data = NULL;
701  int sign, byte_order = 0, section, last_section = -1;
702 
703  // the below two covnert_ variables are only used when the wav format is not
704  // PCM. DirectSound only takes PCM sound data, so we must convert to PCM if required
705  ubyte *convert_buffer = NULL; // storage for converted wav file
706  int convert_len; // num bytes of converted wav file
707  uint src_bytes_used; // number of source bytes actually converted (should always be equal to original size)
708  int rc;
709  WAVEFORMATEX *pwfx = (WAVEFORMATEX *)header;
710 
711  // this is only used if converting a stereo sound to mono for 3D playback
712  ubyte *mono_buffer = nullptr;
713 
714  switch (si->format) {
715  case WAVE_FORMAT_PCM: {
716  Assert( si->data != NULL );
717 
718  bits = si->bits;
719  bps = si->avg_bytes_per_sec;
720  size = si->size;
721 
722 #if BYTE_ORDER == BIG_ENDIAN
723  // swap 16-bit sound data
724  if (bits == 16) {
725  ushort *swap_tmp;
726 
727  for (uint i=0; i<size; i=i+2) {
728  swap_tmp = (ushort*)(si->data + i);
729  *swap_tmp = INTEL_SHORT(*swap_tmp);
730  }
731  }
732 #endif
733 
734  data = si->data;
735  break;
736  }
737 
738  case WAVE_FORMAT_ADPCM: {
739  Assert( si->data != NULL );
740 
741  bits = (Ds_sound_quality == DS_SQ_LOW) ? 8 : 16;
742 
743  nprintf(( "Sound", "SOUND ==> Converting sound from ADPCM to PCM\n" ));
744 
745  rc = ACM_convert_ADPCM_to_PCM(pwfx, si->data, si->size, &convert_buffer, 0, &convert_len, &src_bytes_used, bits);
746 
747  if ( rc == -1 ) {
748  return -1;
749  }
750 
751  if (src_bytes_used != si->size) {
752  return -1; // ACM conversion failed?
753  }
754 
755  bps = (((si->n_channels * bits) / 8) * si->sample_rate);
756  size = convert_len;
757  data = convert_buffer;
758 
759  nprintf(( "Sound", "SOUND ==> Coverted sound from ADPCM to PCM successfully\n" ));
760  break;
761  }
762 
763  case WAVE_FORMAT_IEEE_FLOAT: {
764  Assert( si->data != NULL );
765 
766  bits = si->bits;
767 
768 #if BYTE_ORDER == BIG_ENDIAN
769  // need to byte-swap before any later conversions
770  float *swap_tmp;
771 
772  for (uint i = 0; i < si->size; i += sizeof(float)) {
773  swap_tmp = (float *)(si->data + i);
774  *swap_tmp = INTEL_FLOAT(swap_tmp);
775  }
776 #endif
777 
778  if (bits == 32) {
779  bps = si->avg_bytes_per_sec;
780  size = si->size;
781 
782  data = si->data;
783  } else if (bits == 16) {
784  bps = si->avg_bytes_per_sec >> 1;
785  size = si->size >> 1;
786 
787  convert_buffer = (ubyte*)vm_malloc_q(size);
788 
789  if (convert_buffer == NULL) {
790  return -1;
791  }
792 
793  float *in_p = (float*)si->data;
794  short *out_p = (short*)convert_buffer;
795 
796  int end = si->size / sizeof(float);
797 
798  for (int i = 0; i < end; i++) {
799  int i_val = (int)(in_p[i] * 32767.0f + 0.5f);
800  CLAMP(i_val, -32768, 32767);
801 
802  *out_p++ = (short)i_val;
803  }
804 
805  data = convert_buffer;
806  } else {
807  bps = si->avg_bytes_per_sec >> 2;
808  size = si->size >> 2;
809 
810  convert_buffer = (ubyte*)vm_malloc_q(size);
811 
812  if (convert_buffer == NULL) {
813  return -1;
814  }
815 
816  float *in_p = (float*)si->data;
817  ubyte *out_p = (ubyte*)convert_buffer;
818 
819  int end = si->size / sizeof(float);
820 
821  for (int i = 0; i < end; i++) {
822  int i_val = (int)(in_p[i] * 127.0f + 0.5f) + 128;
823  CLAMP(i_val, 0, 255);
824  *out_p++ = (ubyte)i_val;
825  }
826 
827  data = convert_buffer;
828  }
829  break;
830  }
831 
832  case OGG_FORMAT_VORBIS: {
833  nprintf(( "Sound", "SOUND ==> converting sound from OGG to PCM\n" ));
834 
835  sign = (si->bits == 8) ? 0 : 1;
836 #if BYTE_ORDER == BIG_ENDIAN
837  byte_order = 1;
838 #endif
839  src_bytes_used = 0;
840 
841  convert_buffer = (ubyte*)vm_malloc_q(si->size);
842 
843  if (convert_buffer == NULL) {
844  return -1;
845  }
846 
847  while (src_bytes_used < si->size) {
848  float **pcm = NULL;
849 
850  if (si->bits == 32) {
851  rc = ov_read_float(&si->ogg_info, &pcm, 1024, &section);
852  } else {
853  rc = ov_read(&si->ogg_info, (char *) convert_buffer + src_bytes_used, si->size - src_bytes_used, byte_order, si->bits / 8, sign, &section);
854  }
855 
856  // fail if the bitstream changes, shouldn't get this far if that's the case though
857  if ((last_section != -1) && (last_section != section)) {
858  nprintf(( "Sound", "SOUND ==> OGG reading error: We don't support bitstream changes!\n" ));
859  ov_clear(&si->ogg_info);
860  vm_free(convert_buffer);
861  convert_buffer = NULL;
862  return -1;
863  }
864 
865  if (rc == OV_EBADLINK) {
866  ov_clear(&si->ogg_info);
867  vm_free(convert_buffer);
868  convert_buffer = NULL;
869 
870  return -1;
871  } else if (rc == 0) {
872  break;
873  } else if (rc > 0) {
874  if (si->bits == 32) {
875  float *out_p = (float*)(convert_buffer + src_bytes_used);
876 
877  for (int i = 0; i < rc; i++) {
878  for (int j = 0; j < si->n_channels; j++) {
879  *out_p++ = pcm[j][i];
880  }
881  }
882 
883  src_bytes_used += (rc * si->n_block_align);
884  } else {
885  src_bytes_used += rc;
886  }
887  last_section = section;
888  }
889  }
890 
891  bits = si->bits;
892  bps = si->avg_bytes_per_sec;
893  size = (int)src_bytes_used;
894 
895  data = convert_buffer;
896 
897  // we're done with ogg stuff so clean it up
898  ov_clear(&si->ogg_info);
899 
900  nprintf(( "Sound", "SOUND ==> Coverted sound from OGG successfully\n" ));
901  break;
902  }
903 
904  default:
905  return -1;
906  }
907 
908  // if this is supposed to play in 3D then make sure it's mono
909  if ( (flags & DS_3D) && (n_channels > 1) ) {
910  mono_buffer = (ubyte*)vm_malloc_q(size >> 1);
911 
912  if (mono_buffer == NULL) {
913  if (convert_buffer) {
914  vm_free(convert_buffer);
915  }
916 
917  return -1;
918  }
919 
920  if (bits == 32) {
921  float *in_p = (float*)data;
922  float *out_p = (float*)mono_buffer;
923 
924  int end = size / sizeof(float);
925 
926  for (int i = 0; i < end; i += 2) {
927  float i_val = (in_p[i] + in_p[i+1]) * 0.5f;
928  CLAMP(i_val, -1.0f, 1.0f);
929  *out_p++ = i_val;
930  }
931  } else if (bits == 16) {
932  short *in_p = (short*)data;
933  short *out_p = (short*)mono_buffer;
934  int end = size / sizeof(short);
935 
936  for (int i = 0; i < end; i += 2) {
937  int i_val = (in_p[i] + in_p[i+1]) >> 1;
938  CLAMP(i_val, -32768, 32767);
939  *out_p++ = (short)i_val;
940  }
941  } else {
942  Assert( bits == 8 );
943  ubyte *in_p = (ubyte*)data;
944  ubyte *out_p = (ubyte*)mono_buffer;
945 
946  for (int i = 0; i < size; i += 2) {
947  int i_val = (in_p[i] + in_p[i+1]) >> 1;
948  CLAMP(i_val, 0, 255);
949  *out_p++ = (ubyte)i_val;
950  }
951  }
952 
953  n_channels = 1;
954  size >>= 1;
955  bps >>= 1;
956  data = mono_buffer;
957 
958  if (convert_buffer) {
959  vm_free(convert_buffer);
960  convert_buffer = NULL;
961  }
962  nprintf(("Sound", "SOUND ==> Converted 3D sound from stereo to mono\n"));
963  }
964 
965  // format is now in pcm
966  frequency = si->sample_rate;
967  format = openal_get_format(bits, n_channels);
968 
969  if (format == AL_INVALID_VALUE) {
970  if (convert_buffer) {
971  vm_free(convert_buffer);
972  }
973  return -1;
974  }
975 
976  Snd_sram += size;
977 
978  if (final_size) {
979  *final_size = size;
980  }
981 
982  OpenAL_ErrorCheck( alBufferData(pi, format, data, size, frequency), { if (convert_buffer) vm_free(convert_buffer); return -1; } );
983 
984  sound_buffers[*sid].buf_id = pi;
985  sound_buffers[*sid].channel_id = -1;
986  sound_buffers[*sid].frequency = frequency;
987  sound_buffers[*sid].bits_per_sample = bits;
988  sound_buffers[*sid].nchannels = n_channels;
989  sound_buffers[*sid].nseconds = size / bps;
990  sound_buffers[*sid].nbytes = size;
991 
992  // update sound_info struct with any changed data
993  si->bits = bits;
994  si->n_channels = n_channels;
995  si->size = size;
996  si->n_block_align = (bits / 8) * n_channels;
997  si->avg_bytes_per_sec = bps;
998 
999  if ( convert_buffer ) {
1000  vm_free( convert_buffer );
1001  }
1002  if ( mono_buffer != nullptr ) {
1003  vm_free( mono_buffer );
1004  }
1005  return 0;
1006 }
1007 
1012 {
1013  MAX_CHANNELS = Cmdline_no_enhanced_sound ? 32 : 128;
1014 
1015  try {
1016  Channels = new channel[MAX_CHANNELS];
1017  } catch (std::bad_alloc) {
1018  Error(LOCATION, "Unable to allocate " SIZE_T_ARG " bytes for %d audio channels.", sizeof(channel) * MAX_CHANNELS, MAX_CHANNELS);
1019  }
1020 }
1021 
1026 {
1027  sound_buffers.clear();
1028 
1029  // pre-allocate for at least BUFFER_BUMP buffers
1030  sound_buffers.reserve( BUFFER_BUMP );
1031 }
1032 
1039 {
1040  const ALchar * renderer = alGetString(AL_RENDERER);
1041  if (renderer == NULL)
1042  {
1043  mprintf(("ds_check_for_openal_soft: renderer is null!"));
1044  return false;
1045  }
1046  else if (!stricmp((const char *)renderer, "OpenAL Soft"))
1047  {
1048  return true;
1049  }
1050  else
1051  {
1052  return false;
1053  }
1054 }
1055 
1060 int ds_init()
1061 {
1062  ALfloat list_orien[] = { 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f };
1063  ALCint attrList[] = { ALC_FREQUENCY, 22050, 0 };
1064  unsigned int sample_rate = 22050;
1065 
1066  mprintf(("Initializing OpenAL...\n"));
1067 
1068  Ds_sound_quality = os_config_read_uint("Sound", "Quality", DS_SQ_MEDIUM);
1070 
1071  switch (Ds_sound_quality) {
1072  case DS_SQ_HIGH:
1073  sample_rate = 48000;
1074  break;
1075 
1076  case DS_SQ_MEDIUM:
1077  sample_rate = 44100;
1078  break;
1079 
1080  default:
1081  sample_rate = 22050;
1082  break;
1083  }
1084 
1085  sample_rate = os_config_read_uint("Sound", "SampleRate", sample_rate);
1086  attrList[1] = sample_rate;
1087  SCP_string playback_device;
1088  SCP_string capture_device;
1089 
1090  if ( openal_init_device(&playback_device, &capture_device) == false ) {
1091  mprintf(("\n ERROR: Unable to find suitable playback device!\n\n"));
1092  goto AL_InitError;
1093  }
1094 
1095  ds_sound_device = alcOpenDevice( (const ALCchar*) playback_device.c_str() );
1096 
1097  if (ds_sound_device == NULL) {
1098  mprintf((" Failed to open playback_device (%s) returning error (%s)\n", playback_device.c_str(), openal_error_string(1)));
1099  goto AL_InitError;
1100  }
1101 
1102  ds_sound_context = alcCreateContext(ds_sound_device, attrList);
1103 
1104  if (ds_sound_context == NULL) {
1105  mprintf((" Failed to create context for playback_device (%s) with attrList = { 0x%x, %d, %d } returning error (%s)\n",
1106  playback_device.c_str(), attrList[0], attrList[1], attrList[2], openal_error_string(1)));
1107  goto AL_InitError;
1108  }
1109 
1110  alcMakeContextCurrent(ds_sound_context);
1111 
1112  alcGetError(ds_sound_device);
1113 
1114  mprintf((" OpenAL Vendor : %s\n", alGetString(AL_VENDOR)));
1115  mprintf((" OpenAL Renderer : %s\n", alGetString(AL_RENDERER)));
1116  mprintf((" OpenAL Version : %s\n", alGetString(AL_VERSION)));
1117  mprintf(("\n"));
1118 
1119  // we need to clear out all errors before moving on
1120  alcGetError(NULL);
1121  alGetError();
1122 
1123  // set distance model to basically match what the D3D code does
1124  alDistanceModel(AL_INVERSE_DISTANCE_CLAMPED);
1125 
1126  // make sure we can actually use AL_BYTE_LOKI (Mac/Win OpenAL doesn't have it)
1127  if ( alIsExtensionPresent( (const ALchar*)"AL_LOKI_play_position" ) == AL_TRUE ) {
1128  mprintf((" Found extension \"AL_LOKI_play_position\".\n"));
1129  AL_play_position = 1;
1130  }
1131 
1132  if ( alIsExtensionPresent( (const ALchar*)"AL_EXT_float32" ) == AL_TRUE ) {
1133  mprintf((" Found extension \"AL_EXT_float32\".\n"));
1134  Ds_float_supported = 1;
1135  }
1136 
1137  Ds_use_eax = 0;
1138 
1139  if ( alcIsExtensionPresent(ds_sound_device, (const ALchar*)"ALC_EXT_EFX") == AL_TRUE ) {
1140  mprintf((" Found extension \"ALC_EXT_EFX\".\n"));
1141  Ds_use_eax = os_config_read_uint("Sound", "EnableEFX", Fred_running);
1142  }
1143 
1144  if (Ds_use_eax == 1) {
1145  if (ds_eax_init() != 0) {
1146  Ds_use_eax = 0;
1147  }
1148  }
1149 
1150  // the presets always need to be available to FRED
1151  if ( !Ds_use_eax && Fred_running ) {
1152  EFX_presets.reserve(EAX_ENVIRONMENT_COUNT);
1153 
1154  for (size_t i = 0; i < EAX_ENVIRONMENT_COUNT; i++) {
1155  EFX_presets.push_back( EFX_Reverb_Defaults[i] );
1156  }
1157  }
1158 
1160  {
1161  if (!ds_check_for_openal_soft())
1162  {
1163  mprintf(("You are not using OpenAL Soft. Disabling enhanced sound.\n"));
1165  }
1166  else
1167  {
1168  mprintf(("Enhanced sound is enabled.\n"));
1169  }
1170  }
1171  else
1172  {
1173  mprintf(("Enhanced sound is manually disabled.\n"));
1174  }
1175 
1176  // setup default listener position/orientation
1177  // this is needed for 2D pan
1178  OpenAL_ErrorPrint( alListener3f(AL_POSITION, 0.0, 0.0, 0.0) );
1179  OpenAL_ErrorPrint( alListenerfv(AL_ORIENTATION, list_orien) );
1180 
1181  // disable doppler (FIXME)
1182  OpenAL_ErrorPrint( alDopplerFactor(0.0f) );
1183 
1184  ds_init_channels();
1185  ds_init_buffers();
1186 
1187  mprintf(("\n"));
1188 
1189  {
1190  ALCint freq = 0;
1191  OpenAL_ErrorPrint( alcGetIntegerv(ds_sound_device, ALC_FREQUENCY, sizeof(ALCint), &freq) );
1192 
1193  mprintf((" Sample rate: %d (%d)\n", freq, sample_rate));
1194  }
1195 
1196  if (Ds_use_eax) {
1197  ALCint major = 0, minor = 0, max_sends = 0;
1198 
1199  alcGetIntegerv(ds_sound_device, ALC_EFX_MAJOR_VERSION, 1, &major);
1200  alcGetIntegerv(ds_sound_device, ALC_EFX_MINOR_VERSION, 1, &minor);
1201  alcGetIntegerv(ds_sound_device, ALC_MAX_AUXILIARY_SENDS, 1, &max_sends);
1202 
1203  mprintf((" EFX version: %d.%d\n", (int)major, (int)minor));
1204  mprintf((" Max auxiliary sends: %d\n", max_sends));
1205  } else {
1206  mprintf((" EFX enabled: NO\n"));
1207  }
1208 
1209  mprintf((" Playback device: %s\n", playback_device.c_str()));
1210  mprintf((" Capture device: %s\n", (capture_device.empty()) ? "<not available>" : capture_device.c_str()));
1211 
1212  mprintf(("... OpenAL successfully initialized!\n"));
1213 
1214  // we need to clear out any errors before moving on
1215  alcGetError(NULL);
1216  alGetError();
1217 
1218  return 0;
1219 
1220 AL_InitError:
1221  alcMakeContextCurrent(NULL);
1222 
1223  if (ds_sound_context != NULL) {
1224  alcDestroyContext(ds_sound_context);
1225  ds_sound_context = NULL;
1226  }
1227 
1228  if (ds_sound_device != NULL) {
1229  alcCloseDevice(ds_sound_device);
1230  ds_sound_device = NULL;
1231  }
1232 
1233  mprintf(("... OpenAL failed to initialize!\n"));
1234 
1235  return -1;
1236 }
1237 
1242 {
1243  if ( (i < 0) || (i >= MAX_CHANNELS) ) {
1244  return;
1245  }
1246 
1247  if ( (Channels[i].source_id != 0) && alIsSource(Channels[i].source_id) ) {
1248  OpenAL_ErrorPrint( alSourceStop(Channels[i].source_id) );
1249  OpenAL_ErrorPrint( alSourcei(Channels[i].source_id, AL_BUFFER, 0) );
1250 
1251  if (Ds_eax_inited) {
1252  OpenAL_ErrorPrint( alSource3i(Channels[i].source_id, AL_AUXILIARY_SEND_FILTER, AL_EFFECTSLOT_NULL, 0, AL_FILTER_NULL) );
1253  }
1254 
1255  OpenAL_ErrorPrint( alDeleteSources(1, &Channels[i].source_id) );
1256 
1257  if (Channels[i].sid >= 0) {
1258  sound_buffers[Channels[i].sid].channel_id = -1;
1259  }
1260 
1261  Channels[i].source_id = 0;
1262  Channels[i].sid = -1;
1263  Channels[i].sig = -1;
1264  Channels[i].snd_id = -1;
1265  }
1266 }
1267 
1269 {
1270  if ( (i < 0) || (i >= MAX_CHANNELS) ) {
1271  return;
1272  }
1273 
1274  if ( (Channels[i].source_id != 0) && alIsSource(Channels[i].source_id) ) {
1275  OpenAL_ErrorPrint( alSourceStop(Channels[i].source_id) );
1276  OpenAL_ErrorPrint( alSourcei(Channels[i].source_id, AL_BUFFER, 0) );
1277 
1278  if (Ds_eax_inited) {
1279  OpenAL_ErrorPrint( alSource3i(Channels[i].source_id, AL_AUXILIARY_SEND_FILTER, AL_EFFECTSLOT_NULL, 0, AL_FILTER_NULL) );
1280  }
1281 
1282  if (Channels[i].sid >= 0) {
1283  sound_buffers[Channels[i].sid].channel_id = -1;
1284  }
1285 
1286  Channels[i].sid = -1;
1287  Channels[i].sig = -1;
1288  Channels[i].snd_id = -1;
1289  }
1290 }
1291 
1296 {
1297  int i;
1298 
1299  for (i = 0; i < MAX_CHANNELS; i++) {
1300  ds_close_channel(i);
1301  }
1302 }
1303 
1307 void ds_unload_buffer(int sid)
1308 {
1309  if ( (sid < 0) || ((size_t)sid >= sound_buffers.size()) ) {
1310  return;
1311  }
1312 
1313  if (sound_buffers[sid].channel_id >= 0) {
1314  ds_close_channel_fast(sound_buffers[sid].channel_id);
1315  sound_buffers[sid].channel_id = -1;
1316  }
1317 
1318  ALuint buf_id = sound_buffers[sid].buf_id;
1319 
1320  if ( (buf_id != 0) && alIsBuffer(buf_id) ) {
1321  OpenAL_ErrorCheck( alDeleteBuffers(1, &buf_id), return );
1322  }
1323 
1324  sound_buffers[sid].buf_id = 0;
1325 }
1326 
1331 {
1332  size_t i;
1333 
1334  for (i = 0; i < sound_buffers.size(); i++) {
1335  ds_unload_buffer(i);
1336  }
1337 
1338  sound_buffers.clear();
1339 }
1340 
1344 void ds_close()
1345 {
1347  ds_close_buffers();
1348  ds_eax_close();
1349 
1350  // free the Channels[] array, since it was dynamically allocated
1351  delete [] Channels;
1352  Channels = NULL;
1353 
1354  alcMakeContextCurrent(NULL); // hangs on me for some reason
1355 
1356  if (ds_sound_context != NULL) {
1357  alcDestroyContext(ds_sound_context);
1358  ds_sound_context = NULL;
1359  }
1360 
1361  if (ds_sound_device != NULL) {
1362  alcCloseDevice(ds_sound_device);
1363  ds_sound_device = NULL;
1364  }
1365 }
1366 
1367 
1380 int ds_get_free_channel_retail(float new_volume, int snd_id, int priority)
1381 {
1382  int i, first_free_channel, limit = 100;
1383  int instance_count; // number of instances of sound already playing
1384  int lowest_vol_index = -1, lowest_instance_vol_index = -1;
1385  float lowest_vol = 1.0f, lowest_instance_vol = 1.0f;
1386  channel *chp;
1387  int status;
1388 
1389  instance_count = 0;
1390  first_free_channel = -1;
1391 
1392  // determine the limit of concurrent instances of this sound
1393  switch (priority) {
1394  case DS_MUST_PLAY:
1395  limit = 100;
1396  break;
1397 
1398  case DS_LIMIT_ONE:
1399  limit = 1;
1400  break;
1401 
1402  case DS_LIMIT_TWO:
1403  limit = 2;
1404  break;
1405 
1406  case DS_LIMIT_THREE:
1407  limit = 3;
1408  break;
1409 
1410  default:
1411  Int3(); // get Alan
1412  limit = 100;
1413  break;
1414  }
1415 
1416  // Look for a channel to use to play this sample
1417  for ( i = 0; i < MAX_CHANNELS; i++ ) {
1418  chp = &Channels[i];
1419 
1420  // source not created yet
1421  if (chp->source_id == 0) {
1422  if (first_free_channel == -1) {
1423  first_free_channel = i;
1424  }
1425  continue;
1426  }
1427 
1428  // source not bound to a buffer
1429  if (chp->sid == -1) {
1430  if (first_free_channel == -1) {
1431  first_free_channel = i;
1432  }
1433  continue;
1434  }
1435 
1436  OpenAL_ErrorCheck( alGetSourcei(chp->source_id, AL_SOURCE_STATE, &status), continue );
1437 
1438  if ( (status == AL_INITIAL) || (status == AL_STOPPED) ) {
1440 
1441  if (first_free_channel == -1) {
1442  first_free_channel = i;
1443  }
1444  continue;
1445  } else {
1446  if ( chp->snd_id == snd_id ) {
1447  instance_count++;
1448  if ( (chp->vol < lowest_instance_vol) && (chp->looping == FALSE) ) {
1449  lowest_instance_vol = chp->vol;
1450  lowest_instance_vol_index = i;
1451  }
1452  } else if ( chp->is_voice_msg ) {
1453  // a playing voice message is not allowed to be preempted.
1454  } else if ( (chp->vol < lowest_vol) && (chp->looping == FALSE) ) {
1455  lowest_vol_index = i;
1456  lowest_vol = chp->vol;
1457  }
1458  }
1459  }
1460 
1461  // If we've exceeded the limit, then maybe stop the duplicate if it is lower volume
1462  if ( (instance_count >= limit) && (lowest_instance_vol_index >= 0) ) {
1463  // If there is a lower volume duplicate, stop it.... otherwise, don't play the sound
1464  if (lowest_instance_vol <= new_volume) {
1465  ds_close_channel_fast(lowest_instance_vol_index);
1466  first_free_channel = lowest_instance_vol_index;
1467  } else {
1468  // NOTE: yes we are preventing the sound from playing even if
1469  // there is an available channel because we are over the limit
1470  // requested by the rest of the engine, which means if we do
1471  // not honour its request to limit the count then the engine
1472  // will trip itself up by using all channels without having
1473  // the intention of actually doing so. This means we get
1474  // very loud sounds, missing more important sounds, etc.
1475  // Effectivly the problem is the rest of the engine assumes
1476  // it is still stuck in the 90s with a sound card that only has
1477  // <=16 channels so we need to give it a sound card that
1478  // has 16 channels (though we are actually allowing 32 channels
1479  // just because we can).
1480  first_free_channel = -1;
1481  }
1482  } else if (first_free_channel == -1) {
1483  // there is no limit barrier to play the sound, but we have run out of channels
1484  // stop the lowest volume instance to play our sound if priority demands it
1485  if ( (lowest_vol_index != -1) && (priority == DS_MUST_PLAY) ) {
1486  // Check if the lowest volume playing is less than the volume of the requested sound.
1487  // If so, then we are going to trash the lowest volume sound.
1488  if ( Channels[lowest_vol_index].vol <= new_volume ) {
1489  ds_close_channel_fast(lowest_vol_index);
1490  first_free_channel = lowest_vol_index;
1491  }
1492  }
1493  }
1494 
1495  if ( (first_free_channel >= 0) && (Channels[first_free_channel].source_id == 0) ) {
1496  OpenAL_ErrorCheck( alGenSources(1, &Channels[first_free_channel].source_id), return -1 );
1497  }
1498  return first_free_channel;
1499 }
1500 
1514 int ds_get_free_channel_enhanced(float new_volume, int snd_id, int enhanced_priority, unsigned int enhanced_limit)
1515 {
1516  int i, first_free_channel;
1517  int instance_count; // number of instances of sound already playing
1518  // least important means lowest volume among lowest priority
1519  // note that higher priority value means lower priority
1520  int least_important_index = -1, least_important_instance_index = -1;
1521  float least_important_vol = 1.1f, least_important_instance_vol = 1.1f;
1522  int least_important_priority = -1, least_important_instance_priority = -1;
1523  channel *chp;
1524  int status;
1525 
1526  instance_count = 0;
1527  first_free_channel = -1;
1528 
1529  // Look for a channel to use to play this sample
1530  for ( i = 0; i < MAX_CHANNELS; i++ ) {
1531  chp = &Channels[i];
1532 
1533  // source not created yet
1534  if (chp->source_id == 0) {
1535  if (first_free_channel == -1) {
1536  first_free_channel = i;
1537  }
1538  continue;
1539  }
1540 
1541  // source not bound to a buffer
1542  if (chp->sid == -1) {
1543  if (first_free_channel == -1) {
1544  first_free_channel = i;
1545  }
1546  continue;
1547  }
1548 
1549  OpenAL_ErrorCheck( alGetSourcei(chp->source_id, AL_SOURCE_STATE, &status), continue );
1550 
1551  if ( (status == AL_INITIAL) || (status == AL_STOPPED) ) {
1553 
1554  if (first_free_channel == -1) {
1555  first_free_channel = i;
1556  }
1557  continue;
1558  } else {
1559  if ( chp->snd_id == snd_id ) {
1560  instance_count++;
1561 
1562  // looping or ambient soudns can't be preempted
1563  if ((chp->looping == FALSE) && !chp->is_ambient)
1564  {
1565  if (chp->priority > least_important_instance_priority) {
1566  least_important_instance_vol = chp->vol;
1567  least_important_instance_priority = chp->priority;
1568  least_important_instance_index = i;
1569  } else if ((chp->priority == least_important_instance_priority)
1570  && (chp->vol < least_important_instance_vol)) {
1571  least_important_instance_vol = chp->vol;
1572  least_important_instance_priority = chp->priority;
1573  least_important_instance_index = i;
1574  }
1575  }
1576  } else if ( chp->is_voice_msg || (chp->looping == TRUE) || chp->is_ambient ) {
1577  // a playing voice message, looping sound, or ambient sound is not allowed to be preempted.
1578  } else if ( (chp->priority > least_important_priority) ) {
1579  least_important_index = i;
1580  least_important_vol = chp->vol;
1581  least_important_priority = chp->priority;
1582  } else if ( (chp->priority == least_important_priority) && (chp->vol < least_important_vol) ) {
1583  least_important_index = i;
1584  least_important_vol = chp->vol;
1585  least_important_priority = chp->priority;
1586  }
1587  }
1588  }
1589 
1590  // If we've exceeded the limit, then stop the least important duplicate if it is lower or equal volume
1591  // otherwise, don't play the sound
1592  if ( ((unsigned int)instance_count >= enhanced_limit) && (least_important_instance_index >= 0) ) {
1593  if (least_important_instance_vol <= new_volume) {
1594  ds_close_channel_fast(least_important_instance_index);
1595  first_free_channel =least_important_instance_index;
1596  } else {
1597  // don't exceed per-sound concurrency limits, even if there are spare channels
1598  first_free_channel = -1;
1599  }
1600  } else if (first_free_channel == -1) {
1601  // we haven't reached the limit, but we have run out of channels
1602  // attempt to stop the least important sound to play our sound if priority demands it
1603  if ( (least_important_index != -1)) {
1604  // Check if the priority difference is great enough (must play or at least 2 levels away)
1605  // and if the least important sound's volume playing is less than or equal to the volume of the requested sound.
1606  // If so, then we are going to trash the least important sound.
1607  if ( (enhanced_priority == SND_ENHANCED_PRIORITY_MUST_PLAY) || (Channels[least_important_index].priority - enhanced_priority >= 2)) {
1608  if ( Channels[least_important_index].vol <= new_volume ) {
1609  ds_close_channel_fast(least_important_index);
1610  first_free_channel = least_important_index;
1611  }
1612  }
1613  }
1614  }
1615 
1616  if ( (first_free_channel >= 0) && (Channels[first_free_channel].source_id == 0) ) {
1617  OpenAL_ErrorCheck( alGenSources(1, &Channels[first_free_channel].source_id), return -1 );
1618  }
1619  return first_free_channel;
1620 }
1621 
1641 int ds_get_free_channel(float volume, int snd_id, int priority, int & enhanced_priority, const EnhancedSoundData & enhanced_sound_data)
1642 {
1643  int first_free_channel = -1;
1644  unsigned int enhanced_limit = 0;
1645 
1647  enhanced_priority = enhanced_sound_data.priority;
1648  enhanced_limit = enhanced_sound_data.limit;
1649 
1650  // exception: if retail priority is must play, we assume it's for a good reason
1651  // and thus follow suit with enhanced sound
1652  if (priority == DS_MUST_PLAY) {
1653  enhanced_priority = SND_ENHANCED_PRIORITY_MUST_PLAY;
1654  }
1655 
1656  first_free_channel = ds_get_free_channel_enhanced(volume, snd_id, enhanced_priority, enhanced_limit);
1657  } else { // enhanced sound is off
1658  first_free_channel = ds_get_free_channel_retail(volume, snd_id, priority);
1659  }
1660 
1661  return first_free_channel;
1662 }
1663 
1667 int ds_create_buffer(int frequency, int bits_per_sample, int nchannels, int nseconds)
1668 {
1669  ALuint i;
1670  int sid;
1671 
1672  if (!ds_initialized) {
1673  return -1;
1674  }
1675 
1676  sid = ds_get_sid();
1677  if ( sid == -1 ) {
1678  nprintf(("Sound","SOUND ==> No more OpenAL buffers available\n"));
1679  return -1;
1680  }
1681 
1682  OpenAL_ErrorCheck( alGenBuffers(1, &i), return -1 );
1683 
1684  sound_buffers[sid].buf_id = i;
1685  sound_buffers[sid].channel_id = -1;
1686  sound_buffers[sid].frequency = frequency;
1687  sound_buffers[sid].bits_per_sample = bits_per_sample;
1688  sound_buffers[sid].nchannels = nchannels;
1689  sound_buffers[sid].nseconds = nseconds;
1690  sound_buffers[sid].nbytes = nseconds * (bits_per_sample / 8) * nchannels * frequency;
1691 
1692  return sid;
1693 }
1694 
1698 int ds_lock_data(int sid, unsigned char *data, int size)
1699 {
1700  if ( (sid < 0) || ((size_t)sid >= sound_buffers.size()) ) {
1701  return -1;
1702  }
1703 
1704  ALenum format = openal_get_format(sound_buffers[sid].bits_per_sample, sound_buffers[sid].nchannels);
1705 
1706  if (format == AL_INVALID_VALUE) {
1707  return -1;
1708  }
1709 
1710  sound_buffers[sid].nbytes = size;
1711 
1712  OpenAL_ErrorCheck( alBufferData(sound_buffers[sid].buf_id, format, data, size, sound_buffers[sid].frequency), return -1 );
1713 
1714  return 0;
1715 }
1716 
1720 void ds_stop_easy(int sid)
1721 {
1722  Assert(sid >= 0);
1723 
1724  int cid = sound_buffers[sid].channel_id;
1725 
1726  if (cid != -1) {
1727  ALuint source_id = Channels[cid].source_id;
1728  OpenAL_ErrorPrint( alSourceStop(source_id) );
1729  }
1730 }
1731 
1738 int ds_play_easy(int sid, float volume)
1739 {
1740  if (!ds_initialized) {
1741  return -1;
1742  }
1743 
1744  int ch_idx = -1;
1747  } else {
1749  }
1750 
1751  if (ch_idx < 0) {
1752  return -1;
1753  }
1754 
1755  ALuint source_id = Channels[ch_idx].source_id;
1756 
1757  OpenAL_ErrorPrint( alSourceStop(source_id) );
1758 
1759  if (Channels[ch_idx].sid != sid) {
1760  ALuint buffer_id = sound_buffers[sid].buf_id;
1761  OpenAL_ErrorCheck( alSourcei(source_id, AL_BUFFER, buffer_id), return -1 );
1762  }
1763 
1764  Channels[ch_idx].sid = sid;
1765 
1766  OpenAL_ErrorPrint( alSourcef(source_id, AL_GAIN, volume) );
1767 
1768  OpenAL_ErrorPrint( alSourcei(source_id, AL_LOOPING, AL_FALSE) );
1769  OpenAL_ErrorPrint( alSourcei(source_id, AL_SOURCE_RELATIVE, AL_TRUE) );
1770 
1771  OpenAL_ErrorPrint( alSource3f(Channels[ch_idx].source_id, AL_POSITION, 0.0f, 0.0f, 0.0f) );
1772  OpenAL_ErrorPrint( alSource3f(Channels[ch_idx].source_id, AL_VELOCITY, 0.0f, 0.0f, 0.0f) );
1773 
1774  OpenAL_ErrorPrint( alDopplerFactor(0.0f) );
1775 
1776  OpenAL_ErrorPrint( alSourcePlay(source_id) );
1777 
1778  return 0;
1779 }
1780 
1794 int ds_play(int sid, int snd_id, int priority, const EnhancedSoundData * enhanced_sound_data, float volume, float pan, int looping, bool is_voice_msg)
1795 {
1796  int ch_idx;
1797  int enhanced_priority = SND_ENHANCED_PRIORITY_INVALID;
1798 
1799  if (!ds_initialized) {
1800  return -1;
1801  }
1802 
1803  ch_idx = ds_get_free_channel(volume, snd_id, priority, enhanced_priority, *enhanced_sound_data);
1804 
1805  if (ch_idx < 0) {
1806  return -1;
1807  }
1808 
1809  if (Channels[ch_idx].source_id == 0) {
1810  return -1;
1811  }
1812 
1813  if (pan) {
1814  OpenAL_ErrorPrint( alSource3f(Channels[ch_idx].source_id, AL_POSITION, pan, 0.0f, 1.0f) );
1815  } else {
1816  OpenAL_ErrorPrint( alSource3f(Channels[ch_idx].source_id, AL_POSITION, 0.0f, 0.0f, 0.0f) );
1817  }
1818 
1819  OpenAL_ErrorPrint( alSource3f(Channels[ch_idx].source_id, AL_VELOCITY, 0.0f, 0.0f, 0.0f) );
1820 
1821  OpenAL_ErrorPrint( alDopplerFactor(0.0f) );
1822  OpenAL_ErrorPrint( alSourcef(Channels[ch_idx].source_id, AL_PITCH, 1.0f) );
1823  OpenAL_ErrorPrint( alSourcef(Channels[ch_idx].source_id, AL_GAIN, volume) );
1824 
1825 
1826  ALint status;
1827  OpenAL_ErrorCheck( alGetSourcei(Channels[ch_idx].source_id, AL_SOURCE_STATE, &status), return -1 );
1828 
1829  if (status == AL_PLAYING) {
1830  OpenAL_ErrorPrint( alSourceStop(Channels[ch_idx].source_id) );
1831  }
1832 
1833 
1834  OpenAL_ErrorCheck( alSourcei(Channels[ch_idx].source_id, AL_BUFFER, sound_buffers[sid].buf_id), return -1 );
1835 
1836  OpenAL_ErrorPrint( alSourcei(Channels[ch_idx].source_id, AL_SOURCE_RELATIVE, AL_TRUE) );
1837 
1838  OpenAL_ErrorPrint( alSourcei(Channels[ch_idx].source_id, AL_LOOPING, (looping) ? AL_TRUE : AL_FALSE) );
1839 
1840  if (Ds_eax_inited) {
1841  OpenAL_ErrorPrint( alSource3i(Channels[ch_idx].source_id, AL_AUXILIARY_SEND_FILTER, AL_EFX_aux_id, 0, AL_FILTER_NULL) );
1842  }
1843 
1844  OpenAL_ErrorPrint( alSourcePlay(Channels[ch_idx].source_id) );
1845 
1846  sound_buffers[sid].channel_id = ch_idx;
1847 
1848  Channels[ch_idx].sid = sid;
1849  Channels[ch_idx].snd_id = snd_id;
1850  Channels[ch_idx].sig = channel_next_sig++;
1851  Channels[ch_idx].last_position = 0;
1852  Channels[ch_idx].is_voice_msg = is_voice_msg;
1853  Channels[ch_idx].vol = volume;
1854  Channels[ch_idx].looping = looping;
1855  Channels[ch_idx].priority = enhanced_priority;
1856  Channels[ch_idx].is_ambient = false; // no support for 2D ambient sounds
1857 
1858  if (channel_next_sig < 0) {
1859  channel_next_sig = 1;
1860  }
1861 
1862  return Channels[ch_idx].sig;
1863 }
1864 
1865 
1870 int ds_get_channel(int sig)
1871 {
1872  int i;
1873 
1874  for ( i = 0; i < MAX_CHANNELS; i++ ) {
1875  if ( Channels[i].source_id && (Channels[i].sig == sig) ) {
1876  if ( ds_is_channel_playing(i) == TRUE ) {
1877  return i;
1878  }
1879  }
1880  }
1881 
1882  return -1;
1883 }
1884 
1888 int ds_is_channel_playing(int channel_id)
1889 {
1890  if ( Channels[channel_id].source_id != 0 ) {
1891  ALint status;
1892 
1893  OpenAL_ErrorPrint( alGetSourcei(Channels[channel_id].source_id, AL_SOURCE_STATE, &status) );
1894 
1895  return (status == AL_PLAYING);
1896  }
1897 
1898  return 0;
1899 }
1900 
1904 void ds_stop_channel(int channel_id)
1905 {
1906  if ( Channels[channel_id].source_id != 0 ) {
1907  OpenAL_ErrorPrint( alSourceStop(Channels[channel_id].source_id) );
1908  }
1909 }
1910 
1915 {
1916  int i;
1917 
1918  for ( i=0; i<MAX_CHANNELS; i++ ) {
1919  if ( Channels[i].source_id != 0 ) {
1920  OpenAL_ErrorPrint( alSourceStop(Channels[i].source_id) );
1921  }
1922  }
1923 }
1924 
1929 void ds_set_volume( int channel_id, float vol )
1930 {
1931  if ( (channel_id < 0) || (channel_id >= MAX_CHANNELS) ) {
1932  return;
1933  }
1934 
1935  ALuint source_id = Channels[channel_id].source_id;
1936 
1937  if (source_id != 0) {
1938  CAP(vol, 0.0f, 1.0f);
1939  OpenAL_ErrorPrint( alSourcef(source_id, AL_GAIN, vol) );
1940  }
1941 }
1942 
1946 void ds_set_pan( int channel_id, float pan )
1947 {
1948  if ( (channel_id < 0) || (channel_id >= MAX_CHANNELS) ) {
1949  return;
1950  }
1951 
1952  ALint state;
1953 
1954  OpenAL_ErrorCheck( alGetSourcei(Channels[channel_id].source_id, AL_SOURCE_STATE, &state), return );
1955 
1956  if (state == AL_PLAYING) {
1957  //OpenAL_ErrorPrint( alSourcei(Channels[channel_id].source_id, AL_SOURCE_RELATIVE, AL_TRUE) );
1958  OpenAL_ErrorPrint( alSource3f(Channels[channel_id].source_id, AL_POSITION, pan, 0.0f, 1.0f) );
1959  }
1960 }
1961 
1965 int ds_get_pitch(int channel_id)
1966 {
1967  ALint status;
1968  ALfloat alpitch = 0;
1969  int pitch;
1970 
1971  if ( (channel_id < 0) || (channel_id >= MAX_CHANNELS) ) {
1972  return -1;
1973  }
1974 
1975  OpenAL_ErrorCheck( alGetSourcei(Channels[channel_id].source_id, AL_SOURCE_STATE, &status), return -1 );
1976 
1977  if (status == AL_PLAYING) {
1978  OpenAL_ErrorPrint( alGetSourcef(Channels[channel_id].source_id, AL_PITCH, &alpitch) );
1979  }
1980 
1981  // convert OpenAL values to DirectSound values and return
1982  pitch = fl2i( pow(10.0, (alpitch + 2.0)) );
1983 
1984  return pitch;
1985 }
1986 
1990 void ds_set_pitch(int channel_id, int pitch)
1991 {
1992  ALint status;
1993 
1994  if ( (channel_id < 0) || (channel_id >= MAX_CHANNELS) ) {
1995  return;
1996  }
1997 
1998  if ( pitch < MIN_PITCH ) {
1999  pitch = MIN_PITCH;
2000  }
2001 
2002  if ( pitch > MAX_PITCH ) {
2003  pitch = MAX_PITCH;
2004  }
2005 
2006  OpenAL_ErrorCheck( alGetSourcei(Channels[channel_id].source_id, AL_SOURCE_STATE, &status), return );
2007 
2008  if (status == AL_PLAYING) {
2009  ALfloat alpitch = log10f((float)pitch) - 2.0f;
2010  OpenAL_ErrorPrint( alSourcef(Channels[channel_id].source_id, AL_PITCH, alpitch) );
2011  }
2012 }
2013 
2017 void ds_chg_loop_status(int channel_id, int loop)
2018 {
2019  if ( (channel_id < 0) || (channel_id >= MAX_CHANNELS) ) {
2020  return;
2021  }
2022 
2023  ALuint source_id = Channels[channel_id].source_id;
2024 
2025  OpenAL_ErrorPrint( alSourcei(source_id, AL_LOOPING, loop ? AL_TRUE : AL_FALSE) );
2026 }
2027 
2044 int ds3d_play(int sid, int snd_id, vec3d *pos, vec3d *vel, float min, float max, int looping, float max_volume, float estimated_vol, const EnhancedSoundData * enhanced_sound_data, int priority, bool is_ambient)
2045 {
2046  int channel_id;
2047  int enhanced_priority = SND_ENHANCED_PRIORITY_INVALID;
2048 
2049 
2050  if (!ds_initialized) {
2051  return -1;
2052  }
2053 
2054  channel_id = ds_get_free_channel(estimated_vol, snd_id, priority, enhanced_priority, *enhanced_sound_data);
2055 
2056  if (channel_id < 0) {
2057  return -1;
2058  }
2059 
2060  if ( Channels[channel_id].source_id == 0 ) {
2061  return -1;
2062  }
2063 
2064  // set up 3D sound data here
2065  ds3d_update_buffer(channel_id, min, max, pos, vel);
2066 
2067 
2068  OpenAL_ErrorPrint( alSourcef(Channels[channel_id].source_id, AL_PITCH, 1.0f) );
2069 
2070  OpenAL_ErrorPrint( alSourcef(Channels[channel_id].source_id, AL_GAIN, max_volume) );
2071 
2072  ALint status;
2073  OpenAL_ErrorCheck( alGetSourcei(Channels[channel_id].source_id, AL_SOURCE_STATE, &status), return -1 );
2074 
2075  if (status == AL_PLAYING) {
2076  OpenAL_ErrorPrint( alSourceStop(Channels[channel_id].source_id) );
2077  }
2078 
2079 
2080  OpenAL_ErrorCheck( alSourcei(Channels[channel_id].source_id, AL_BUFFER, sound_buffers[sid].buf_id), return -1 );
2081 
2082  if (Ds_eax_inited) {
2083  OpenAL_ErrorPrint( alSource3i(Channels[channel_id].source_id, AL_AUXILIARY_SEND_FILTER, AL_EFX_aux_id, 0, AL_FILTER_NULL) );
2084  }
2085 
2086  OpenAL_ErrorPrint( alSourcei(Channels[channel_id].source_id, AL_SOURCE_RELATIVE, AL_FALSE) );
2087 
2088  OpenAL_ErrorPrint( alSourcei(Channels[channel_id].source_id, AL_LOOPING, (looping) ? AL_TRUE : AL_FALSE) );
2089 
2090  OpenAL_ErrorPrint( alSourcePlay(Channels[channel_id].source_id) );
2091 
2092 
2093  sound_buffers[sid].channel_id = channel_id;
2094 
2095  Channels[channel_id].sid = sid;
2096  Channels[channel_id].snd_id = snd_id;
2097  Channels[channel_id].sig = channel_next_sig++;
2098  Channels[channel_id].last_position = 0;
2099  Channels[channel_id].is_voice_msg = false;
2100  Channels[channel_id].vol = max_volume;
2101  Channels[channel_id].looping = looping;
2102  Channels[channel_id].priority = enhanced_priority;
2103  Channels[channel_id].is_ambient = is_ambient;
2104 
2105  if (channel_next_sig < 0 ) {
2106  channel_next_sig = 1;
2107  }
2108 
2109  return Channels[channel_id].sig;
2110 }
2111 
2115 void ds_set_position(int channel_id, unsigned int offset)
2116 {
2117  if ( (channel_id < 0) || (channel_id >= MAX_CHANNELS) ) {
2118  return;
2119  }
2120 
2121  OpenAL_ErrorPrint( alSourcei(Channels[channel_id].source_id, AL_BYTE_OFFSET, offset) );
2122 }
2123 
2127 unsigned int ds_get_play_position(int channel_id)
2128 {
2129  if ( (channel_id < 0) || (channel_id >= MAX_CHANNELS) ) {
2130  return 0;
2131  }
2132 
2133  ALint pos = -1;
2134  int sid = Channels[channel_id].sid;
2135 
2136  if ( (sid < 0) || ((size_t)sid >= sound_buffers.size()) ) {
2137  return 0;
2138  }
2139 
2140  if (AL_play_position) {
2141  OpenAL_ErrorPrint( alGetSourcei(Channels[channel_id].source_id, AL_BYTE_LOKI, &pos) );
2142 
2143  if ( pos < 0 ) {
2144  pos = 0;
2145  } else if ( pos > 0 ) {
2146  // AL_BYTE_LOKI returns position in canon format which may differ
2147  // from our sample, so we may have to scale it
2148  ALuint buf_id = sound_buffers[sid].buf_id;
2149  ALint size;
2150 
2151  OpenAL_ErrorCheck( alGetBufferi(buf_id, AL_SIZE, &size), return 0 );
2152 
2153  pos = (ALint)(pos * ((float)sound_buffers[sid].nbytes / size));
2154  }
2155  } else {
2156  OpenAL_ErrorPrint( alGetSourcei(Channels[channel_id].source_id, AL_BYTE_OFFSET, &pos) );
2157 
2158  if (pos < 0) {
2159  pos = 0;
2160  }
2161  }
2162 
2163  return (unsigned int) pos;
2164 }
2165 
2169 unsigned int ds_get_write_position(int channel_id)
2170 {
2171  return 0;
2172 }
2173 
2177 int ds_get_channel_size(int channel_id)
2178 {
2179  if ( (channel_id < 0) || (channel_id >= MAX_CHANNELS) ) {
2180  return 0;
2181  }
2182 
2183  int sid = Channels[channel_id].sid;
2184 
2185  if ( (sid < 0) || ((size_t)sid >= sound_buffers.size()) ) {
2186  return 0;
2187  }
2188 
2189  ALuint buf_id = sound_buffers[sid].buf_id;
2190  ALint data_size = 0;
2191 
2192  if ( (buf_id != 0) && alIsBuffer(buf_id)) {
2193  OpenAL_ErrorPrint( alGetBufferi(buf_id, AL_SIZE, &data_size) );
2194  }
2195 
2196  return (int) data_size;
2197 }
2198 
2203 {
2204  int i,n;
2205 
2206  if (!ds_initialized) {
2207  return 0;
2208  }
2209 
2210  n = 0;
2211  for ( i = 0; i < MAX_CHANNELS; i++ ) {
2212  if ( Channels[i].source_id ) {
2213  if ( ds_is_channel_playing(i) == TRUE ) {
2214  n++;
2215  }
2216  }
2217  }
2218 
2219  return n;
2220 }
2221 
2225 int ds_get_data(int sid, char *data)
2226 {
2227  return -1;
2228 }
2229 
2233 int ds_get_size(int sid, int *size)
2234 {
2235  Assert(sid >= 0);
2236 
2237  if ( (sid < 0) || ((size_t)sid >= sound_buffers.size()) ) {
2238  return 0;
2239  }
2240 
2241  ALuint buf_id = sound_buffers[sid].buf_id;
2242  ALint data_size = 0;
2243 
2244  if ( (buf_id != 0) && alIsBuffer(buf_id)) {
2245  OpenAL_ErrorPrint( alGetBufferi(buf_id, AL_SIZE, &data_size) );
2246 
2247  if (size) {
2248  *size = (int) data_size;
2249  }
2250  return 0;
2251 
2252  }
2253  return -1;
2254 }
2255 
2256 // --------------------
2257 //
2258 // EAX Functions below
2259 //
2260 // --------------------
2261 
2268 int ds_eax_set_volume(float volume)
2269 {
2270  if ( !Ds_eax_inited ) {
2271  return -1;
2272  }
2273 
2274  CAP(volume, 0.0f, 1.0f);
2275 
2276  OpenAL_ErrorPrint( v_alEffectf(AL_EFX_effect_id, AL_EAXREVERB_GAIN, volume) );
2277 
2279 
2280  return 0;
2281 }
2282 
2289 int ds_eax_set_decay_time(float seconds)
2290 {
2291  if ( !Ds_eax_inited ) {
2292  return -1;
2293  }
2294 
2295  CAP(seconds, 0.1f, 20.0f);
2296 
2297  OpenAL_ErrorPrint( v_alEffectf(AL_EFX_effect_id, AL_EAXREVERB_DECAY_TIME, seconds) );
2298 
2300 
2301  return 0;
2302 }
2303 
2310 int ds_eax_set_damping(float damp)
2311 {
2312  if ( !Ds_eax_inited ) {
2313  return -1;
2314  }
2315 
2316  CAP(damp, 0.1f, 2.0f);
2317 
2318  OpenAL_ErrorPrint( v_alEffectf(AL_EFX_effect_id, AL_EAXREVERB_DECAY_HFRATIO, damp) );
2319 
2321 
2322  return 0;
2323 }
2324 
2332 int ds_eax_set_environment(unsigned long envid)
2333 {
2334  al_efx_load_preset(envid);
2335 
2336  return 0;
2337 }
2338 
2348 int ds_eax_set_all(unsigned long id, float vol, float damping, float decay)
2349 {
2350  if ( !Ds_eax_inited ) {
2351  return -1;
2352  }
2353 
2354  // special disabled case
2355  if ( (id == EAX_ENVIRONMENT_GENERIC) && (vol == 0.0f) && (damping == 0.0f) && (decay == 0.0f) ) {
2357  Ds_active_env = -1;
2358  return 0;
2359  }
2360 
2361  al_efx_load_preset(id);
2362 
2363  CAP(vol, 0.0f, 1.0f);
2364  CAP(decay, 0.1f, 20.0f);
2365  CAP(damping, 0.1f, 2.0f);
2366 
2367  OpenAL_ErrorPrint( v_alEffectf(AL_EFX_effect_id, AL_EAXREVERB_GAIN, vol) );
2368  OpenAL_ErrorPrint( v_alEffectf(AL_EFX_effect_id, AL_EAXREVERB_DECAY_TIME, decay) );
2369  OpenAL_ErrorPrint( v_alEffectf(AL_EFX_effect_id, AL_EAXREVERB_DECAY_HFRATIO, damping) );
2370 
2372 
2373  return 0;
2374 }
2375 
2376 int ds_eax_get_preset_id(const char *name)
2377 {
2378  if ( !name || !strlen(name) ) {
2379  return -1;
2380  }
2381 
2382  size_t count = EFX_presets.size();
2383 
2384  for (size_t i = 0; i < count; i++) {
2385  if ( !stricmp(name, EFX_presets[i].name.c_str()) ) {
2386  return i;
2387  }
2388  }
2389 
2390  return -1;
2391 }
2392 
2393 int ds_eax_get_prop(EFXREVERBPROPERTIES **props, const char *name, const char *template_name)
2394 {
2395  Assert( props != NULL );
2396  Assert( name != NULL );
2397  Assert( strlen(name) > 0 ); //-V805
2398 
2399  int template_id = -1;
2400 
2401  int id = ds_eax_get_preset_id(name);
2402 
2403  if (id >= 0) {
2404  *props = &EFX_presets[id];
2405  } else {
2406  id = EFX_presets.size();
2407 
2408  EFXREVERBPROPERTIES n_prop;
2409 
2410  if ( (template_name != NULL) && (template_name[0] != '\0') ) {
2411  template_id = ds_eax_get_preset_id(template_name);
2412  }
2413 
2414  if (template_id >= 0) {
2415  n_prop = EFX_presets[template_id];
2416  n_prop.name = name;
2417  } else {
2418  n_prop.name = name;
2419  n_prop.flDensity = 1.0f;
2420  n_prop.flDiffusion = 1.0f;
2421  n_prop.flGain = 0.32f;
2422  n_prop.flGainHF = 0.89f;
2423  n_prop.flGainLF = 0.0f;
2424  n_prop.flDecayTime = 1.49f;
2425  n_prop.flDecayHFRatio = 0.83f;
2426  n_prop.flDecayLFRatio = 1.0f;
2427  n_prop.flReflectionsGain = 0.05f;
2428  n_prop.flReflectionsDelay = 0.007f;
2429  n_prop.flReflectionsPan[0] = 0.0f;
2430  n_prop.flReflectionsPan[1] = 0.0f;
2431  n_prop.flReflectionsPan[2] = 0.0f;
2432  n_prop.flLateReverbGain = 1.26f;
2433  n_prop.flLateReverbDelay = 0.011f;
2434  n_prop.flLateReverbPan[0] = 0.0f;
2435  n_prop.flLateReverbPan[1] = 0.0f;
2436  n_prop.flLateReverbPan[2] = 0.0f;
2437  n_prop.flEchoTime = 0.25f;
2438  n_prop.flEchoDepth = 0.0f;
2439  n_prop.flModulationTime = 0.25f;
2440  n_prop.flModulationDepth = 0.0f;
2441  n_prop.flAirAbsorptionGainHF = 0.994f;
2442  n_prop.flHFReference = 5000.0f;
2443  n_prop.flLFReference = 250.0f;
2444  n_prop.flRoomRolloffFactor = 0.0f;
2445  n_prop.iDecayHFLimit = AL_TRUE;
2446  }
2447 
2448  EFX_presets.push_back( n_prop );
2449 
2450  *props = &EFX_presets[id];
2451  }
2452 
2453  if ( !stricmp(name, "default") ) {
2454  extern unsigned int SND_ENV_DEFAULT;
2455  SND_ENV_DEFAULT = id;
2456  }
2457 
2458  return 0;
2459 }
2460 
2469 {
2470  if ( !er ) {
2471  return -1;
2472  }
2473 
2474  if (id < 0) {
2475  if (Ds_active_env < 0) {
2476  return -1;
2477  }
2478 
2479  er->environment = Ds_active_env;
2480 
2481  OpenAL_ErrorPrint( v_alGetEffectf(AL_EFX_effect_id, AL_EAXREVERB_GAIN, &er->fVolume) );
2484  } else if (id < (int)EFX_presets.size()) {
2485  er->environment = (unsigned int)id;
2486 
2487  er->fVolume = EFX_presets[id].flGain;
2488  er->fDecayTime_sec = EFX_presets[id].flDecayTime;
2489  er->fDamping = EFX_presets[id].flDecayHFRatio;
2490  } else {
2491  return -1;
2492  }
2493 
2494  return 0;
2495 }
2496 
2501 {
2502  if (Ds_eax_inited == 0) {
2503  return;
2504  }
2505 
2507 
2508  v_alDeleteEffects(1, &AL_EFX_effect_id);
2509  AL_EFX_effect_id = 0;
2510 
2512  AL_EFX_aux_id = 0;
2513 
2514  Ds_eax_inited = 0;
2515 }
2516 
2522 {
2523  if (Ds_eax_inited) {
2524  return 0;
2525  }
2526 
2527  try {
2528  v_alGenFilters = (ALGENFILTERS) al_load_function("alGenFilters");
2529  v_alDeleteFilters = (ALDELETEFILTERS) al_load_function("alDeleteFilters");
2530  v_alFilteri = (ALFILTERI) al_load_function("alFilteri");
2531  v_alGenEffecs = (ALGENEFFECTS) al_load_function("alGenEffects");
2532  v_alDeleteEffects = (ALDELETEEFFECTS) al_load_function("alDeleteEffects");
2533  v_alEffecti = (ALEFFECTI) al_load_function("alEffecti");
2534  v_alEffectf = (ALEFFECTF) al_load_function("alEffectf");
2535  v_alEffectfv = (ALEFFECTFV) al_load_function("alEffectfv");
2536  v_alGetEffectf = (ALGETEFFECTF) al_load_function("alGetEffectf");
2537 
2538  v_alGenAuxiliaryEffectSlots = (ALGENAUXILIARYEFFECTSLOTS) al_load_function("alGenAuxiliaryEffectSlots");
2539  v_alDeleteAuxiliaryEffectSlots = (ALDELETEAUXILIARYEFFECTSLOTS) al_load_function("alDeleteAuxiliaryEffectSlots");
2540  v_alIsAuxiliaryEffectSlot = (ALISAUXILIARYEFFECTSLOT) al_load_function("alIsAuxiliaryEffectSlot");
2541  v_alAuxiliaryEffectSloti = (ALAUXILIARYEFFECTSLOTI) al_load_function("alAuxiliaryEffectSloti");
2542  v_alAuxiliaryEffectSlotiv = (ALAUXILIARYEFFECTSLOTIV) al_load_function("alAuxiliaryEffectSlotiv");
2543  v_alAuxiliaryEffectSlotf = (ALAUXILIARYEFFECTSLOTF) al_load_function("alAuxiliaryEffectSlotf");
2544  v_alAuxiliaryEffectSlotfv = (ALAUXILIARYEFFECTSLOTFV) al_load_function("alAuxiliaryEffectSlotfv");
2545  } catch (const char *err) {
2546  mprintf(("\n EFX: Unable to load function: %s()\n", err));
2547 
2548  Ds_eax_inited = 0;
2549  return -1;
2550  }
2551 
2553 
2554  if (alGetError() != AL_NO_ERROR) {
2555  mprintf(("\n EFX: Unable to create Aux effect!\n"));
2556  return -1;
2557  }
2558 
2559  v_alGenEffecs(1, &AL_EFX_effect_id);
2560 
2561  if (alGetError() != AL_NO_ERROR) {
2562  mprintf(("\n EFX: Unable to create effect!\n"));
2563  return -1;
2564  }
2565 
2566  v_alEffecti(AL_EFX_effect_id, AL_EFFECT_TYPE, AL_EFFECT_EAXREVERB);
2567 
2568  if (alGetError() != AL_NO_ERROR) {
2569  mprintf(("\n EFX: EAXReverb not supported!\n"));
2570  return -1;
2571  }
2572 
2574 
2575  if (alGetError() != AL_NO_ERROR) {
2576  mprintf(("\n EFX: Couldn't load effect!\n"));
2577  return -1;
2578  }
2579 
2580  // add default presets
2581  EFX_presets.reserve(EAX_ENVIRONMENT_COUNT);
2582 
2583  for (int i = 0; i < EAX_ENVIRONMENT_COUNT; i++) {
2584  EFX_presets.push_back( EFX_Reverb_Defaults[i] );
2585  }
2586 
2587  Ds_eax_inited = 1;
2588 
2589  // disabled by default
2591 
2592  return 0;
2593 }
2594 
2599 {
2600  return Ds_eax_inited;
2601 }
2602 
2607 {
2608  if (!ds_initialized) {
2609  return;
2610  }
2611 
2612  int i;
2613  channel *cp = NULL;
2614 
2615  for (i = 0; i < MAX_CHANNELS; i++) {
2616  cp = &Channels[i];
2617  Assert( cp != NULL );
2618 
2619  if (cp->is_voice_msg) {
2620  if( cp->source_id == 0 ) {
2621  continue;
2622  }
2623 
2624  unsigned int current_position = ds_get_play_position(i);
2625  if (current_position != 0) {
2626  if (current_position < cp->last_position) {
2627  ds_close_channel(i);
2628  } else {
2629  cp->last_position = current_position;
2630  }
2631  }
2632  }
2633  }
2634 }
2635 
2639 int ds_get_sound_id(int channel_id)
2640 {
2641  Assert( channel_id >= 0 );
2642 
2643  return Channels[channel_id].snd_id;
2644 }
float flDiffusion
Definition: ds.h:142
GLenum GLsizei GLenum format
Definition: Gl.h:1509
int nchannels
Definition: ds.cpp:33
#define MAX_FILENAME_LEN
Definition: pstypes.h:324
int ds_init()
Definition: ds.cpp:1060
#define vm_malloc_q(size)
Definition: pstypes.h:554
int ds_get_free_channel(float volume, int snd_id, int priority, int &enhanced_priority, const EnhancedSoundData &enhanced_sound_data)
Definition: ds.cpp:1641
int i
Definition: multi_pxo.cpp:466
#define vm_free(ptr)
Definition: pstypes.h:548
ALGETEFFECTF v_alGetEffectf
Definition: ds.cpp:160
uint os_config_read_uint(const char *section, const char *name, uint default_value)
Definition: osregistry.cpp:372
#define DS_MUST_PLAY
Definition: ds.h:40
float flDecayLFRatio
Definition: ds.h:148
#define AL_EFFECTSLOT_NULL
Definition: openal.h:112
float flLateReverbPan[3]
Definition: ds.h:126
#define OpenAL_ErrorCheck(x, y)
Definition: openal.h:24
#define ALC_EFX_MINOR_VERSION
Definition: openal.h:83
int ds_eax_set_environment(unsigned long envid)
Definition: ds.cpp:2332
#define AL_BYTE_LOKI
Definition: openal.h:64
float flGainLF
Definition: ds.h:145
#define WAVE_FORMAT_ADPCM
Definition: mmreg.h:1303
WAVEFORMAT wf
Definition: config.h:160
unsigned int ds_get_play_position(int channel_id)
Definition: ds.cpp:2127
float flReflectionsPan[3]
Definition: ds.h:151
int ds_eax_set_volume(float volume)
Definition: ds.cpp:2268
#define AL_EFFECT_NULL
Definition: openal.h:78
#define AL_EAXREVERB_ECHO_TIME
Definition: openal.h:102
#define AL_EAXREVERB_DECAY_HFRATIO
Definition: openal.h:94
const char * audio_ext_list[]
Definition: audiostr.cpp:49
int ds_play(int sid, int snd_id, int priority, const EnhancedSoundData *enhanced_sound_data, float volume, float pan, int looping, bool is_voice_msg)
Definition: ds.cpp:1794
T sign(T t)
Definition: sexp.cpp:8941
#define DS_LIMIT_ONE
Definition: ds.h:41
int cfread(void *buf, int elsize, int nelem, CFILE *fp)
ALFILTERI v_alFilteri
Definition: ds.cpp:152
#define MAX_PATH
int Fred_running
Definition: fred.cpp:44
int ds_initialized
Definition: ds.cpp:229
#define AL_EAXREVERB_GAINLF
Definition: openal.h:92
void ds_set_pan(int channel_id, float pan)
Definition: ds.cpp:1946
int Cmdline_no_enhanced_sound
Definition: cmdline.cpp:392
GLenum func
Definition: Glext.h:5605
Assert(pm!=NULL)
int bits_per_sample
Definition: ds.cpp:32
Definition: pstypes.h:88
#define mprintf(args)
Definition: pstypes.h:238
void ds_set_pitch(int channel_id, int pitch)
Definition: ds.cpp:1990
void ds_stop_channel_all()
Definition: ds.cpp:1914
float flDecayTime
Definition: ds.h:146
int ds_load_buffer(int *sid, int *final_size, void *header, sound_info *si, int flags)
Load a secondary buffer with sound data.
Definition: ds.cpp:676
GLclampf f
Definition: Glext.h:7097
#define INTEL_SHORT(x)
Definition: pstypes.h:389
#define AL_EAXREVERB_GAIN
Definition: openal.h:90
#define SIZE_T_ARG
Definition: clang.h:61
ALAUXILIARYEFFECTSLOTI v_alAuxiliaryEffectSloti
Definition: ds.cpp:166
#define TRUE
Definition: pstypes.h:399
int bits
Definition: ds.h:56
ALuint source_id
Definition: channel.h:20
int ds_eax_get_all(EAX_REVERBPROPERTIES *er, int id)
Definition: ds.cpp:2468
Definition: cfile.h:28
#define AL_EAXREVERB_REFLECTIONS_GAIN
Definition: openal.h:96
#define CF_SEEK_SET
Definition: cfile.h:24
WORD nChannels
Definition: config.h:153
#define OpenAL_ErrorPrint(x)
Definition: openal.h:34
unsigned int ds_get_write_position(int channel_id)
Definition: ds.cpp:2169
#define AL_AUXILIARY_SEND_FILTER
Definition: openal.h:86
#define DS_LIMIT_TWO
Definition: ds.h:42
int ds_eax_get_preset_id(const char *name)
Definition: ds.cpp:2376
float flDecayHFRatio
Definition: ds.h:147
int cf_find_file_location_ext(const char *filename, const int ext_num, const char **ext_list, int pathtype, int max_out=0, char *pack_filename=NULL, int *size=NULL, int *offset=NULL, bool localize=false)
int n_block_align
Definition: ds.h:55
ALuint *typedef ALuint *typedef ALenum
Definition: ds.cpp:133
WORD wBitsPerSample
Definition: config.h:161
float flLateReverbDelay
Definition: ds.h:153
#define AL_EAXREVERB_LATE_REVERB_DELAY
Definition: openal.h:100
int ds_eax_set_decay_time(float seconds)
Definition: ds.cpp:2289
#define DS_LIMIT_THREE
Definition: ds.h:43
float flEchoDepth
Definition: ds.h:156
std::basic_string< char, std::char_traits< char >, std::allocator< char > > SCP_string
Definition: vmallocator.h:21
ALAUXILIARYEFFECTSLOTF v_alAuxiliaryEffectSlotf
Definition: ds.cpp:168
GLsizeiptr size
Definition: Glext.h:5496
#define Int3()
Definition: pstypes.h:292
#define WAVE_FORMAT_PCM
Definition: mmreg.h:1394
float flModulationTime
Definition: ds.h:129
unsigned int last_position
Definition: channel.h:25
#define cfopen_special(...)
Definition: cfile.h:140
#define AL_EAXREVERB_DECAY_TIME
Definition: openal.h:93
#define AL_EAXREVERB_DECAY_LFRATIO
Definition: openal.h:95
const int BUFFER_BUMP
Definition: ds.cpp:49
ALEFFECTF v_alEffectf
Definition: ds.cpp:158
#define CLAMP(x, min, max)
Definition: pstypes.h:488
float vol
Definition: channel.h:23
ALEFFECTI v_alEffecti
Definition: ds.cpp:157
float flLFReference
Definition: ds.h:161
int ds3d_update_buffer(int channel_id, float min, float max, vec3d *pos, vec3d *vel)
Definition: ds3d.cpp:35
int frequency
Definition: ds.cpp:31
typedef int(SCP_EXT_CALLCONV *SCPDLL_PFVERSION)(SCPDLL_Version *)
GLintptr offset
Definition: Glext.h:5497
int ds_create_buffer(int frequency, int bits_per_sample, int nchannels, int nseconds)
Definition: ds.cpp:1667
#define AL_EAXREVERB_LATE_REVERB_PAN
Definition: openal.h:101
float flLateReverbDelay
Definition: ds.h:125
void ds_eax_close()
Definition: ds.cpp:2500
int ds_get_channel(int sig)
Definition: ds.cpp:1870
float flDecayHFRatio
Definition: ds.h:119
unsigned int uint
Definition: pstypes.h:64
float flAirAbsorptionGainHF
Definition: ds.h:131
ALuint *typedef ALuint *typedef ALint
Definition: ds.cpp:133
#define nprintf(args)
Definition: pstypes.h:239
ALDELETEEFFECTS v_alDeleteEffects
Definition: ds.cpp:155
bool is_ambient
Definition: channel.h:27
int sample_rate
Definition: ds.h:53
GLenum GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * bits
Definition: Glext.h:10400
ALDELETEFILTERS v_alDeleteFilters
Definition: ds.cpp:150
switch(qd->index)
Definition: lua.cpp:3137
int ds_eax_is_inited()
Definition: ds.cpp:2598
char * filename
#define AL_EAXREVERB_MODULATION_DEPTH
Definition: openal.h:105
ALGENAUXILIARYEFFECTSLOTS v_alGenAuxiliaryEffectSlots
Definition: ds.cpp:162
void ds_init_buffers()
Definition: ds.cpp:1025
ALGENEFFECTS v_alGenEffecs
Definition: ds.cpp:154
#define AL_EAXREVERB_AIR_ABSORPTION_GAINHF
Definition: openal.h:106
int ACM_convert_ADPCM_to_PCM(WAVEFORMATEX *pwfxSrc, ubyte *src, int src_len, ubyte **dest, int max_dest_bytes, int *dest_len, unsigned int *src_bytes_used, int dest_bps)
Definition: acm.cpp:351
int format
Definition: ds.h:50
float flEchoTime
Definition: ds.h:155
float flRoomRolloffFactor
Definition: ds.h:162
const int NUM_AUDIO_EXT
Definition: audiostr.cpp:50
#define DS_SQ_LOW
Definition: ds.h:32
void ds_close_buffers()
Definition: ds.cpp:1330
ALDELETEAUXILIARYEFFECTSLOTS v_alDeleteAuxiliaryEffectSlots
Definition: ds.cpp:163
uint size
Definition: ds.h:52
DWORD nAvgBytesPerSec
Definition: config.h:155
void ds_init_channels()
Definition: ds.cpp:1011
unsigned int limit
Definition: sound.h:46
GLenum GLuint id
Definition: Glext.h:5156
int ds_get_size(int sid, int *size)
Definition: ds.cpp:2233
bool ds_check_for_openal_soft()
Definition: ds.cpp:1038
int looping
Definition: channel.h:22
int ds_get_data(int sid, char *data)
Definition: ds.cpp:2225
cfbp fp
Definition: cfile.cpp:1065
#define AL_EFFECT_EAXREVERB
Definition: openal.h:79
#define AL_EFFECTSLOT_EFFECT
Definition: openal.h:113
float flModulationDepth
Definition: ds.h:158
float flReflectionsPan[3]
Definition: ds.h:123
void ds_close()
Definition: ds.cpp:1344
Definition: ds.h:49
int nbytes
Definition: ds.cpp:35
float flDecayLFRatio
Definition: ds.h:120
#define AL_EAXREVERB_LATE_REVERB_GAIN
Definition: openal.h:99
float flReflectionsDelay
Definition: ds.h:150
GLclampd n
Definition: Glext.h:7286
unsigned char ubyte
Definition: pstypes.h:62
int ds_get_pitch(int channel_id)
Definition: ds.cpp:1965
int iDecayHFLimit
Definition: ds.h:163
void ds_do_frame()
Definition: ds.cpp:2606
unsigned int environment
Definition: ds.h:174
int ds_play_easy(int sid, float volume)
Definition: ds.cpp:1738
int ds_eax_set_damping(float damp)
Definition: ds.cpp:2310
#define AL_BYTE_OFFSET
Definition: openal.h:69
ALfloat *typedef ALfloat *typedef ALuint *typedef ALuint *typedef ALboolean(AL_APIENTRY *ALISAUXILIARYEFFECTSLOT)(ALuint)
Definition: ds.cpp:142
int ds_get_channel_size(int channel_id)
Definition: ds.cpp:2177
#define AL_EAXREVERB_HFREFERENCE
Definition: openal.h:107
ALint *typedef ALfloat
Definition: ds.cpp:145
void _cdecl void void _cdecl Error(const char *filename, int line, SCP_FORMAT_STRING const char *format,...) SCP_FORMAT_STRING_ARGS(3
GLbitfield flags
Definition: Glext.h:6722
#define MAX_PITCH
Definition: ds.h:28
#define vm_malloc(size)
Definition: pstypes.h:547
unsigned int SND_ENV_DEFAULT
Definition: sound.cpp:56
int ds_get_number_channels()
Definition: ds.cpp:2202
#define INTEL_INT(x)
Definition: pstypes.h:388
int ds_eax_init()
Definition: ds.cpp:2521
GLuint const GLchar * name
Definition: Glext.h:5608
#define INTEL_FLOAT(x)
Definition: pstypes.h:391
void ds_close_channel_fast(int i)
Definition: ds.cpp:1268
ov_callbacks cfile_callbacks
Definition: ogg.cpp:17
ALEFFECTFV v_alEffectfv
Definition: ds.cpp:159
WORD nBlockAlign
Definition: config.h:156
struct sound_buffer sound_buffer
int cftell(CFILE *fp)
channel * Channels
Definition: ds.cpp:46
float fDecayTime_sec
Definition: ds.h:176
void ds_chg_loop_status(int channel_id, int loop)
Definition: ds.cpp:2017
typedef float(SCP_EXT_CALLCONV *SCPTRACKIR_PFFLOATVOID)()
ALuint buf_id
Definition: ds.cpp:28
float flHFReference
Definition: ds.h:160
ALuint AL_EFX_aux_id
Definition: ds.cpp:174
#define AL_EAXREVERB_REFLECTIONS_PAN
Definition: openal.h:98
void CAP(T &v, T mn, T mx)
Definition: pstypes.h:478
#define AL_EAXREVERB_LFREFERENCE
Definition: openal.h:108
ALuint *typedef ALvoid(AL_APIENTRY *ALDELETEFILTERS)(ALsizei
Definition: ds.cpp:132
SCP_vector< sound_buffer > sound_buffers
Definition: ds.cpp:50
int ds_eax_get_prop(EFXREVERBPROPERTIES **props, const char *name, const char *template_name)
Definition: ds.cpp:2393
ubyte * data
Definition: ds.h:59
SCP_string name
Definition: ds.h:140
float flDensity
Definition: ds.h:141
const unsigned int SND_ENHANCED_MAX_LIMIT
Definition: sound.cpp:35
ALenum openal_get_format(ALint bits, ALint n_channels)
Definition: openal.cpp:78
#define AL_EAXREVERB_REFLECTIONS_DELAY
Definition: openal.h:97
int Ds_float_supported
Definition: ds.cpp:62
#define fl2i(fl)
Definition: floating.h:33
#define AL_FILTER_NULL
Definition: openal.h:76
int snd_id
Definition: channel.h:19
float flReflectionsGain
Definition: ds.h:121
EFXREVERBPROPERTIES()
Definition: ds.h:164
void ds_close_all_channels()
Definition: ds.cpp:1295
#define DS_SQ_MEDIUM
Definition: ds.h:33
Definition: multi.h:385
int ds_get_free_channel_retail(float new_volume, int snd_id, int priority)
Definition: ds.cpp:1380
unsigned short ushort
Definition: pstypes.h:63
ALCdevice * ds_sound_device
Definition: ds.cpp:171
sound_buffer()
Definition: ds.cpp:37
GLfloat GLfloat p
Definition: Glext.h:8373
SCP_vector< EFXREVERBPROPERTIES > EFX_presets
Definition: ds.cpp:128
int n_channels
Definition: ds.h:57
#define LOCATION
Definition: pstypes.h:245
int ds_get_free_channel_enhanced(float new_volume, int snd_id, int enhanced_priority, unsigned int enhanced_limit)
Definition: ds.cpp:1514
WORD wFormatTag
Definition: config.h:152
int priority
Definition: channel.h:24
bool openal_init_device(SCP_string *playback, SCP_string *capture)
Definition: openal.cpp:323
GLenum GLsizei GLenum GLenum const GLvoid * data
Definition: Gl.h:1509
int ds_eax_set_all(unsigned long id, float vol, float damping, float decay)
Definition: ds.cpp:2348
OggVorbis_File ogg_info
Definition: ds.h:51
#define ALC_MAX_AUXILIARY_SENDS
Definition: openal.h:84
float flReflectionsGain
Definition: ds.h:149
int ds_parse_sound_info(char *real_filename, sound_info *s_info)
Definition: ds.cpp:457
float flGain
Definition: ds.h:143
hull_check pos
Definition: lua.cpp:5050
#define AL_EAXREVERB_DENSITY
Definition: openal.h:88
#define MIN_PITCH
Definition: ds.h:27
ushort cfread_ushort(CFILE *file, int ver, ushort deflt)
Definition: cfile.cpp:1206
float fDamping
Definition: ds.h:177
#define AL_EAXREVERB_DECAY_HFLIMIT
Definition: openal.h:110
#define AL_EAXREVERB_ECHO_DEPTH
Definition: openal.h:103
int ds_get_sound_id(int channel_id)
Definition: ds.cpp:2639
GLint GLsizei count
Definition: Gl.h:1491
bool is_voice_msg
Definition: channel.h:26
void ds_stop_channel(int channel_id)
Definition: ds.cpp:1904
float flLateReverbPan[3]
Definition: ds.h:154
ALISAUXILIARYEFFECTSLOT v_alIsAuxiliaryEffectSlot
Definition: ds.cpp:165
void ds_stop_easy(int sid)
Definition: ds.cpp:1720
int nseconds
Definition: ds.cpp:34
DWORD nSamplesPerSec
Definition: config.h:154
#define AL_EAXREVERB_GAINHF
Definition: openal.h:91
int ds3d_play(int sid, int snd_id, vec3d *pos, vec3d *vel, float min, float max, int looping, float max_volume, float estimated_vol, const EnhancedSoundData *enhanced_sound_data, int priority, bool is_ambient)
Definition: ds.cpp:2044
int ds_parse_sound(CFILE *fp, ubyte **dest, uint *dest_size, WAVEFORMATEX **header, bool ogg, OggVorbis_File *ovf)
Parse a wave file.
Definition: ds.cpp:246
float flModulationDepth
Definition: ds.h:130
#define AL_EAXREVERB_ROOM_ROLLOFF_FACTOR
Definition: openal.h:109
float fVolume
Definition: ds.h:175
float flAirAbsorptionGainHF
Definition: ds.h:159
void ds_close_channel(int i)
Definition: ds.cpp:1241
int Ds_sound_quality
Definition: ds.cpp:61
#define DS_3D
Definition: ds.h:47
#define AL_EFFECT_TYPE
Definition: openal.h:75
ALfloat *ALGENFILTERS v_alGenFilters
Definition: ds.cpp:149
int channel_id
Definition: ds.cpp:29
float flGainHF
Definition: ds.h:144
int avg_bytes_per_sec
Definition: ds.h:54
ALAUXILIARYEFFECTSLOTFV v_alAuxiliaryEffectSlotfv
Definition: ds.cpp:169
const char * openal_error_string(int get_alc)
Definition: openal.cpp:56
float flLateReverbGain
Definition: ds.h:124
int Snd_sram
Definition: sound.cpp:52
#define ALC_EFX_MAJOR_VERSION
Definition: openal.h:82
void ds_unload_buffer(int sid)
Definition: ds.cpp:1307
int cfclose(CFILE *cfile)
Definition: cfile.cpp:895
float flLateReverbGain
Definition: ds.h:152
int ds_lock_data(int sid, unsigned char *data, int size)
Definition: ds.cpp:1698
void ds_set_volume(int channel_id, float vol)
Set the volume for a channel. The volume is expected to be in linear scale.
Definition: ds.cpp:1929
#define CF_TYPE_ANY
Definition: cfile.h:42
GLint limit
Definition: Glext.h:9797
ALAUXILIARYEFFECTSLOTIV v_alAuxiliaryEffectSlotiv
Definition: ds.cpp:167
float flRoomRolloffFactor
Definition: ds.h:134
#define FALSE
Definition: pstypes.h:400
#define DS_SQ_HIGH
Definition: ds.h:34
int ds_get_sid()
Definition: ds.cpp:644
#define stricmp(s1, s2)
Definition: config.h:271
int ds_is_channel_playing(int channel_id)
Definition: ds.cpp:1888
int sid
Definition: channel.h:21
float flModulationTime
Definition: ds.h:157
void ds_set_position(int channel_id, unsigned int offset)
Definition: ds.cpp:2115
#define AL_EAXREVERB_MODULATION_TIME
Definition: openal.h:104
ALCcontext * ds_sound_context
Definition: ds.cpp:172
GLuint GLuint end
Definition: Gl.h:1502
uint cfread_uint(CFILE *file, int ver, uint deflt)
Definition: cfile.cpp:1178
#define AL_EAXREVERB_DIFFUSION
Definition: openal.h:89
#define strcpy_s(...)
Definition: safe_strings.h:67
#define WAVE_FORMAT_IEEE_FLOAT
Definition: mmreg.h:1304
float flReflectionsDelay
Definition: ds.h:122
int sig
Definition: channel.h:18
int cfseek(CFILE *fp, int offset, int where)
#define OGG_FORMAT_VORBIS
Definition: ogg.h:15