File: ambient.cpp

package info (click to toggle)
descent3 1.5.0%2Bds-1
  • links: PTS
  • area: contrib
  • in suites: forky, sid, trixie
  • size: 35,204 kB
  • sloc: cpp: 416,147; ansic: 3,233; sh: 10; makefile: 8
file content (336 lines) | stat: -rw-r--r-- 8,851 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
/*
* Descent 3 
* Copyright (C) 2024 Parallax Software
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program.  If not, see <http://www.gnu.org/licenses/>.

--- HISTORICAL COMMENTS FOLLOW ---

 * $Logfile: /DescentIII/Main/ambient.cpp $
 * $Revision: 13 $
 * $Date: 8/10/99 2:10p $
 * $Author: Gwar $
 *
 * Ambient sound system
 *
 * $Log: /DescentIII/Main/ambient.cpp $
 *
 * 13    8/10/99 2:10p Gwar
 * added sound support to neweditor
 *
 * 12    5/10/99 10:00p Ardussi
 * changes to compile on Mac
 *
 * 11    4/21/99 11:05a Kevin
 * new ps_rand and ps_srand to replace rand & srand
 *
 * 10    4/14/99 2:50a Jeff
 * fixed some case mismatched #includes
 *
 * 9     3/24/99 7:49p Jason
 * fixed multiplayer bugs
 *
 * 8     2/10/99 4:44p Jeff
 * table file parser stuff
 *
 * 7     2/10/99 2:31p Matt
 * Deleted some unused code and fixed a slightly stupid thing.
 *
 * 6     1/21/99 11:15p Jeff
 * pulled out some structs and defines from header files and moved them
 * into seperate header files so that multiplayer dlls don't require major
 * game headers, just those new headers.  Side effect is a shorter build
 * time.  Also cleaned up some header file #includes that weren't needed.
 * This affected polymodel.h, object.h, player.h, vecmat.h, room.h,
 * manage.h and multi.h
 *
 * 5     10/09/98 4:13p Matt
 * Don't specify explicit path for ambient sound pattern file.
 *
 * 4     10/08/98 4:23p Kevin
 * Changed code to comply with memory library usage. Always use mem_malloc
 * , mem_free and mem_strdup
 *
 * 3     8/20/98 12:35p Matt
 * Added nice editing for ambient sound patterns
 *
 * 2     8/17/98 8:32p Craig
 * Fixed Matt's bug.
 *
 * 1     8/17/98 7:00p Matt
 * Added ambient sound system
 *
 */

#include <stdlib.h>
#include <string.h>

#include "ambient.h"

#include "hlsoundlib.h"

#include "room.h"
#include "game.h"
#include "psrand.h"

#define MAX_AMBIENT_SOUND_PATTERNS 100
asp Ambient_sound_patterns[MAX_AMBIENT_SOUND_PATTERNS];
int Num_ambient_sound_patterns = 0;

// Computes a floating-point pseudo-random number.
// Returns value in the range 0..1, with the precision 1/D3_RAND_MAX
static float randf() { return ((float)ps_rand()) / ((float)D3_RAND_MAX); }

// Process an Ambient Sound Pattern
static void ProcessASP(asp *asp) {
  // Check for empty ASP
  if (!asp->num_sounds)
    return;

  // Decrement delay
  asp->delay -= Frametime;

  // Time to play?
  if (asp->delay < 0.0) {

    // Figure out which sound to play
    int roll = (ps_rand() * 100) / (D3_RAND_MAX + 1); // roll = 0..99
    int s;

    for (s = 0; s < asp->num_sounds; s++)
      if ((roll -= asp->sounds[s].probability) < 0)
        break;

    ASSERT(s < asp->num_sounds);

    // Play sound i
    ase *sound = &asp->sounds[s];
    float volume = sound->min_volume + (sound->max_volume - sound->min_volume) * randf();
    Sound_system.Play2dSound(sound->handle, volume);

    // Compute delay until next sound
    asp->delay = asp->min_delay + (asp->max_delay - asp->min_delay) * randf();
  }
}

// Does the ambient sound processing for one frame, maybe playing a sound or two
void DoAmbientSounds() {
  if (OBJECT_OUTSIDE(Viewer_object))
    return;

  room *rp = &Rooms[Viewer_object->roomnum];

  if (rp->ambient_sound != -1)
    ProcessASP(&Ambient_sound_patterns[rp->ambient_sound]);
}

// Initializes the ambient sounds for the current level
void InitAmbientSounds() {
  // Loop through all ambient sound patterns
  for (int p = 0; p < Num_ambient_sound_patterns; p++) {
    asp *asp = &Ambient_sound_patterns[p];

    // Initialize delay
    asp->delay = asp->min_delay + (asp->max_delay - asp->min_delay) * randf();

    // Make sure the probabilities add up
    int prob = 0;
    for (int s = 0; s < asp->num_sounds; s++)
      prob += asp->sounds[s].probability;
    if (asp->num_sounds && prob != 100) {
      Int3();
      asp->sounds[0].probability += 100 - prob; // make it total 100
    }
  }
}

#include "ddio.h"
#include "soundload.h"
#include "descent.h"
#include "mem.h"

// Close down ambient sound system and free data
static void FreeAmbientSoundData() {
  for (int p = 0; p < Num_ambient_sound_patterns; p++)
    if (Ambient_sound_patterns[p].num_sounds)
      mem_free(Ambient_sound_patterns[p].sounds);

  Num_ambient_sound_patterns = 0;
}

// Initialize the ambient sound system
void InitAmbientSoundSystem() {
  atexit(FreeAmbientSoundData);

  ReadAmbientData();

  // Get rid of deleted patterns
  for (int p = 0; p < Num_ambient_sound_patterns; p++) {

    asp *asp = &Ambient_sound_patterns[p];

    if (!asp->name[0]) {
      Ambient_sound_patterns[p] = Ambient_sound_patterns[Num_ambient_sound_patterns - 1];
      Num_ambient_sound_patterns--;
    }
  }
}

// Return the index of a named ambient sound pattern
// Returns number, or -1 if can't find
int FindAmbientSoundPattern(char *aspname) {
  if (!aspname[0])
    return -1;

  for (int i = 0; i < Num_ambient_sound_patterns; i++)
    if (stricmp(Ambient_sound_patterns[i].name, aspname) == 0)
      return i;

  return -1;
}

// Returns a pointer to the name of the specified ambient sound pattern
char *AmbientSoundPatternName(int n) { return Ambient_sound_patterns[n].name; }

#define AMBIENT_FILE_ID "ASPF"
#define AMBIENT_FILE_VERSION 0

// Reads data from the ambient sound data file
void ReadAmbientData() {
  CFILE *ifile;
  char file_id[sizeof(AMBIENT_FILE_ID)];
  int version;

  // Get rid of any old data
  FreeAmbientSoundData();

  // Build filename
  ifile = cfopen(AMBIENT_FILE_NAME, "rb");

  if (!ifile) {
    Int3();
    return;
  }

  // Read file ID
  cf_ReadBytes((uint8_t *)file_id, strlen(AMBIENT_FILE_ID), ifile);
  if (strncmp(file_id, AMBIENT_FILE_ID, strlen(AMBIENT_FILE_ID)) != 0) {
    Int3();
    cfclose(ifile);
    return;
  }

  // Read version
  version = cf_ReadInt(ifile);

  if (version > AMBIENT_FILE_VERSION) {
    Int3();
    cfclose(ifile);
    return;
  }

  // Get the number of patterns
  Num_ambient_sound_patterns = cf_ReadInt(ifile);

  // Read the patterns
  for (int p = 0; p < Num_ambient_sound_patterns; p++) {

    asp *asp = &Ambient_sound_patterns[p];

    cf_ReadString(asp->name, sizeof(asp->name), ifile);

    asp->min_delay = cf_ReadFloat(ifile);
    asp->max_delay = cf_ReadFloat(ifile);

    asp->num_sounds = cf_ReadInt(ifile);

    if (asp->num_sounds > 0)
      asp->sounds = (ase *)mem_malloc(sizeof(*asp->sounds) * asp->num_sounds);
    else
      asp->sounds = NULL;

    int prob = 0;
    for (int s = 0; s < asp->num_sounds; s++) {
      char tbuf[PAGENAME_LEN];

      cf_ReadString(tbuf, sizeof(tbuf), ifile);
      asp->sounds[s].handle = FindSoundName(IGNORE_TABLE(tbuf));

      asp->sounds[s].min_volume = cf_ReadFloat(ifile);
      asp->sounds[s].max_volume = cf_ReadFloat(ifile);
      asp->sounds[s].probability = cf_ReadInt(ifile);

      prob += asp->sounds[s].probability;
    }

    if (asp->num_sounds && (prob != 100)) {
      Int3();
      asp->sounds[0].probability += 100 - prob; // make it total 100
    }
  }

  cfclose(ifile);
}

#ifdef NEWEDITOR
extern char D3HogDir[_MAX_PATH * 2];
#endif

// Writes data from the ambient sound data file
void WriteAmbientData() {
  char filename[_MAX_PATH];
  CFILE *ofile;

#ifndef NEWEDITOR
  ddio_MakePath(filename, Base_directory_write, "data", "misc", AMBIENT_FILE_NAME, NULL);
#else
  ddio_MakePath(filename, D3HogDir, "data", "misc", AMBIENT_FILE_NAME, NULL);
#endif
  ofile = cfopen(filename, "wb");

  if (!ofile) {
    Int3();
    return;
  }

  // Write file ID & version
  cf_WriteBytes((uint8_t *)AMBIENT_FILE_ID, strlen(AMBIENT_FILE_ID), ofile);
  cf_WriteInt(ofile, AMBIENT_FILE_VERSION);

  // Write the number of patterns
  cf_WriteInt(ofile, Num_ambient_sound_patterns);

  // Read the patterns
  for (int p = 0; p < Num_ambient_sound_patterns; p++) {

    asp *asp = &Ambient_sound_patterns[p];

    cf_WriteString(ofile, asp->name);

    cf_WriteFloat(ofile, asp->min_delay);
    cf_WriteFloat(ofile, asp->max_delay);

    cf_WriteInt(ofile, asp->num_sounds);

    for (int s = 0; s < asp->num_sounds; s++) {
      cf_WriteString(ofile, Sounds[asp->sounds[s].handle].name);

      cf_WriteFloat(ofile, asp->sounds[s].min_volume);
      cf_WriteFloat(ofile, asp->sounds[s].max_volume);
      cf_WriteInt(ofile, asp->sounds[s].probability);
    }
  }

  cfclose(ofile);
}