UFO: Alien Invasion
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
s_sample.cpp
Go to the documentation of this file.
1 
6 /*
7 All original material Copyright (C) 2002-2020 UFO: Alien Invasion.
8 
9 This program is free software; you can redistribute it and/or
10 modify it under the terms of the GNU General Public License
11 as published by the Free Software Foundation; either version 2
12 of the License, or (at your option) any later version.
13 
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 
18 See the GNU General Public License for more details.
19 
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 
24 */
25 
26 #include "s_sample.h"
27 #include "s_main.h" /* for MAX_SOUNDIDS */
28 #include "../../common/filesys.h" /* for MAX_QPATH */
29 #include "../../common/common.h" /* for many */
30 
31 #define SAMPLE_HASH_SIZE 64
33 
34 /* an index into the sampleHash to retrieve samples by an ID/number */
35 #define SAMPLE_MAX_COUNT 1000
37 static int sampleIndexLast = 0;
38 
41 
47 static s_sample_t* S_FindByName (const char* name)
48 {
49  const unsigned hash = Com_HashKey(name, SAMPLE_HASH_SIZE);
50 
51  for (s_sample_t* sample = sampleHash[hash]; sample; sample = sample->hashNext)
52  if (Q_streq(name, sample->name))
53  return sample;
54 
55  return nullptr;
56 }
57 
58 static Mix_Chunk* S_LoadSampleChunk (const char* sound)
59 {
60  byte* buf;
61  const char* soundExtensions[] = SAMPLE_TYPES;
62  const char** extension = soundExtensions;
63 
64  if (!sound || sound[0] == '*')
65  return nullptr;
66 
67  size_t len = strlen(sound);
68  if (len + 4 >= MAX_QPATH) {
69  Com_Printf("S_LoadSound: MAX_QPATH exceeded for: '%s'\n", sound);
70  return nullptr;
71  }
72 
73  while (*extension) {
74  if ((len = FS_LoadFile(va("sound/%s.%s", sound, *extension++), &buf)) == -1)
75  continue;
76 
77  SDL_RWops* rw = SDL_RWFromMem(buf, len);
78  if (!rw){
79  FS_FreeFile(buf);
80  continue;
81  }
82 
83  Mix_Chunk* chunk = Mix_LoadWAV_RW(rw, false);
84  if (!chunk)
85  Com_Printf("S_LoadSound: %s.\n", Mix_GetError());
86 
87  FS_FreeFile(buf);
88 
89  SDL_FreeRW(rw);
90 
91  if (chunk)
92  return chunk;
93  }
94 
95  Com_Printf("S_LoadSound: Could not find sound file: '%s'\n", sound);
96  return nullptr;
97 }
98 
105 int S_LoadSampleIdx (const char* soundFile)
106 {
107  if (!s_env.initialized)
108  return 0;
109 
110  char name[MAX_QPATH];
111  Com_StripExtension(soundFile, name, sizeof(name));
112 
113  if (s_sample_t* const sample = S_FindByName(name))
114  return sample->index;
115 
116  /* make sure the sound is loaded */
117  Mix_Chunk* chunk = S_LoadSampleChunk(name);
118  if (!chunk)
119  return 0; /* couldn't load the sound's data */
120 
121  const unsigned hash = Com_HashKey(name, SAMPLE_HASH_SIZE);
123  sample->name = Mem_PoolStrDup(name, cl_soundSysPool, 0);
124  sample->chunk = chunk;
125  sample->hashNext = sampleHash[hash];
126  sampleHash[hash] = sample;
127  sampleIndex[++sampleIndexLast] = sample;
128  sample->index = sampleIndexLast;
129  return sample->index;
130 }
131 
132 s_sample_t* S_GetSample (const int soundIdx)
133 {
134  if (soundIdx > 0 && soundIdx <= sampleIndexLast)
135  return sampleIndex[soundIdx];
136  return nullptr;
137 }
138 
139 void S_FreeSamples (void)
140 {
141  for (int i = 0; i < SAMPLE_HASH_SIZE; i++)
142  for (s_sample_t* sample = sampleHash[i]; sample; sample = sample->hashNext) {
143  Mix_FreeChunk(sample->chunk);
144  Mem_Free(sample->name);
145  }
146 
147  for (int i = 0; i < SAMPLE_HASH_SIZE; i++) {
148  s_sample_t* next;
149  for (s_sample_t* sample = sampleHash[i]; sample; sample = next) {
150  next = sample->hashNext;
151  Mem_Free(sample);
152  }
153  }
154 
155  OBJZERO(sampleHash);
156  OBJZERO(sampleIndex);
157 }
158 
163 void S_PrecacheSamples (void)
164 {
165  if (!s_env.initialized)
166  return;
167 
168  /* load weapon sounds */
169  for (int i = 0; i < csi.numODs; i++) { /* i = obj */
170  const objDef_t* od = INVSH_GetItemByIDX(i);
171  for (int j = 0; j < od->numWeapons; j++) { /* j = weapon-entry per obj */
172  for (int k = 0; k < od->numFiredefs[j]; k++) { /* k = firedef per weapon */
173  const fireDef_t* fd = &od->fd[j][k];
174  if (fd->fireSound != nullptr)
175  S_LoadSample(fd->fireSound);
176  if (fd->impactSound != nullptr)
178  if (fd->hitBodySound != nullptr)
180  if (fd->bounceSound != nullptr)
182  }
183  }
184  }
185 
186  /* precache the sound pool */
187  stdSoundPool[SOUND_WATER_IN] = S_LoadSample("footsteps/water_in");
188  stdSoundPool[SOUND_WATER_OUT] = S_LoadSample("footsteps/water_out");
189  stdSoundPool[SOUND_WATER_MOVE] = S_LoadSample("footsteps/water_under");
190 }
const char * bounceSound
Definition: inv_shared.h:118
int S_LoadSampleIdx(const char *soundFile)
Loads and registers a sound file for later use.
Definition: s_sample.cpp:105
int index
Definition: s_local.h:47
this is a fire definition for our weapons/ammo
Definition: inv_shared.h:110
s_sample_t * S_LoadSample(const char *soundFile)
Loads and registers a sound file for later use.
Definition: s_main.cpp:342
const char * va(const char *format,...)
does a varargs printf into a temp buffer, so I don't need to have varargs versions of all text functi...
Definition: shared.cpp:410
static s_sample_t * sampleIndex[SAMPLE_MAX_COUNT]
Definition: s_sample.cpp:36
csi_t csi
Definition: common.cpp:39
void Com_StripExtension(const char *in, char *out, const size_t size)
Removes the file extension from a filename.
Definition: shared.cpp:259
bool initialized
Definition: s_local.h:70
fireDef_t fd[MAX_WEAPONS_PER_OBJDEF][MAX_FIREDEFS_PER_WEAPON]
Definition: inv_shared.h:314
int FS_LoadFile(const char *path, byte **buffer)
Filenames are relative to the quake search path.
Definition: files.cpp:384
void Com_Printf(const char *const fmt,...)
Definition: common.cpp:386
int numODs
Definition: q_shared.h:518
const char * hitBodySound
Definition: inv_shared.h:116
Defines all attributes of objects used in the inventory.
Definition: inv_shared.h:264
const char * impactSound
Definition: inv_shared.h:114
voidpf void * buf
Definition: ioapi.h:42
void S_PrecacheSamples(void)
Definition: s_sample.cpp:163
#define SAMPLE_MAX_COUNT
Definition: s_sample.cpp:35
static s_sample_t * sampleHash[SAMPLE_HASH_SIZE]
Definition: s_sample.cpp:32
fireDefIndex_t numFiredefs[MAX_WEAPONS_PER_OBJDEF]
Definition: inv_shared.h:315
#define OBJZERO(obj)
Definition: shared.h:178
void S_FreeSamples(void)
Definition: s_sample.cpp:139
s_sample_t * stdSoundPool[MAX_SOUNDIDS]
Definition: s_sample.cpp:40
int numWeapons
Definition: inv_shared.h:317
static wrapCache_t * hash[MAX_WRAP_HASH]
Definition: r_font.cpp:86
s_env_t s_env
Definition: s_main.cpp:40
#define SAMPLE_HASH_SIZE
Definition: s_sample.cpp:31
static Mix_Chunk * S_LoadSampleChunk(const char *sound)
Definition: s_sample.cpp:58
const char * fireSound
Definition: inv_shared.h:117
char * name
Definition: s_local.h:42
static int sampleIndexLast
Definition: s_sample.cpp:37
s_sample_t * S_GetSample(const int soundIdx)
Definition: s_sample.cpp:132
#define SAMPLE_TYPES
Supported sound file extensions.
Definition: s_local.h:39
#define MAX_QPATH
Definition: filesys.h:40
QGL_EXTERN GLint i
Definition: r_gl.h:113
QGL_EXTERN GLuint GLchar GLuint * len
Definition: r_gl.h:99
memPool_t * cl_soundSysPool
Definition: s_main.cpp:48
QGL_EXTERN GLuint GLsizei GLsizei GLint GLenum GLchar * name
Definition: r_gl.h:110
Specifies sound API?
#define Mem_Free(ptr)
Definition: mem.h:35
unsigned int Com_HashKey(const char *name, int hashsize)
returns hash key for a string
Definition: shared.cpp:336
Mix_Chunk * chunk
Definition: s_local.h:45
static s_sample_t * S_FindByName(const char *name)
Searches the hash for a given sound file.
Definition: s_sample.cpp:47
const objDef_t * INVSH_GetItemByIDX(int index)
Returns the item that belongs to the given index or nullptr if the index is invalid.
Definition: inv_shared.cpp:266
#define Q_streq(a, b)
Definition: shared.h:136
#define Mem_PoolStrDup(in, pool, tagNum)
Definition: mem.h:50
#define Mem_PoolAllocType(type, pool)
Definition: mem.h:43
uint8_t byte
Definition: ufotypes.h:34
void FS_FreeFile(void *buffer)
Definition: files.cpp:411
struct s_sample_s * hashNext
Definition: s_local.h:46