Skip to content

Latest commit

 

History

History
583 lines (470 loc) · 17.9 KB

voc.c

File metadata and controls

583 lines (470 loc) · 17.9 KB
 
Sep 18, 2001
Sep 18, 2001
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
/*
* SDL_sound -- An abstract sound format decoding API.
* Copyright (C) 2001 Ryan C. Gordon.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
* VOC decoder for SDL_sound.
*
* This driver handles Creative Labs VOC audio data...this is a legacy format,
* but there's some game ports that could make use of such a decoder. Plus,
* VOC is fairly straightforward to decode, so this is a more complex, but
* still palatable example of an SDL_sound decoder. Y'know, in case the
* RAW decoder didn't do it for you. :)
*
* This code was ripped from a decoder I had written for SDL_mixer, which was
* largely ripped from sox v12.17.1's voc.c.
*
* SDL_mixer: http://www.libsdl.org/projects/SDL_mixer/
* sox: http://www.freshmeat.net/projects/sox/
*
Dec 26, 2001
Dec 26, 2001
35
* Please see the file COPYING in the source's root directory.
Sep 18, 2001
Sep 18, 2001
36
37
38
39
*
* This file written by Ryan C. Gordon. (icculus@clutteredmind.org)
*/
Oct 3, 2001
Oct 3, 2001
40
41
42
#if HAVE_CONFIG_H
# include <config.h>
#endif
Oct 3, 2001
Oct 3, 2001
43
Oct 4, 2001
Oct 4, 2001
44
#ifdef SOUND_SUPPORTS_VOC
Oct 3, 2001
Oct 3, 2001
45
Sep 18, 2001
Sep 18, 2001
46
47
48
49
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
Oct 3, 2001
Oct 3, 2001
50
51
52
53
54
#include "SDL_sound.h"
#define __SDL_SOUND_INTERNAL__
#include "SDL_sound_internal.h"
Sep 22, 2001
Sep 22, 2001
55
56
static int VOC_init(void);
static void VOC_quit(void);
Sep 18, 2001
Sep 18, 2001
57
58
59
static int VOC_open(Sound_Sample *sample, const char *ext);
static void VOC_close(Sound_Sample *sample);
static Uint32 VOC_read(Sound_Sample *sample);
Jan 17, 2002
Jan 17, 2002
60
static int VOC_rewind(Sound_Sample *sample);
Apr 21, 2002
Apr 21, 2002
61
static int VOC_seek(Sound_Sample *sample, Uint32 ms);
Sep 18, 2001
Sep 18, 2001
62
Nov 1, 2001
Nov 1, 2001
63
static const char *extensions_voc[] = { "VOC", NULL };
Sep 18, 2001
Sep 18, 2001
64
65
66
const Sound_DecoderFunctions __Sound_DecoderFunctions_VOC =
{
{
Nov 1, 2001
Nov 1, 2001
67
extensions_voc,
Sep 18, 2001
Sep 18, 2001
68
69
70
71
72
"Creative Labs Voice format",
"Ryan C. Gordon <icculus@clutteredmind.org>",
"http://www.icculus.org/SDL_sound/"
},
Jan 17, 2002
Jan 17, 2002
73
74
75
76
77
VOC_init, /* init() method */
VOC_quit, /* quit() method */
VOC_open, /* open() method */
VOC_close, /* close() method */
VOC_read, /* read() method */
Apr 21, 2002
Apr 21, 2002
78
79
VOC_rewind, /* rewind() method */
VOC_seek /* seek() method */
Sep 18, 2001
Sep 18, 2001
80
81
82
83
84
};
/* Private data for VOC file */
typedef struct vocstuff {
Jul 5, 2002
Jul 5, 2002
85
86
87
88
89
90
91
92
Uint32 rest; /* bytes remaining in current block */
Uint32 rate; /* rate code (byte) of this chunk */
int silent; /* sound or silence? */
Uint32 srate; /* rate code (byte) of silence */
Uint32 blockseek; /* start of current output block */
Uint32 samples; /* number of samples output */
Uint32 size; /* word length of data */
Uint8 channels; /* number of sound channels */
Sep 18, 2001
Sep 18, 2001
93
94
int extended; /* Has an extended block been read? */
Uint32 bufpos; /* byte position in internal->buffer. */
Jan 18, 2002
Jan 18, 2002
95
Uint32 start_pos; /* offset to seek to in stream when rewinding. */
Jul 5, 2002
Jul 5, 2002
96
int error; /* error condition (as opposed to EOF). */
Sep 18, 2001
Sep 18, 2001
97
98
} vs_t;
Jul 5, 2002
Jul 5, 2002
99
Sep 24, 2001
Sep 24, 2001
100
/* Size field */
Sep 18, 2001
Sep 18, 2001
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
/* SJB: note that the 1st 3 are sometimes used as sizeof(type) */
#define ST_SIZE_BYTE 1
#define ST_SIZE_8BIT 1
#define ST_SIZE_WORD 2
#define ST_SIZE_16BIT 2
#define ST_SIZE_DWORD 4
#define ST_SIZE_32BIT 4
#define ST_SIZE_FLOAT 5
#define ST_SIZE_DOUBLE 6
#define ST_SIZE_IEEE 7 /* IEEE 80-bit floats. */
/* Style field */
#define ST_ENCODING_UNSIGNED 1 /* unsigned linear: Sound Blaster */
#define ST_ENCODING_SIGN2 2 /* signed linear 2's comp: Mac */
#define ST_ENCODING_ULAW 3 /* U-law signed logs: US telephony, SPARC */
#define ST_ENCODING_ALAW 4 /* A-law signed logs: non-US telephony */
#define ST_ENCODING_ADPCM 5 /* Compressed PCM */
#define ST_ENCODING_IMA_ADPCM 6 /* Compressed PCM */
#define ST_ENCODING_GSM 7 /* GSM 6.10 33-byte frame lossy compression */
#define VOC_TERM 0
#define VOC_DATA 1
#define VOC_CONT 2
#define VOC_SILENCE 3
#define VOC_MARKER 4
#define VOC_TEXT 5
#define VOC_LOOP 6
#define VOC_LOOPEND 7
#define VOC_EXTENDED 8
#define VOC_DATA_16 9
Sep 22, 2001
Sep 22, 2001
133
134
135
136
137
138
139
140
141
142
143
144
static int VOC_init(void)
{
return(1); /* always succeeds. */
} /* VOC_init */
static void VOC_quit(void)
{
/* it's a no-op. */
} /* VOC_quit */
Jul 12, 2002
Jul 12, 2002
145
static __inline__ int voc_readbytes(SDL_RWops *src, vs_t *v, void *p, int size)
Jul 5, 2002
Jul 5, 2002
146
147
148
149
{
if (SDL_RWread(src, p, size, 1) != 1)
{
v->error = 1;
Jul 5, 2002
Jul 5, 2002
150
BAIL_MACRO("VOC: i/o error", 0);
Jul 5, 2002
Jul 5, 2002
151
152
153
154
155
156
} /* if */
return(1);
} /* voc_readbytes */
Jul 12, 2002
Jul 12, 2002
157
static __inline__ int voc_check_header(SDL_RWops *src)
Sep 18, 2001
Sep 18, 2001
158
159
160
161
{
/* VOC magic header */
Uint8 signature[20]; /* "Creative Voice File\032" */
Uint16 datablockofs;
Jul 5, 2002
Jul 5, 2002
162
vs_t v; /* dummy struct for voc_readbytes */
Sep 18, 2001
Sep 18, 2001
163
Jul 5, 2002
Jul 5, 2002
164
if (!voc_readbytes(src, &v, signature, sizeof (signature)))
Sep 18, 2001
Sep 18, 2001
165
166
return(0);
Jul 5, 2002
Jul 5, 2002
167
168
if (memcmp(signature, "Creative Voice File\032", sizeof (signature)) != 0)
{
Jul 5, 2002
Jul 5, 2002
169
BAIL_MACRO("VOC: Wrong signature; not a VOC file.", 0);
Jul 5, 2002
Jul 5, 2002
170
} /* if */
Sep 18, 2001
Sep 18, 2001
171
172
/* get the offset where the first datablock is located */
Jul 5, 2002
Jul 5, 2002
173
if (!voc_readbytes(src, &v, &datablockofs, sizeof (Uint16)))
Sep 18, 2001
Sep 18, 2001
174
175
176
177
178
return(0);
datablockofs = SDL_SwapLE16(datablockofs);
if (SDL_RWseek(src, datablockofs, SEEK_SET) != datablockofs)
Jul 5, 2002
Jul 5, 2002
179
{
Jul 5, 2002
Jul 5, 2002
180
BAIL_MACRO("VOC: Failed to seek to data block.", 0);
Jul 5, 2002
Jul 5, 2002
181
} /* if */
Sep 18, 2001
Sep 18, 2001
182
183
184
185
186
187
return(1); /* success! */
} /* voc_check_header */
/* Read next block header, save info, leave position at start of data */
Oct 25, 2003
Oct 25, 2003
188
static int voc_get_block(Sound_Sample *sample, vs_t *v)
Sep 18, 2001
Sep 18, 2001
189
190
191
192
193
194
195
196
197
198
{
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
SDL_RWops *src = internal->rw;
Uint8 bits24[3];
Uint8 uc, block;
Uint32 sblen;
Uint16 new_rate_short;
Uint32 new_rate_long;
Uint8 trash[6];
Uint16 period;
May 8, 2004
May 8, 2004
199
Uint32 bytes_per_second;
Sep 18, 2001
Sep 18, 2001
200
201
202
203
204
205
206
207
208
209
210
211
212
int i;
v->silent = 0;
while (v->rest == 0)
{
if (SDL_RWread(src, &block, sizeof (block), 1) != 1)
return 1; /* assume that's the end of the file. */
if (block == VOC_TERM)
return 1;
if (SDL_RWread(src, bits24, sizeof (bits24), 1) != 1)
return 1; /* assume that's the end of the file. */
Sep 24, 2001
Sep 24, 2001
213
Sep 18, 2001
Sep 18, 2001
214
215
216
217
218
219
/* Size is an 24-bit value. Ugh. */
sblen = ( (bits24[0]) | (bits24[1] << 8) | (bits24[2] << 16) );
switch(block)
{
case VOC_DATA:
Jul 5, 2002
Jul 5, 2002
220
if (!voc_readbytes(src, v, &uc, sizeof (uc)))
Sep 18, 2001
Sep 18, 2001
221
222
223
224
225
226
return 0;
/* When DATA block preceeded by an EXTENDED */
/* block, the DATA blocks rate value is invalid */
if (!v->extended)
{
Jul 5, 2002
Jul 5, 2002
227
BAIL_IF_MACRO(uc == 0, "VOC: Sample rate is zero?", 0);
Sep 18, 2001
Sep 18, 2001
228
229
if ((v->rate != -1) && (uc != v->rate))
Jul 5, 2002
Jul 5, 2002
230
BAIL_MACRO("VOC sample rate codes differ", 0);
Sep 18, 2001
Sep 18, 2001
231
232
233
234
v->rate = uc;
sample->actual.rate = 1000000.0/(256 - v->rate);
v->channels = 1;
Jul 5, 2002
Jul 5, 2002
235
} /* if */
Sep 18, 2001
Sep 18, 2001
236
Jul 5, 2002
Jul 5, 2002
237
if (!voc_readbytes(src, v, &uc, sizeof (uc)))
Jul 5, 2002
Jul 5, 2002
238
return(0);
Sep 18, 2001
Sep 18, 2001
239
Jul 5, 2002
Jul 5, 2002
240
BAIL_IF_MACRO(uc != 0, "VOC: only supports 8-bit data", 0);
Sep 18, 2001
Sep 18, 2001
241
242
243
244
v->extended = 0;
v->rest = sblen - 2;
v->size = ST_SIZE_BYTE;
May 8, 2004
May 8, 2004
245
246
247
248
249
250
bytes_per_second = sample->actual.rate
* sample->actual.channels;
sample->total_time += ( v->rest ) / bytes_per_second * 1000;
sample->total_time += (v->rest % bytes_per_second) * 1000
/ bytes_per_second;
Sep 18, 2001
Sep 18, 2001
251
252
253
return 1;
case VOC_DATA_16:
Jul 5, 2002
Jul 5, 2002
254
if (!voc_readbytes(src, v, &new_rate_long, sizeof (Uint32)))
Sep 18, 2001
Sep 18, 2001
255
return 0;
Jul 5, 2002
Jul 5, 2002
256
Sep 18, 2001
Sep 18, 2001
257
new_rate_long = SDL_SwapLE32(new_rate_long);
Jul 5, 2002
Jul 5, 2002
258
259
BAIL_IF_MACRO(!new_rate_long, "VOC: Sample rate is zero?", 0);
Sep 18, 2001
Sep 18, 2001
260
if ((v->rate != -1) && (new_rate_long != v->rate))
Jul 5, 2002
Jul 5, 2002
261
262
BAIL_MACRO("VOC: sample rate codes differ", 0);
Sep 18, 2001
Sep 18, 2001
263
264
265
v->rate = new_rate_long;
sample->actual.rate = new_rate_long;
Jul 5, 2002
Jul 5, 2002
266
if (!voc_readbytes(src, v, &uc, sizeof (uc)))
Sep 18, 2001
Sep 18, 2001
267
268
269
270
271
272
273
return 0;
switch (uc)
{
case 8: v->size = ST_SIZE_BYTE; break;
case 16: v->size = ST_SIZE_WORD; break;
default:
Jul 5, 2002
Jul 5, 2002
274
BAIL_MACRO("VOC: unknown data size", 0);
Jul 5, 2002
Jul 5, 2002
275
} /* switch */
Sep 18, 2001
Sep 18, 2001
276
Jul 5, 2002
Jul 5, 2002
277
if (!voc_readbytes(src, v, &v->channels, sizeof (Uint8)))
Sep 18, 2001
Sep 18, 2001
278
279
return 0;
Jul 5, 2002
Jul 5, 2002
280
if (!voc_readbytes(src, v, trash, sizeof (Uint8) * 6))
Sep 18, 2001
Sep 18, 2001
281
282
return 0;
v->rest = sblen - 12;
May 8, 2004
May 8, 2004
283
284
285
286
287
288
bytes_per_second = ((v->size == ST_SIZE_WORD) ? (2) : (1)) *
sample->actual.rate * v->channels;
sample->total_time += v->rest / bytes_per_second * 1000;
sample->total_time += ( v->rest % bytes_per_second ) * 1000
/ bytes_per_second;
Sep 18, 2001
Sep 18, 2001
289
290
291
292
293
294
295
return 1;
case VOC_CONT:
v->rest = sblen;
return 1;
case VOC_SILENCE:
Jul 5, 2002
Jul 5, 2002
296
if (!voc_readbytes(src, v, &period, sizeof (period)))
Sep 18, 2001
Sep 18, 2001
297
return 0;
Jul 5, 2002
Jul 5, 2002
298
Sep 18, 2001
Sep 18, 2001
299
300
period = SDL_SwapLE16(period);
Jul 5, 2002
Jul 5, 2002
301
if (!voc_readbytes(src, v, &uc, sizeof (uc)))
Sep 18, 2001
Sep 18, 2001
302
return 0;
Jul 5, 2002
Jul 5, 2002
303
Jul 5, 2002
Jul 5, 2002
304
BAIL_IF_MACRO(uc == 0, "VOC: silence sample rate is zero", 0);
Sep 18, 2001
Sep 18, 2001
305
306
307
308
309
310
311
312
313
314
315
316
/*
* Some silence-packed files have gratuitously
* different sample rate codes in silence.
* Adjust period.
*/
if ((v->rate != -1) && (uc != v->rate))
period = (period * (256 - uc))/(256 - v->rate);
else
v->rate = uc;
v->rest = period;
v->silent = 1;
May 8, 2004
May 8, 2004
317
318
319
sample->total_time += (period) / (v->rate) * 1000;
sample->total_time += (period % v->rate) * 1000 / v->rate;
Sep 18, 2001
Sep 18, 2001
320
321
322
323
324
325
return 1;
case VOC_LOOP:
case VOC_LOOPEND:
for(i = 0; i < sblen; i++) /* skip repeat loops. */
{
Jul 5, 2002
Jul 5, 2002
326
if (!voc_readbytes(src, v, trash, sizeof (Uint8)))
Sep 18, 2001
Sep 18, 2001
327
return 0;
Jul 5, 2002
Jul 5, 2002
328
} /* for */
Sep 18, 2001
Sep 18, 2001
329
330
331
332
333
334
335
336
break;
case VOC_EXTENDED:
/* An Extended block is followed by a data block */
/* Set this byte so we know to use the rate */
/* value from the extended block and not the */
/* data block. */
v->extended = 1;
Jul 5, 2002
Jul 5, 2002
337
if (!voc_readbytes(src, v, &new_rate_short, sizeof (Uint16)))
Sep 18, 2001
Sep 18, 2001
338
return 0;
Jul 5, 2002
Jul 5, 2002
339
Sep 18, 2001
Sep 18, 2001
340
new_rate_short = SDL_SwapLE16(new_rate_short);
Jul 5, 2002
Jul 5, 2002
341
342
BAIL_IF_MACRO(!new_rate_short, "VOC: sample rate is zero", 0);
Sep 18, 2001
Sep 18, 2001
343
if ((v->rate != -1) && (new_rate_short != v->rate))
Jul 5, 2002
Jul 5, 2002
344
345
BAIL_MACRO("VOC: sample rate codes differ", 0);
Sep 18, 2001
Sep 18, 2001
346
347
v->rate = new_rate_short;
Jul 5, 2002
Jul 5, 2002
348
if (!voc_readbytes(src, v, &uc, sizeof (uc)))
Sep 18, 2001
Sep 18, 2001
349
350
return 0;
Jul 5, 2002
Jul 5, 2002
351
BAIL_IF_MACRO(uc != 0, "VOC: only supports 8-bit data", 0);
Sep 18, 2001
Sep 18, 2001
352
Jul 5, 2002
Jul 5, 2002
353
if (!voc_readbytes(src, v, &uc, sizeof (uc)))
Sep 18, 2001
Sep 18, 2001
354
355
356
357
return 0;
if (uc)
sample->actual.channels = 2; /* Stereo */
Jul 5, 2002
Jul 5, 2002
358
Sep 18, 2001
Sep 18, 2001
359
360
361
362
363
364
365
366
367
368
/* Needed number of channels before finishing
compute for rate */
sample->actual.rate =
(256000000L/(65536L - v->rate)) / sample->actual.channels;
/* An extended block must be followed by a data */
/* block to be valid so loop back to top so it */
/* can be grabed. */
continue;
case VOC_MARKER:
Jul 5, 2002
Jul 5, 2002
369
if (!voc_readbytes(src, v, trash, sizeof (Uint8) * 2))
Sep 18, 2001
Sep 18, 2001
370
371
372
373
374
return 0;
/* Falling! Falling! */
default: /* text block or other krapola. */
Jul 5, 2002
Jul 5, 2002
375
376
377
378
379
for(i = 0; i < sblen; i++) /* skip repeat loops. */
{
if (!voc_readbytes(src, v, trash, sizeof (Uint8)))
return 0;
} /* for */
Sep 18, 2001
Sep 18, 2001
380
381
382
if (block == VOC_TEXT)
continue; /* get next block */
Jul 5, 2002
Jul 5, 2002
383
384
} /* switch */
} /* while */
Sep 18, 2001
Sep 18, 2001
385
386
return 1;
May 20, 2002
May 20, 2002
387
} /* voc_get_block */
Sep 18, 2001
Sep 18, 2001
388
389
May 20, 2002
May 20, 2002
390
static int voc_read_waveform(Sound_Sample *sample, int fill_buf, Uint32 max)
Sep 18, 2001
Sep 18, 2001
391
392
393
394
395
396
397
398
399
400
{
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
SDL_RWops *src = internal->rw;
vs_t *v = (vs_t *) internal->decoder_private;
int done = 0;
Uint8 silence = 0x80;
Uint8 *buf = internal->buffer;
if (v->rest == 0)
{
Oct 25, 2003
Oct 25, 2003
401
if (!voc_get_block(sample, v))
Sep 18, 2001
Sep 18, 2001
402
return 0;
May 20, 2002
May 20, 2002
403
} /* if */
Sep 18, 2001
Sep 18, 2001
404
405
406
407
if (v->rest == 0)
return 0;
May 20, 2002
May 20, 2002
408
409
max = (v->rest < max) ? v->rest : max;
Sep 18, 2001
Sep 18, 2001
410
411
412
413
414
415
if (v->silent)
{
if (v->size == ST_SIZE_WORD)
silence = 0x00;
/* Fill in silence */
May 20, 2002
May 20, 2002
416
417
418
419
420
421
if (fill_buf)
memset(buf + v->bufpos, silence, max);
done = max;
v->rest -= done;
} /* if */
Sep 18, 2001
Sep 18, 2001
422
423
424
else
{
May 20, 2002
May 20, 2002
425
if (fill_buf)
Jul 5, 2002
Jul 5, 2002
426
{
May 20, 2002
May 20, 2002
427
done = SDL_RWread(src, buf + v->bufpos, 1, max);
Jul 5, 2002
Jul 5, 2002
428
429
if (done < max)
{
Jul 5, 2002
Jul 5, 2002
430
__Sound_SetError("VOC: i/o error");
Jul 5, 2002
Jul 5, 2002
431
432
433
434
sample->flags |= SOUND_SAMPLEFLAG_ERROR;
} /* if */
} /* if */
May 20, 2002
May 20, 2002
435
436
437
438
439
440
441
442
443
else
{
int cur, rc;
cur = SDL_RWtell(src);
if (cur >= 0)
{
rc = SDL_RWseek(src, max, SEEK_CUR);
if (rc >= 0)
done = rc - cur;
Jul 5, 2002
Jul 5, 2002
444
445
else
{
Jul 5, 2002
Jul 5, 2002
446
__Sound_SetError("VOC: seek error");
Jul 5, 2002
Jul 5, 2002
447
448
sample->flags |= SOUND_SAMPLEFLAG_ERROR;
} /* else */
May 20, 2002
May 20, 2002
449
450
451
} /* if */
} /* else */
Sep 18, 2001
Sep 18, 2001
452
453
v->rest -= done;
v->bufpos += done;
May 20, 2002
May 20, 2002
454
} /* else */
Sep 18, 2001
Sep 18, 2001
455
Jul 5, 2002
Jul 5, 2002
456
return(done);
Sep 19, 2001
Sep 19, 2001
457
} /* voc_read_waveform */
Sep 18, 2001
Sep 18, 2001
458
459
460
461
462
463
464
465
466
467
468
469
470
471
static int VOC_open(Sound_Sample *sample, const char *ext)
{
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
vs_t *v = NULL;
if (!voc_check_header(internal->rw))
return(0);
v = (vs_t *) malloc(sizeof (vs_t));
BAIL_IF_MACRO(v == NULL, ERR_OUT_OF_MEMORY, 0);
memset(v, '\0', sizeof (vs_t));
Jan 18, 2002
Jan 18, 2002
472
v->start_pos = SDL_RWtell(internal->rw);
Sep 18, 2001
Sep 18, 2001
473
v->rate = -1;
Oct 25, 2003
Oct 25, 2003
474
if (!voc_get_block(sample, v))
Sep 18, 2001
Sep 18, 2001
475
476
477
478
479
480
481
482
{
free(v);
return(0);
} /* if */
if (v->rate == -1)
{
free(v);
Jul 5, 2002
Jul 5, 2002
483
BAIL_MACRO("VOC: data had no sound!", 0);
Sep 18, 2001
Sep 18, 2001
484
485
} /* if */
Sep 24, 2001
Sep 24, 2001
486
SNDDBG(("VOC: Accepting data stream.\n"));
Sep 18, 2001
Sep 18, 2001
487
488
sample->actual.format = (v->size == ST_SIZE_WORD) ? AUDIO_S16LSB:AUDIO_U8;
sample->actual.channels = v->channels;
May 20, 2002
May 20, 2002
489
sample->flags = SOUND_SAMPLEFLAG_CANSEEK;
Sep 13, 2003
Sep 13, 2003
490
internal->decoder_private = v;
Sep 18, 2001
Sep 18, 2001
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
return(1);
} /* VOC_open */
static void VOC_close(Sound_Sample *sample)
{
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
free(internal->decoder_private);
} /* VOC_close */
static Uint32 VOC_read(Sound_Sample *sample)
{
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
vs_t *v = (vs_t *) internal->decoder_private;
v->bufpos = 0;
while (v->bufpos < internal->buffer_size)
{
May 20, 2002
May 20, 2002
510
Uint32 rc = voc_read_waveform(sample, 1, internal->buffer_size);
Jul 5, 2002
Jul 5, 2002
511
if (rc == 0)
Sep 18, 2001
Sep 18, 2001
512
{
Jul 5, 2002
Jul 5, 2002
513
514
515
sample->flags |= (v->error) ?
SOUND_SAMPLEFLAG_ERROR :
SOUND_SAMPLEFLAG_EOF;
Sep 18, 2001
Sep 18, 2001
516
517
518
break;
} /* if */
Oct 25, 2003
Oct 25, 2003
519
if (!voc_get_block(sample, v))
Sep 18, 2001
Sep 18, 2001
520
{
Jul 5, 2002
Jul 5, 2002
521
522
523
sample->flags |= (v->error) ?
SOUND_SAMPLEFLAG_ERROR :
SOUND_SAMPLEFLAG_EOF;
Sep 18, 2001
Sep 18, 2001
524
525
526
527
528
529
530
break;
} /* if */
} /* while */
return(v->bufpos);
} /* VOC_read */
Jan 17, 2002
Jan 17, 2002
531
532
533
static int VOC_rewind(Sound_Sample *sample)
{
Jan 18, 2002
Jan 18, 2002
534
535
536
537
538
539
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
vs_t *v = (vs_t *) internal->decoder_private;
int rc = SDL_RWseek(internal->rw, v->start_pos, SEEK_SET);
BAIL_IF_MACRO(rc != v->start_pos, ERR_IO_ERROR, 0);
v->rest = 0;
return(1);
Jan 17, 2002
Jan 17, 2002
540
541
} /* VOC_rewind */
Apr 21, 2002
Apr 21, 2002
542
543
544
static int VOC_seek(Sound_Sample *sample, Uint32 ms)
{
May 20, 2002
May 20, 2002
545
546
547
548
549
550
551
552
553
/*
* VOCs don't lend themselves well to seeking, since you have to
* parse each section, which is an arbitrary size. The best we can do
* is rewind, set a flag saying not to write the waveforms to a buffer,
* and decode to the point that we want. Ugh. Fortunately, there's
* really no such thing as a large VOC, due to the era and hardware that
* spawned them, so even though this is inefficient, this is still a
* relatively fast operation in most cases.
*/
Apr 21, 2002
Apr 21, 2002
554
May 20, 2002
May 20, 2002
555
556
557
558
559
560
561
562
563
564
565
566
567
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
vs_t *v = (vs_t *) internal->decoder_private;
int offset = __Sound_convertMsToBytePos(&sample->actual, ms);
int origpos = SDL_RWtell(internal->rw);
int origrest = v->rest;
BAIL_IF_MACRO(!VOC_rewind(sample), NULL, 0);
v->bufpos = 0;
while (offset > 0)
{
Uint32 rc = voc_read_waveform(sample, 0, offset);
Oct 25, 2003
Oct 25, 2003
568
if ( (rc == 0) || (!voc_get_block(sample, v)) )
May 20, 2002
May 20, 2002
569
570
571
572
573
574
575
576
577
578
579
{
SDL_RWseek(internal->rw, origpos, SEEK_SET);
v->rest = origrest;
return(0);
} /* if */
offset -= rc;
} /* while */
return(1);
} /* VOC_seek */
Apr 21, 2002
Apr 21, 2002
580
Sep 24, 2001
Sep 24, 2001
581
#endif /* SOUND_SUPPORTS_VOC */
Sep 18, 2001
Sep 18, 2001
582
583
/* end of voc.c ... */