vkQuake2 doxygen  1.0 dev
snd_mem.c
Go to the documentation of this file.
1 /*
2 Copyright (C) 1997-2001 Id Software, Inc.
3 
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8 
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 
13 See the GNU General Public License for more details.
14 
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 
19 */
20 // snd_mem.c: sound caching
21 
22 #include "client.h"
23 #include "snd_loc.h"
24 #include <inttypes.h>
25 
27 
28 byte *S_Alloc (int size);
29 
30 /*
31 ================
32 ResampleSfx
33 ================
34 */
35 void ResampleSfx (sfx_t *sfx, int inrate, int inwidth, byte *data)
36 {
37  int outcount;
38  int srcsample;
39  float stepscale;
40  int i;
41  int sample, samplefrac, fracstep;
42  sfxcache_t *sc;
43 
44  sc = sfx->cache;
45  if (!sc)
46  return;
47 
48  stepscale = (float)inrate / dma.speed; // this is usually 0.5, 1, or 2
49 
50  outcount = sc->length / stepscale;
51  sc->length = outcount;
52  if (sc->loopstart != -1)
53  sc->loopstart = sc->loopstart / stepscale;
54 
55  sc->speed = dma.speed;
56  if (s_loadas8bit->value)
57  sc->width = 1;
58  else
59  sc->width = inwidth;
60  sc->stereo = 0;
61 
62 // resample / decimate to the current source rate
63 
64  if (stepscale == 1 && inwidth == 1 && sc->width == 1)
65  {
66 // fast special case
67  for (i=0 ; i<outcount ; i++)
68  ((signed char *)sc->data)[i]
69  = (int)( (unsigned char)(data[i]) - 128);
70  }
71  else
72  {
73 // general case
74  samplefrac = 0;
75  fracstep = stepscale*256;
76  for (i=0 ; i<outcount ; i++)
77  {
78  srcsample = samplefrac >> 8;
79  samplefrac += fracstep;
80  if (inwidth == 2)
81  sample = LittleShort ( ((short *)data)[srcsample] );
82  else
83  sample = (int)( (unsigned char)(data[srcsample]) - 128) << 8;
84  if (sc->width == 2)
85  ((short *)sc->data)[i] = sample;
86  else
87  ((signed char *)sc->data)[i] = sample >> 8;
88  }
89  }
90 }
91 
92 //=============================================================================
93 
94 /*
95 ==============
96 S_LoadSound
97 ==============
98 */
100 {
101  char namebuffer[MAX_QPATH];
102  byte *data;
103  wavinfo_t info;
104  int len;
105  float stepscale;
106  sfxcache_t *sc;
107  int size;
108  char *name;
109 
110  if (s->name[0] == '*')
111  return NULL;
112 
113 // see if still in memory
114  sc = s->cache;
115  if (sc)
116  return sc;
117 
118 //Com_Printf ("S_LoadSound: %x\n", (int)stackbuf);
119 // load it in
120  if (s->truename)
121  name = s->truename;
122  else
123  name = s->name;
124 
125  if (name[0] == '#')
126  strcpy(namebuffer, &name[1]);
127  else
128  Com_sprintf (namebuffer, sizeof(namebuffer), "sound/%s", name);
129 
130 // Com_Printf ("loading %s\n",namebuffer);
131 
132  size = FS_LoadFile (namebuffer, (void **)&data);
133 
134  if (!data)
135  {
136  Com_DPrintf ("Couldn't load %s\n", namebuffer);
137  return NULL;
138  }
139 
140  info = GetWavinfo (s->name, data, size);
141  if (info.channels != 1)
142  {
143  Com_Printf ("%s is a stereo sample\n",s->name);
144  FS_FreeFile (data);
145  return NULL;
146  }
147 
148  stepscale = (float)info.rate / dma.speed;
149  len = info.samples / stepscale;
150 
151  len = len * info.width * info.channels;
152 
153  sc = s->cache = Z_Malloc (len + sizeof(sfxcache_t));
154  if (!sc)
155  {
156  FS_FreeFile (data);
157  return NULL;
158  }
159 
160  sc->length = info.samples;
161  sc->loopstart = info.loopstart;
162  sc->speed = info.rate;
163  sc->width = info.width;
164  sc->stereo = info.channels;
165 
166  ResampleSfx (s, sc->speed, sc->width, data + info.dataofs);
167 
168  FS_FreeFile (data);
169 
170  return sc;
171 }
172 
173 
174 
175 /*
176 ===============================================================================
177 
178 WAV loading
179 
180 ===============================================================================
181 */
182 
183 
184 byte *data_p;
185 byte *iff_end;
187 byte *iff_data;
189 
190 
191 short GetLittleShort(void)
192 {
193  short val = 0;
194  val = *data_p;
195  val = val + (*(data_p+1)<<8);
196  data_p += 2;
197  return val;
198 }
199 
200 int GetLittleLong(void)
201 {
202  int val = 0;
203  val = *data_p;
204  val = val + (*(data_p+1)<<8);
205  val = val + (*(data_p+2)<<16);
206  val = val + (*(data_p+3)<<24);
207  data_p += 4;
208  return val;
209 }
210 
211 void FindNextChunk(char *name)
212 {
213  while (1)
214  {
216 
217  if (data_p >= iff_end)
218  { // didn't find the chunk
219  data_p = NULL;
220  return;
221  }
222 
223  data_p += 4;
225  if (iff_chunk_len < 0)
226  {
227  data_p = NULL;
228  return;
229  }
230 // if (iff_chunk_len > 1024*1024)
231 // Sys_Error ("FindNextChunk: %i length is past the 1 meg sanity limit", iff_chunk_len);
232  data_p -= 8;
233  last_chunk = data_p + 8 + ( (iff_chunk_len + 1) & ~1 );
234  if (!strncmp(data_p, name, 4))
235  return;
236  }
237 }
238 
239 void FindChunk(char *name)
240 {
243 }
244 
245 
246 void DumpChunks(void)
247 {
248  char str[5];
249 
250  str[4] = 0;
252  do
253  {
254  memcpy (str, data_p, 4);
255  data_p += 4;
257  Com_Printf ("0x"PRIxPTR" : %s (%d)\n", (intptr_t)(data_p - 4), str, iff_chunk_len);
258  data_p += (iff_chunk_len + 1) & ~1;
259  } while (data_p < iff_end);
260 }
261 
262 /*
263 ============
264 GetWavinfo
265 ============
266 */
267 wavinfo_t GetWavinfo (char *name, byte *wav, int wavlength)
268 {
269  wavinfo_t info;
270  int i;
271  int format;
272  int samples;
273 
274  memset (&info, 0, sizeof(info));
275 
276  if (!wav)
277  return info;
278 
279  iff_data = wav;
280  iff_end = wav + wavlength;
281 
282 // find "RIFF" chunk
283  FindChunk("RIFF");
284  if (!(data_p && !strncmp(data_p+8, "WAVE", 4)))
285  {
286  Com_Printf("Missing RIFF/WAVE chunks\n");
287  return info;
288  }
289 
290 // get "fmt " chunk
291  iff_data = data_p + 12;
292 // DumpChunks ();
293 
294  FindChunk("fmt ");
295  if (!data_p)
296  {
297  Com_Printf("Missing fmt chunk\n");
298  return info;
299  }
300  data_p += 8;
302  if (format != 1)
303  {
304  Com_Printf("Microsoft PCM format only\n");
305  return info;
306  }
307 
308  info.channels = GetLittleShort();
309  info.rate = GetLittleLong();
310  data_p += 4+2;
311  info.width = GetLittleShort() / 8;
312 
313 // get cue chunk
314  FindChunk("cue ");
315  if (data_p)
316  {
317  data_p += 32;
318  info.loopstart = GetLittleLong();
319 // Com_Printf("loopstart=%d\n", sfx->loopstart);
320 
321  // if the next chunk is a LIST chunk, look for a cue length marker
322  FindNextChunk ("LIST");
323  if (data_p)
324  {
325  if (!strncmp (data_p + 28, "mark", 4))
326  { // this is not a proper parse, but it works with cooledit...
327  data_p += 24;
328  i = GetLittleLong (); // samples in loop
329  info.samples = info.loopstart + i;
330 // Com_Printf("looped length: %i\n", i);
331  }
332  }
333  }
334  else
335  info.loopstart = -1;
336 
337 // find data chunk
338  FindChunk("data");
339  if (!data_p)
340  {
341  Com_Printf("Missing data chunk\n");
342  return info;
343  }
344 
345  data_p += 4;
346  samples = GetLittleLong () / info.width;
347 
348  if (info.samples)
349  {
350  if (samples < info.samples)
351  Com_Error (ERR_DROP, "Sound %s has a bad loop length", name);
352  }
353  else
354  info.samples = samples;
355 
356  info.dataofs = data_p - wav;
357 
358  return info;
359 }
360 
MAX_QPATH
#define MAX_QPATH
Definition: q_shared.h:80
LittleShort
short LittleShort(short l)
Definition: q_shared.c:946
int
CONST PIXELFORMATDESCRIPTOR int
Definition: qgl_win.c:35
wavinfo_t::width
int width
Definition: snd_loc.h:95
sfxcache_t::length
int length
Definition: snd_loc.h:31
FindChunk
void FindChunk(char *name)
Definition: snd_mem.c:239
S_Alloc
byte * S_Alloc(int size)
wavinfo_t::channels
int channels
Definition: snd_loc.h:96
data_p
byte * data_p
Definition: snd_mem.c:184
wavinfo_t::samples
int samples
Definition: snd_loc.h:98
i
int i
Definition: q_shared.c:305
sfx_s
Definition: snd_loc.h:39
sfxcache_t::stereo
int stereo
Definition: snd_loc.h:35
FindNextChunk
void FindNextChunk(char *name)
Definition: snd_mem.c:211
GetWavinfo
wavinfo_t GetWavinfo(char *name, byte *wav, int wavlength)
Definition: snd_mem.c:267
sfxcache_t::speed
int speed
Definition: snd_loc.h:33
GetLittleShort
short GetLittleShort(void)
Definition: snd_mem.c:191
S_LoadSound
sfxcache_t * S_LoadSound(sfx_t *s)
Definition: snd_mem.c:99
playsound_s::sfx
sfx_t * sfx
Definition: snd_loc.h:53
sfx_s::cache
sfxcache_t * cache
Definition: snd_loc.h:43
ResampleSfx
void ResampleSfx(sfx_t *sfx, int inrate, int inwidth, byte *data)
Definition: snd_mem.c:35
DumpChunks
void DumpChunks(void)
Definition: snd_mem.c:246
FS_LoadFile
int FS_LoadFile(char *path, void **buffer)
Definition: files.c:398
cvar_s::value
float value
Definition: q_shared.h:331
dma_t::speed
int speed
Definition: snd_loc.h:70
cache_full_cycle
int cache_full_cycle
Definition: snd_mem.c:26
NULL
#define NULL
Definition: q_shared.h:67
dma
dma_t dma
Definition: snd_dma.c:47
Com_Error
void Com_Error(int code, char *fmt,...)
Definition: common.c:181
wavinfo_t::rate
int rate
Definition: snd_loc.h:94
Z_Malloc
void * Z_Malloc(int size)
Definition: common.c:1200
ERR_DROP
#define ERR_DROP
Definition: qcommon.h:744
name
cvar_t * name
Definition: cl_main.c:79
s
static fixed16_t s
Definition: r_scan.c:30
iff_data
byte * iff_data
Definition: snd_mem.c:187
iff_end
byte * iff_end
Definition: snd_mem.c:185
s_loadas8bit
cvar_t * s_loadas8bit
Definition: snd_dma.c:76
snd_loc.h
wavinfo_t::loopstart
int loopstart
Definition: snd_loc.h:97
format
GLsizei GLenum format
Definition: qgl_win.c:131
Com_DPrintf
void Com_DPrintf(char *fmt,...)
Definition: common.c:157
sfxcache_t
Definition: snd_loc.h:29
iff_chunk_len
int iff_chunk_len
Definition: snd_mem.c:188
FS_FreeFile
void FS_FreeFile(void *buffer)
Definition: files.c:437
sfxcache_t::data
byte data[1]
Definition: snd_loc.h:36
sfxcache_t::width
int width
Definition: snd_loc.h:34
GetLittleLong
int GetLittleLong(void)
Definition: snd_mem.c:200
sample
Definition: jar_mod.h:111
Com_Printf
void Com_Printf(char *fmt,...)
Definition: common.c:104
last_chunk
byte * last_chunk
Definition: snd_mem.c:186
wavinfo_t::dataofs
int dataofs
Definition: snd_loc.h:99
Com_sprintf
void Com_sprintf(char *dest, int size, char *fmt,...)
Definition: q_shared.c:1223
client.h
sfxcache_t::loopstart
int loopstart
Definition: snd_loc.h:32
wavinfo_t
Definition: snd_loc.h:92