Mercurial > SDL_sound_CoreAudio
annotate decoders/voc.c @ 474:c66080364dff
Most decoders now report total sample play time, now. Technically, this
breaks binary compatibility with the 1.0 branch, since it extends the
Sound_Sample struct, but most (all?) programs are just passing pointers
allocated by SDL_sound around, and might be okay.
Source-level compatibility is not broken...yet! :)
--ryan.
-------- Original Message --------
Subject: SDL_sound patch: Finding total length of time of sound file.
Date: Sun, 26 Jan 2003 09:31:17 -0800 (PST)
Hi Ryan,
I am working with Eric Wing and helping him modify
SDL_sound. AS part of our efforts in improving and
enhancing SDL_sound, we like to submit this patch. We
modified the codecs to find the total time of a sound
file. Below is the explanation of the patch. The
patch is appended as an attachment to this email.
* MOTIVATION:
We needed the ability to get the total play time of a
sample (And we noticed that we're not the only ones).
Since SDL_sound blocks direct access to the specific
decoders, there is no way for a user to know this
information short of decoding the whole thing.
Because of this, we believe this will be a useful
addition, even though the accuracy may not be perfect
(subject to each decoder) or the information may not
always be available.
* CONTRIBUTORS:
Wesley Leong (modified the majority of the codecs and
verified the results)
Eric Wing (showed everyone how to do modify codec,
modified mikmod)
Wang Lam (modified a handful of codecs, researched
into specs and int overflow)
Ahilan Anantha (modified a few codecs and helped with
integer math)
* GENERAL ISSUES:
We chose the value to be milliseconds as an Sint32.
Milliseconds because that's what Sound_Seek takes as a
parameter and -1 to allow for instances/codecs where
the value could not be determined. We are
not sure if this is the final convention you want, so
we are willing to work with you on this.
We also expect the total_time field to be set on open
and never again modified by SDL_sound. Users may
access it directly much like the sample buffer and
buffer_size. We thought about recomputing the time
on DecodeAll, but since users may seek or decode small
chunks first, not all the data may be there. So this
is better done by the user. This may be good
information to document.
Currently, all the main codecs are implemented except
for QuickTime.
author | Ryan C. Gordon <icculus@icculus.org> |
---|---|
date | Sat, 08 May 2004 08:19:50 +0000 |
parents | cd46c97e58bc |
children | 3e705c9180e5 |
rev | line source |
---|---|
14 | 1 /* |
2 * SDL_sound -- An abstract sound format decoding API. | |
3 * Copyright (C) 2001 Ryan C. Gordon. | |
4 * | |
5 * This library is free software; you can redistribute it and/or | |
6 * modify it under the terms of the GNU Lesser General Public | |
7 * License as published by the Free Software Foundation; either | |
8 * version 2.1 of the License, or (at your option) any later version. | |
9 * | |
10 * This library is distributed in the hope that it will be useful, | |
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 * Lesser General Public License for more details. | |
14 * | |
15 * You should have received a copy of the GNU Lesser General Public | |
16 * License along with this library; if not, write to the Free Software | |
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
18 */ | |
19 | |
20 /* | |
21 * VOC decoder for SDL_sound. | |
22 * | |
23 * This driver handles Creative Labs VOC audio data...this is a legacy format, | |
24 * but there's some game ports that could make use of such a decoder. Plus, | |
25 * VOC is fairly straightforward to decode, so this is a more complex, but | |
26 * still palatable example of an SDL_sound decoder. Y'know, in case the | |
27 * RAW decoder didn't do it for you. :) | |
28 * | |
29 * This code was ripped from a decoder I had written for SDL_mixer, which was | |
30 * largely ripped from sox v12.17.1's voc.c. | |
31 * | |
32 * SDL_mixer: http://www.libsdl.org/projects/SDL_mixer/ | |
33 * sox: http://www.freshmeat.net/projects/sox/ | |
34 * | |
184
47cc2de2ae36
Changed reference to "LICENSE" file to "COPYING".
Ryan C. Gordon <icculus@icculus.org>
parents:
149
diff
changeset
|
35 * Please see the file COPYING in the source's root directory. |
14 | 36 * |
37 * This file written by Ryan C. Gordon. (icculus@clutteredmind.org) | |
38 */ | |
39 | |
106
40de367eb59e
Changing my include structure to do this right.
Ryan C. Gordon <icculus@icculus.org>
parents:
104
diff
changeset
|
40 #if HAVE_CONFIG_H |
40de367eb59e
Changing my include structure to do this right.
Ryan C. Gordon <icculus@icculus.org>
parents:
104
diff
changeset
|
41 # include <config.h> |
40de367eb59e
Changing my include structure to do this right.
Ryan C. Gordon <icculus@icculus.org>
parents:
104
diff
changeset
|
42 #endif |
100
6d9fdec2f708
added config.h, added --enable-debug flag, various other changes to the build system
fingolfin
parents:
64
diff
changeset
|
43 |
114
dd95a12539fd
Changed an #if defined to #ifdef, for consistency with the other
Ryan C. Gordon <icculus@icculus.org>
parents:
106
diff
changeset
|
44 #ifdef SOUND_SUPPORTS_VOC |
104
103cfcb3c014
Updated to fix build system problem.
Ryan C. Gordon <icculus@icculus.org>
parents:
100
diff
changeset
|
45 |
14 | 46 #include <stdio.h> |
47 #include <stdlib.h> | |
48 #include <string.h> | |
49 | |
106
40de367eb59e
Changing my include structure to do this right.
Ryan C. Gordon <icculus@icculus.org>
parents:
104
diff
changeset
|
50 #include "SDL_sound.h" |
40de367eb59e
Changing my include structure to do this right.
Ryan C. Gordon <icculus@icculus.org>
parents:
104
diff
changeset
|
51 |
40de367eb59e
Changing my include structure to do this right.
Ryan C. Gordon <icculus@icculus.org>
parents:
104
diff
changeset
|
52 #define __SDL_SOUND_INTERNAL__ |
40de367eb59e
Changing my include structure to do this right.
Ryan C. Gordon <icculus@icculus.org>
parents:
104
diff
changeset
|
53 #include "SDL_sound_internal.h" |
40de367eb59e
Changing my include structure to do this right.
Ryan C. Gordon <icculus@icculus.org>
parents:
104
diff
changeset
|
54 |
47
ea58bc3b15d7
Added init() and quit() methods.
Ryan C. Gordon <icculus@icculus.org>
parents:
32
diff
changeset
|
55 static int VOC_init(void); |
ea58bc3b15d7
Added init() and quit() methods.
Ryan C. Gordon <icculus@icculus.org>
parents:
32
diff
changeset
|
56 static void VOC_quit(void); |
14 | 57 static int VOC_open(Sound_Sample *sample, const char *ext); |
58 static void VOC_close(Sound_Sample *sample); | |
59 static Uint32 VOC_read(Sound_Sample *sample); | |
221
c9772a9f5271
Initial implementation or stubs for rewind method. Other cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents:
184
diff
changeset
|
60 static int VOC_rewind(Sound_Sample *sample); |
306
c97be6e1bd27
Added framework for Sound_Seek() support.
Ryan C. Gordon <icculus@icculus.org>
parents:
301
diff
changeset
|
61 static int VOC_seek(Sound_Sample *sample, Uint32 ms); |
14 | 62 |
149
1df5c106504e
Decoders can now list multiple file extensions.
Ryan C. Gordon <icculus@icculus.org>
parents:
114
diff
changeset
|
63 static const char *extensions_voc[] = { "VOC", NULL }; |
14 | 64 const Sound_DecoderFunctions __Sound_DecoderFunctions_VOC = |
65 { | |
66 { | |
149
1df5c106504e
Decoders can now list multiple file extensions.
Ryan C. Gordon <icculus@icculus.org>
parents:
114
diff
changeset
|
67 extensions_voc, |
14 | 68 "Creative Labs Voice format", |
69 "Ryan C. Gordon <icculus@clutteredmind.org>", | |
70 "http://www.icculus.org/SDL_sound/" | |
71 }, | |
72 | |
221
c9772a9f5271
Initial implementation or stubs for rewind method. Other cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents:
184
diff
changeset
|
73 VOC_init, /* init() method */ |
c9772a9f5271
Initial implementation or stubs for rewind method. Other cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents:
184
diff
changeset
|
74 VOC_quit, /* quit() method */ |
c9772a9f5271
Initial implementation or stubs for rewind method. Other cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents:
184
diff
changeset
|
75 VOC_open, /* open() method */ |
c9772a9f5271
Initial implementation or stubs for rewind method. Other cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents:
184
diff
changeset
|
76 VOC_close, /* close() method */ |
c9772a9f5271
Initial implementation or stubs for rewind method. Other cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents:
184
diff
changeset
|
77 VOC_read, /* read() method */ |
306
c97be6e1bd27
Added framework for Sound_Seek() support.
Ryan C. Gordon <icculus@icculus.org>
parents:
301
diff
changeset
|
78 VOC_rewind, /* rewind() method */ |
c97be6e1bd27
Added framework for Sound_Seek() support.
Ryan C. Gordon <icculus@icculus.org>
parents:
301
diff
changeset
|
79 VOC_seek /* seek() method */ |
14 | 80 }; |
81 | |
82 | |
83 /* Private data for VOC file */ | |
84 typedef struct vocstuff { | |
385
9efb760c4a6b
FIXME removal and cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents:
377
diff
changeset
|
85 Uint32 rest; /* bytes remaining in current block */ |
9efb760c4a6b
FIXME removal and cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents:
377
diff
changeset
|
86 Uint32 rate; /* rate code (byte) of this chunk */ |
9efb760c4a6b
FIXME removal and cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents:
377
diff
changeset
|
87 int silent; /* sound or silence? */ |
9efb760c4a6b
FIXME removal and cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents:
377
diff
changeset
|
88 Uint32 srate; /* rate code (byte) of silence */ |
9efb760c4a6b
FIXME removal and cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents:
377
diff
changeset
|
89 Uint32 blockseek; /* start of current output block */ |
9efb760c4a6b
FIXME removal and cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents:
377
diff
changeset
|
90 Uint32 samples; /* number of samples output */ |
9efb760c4a6b
FIXME removal and cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents:
377
diff
changeset
|
91 Uint32 size; /* word length of data */ |
9efb760c4a6b
FIXME removal and cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents:
377
diff
changeset
|
92 Uint8 channels; /* number of sound channels */ |
14 | 93 int extended; /* Has an extended block been read? */ |
94 Uint32 bufpos; /* byte position in internal->buffer. */ | |
224
1bafef18dabf
Implemented rewind method.
Ryan C. Gordon <icculus@icculus.org>
parents:
221
diff
changeset
|
95 Uint32 start_pos; /* offset to seek to in stream when rewinding. */ |
385
9efb760c4a6b
FIXME removal and cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents:
377
diff
changeset
|
96 int error; /* error condition (as opposed to EOF). */ |
14 | 97 } vs_t; |
98 | |
385
9efb760c4a6b
FIXME removal and cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents:
377
diff
changeset
|
99 |
62
b13fafb976be
Changed _D macro to DBGSND.
Ryan C. Gordon <icculus@icculus.org>
parents:
47
diff
changeset
|
100 /* Size field */ |
14 | 101 /* SJB: note that the 1st 3 are sometimes used as sizeof(type) */ |
102 #define ST_SIZE_BYTE 1 | |
103 #define ST_SIZE_8BIT 1 | |
104 #define ST_SIZE_WORD 2 | |
105 #define ST_SIZE_16BIT 2 | |
106 #define ST_SIZE_DWORD 4 | |
107 #define ST_SIZE_32BIT 4 | |
108 #define ST_SIZE_FLOAT 5 | |
109 #define ST_SIZE_DOUBLE 6 | |
110 #define ST_SIZE_IEEE 7 /* IEEE 80-bit floats. */ | |
111 | |
112 /* Style field */ | |
113 #define ST_ENCODING_UNSIGNED 1 /* unsigned linear: Sound Blaster */ | |
114 #define ST_ENCODING_SIGN2 2 /* signed linear 2's comp: Mac */ | |
115 #define ST_ENCODING_ULAW 3 /* U-law signed logs: US telephony, SPARC */ | |
116 #define ST_ENCODING_ALAW 4 /* A-law signed logs: non-US telephony */ | |
117 #define ST_ENCODING_ADPCM 5 /* Compressed PCM */ | |
118 #define ST_ENCODING_IMA_ADPCM 6 /* Compressed PCM */ | |
119 #define ST_ENCODING_GSM 7 /* GSM 6.10 33-byte frame lossy compression */ | |
120 | |
121 #define VOC_TERM 0 | |
122 #define VOC_DATA 1 | |
123 #define VOC_CONT 2 | |
124 #define VOC_SILENCE 3 | |
125 #define VOC_MARKER 4 | |
126 #define VOC_TEXT 5 | |
127 #define VOC_LOOP 6 | |
128 #define VOC_LOOPEND 7 | |
129 #define VOC_EXTENDED 8 | |
130 #define VOC_DATA_16 9 | |
131 | |
132 | |
47
ea58bc3b15d7
Added init() and quit() methods.
Ryan C. Gordon <icculus@icculus.org>
parents:
32
diff
changeset
|
133 static int VOC_init(void) |
ea58bc3b15d7
Added init() and quit() methods.
Ryan C. Gordon <icculus@icculus.org>
parents:
32
diff
changeset
|
134 { |
ea58bc3b15d7
Added init() and quit() methods.
Ryan C. Gordon <icculus@icculus.org>
parents:
32
diff
changeset
|
135 return(1); /* always succeeds. */ |
ea58bc3b15d7
Added init() and quit() methods.
Ryan C. Gordon <icculus@icculus.org>
parents:
32
diff
changeset
|
136 } /* VOC_init */ |
ea58bc3b15d7
Added init() and quit() methods.
Ryan C. Gordon <icculus@icculus.org>
parents:
32
diff
changeset
|
137 |
ea58bc3b15d7
Added init() and quit() methods.
Ryan C. Gordon <icculus@icculus.org>
parents:
32
diff
changeset
|
138 |
ea58bc3b15d7
Added init() and quit() methods.
Ryan C. Gordon <icculus@icculus.org>
parents:
32
diff
changeset
|
139 static void VOC_quit(void) |
ea58bc3b15d7
Added init() and quit() methods.
Ryan C. Gordon <icculus@icculus.org>
parents:
32
diff
changeset
|
140 { |
ea58bc3b15d7
Added init() and quit() methods.
Ryan C. Gordon <icculus@icculus.org>
parents:
32
diff
changeset
|
141 /* it's a no-op. */ |
ea58bc3b15d7
Added init() and quit() methods.
Ryan C. Gordon <icculus@icculus.org>
parents:
32
diff
changeset
|
142 } /* VOC_quit */ |
ea58bc3b15d7
Added init() and quit() methods.
Ryan C. Gordon <icculus@icculus.org>
parents:
32
diff
changeset
|
143 |
ea58bc3b15d7
Added init() and quit() methods.
Ryan C. Gordon <icculus@icculus.org>
parents:
32
diff
changeset
|
144 |
401
c42ac9ee2ce4
Fixed "inline" keyword to compile.
Ryan C. Gordon <icculus@icculus.org>
parents:
387
diff
changeset
|
145 static __inline__ int voc_readbytes(SDL_RWops *src, vs_t *v, void *p, int size) |
385
9efb760c4a6b
FIXME removal and cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents:
377
diff
changeset
|
146 { |
9efb760c4a6b
FIXME removal and cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents:
377
diff
changeset
|
147 if (SDL_RWread(src, p, size, 1) != 1) |
9efb760c4a6b
FIXME removal and cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents:
377
diff
changeset
|
148 { |
9efb760c4a6b
FIXME removal and cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents:
377
diff
changeset
|
149 v->error = 1; |
387
fb519e6028e3
Changed all the Sound_SetError() calls to __Sound_SetError (or BAIL*_MACRO)
Ryan C. Gordon <icculus@icculus.org>
parents:
385
diff
changeset
|
150 BAIL_MACRO("VOC: i/o error", 0); |
385
9efb760c4a6b
FIXME removal and cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents:
377
diff
changeset
|
151 } /* if */ |
9efb760c4a6b
FIXME removal and cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents:
377
diff
changeset
|
152 |
9efb760c4a6b
FIXME removal and cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents:
377
diff
changeset
|
153 return(1); |
9efb760c4a6b
FIXME removal and cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents:
377
diff
changeset
|
154 } /* voc_readbytes */ |
9efb760c4a6b
FIXME removal and cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents:
377
diff
changeset
|
155 |
9efb760c4a6b
FIXME removal and cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents:
377
diff
changeset
|
156 |
401
c42ac9ee2ce4
Fixed "inline" keyword to compile.
Ryan C. Gordon <icculus@icculus.org>
parents:
387
diff
changeset
|
157 static __inline__ int voc_check_header(SDL_RWops *src) |
14 | 158 { |
159 /* VOC magic header */ | |
160 Uint8 signature[20]; /* "Creative Voice File\032" */ | |
161 Uint16 datablockofs; | |
385
9efb760c4a6b
FIXME removal and cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents:
377
diff
changeset
|
162 vs_t v; /* dummy struct for voc_readbytes */ |
14 | 163 |
385
9efb760c4a6b
FIXME removal and cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents:
377
diff
changeset
|
164 if (!voc_readbytes(src, &v, signature, sizeof (signature))) |
14 | 165 return(0); |
166 | |
385
9efb760c4a6b
FIXME removal and cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents:
377
diff
changeset
|
167 if (memcmp(signature, "Creative Voice File\032", sizeof (signature)) != 0) |
9efb760c4a6b
FIXME removal and cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents:
377
diff
changeset
|
168 { |
387
fb519e6028e3
Changed all the Sound_SetError() calls to __Sound_SetError (or BAIL*_MACRO)
Ryan C. Gordon <icculus@icculus.org>
parents:
385
diff
changeset
|
169 BAIL_MACRO("VOC: Wrong signature; not a VOC file.", 0); |
385
9efb760c4a6b
FIXME removal and cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents:
377
diff
changeset
|
170 } /* if */ |
14 | 171 |
172 /* get the offset where the first datablock is located */ | |
385
9efb760c4a6b
FIXME removal and cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents:
377
diff
changeset
|
173 if (!voc_readbytes(src, &v, &datablockofs, sizeof (Uint16))) |
14 | 174 return(0); |
175 | |
176 datablockofs = SDL_SwapLE16(datablockofs); | |
177 | |
178 if (SDL_RWseek(src, datablockofs, SEEK_SET) != datablockofs) | |
385
9efb760c4a6b
FIXME removal and cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents:
377
diff
changeset
|
179 { |
387
fb519e6028e3
Changed all the Sound_SetError() calls to __Sound_SetError (or BAIL*_MACRO)
Ryan C. Gordon <icculus@icculus.org>
parents:
385
diff
changeset
|
180 BAIL_MACRO("VOC: Failed to seek to data block.", 0); |
385
9efb760c4a6b
FIXME removal and cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents:
377
diff
changeset
|
181 } /* if */ |
14 | 182 |
183 return(1); /* success! */ | |
184 } /* voc_check_header */ | |
185 | |
186 | |
187 /* Read next block header, save info, leave position at start of data */ | |
468
cd46c97e58bc
Fixed broken VOC decoder...would always dereference NULL during VOC_open().
Ryan C. Gordon <icculus@icculus.org>
parents:
449
diff
changeset
|
188 static int voc_get_block(Sound_Sample *sample, vs_t *v) |
14 | 189 { |
190 Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque; | |
191 SDL_RWops *src = internal->rw; | |
192 Uint8 bits24[3]; | |
193 Uint8 uc, block; | |
194 Uint32 sblen; | |
195 Uint16 new_rate_short; | |
196 Uint32 new_rate_long; | |
197 Uint8 trash[6]; | |
198 Uint16 period; | |
474
c66080364dff
Most decoders now report total sample play time, now. Technically, this
Ryan C. Gordon <icculus@icculus.org>
parents:
468
diff
changeset
|
199 Uint32 bytes_per_second; |
14 | 200 int i; |
201 | |
202 v->silent = 0; | |
203 while (v->rest == 0) | |
204 { | |
205 if (SDL_RWread(src, &block, sizeof (block), 1) != 1) | |
206 return 1; /* assume that's the end of the file. */ | |
207 | |
208 if (block == VOC_TERM) | |
209 return 1; | |
210 | |
211 if (SDL_RWread(src, bits24, sizeof (bits24), 1) != 1) | |
212 return 1; /* assume that's the end of the file. */ | |
62
b13fafb976be
Changed _D macro to DBGSND.
Ryan C. Gordon <icculus@icculus.org>
parents:
47
diff
changeset
|
213 |
14 | 214 /* Size is an 24-bit value. Ugh. */ |
215 sblen = ( (bits24[0]) | (bits24[1] << 8) | (bits24[2] << 16) ); | |
216 | |
217 switch(block) | |
218 { | |
219 case VOC_DATA: | |
385
9efb760c4a6b
FIXME removal and cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents:
377
diff
changeset
|
220 if (!voc_readbytes(src, v, &uc, sizeof (uc))) |
14 | 221 return 0; |
222 | |
223 /* When DATA block preceeded by an EXTENDED */ | |
224 /* block, the DATA blocks rate value is invalid */ | |
225 if (!v->extended) | |
226 { | |
387
fb519e6028e3
Changed all the Sound_SetError() calls to __Sound_SetError (or BAIL*_MACRO)
Ryan C. Gordon <icculus@icculus.org>
parents:
385
diff
changeset
|
227 BAIL_IF_MACRO(uc == 0, "VOC: Sample rate is zero?", 0); |
14 | 228 |
229 if ((v->rate != -1) && (uc != v->rate)) | |
387
fb519e6028e3
Changed all the Sound_SetError() calls to __Sound_SetError (or BAIL*_MACRO)
Ryan C. Gordon <icculus@icculus.org>
parents:
385
diff
changeset
|
230 BAIL_MACRO("VOC sample rate codes differ", 0); |
14 | 231 |
232 v->rate = uc; | |
233 sample->actual.rate = 1000000.0/(256 - v->rate); | |
234 v->channels = 1; | |
385
9efb760c4a6b
FIXME removal and cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents:
377
diff
changeset
|
235 } /* if */ |
14 | 236 |
385
9efb760c4a6b
FIXME removal and cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents:
377
diff
changeset
|
237 if (!voc_readbytes(src, v, &uc, sizeof (uc))) |
387
fb519e6028e3
Changed all the Sound_SetError() calls to __Sound_SetError (or BAIL*_MACRO)
Ryan C. Gordon <icculus@icculus.org>
parents:
385
diff
changeset
|
238 return(0); |
14 | 239 |
387
fb519e6028e3
Changed all the Sound_SetError() calls to __Sound_SetError (or BAIL*_MACRO)
Ryan C. Gordon <icculus@icculus.org>
parents:
385
diff
changeset
|
240 BAIL_IF_MACRO(uc != 0, "VOC: only supports 8-bit data", 0); |
14 | 241 |
242 v->extended = 0; | |
243 v->rest = sblen - 2; | |
244 v->size = ST_SIZE_BYTE; | |
474
c66080364dff
Most decoders now report total sample play time, now. Technically, this
Ryan C. Gordon <icculus@icculus.org>
parents:
468
diff
changeset
|
245 |
c66080364dff
Most decoders now report total sample play time, now. Technically, this
Ryan C. Gordon <icculus@icculus.org>
parents:
468
diff
changeset
|
246 bytes_per_second = sample->actual.rate |
c66080364dff
Most decoders now report total sample play time, now. Technically, this
Ryan C. Gordon <icculus@icculus.org>
parents:
468
diff
changeset
|
247 * sample->actual.channels; |
c66080364dff
Most decoders now report total sample play time, now. Technically, this
Ryan C. Gordon <icculus@icculus.org>
parents:
468
diff
changeset
|
248 sample->total_time += ( v->rest ) / bytes_per_second * 1000; |
c66080364dff
Most decoders now report total sample play time, now. Technically, this
Ryan C. Gordon <icculus@icculus.org>
parents:
468
diff
changeset
|
249 sample->total_time += (v->rest % bytes_per_second) * 1000 |
c66080364dff
Most decoders now report total sample play time, now. Technically, this
Ryan C. Gordon <icculus@icculus.org>
parents:
468
diff
changeset
|
250 / bytes_per_second; |
14 | 251 return 1; |
252 | |
253 case VOC_DATA_16: | |
385
9efb760c4a6b
FIXME removal and cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents:
377
diff
changeset
|
254 if (!voc_readbytes(src, v, &new_rate_long, sizeof (Uint32))) |
14 | 255 return 0; |
385
9efb760c4a6b
FIXME removal and cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents:
377
diff
changeset
|
256 |
14 | 257 new_rate_long = SDL_SwapLE32(new_rate_long); |
387
fb519e6028e3
Changed all the Sound_SetError() calls to __Sound_SetError (or BAIL*_MACRO)
Ryan C. Gordon <icculus@icculus.org>
parents:
385
diff
changeset
|
258 BAIL_IF_MACRO(!new_rate_long, "VOC: Sample rate is zero?", 0); |
fb519e6028e3
Changed all the Sound_SetError() calls to __Sound_SetError (or BAIL*_MACRO)
Ryan C. Gordon <icculus@icculus.org>
parents:
385
diff
changeset
|
259 |
14 | 260 if ((v->rate != -1) && (new_rate_long != v->rate)) |
387
fb519e6028e3
Changed all the Sound_SetError() calls to __Sound_SetError (or BAIL*_MACRO)
Ryan C. Gordon <icculus@icculus.org>
parents:
385
diff
changeset
|
261 BAIL_MACRO("VOC: sample rate codes differ", 0); |
fb519e6028e3
Changed all the Sound_SetError() calls to __Sound_SetError (or BAIL*_MACRO)
Ryan C. Gordon <icculus@icculus.org>
parents:
385
diff
changeset
|
262 |
14 | 263 v->rate = new_rate_long; |
264 sample->actual.rate = new_rate_long; | |
265 | |
385
9efb760c4a6b
FIXME removal and cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents:
377
diff
changeset
|
266 if (!voc_readbytes(src, v, &uc, sizeof (uc))) |
14 | 267 return 0; |
268 | |
269 switch (uc) | |
270 { | |
271 case 8: v->size = ST_SIZE_BYTE; break; | |
272 case 16: v->size = ST_SIZE_WORD; break; | |
273 default: | |
387
fb519e6028e3
Changed all the Sound_SetError() calls to __Sound_SetError (or BAIL*_MACRO)
Ryan C. Gordon <icculus@icculus.org>
parents:
385
diff
changeset
|
274 BAIL_MACRO("VOC: unknown data size", 0); |
385
9efb760c4a6b
FIXME removal and cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents:
377
diff
changeset
|
275 } /* switch */ |
14 | 276 |
385
9efb760c4a6b
FIXME removal and cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents:
377
diff
changeset
|
277 if (!voc_readbytes(src, v, &v->channels, sizeof (Uint8))) |
14 | 278 return 0; |
279 | |
385
9efb760c4a6b
FIXME removal and cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents:
377
diff
changeset
|
280 if (!voc_readbytes(src, v, trash, sizeof (Uint8) * 6)) |
14 | 281 return 0; |
474
c66080364dff
Most decoders now report total sample play time, now. Technically, this
Ryan C. Gordon <icculus@icculus.org>
parents:
468
diff
changeset
|
282 v->rest = sblen - 12; |
14 | 283 |
474
c66080364dff
Most decoders now report total sample play time, now. Technically, this
Ryan C. Gordon <icculus@icculus.org>
parents:
468
diff
changeset
|
284 bytes_per_second = ((v->size == ST_SIZE_WORD) ? (2) : (1)) * |
c66080364dff
Most decoders now report total sample play time, now. Technically, this
Ryan C. Gordon <icculus@icculus.org>
parents:
468
diff
changeset
|
285 sample->actual.rate * v->channels; |
c66080364dff
Most decoders now report total sample play time, now. Technically, this
Ryan C. Gordon <icculus@icculus.org>
parents:
468
diff
changeset
|
286 sample->total_time += v->rest / bytes_per_second * 1000; |
c66080364dff
Most decoders now report total sample play time, now. Technically, this
Ryan C. Gordon <icculus@icculus.org>
parents:
468
diff
changeset
|
287 sample->total_time += ( v->rest % bytes_per_second ) * 1000 |
c66080364dff
Most decoders now report total sample play time, now. Technically, this
Ryan C. Gordon <icculus@icculus.org>
parents:
468
diff
changeset
|
288 / bytes_per_second; |
14 | 289 return 1; |
290 | |
291 case VOC_CONT: | |
292 v->rest = sblen; | |
293 return 1; | |
294 | |
295 case VOC_SILENCE: | |
385
9efb760c4a6b
FIXME removal and cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents:
377
diff
changeset
|
296 if (!voc_readbytes(src, v, &period, sizeof (period))) |
14 | 297 return 0; |
385
9efb760c4a6b
FIXME removal and cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents:
377
diff
changeset
|
298 |
14 | 299 period = SDL_SwapLE16(period); |
300 | |
385
9efb760c4a6b
FIXME removal and cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents:
377
diff
changeset
|
301 if (!voc_readbytes(src, v, &uc, sizeof (uc))) |
14 | 302 return 0; |
385
9efb760c4a6b
FIXME removal and cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents:
377
diff
changeset
|
303 |
387
fb519e6028e3
Changed all the Sound_SetError() calls to __Sound_SetError (or BAIL*_MACRO)
Ryan C. Gordon <icculus@icculus.org>
parents:
385
diff
changeset
|
304 BAIL_IF_MACRO(uc == 0, "VOC: silence sample rate is zero", 0); |
14 | 305 |
306 /* | |
307 * Some silence-packed files have gratuitously | |
308 * different sample rate codes in silence. | |
309 * Adjust period. | |
310 */ | |
311 if ((v->rate != -1) && (uc != v->rate)) | |
312 period = (period * (256 - uc))/(256 - v->rate); | |
313 else | |
314 v->rate = uc; | |
315 v->rest = period; | |
316 v->silent = 1; | |
474
c66080364dff
Most decoders now report total sample play time, now. Technically, this
Ryan C. Gordon <icculus@icculus.org>
parents:
468
diff
changeset
|
317 |
c66080364dff
Most decoders now report total sample play time, now. Technically, this
Ryan C. Gordon <icculus@icculus.org>
parents:
468
diff
changeset
|
318 sample->total_time += (period) / (v->rate) * 1000; |
c66080364dff
Most decoders now report total sample play time, now. Technically, this
Ryan C. Gordon <icculus@icculus.org>
parents:
468
diff
changeset
|
319 sample->total_time += (period % v->rate) * 1000 / v->rate; |
14 | 320 return 1; |
321 | |
322 case VOC_LOOP: | |
323 case VOC_LOOPEND: | |
324 for(i = 0; i < sblen; i++) /* skip repeat loops. */ | |
325 { | |
387
fb519e6028e3
Changed all the Sound_SetError() calls to __Sound_SetError (or BAIL*_MACRO)
Ryan C. Gordon <icculus@icculus.org>
parents:
385
diff
changeset
|
326 if (!voc_readbytes(src, v, trash, sizeof (Uint8))) |
14 | 327 return 0; |
385
9efb760c4a6b
FIXME removal and cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents:
377
diff
changeset
|
328 } /* for */ |
14 | 329 break; |
330 | |
331 case VOC_EXTENDED: | |
332 /* An Extended block is followed by a data block */ | |
333 /* Set this byte so we know to use the rate */ | |
334 /* value from the extended block and not the */ | |
335 /* data block. */ | |
336 v->extended = 1; | |
385
9efb760c4a6b
FIXME removal and cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents:
377
diff
changeset
|
337 if (!voc_readbytes(src, v, &new_rate_short, sizeof (Uint16))) |
14 | 338 return 0; |
385
9efb760c4a6b
FIXME removal and cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents:
377
diff
changeset
|
339 |
14 | 340 new_rate_short = SDL_SwapLE16(new_rate_short); |
387
fb519e6028e3
Changed all the Sound_SetError() calls to __Sound_SetError (or BAIL*_MACRO)
Ryan C. Gordon <icculus@icculus.org>
parents:
385
diff
changeset
|
341 BAIL_IF_MACRO(!new_rate_short, "VOC: sample rate is zero", 0); |
fb519e6028e3
Changed all the Sound_SetError() calls to __Sound_SetError (or BAIL*_MACRO)
Ryan C. Gordon <icculus@icculus.org>
parents:
385
diff
changeset
|
342 |
14 | 343 if ((v->rate != -1) && (new_rate_short != v->rate)) |
387
fb519e6028e3
Changed all the Sound_SetError() calls to __Sound_SetError (or BAIL*_MACRO)
Ryan C. Gordon <icculus@icculus.org>
parents:
385
diff
changeset
|
344 BAIL_MACRO("VOC: sample rate codes differ", 0); |
fb519e6028e3
Changed all the Sound_SetError() calls to __Sound_SetError (or BAIL*_MACRO)
Ryan C. Gordon <icculus@icculus.org>
parents:
385
diff
changeset
|
345 |
14 | 346 v->rate = new_rate_short; |
347 | |
385
9efb760c4a6b
FIXME removal and cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents:
377
diff
changeset
|
348 if (!voc_readbytes(src, v, &uc, sizeof (uc))) |
14 | 349 return 0; |
350 | |
387
fb519e6028e3
Changed all the Sound_SetError() calls to __Sound_SetError (or BAIL*_MACRO)
Ryan C. Gordon <icculus@icculus.org>
parents:
385
diff
changeset
|
351 BAIL_IF_MACRO(uc != 0, "VOC: only supports 8-bit data", 0); |
14 | 352 |
385
9efb760c4a6b
FIXME removal and cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents:
377
diff
changeset
|
353 if (!voc_readbytes(src, v, &uc, sizeof (uc))) |
14 | 354 return 0; |
355 | |
356 if (uc) | |
357 sample->actual.channels = 2; /* Stereo */ | |
385
9efb760c4a6b
FIXME removal and cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents:
377
diff
changeset
|
358 |
14 | 359 /* Needed number of channels before finishing |
360 compute for rate */ | |
361 sample->actual.rate = | |
362 (256000000L/(65536L - v->rate)) / sample->actual.channels; | |
363 /* An extended block must be followed by a data */ | |
364 /* block to be valid so loop back to top so it */ | |
365 /* can be grabed. */ | |
366 continue; | |
367 | |
368 case VOC_MARKER: | |
385
9efb760c4a6b
FIXME removal and cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents:
377
diff
changeset
|
369 if (!voc_readbytes(src, v, trash, sizeof (Uint8) * 2)) |
14 | 370 return 0; |
371 | |
372 /* Falling! Falling! */ | |
373 | |
374 default: /* text block or other krapola. */ | |
387
fb519e6028e3
Changed all the Sound_SetError() calls to __Sound_SetError (or BAIL*_MACRO)
Ryan C. Gordon <icculus@icculus.org>
parents:
385
diff
changeset
|
375 for(i = 0; i < sblen; i++) /* skip repeat loops. */ |
fb519e6028e3
Changed all the Sound_SetError() calls to __Sound_SetError (or BAIL*_MACRO)
Ryan C. Gordon <icculus@icculus.org>
parents:
385
diff
changeset
|
376 { |
fb519e6028e3
Changed all the Sound_SetError() calls to __Sound_SetError (or BAIL*_MACRO)
Ryan C. Gordon <icculus@icculus.org>
parents:
385
diff
changeset
|
377 if (!voc_readbytes(src, v, trash, sizeof (Uint8))) |
fb519e6028e3
Changed all the Sound_SetError() calls to __Sound_SetError (or BAIL*_MACRO)
Ryan C. Gordon <icculus@icculus.org>
parents:
385
diff
changeset
|
378 return 0; |
fb519e6028e3
Changed all the Sound_SetError() calls to __Sound_SetError (or BAIL*_MACRO)
Ryan C. Gordon <icculus@icculus.org>
parents:
385
diff
changeset
|
379 } /* for */ |
14 | 380 |
381 if (block == VOC_TEXT) | |
382 continue; /* get next block */ | |
385
9efb760c4a6b
FIXME removal and cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents:
377
diff
changeset
|
383 } /* switch */ |
9efb760c4a6b
FIXME removal and cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents:
377
diff
changeset
|
384 } /* while */ |
14 | 385 |
386 return 1; | |
335
f6475949cd59
Implemented seek method.
Ryan C. Gordon <icculus@icculus.org>
parents:
306
diff
changeset
|
387 } /* voc_get_block */ |
14 | 388 |
389 | |
335
f6475949cd59
Implemented seek method.
Ryan C. Gordon <icculus@icculus.org>
parents:
306
diff
changeset
|
390 static int voc_read_waveform(Sound_Sample *sample, int fill_buf, Uint32 max) |
14 | 391 { |
392 Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque; | |
393 SDL_RWops *src = internal->rw; | |
394 vs_t *v = (vs_t *) internal->decoder_private; | |
395 int done = 0; | |
396 Uint8 silence = 0x80; | |
397 Uint8 *buf = internal->buffer; | |
398 | |
399 if (v->rest == 0) | |
400 { | |
468
cd46c97e58bc
Fixed broken VOC decoder...would always dereference NULL during VOC_open().
Ryan C. Gordon <icculus@icculus.org>
parents:
449
diff
changeset
|
401 if (!voc_get_block(sample, v)) |
14 | 402 return 0; |
335
f6475949cd59
Implemented seek method.
Ryan C. Gordon <icculus@icculus.org>
parents:
306
diff
changeset
|
403 } /* if */ |
14 | 404 |
405 if (v->rest == 0) | |
406 return 0; | |
407 | |
335
f6475949cd59
Implemented seek method.
Ryan C. Gordon <icculus@icculus.org>
parents:
306
diff
changeset
|
408 max = (v->rest < max) ? v->rest : max; |
f6475949cd59
Implemented seek method.
Ryan C. Gordon <icculus@icculus.org>
parents:
306
diff
changeset
|
409 |
14 | 410 if (v->silent) |
411 { | |
412 if (v->size == ST_SIZE_WORD) | |
413 silence = 0x00; | |
414 | |
415 /* Fill in silence */ | |
335
f6475949cd59
Implemented seek method.
Ryan C. Gordon <icculus@icculus.org>
parents:
306
diff
changeset
|
416 if (fill_buf) |
f6475949cd59
Implemented seek method.
Ryan C. Gordon <icculus@icculus.org>
parents:
306
diff
changeset
|
417 memset(buf + v->bufpos, silence, max); |
f6475949cd59
Implemented seek method.
Ryan C. Gordon <icculus@icculus.org>
parents:
306
diff
changeset
|
418 |
f6475949cd59
Implemented seek method.
Ryan C. Gordon <icculus@icculus.org>
parents:
306
diff
changeset
|
419 done = max; |
f6475949cd59
Implemented seek method.
Ryan C. Gordon <icculus@icculus.org>
parents:
306
diff
changeset
|
420 v->rest -= done; |
f6475949cd59
Implemented seek method.
Ryan C. Gordon <icculus@icculus.org>
parents:
306
diff
changeset
|
421 } /* if */ |
14 | 422 |
423 else | |
424 { | |
335
f6475949cd59
Implemented seek method.
Ryan C. Gordon <icculus@icculus.org>
parents:
306
diff
changeset
|
425 if (fill_buf) |
385
9efb760c4a6b
FIXME removal and cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents:
377
diff
changeset
|
426 { |
335
f6475949cd59
Implemented seek method.
Ryan C. Gordon <icculus@icculus.org>
parents:
306
diff
changeset
|
427 done = SDL_RWread(src, buf + v->bufpos, 1, max); |
385
9efb760c4a6b
FIXME removal and cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents:
377
diff
changeset
|
428 if (done < max) |
9efb760c4a6b
FIXME removal and cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents:
377
diff
changeset
|
429 { |
387
fb519e6028e3
Changed all the Sound_SetError() calls to __Sound_SetError (or BAIL*_MACRO)
Ryan C. Gordon <icculus@icculus.org>
parents:
385
diff
changeset
|
430 __Sound_SetError("VOC: i/o error"); |
385
9efb760c4a6b
FIXME removal and cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents:
377
diff
changeset
|
431 sample->flags |= SOUND_SAMPLEFLAG_ERROR; |
9efb760c4a6b
FIXME removal and cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents:
377
diff
changeset
|
432 } /* if */ |
9efb760c4a6b
FIXME removal and cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents:
377
diff
changeset
|
433 } /* if */ |
9efb760c4a6b
FIXME removal and cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents:
377
diff
changeset
|
434 |
335
f6475949cd59
Implemented seek method.
Ryan C. Gordon <icculus@icculus.org>
parents:
306
diff
changeset
|
435 else |
f6475949cd59
Implemented seek method.
Ryan C. Gordon <icculus@icculus.org>
parents:
306
diff
changeset
|
436 { |
f6475949cd59
Implemented seek method.
Ryan C. Gordon <icculus@icculus.org>
parents:
306
diff
changeset
|
437 int cur, rc; |
f6475949cd59
Implemented seek method.
Ryan C. Gordon <icculus@icculus.org>
parents:
306
diff
changeset
|
438 cur = SDL_RWtell(src); |
f6475949cd59
Implemented seek method.
Ryan C. Gordon <icculus@icculus.org>
parents:
306
diff
changeset
|
439 if (cur >= 0) |
f6475949cd59
Implemented seek method.
Ryan C. Gordon <icculus@icculus.org>
parents:
306
diff
changeset
|
440 { |
f6475949cd59
Implemented seek method.
Ryan C. Gordon <icculus@icculus.org>
parents:
306
diff
changeset
|
441 rc = SDL_RWseek(src, max, SEEK_CUR); |
f6475949cd59
Implemented seek method.
Ryan C. Gordon <icculus@icculus.org>
parents:
306
diff
changeset
|
442 if (rc >= 0) |
f6475949cd59
Implemented seek method.
Ryan C. Gordon <icculus@icculus.org>
parents:
306
diff
changeset
|
443 done = rc - cur; |
385
9efb760c4a6b
FIXME removal and cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents:
377
diff
changeset
|
444 else |
9efb760c4a6b
FIXME removal and cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents:
377
diff
changeset
|
445 { |
387
fb519e6028e3
Changed all the Sound_SetError() calls to __Sound_SetError (or BAIL*_MACRO)
Ryan C. Gordon <icculus@icculus.org>
parents:
385
diff
changeset
|
446 __Sound_SetError("VOC: seek error"); |
385
9efb760c4a6b
FIXME removal and cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents:
377
diff
changeset
|
447 sample->flags |= SOUND_SAMPLEFLAG_ERROR; |
9efb760c4a6b
FIXME removal and cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents:
377
diff
changeset
|
448 } /* else */ |
335
f6475949cd59
Implemented seek method.
Ryan C. Gordon <icculus@icculus.org>
parents:
306
diff
changeset
|
449 } /* if */ |
f6475949cd59
Implemented seek method.
Ryan C. Gordon <icculus@icculus.org>
parents:
306
diff
changeset
|
450 } /* else */ |
f6475949cd59
Implemented seek method.
Ryan C. Gordon <icculus@icculus.org>
parents:
306
diff
changeset
|
451 |
14 | 452 v->rest -= done; |
453 v->bufpos += done; | |
335
f6475949cd59
Implemented seek method.
Ryan C. Gordon <icculus@icculus.org>
parents:
306
diff
changeset
|
454 } /* else */ |
14 | 455 |
385
9efb760c4a6b
FIXME removal and cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents:
377
diff
changeset
|
456 return(done); |
22
f6e679afe88b
Byte ordering fix, changed voc_read to voc_read_waveform, and cleaned up
Ryan C. Gordon <icculus@icculus.org>
parents:
14
diff
changeset
|
457 } /* voc_read_waveform */ |
14 | 458 |
459 | |
460 static int VOC_open(Sound_Sample *sample, const char *ext) | |
461 { | |
462 Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque; | |
463 vs_t *v = NULL; | |
464 | |
465 if (!voc_check_header(internal->rw)) | |
466 return(0); | |
467 | |
468 v = (vs_t *) malloc(sizeof (vs_t)); | |
469 BAIL_IF_MACRO(v == NULL, ERR_OUT_OF_MEMORY, 0); | |
470 memset(v, '\0', sizeof (vs_t)); | |
471 | |
224
1bafef18dabf
Implemented rewind method.
Ryan C. Gordon <icculus@icculus.org>
parents:
221
diff
changeset
|
472 v->start_pos = SDL_RWtell(internal->rw); |
14 | 473 v->rate = -1; |
468
cd46c97e58bc
Fixed broken VOC decoder...would always dereference NULL during VOC_open().
Ryan C. Gordon <icculus@icculus.org>
parents:
449
diff
changeset
|
474 if (!voc_get_block(sample, v)) |
14 | 475 { |
476 free(v); | |
477 return(0); | |
478 } /* if */ | |
479 | |
480 if (v->rate == -1) | |
481 { | |
482 free(v); | |
387
fb519e6028e3
Changed all the Sound_SetError() calls to __Sound_SetError (or BAIL*_MACRO)
Ryan C. Gordon <icculus@icculus.org>
parents:
385
diff
changeset
|
483 BAIL_MACRO("VOC: data had no sound!", 0); |
14 | 484 } /* if */ |
485 | |
62
b13fafb976be
Changed _D macro to DBGSND.
Ryan C. Gordon <icculus@icculus.org>
parents:
47
diff
changeset
|
486 SNDDBG(("VOC: Accepting data stream.\n")); |
14 | 487 sample->actual.format = (v->size == ST_SIZE_WORD) ? AUDIO_S16LSB:AUDIO_U8; |
488 sample->actual.channels = v->channels; | |
335
f6475949cd59
Implemented seek method.
Ryan C. Gordon <icculus@icculus.org>
parents:
306
diff
changeset
|
489 sample->flags = SOUND_SAMPLEFLAG_CANSEEK; |
449
daeb71a3f1ed
Extremely minor cleanup.
Ryan C. Gordon <icculus@icculus.org>
parents:
401
diff
changeset
|
490 internal->decoder_private = v; |
14 | 491 return(1); |
492 } /* VOC_open */ | |
493 | |
494 | |
495 static void VOC_close(Sound_Sample *sample) | |
496 { | |
497 Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque; | |
498 free(internal->decoder_private); | |
499 } /* VOC_close */ | |
500 | |
501 | |
502 static Uint32 VOC_read(Sound_Sample *sample) | |
503 { | |
504 Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque; | |
505 vs_t *v = (vs_t *) internal->decoder_private; | |
506 | |
507 v->bufpos = 0; | |
508 while (v->bufpos < internal->buffer_size) | |
509 { | |
335
f6475949cd59
Implemented seek method.
Ryan C. Gordon <icculus@icculus.org>
parents:
306
diff
changeset
|
510 Uint32 rc = voc_read_waveform(sample, 1, internal->buffer_size); |
385
9efb760c4a6b
FIXME removal and cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents:
377
diff
changeset
|
511 if (rc == 0) |
14 | 512 { |
385
9efb760c4a6b
FIXME removal and cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents:
377
diff
changeset
|
513 sample->flags |= (v->error) ? |
9efb760c4a6b
FIXME removal and cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents:
377
diff
changeset
|
514 SOUND_SAMPLEFLAG_ERROR : |
9efb760c4a6b
FIXME removal and cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents:
377
diff
changeset
|
515 SOUND_SAMPLEFLAG_EOF; |
14 | 516 break; |
517 } /* if */ | |
518 | |
468
cd46c97e58bc
Fixed broken VOC decoder...would always dereference NULL during VOC_open().
Ryan C. Gordon <icculus@icculus.org>
parents:
449
diff
changeset
|
519 if (!voc_get_block(sample, v)) |
14 | 520 { |
385
9efb760c4a6b
FIXME removal and cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents:
377
diff
changeset
|
521 sample->flags |= (v->error) ? |
9efb760c4a6b
FIXME removal and cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents:
377
diff
changeset
|
522 SOUND_SAMPLEFLAG_ERROR : |
9efb760c4a6b
FIXME removal and cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents:
377
diff
changeset
|
523 SOUND_SAMPLEFLAG_EOF; |
14 | 524 break; |
525 } /* if */ | |
526 } /* while */ | |
527 | |
528 return(v->bufpos); | |
529 } /* VOC_read */ | |
530 | |
221
c9772a9f5271
Initial implementation or stubs for rewind method. Other cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents:
184
diff
changeset
|
531 |
c9772a9f5271
Initial implementation or stubs for rewind method. Other cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents:
184
diff
changeset
|
532 static int VOC_rewind(Sound_Sample *sample) |
c9772a9f5271
Initial implementation or stubs for rewind method. Other cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents:
184
diff
changeset
|
533 { |
224
1bafef18dabf
Implemented rewind method.
Ryan C. Gordon <icculus@icculus.org>
parents:
221
diff
changeset
|
534 Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque; |
1bafef18dabf
Implemented rewind method.
Ryan C. Gordon <icculus@icculus.org>
parents:
221
diff
changeset
|
535 vs_t *v = (vs_t *) internal->decoder_private; |
1bafef18dabf
Implemented rewind method.
Ryan C. Gordon <icculus@icculus.org>
parents:
221
diff
changeset
|
536 int rc = SDL_RWseek(internal->rw, v->start_pos, SEEK_SET); |
1bafef18dabf
Implemented rewind method.
Ryan C. Gordon <icculus@icculus.org>
parents:
221
diff
changeset
|
537 BAIL_IF_MACRO(rc != v->start_pos, ERR_IO_ERROR, 0); |
1bafef18dabf
Implemented rewind method.
Ryan C. Gordon <icculus@icculus.org>
parents:
221
diff
changeset
|
538 v->rest = 0; |
1bafef18dabf
Implemented rewind method.
Ryan C. Gordon <icculus@icculus.org>
parents:
221
diff
changeset
|
539 return(1); |
221
c9772a9f5271
Initial implementation or stubs for rewind method. Other cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents:
184
diff
changeset
|
540 } /* VOC_rewind */ |
c9772a9f5271
Initial implementation or stubs for rewind method. Other cleanups.
Ryan C. Gordon <icculus@icculus.org>
parents:
184
diff
changeset
|
541 |
306
c97be6e1bd27
Added framework for Sound_Seek() support.
Ryan C. Gordon <icculus@icculus.org>
parents:
301
diff
changeset
|
542 |
c97be6e1bd27
Added framework for Sound_Seek() support.
Ryan C. Gordon <icculus@icculus.org>
parents:
301
diff
changeset
|
543 static int VOC_seek(Sound_Sample *sample, Uint32 ms) |
c97be6e1bd27
Added framework for Sound_Seek() support.
Ryan C. Gordon <icculus@icculus.org>
parents:
301
diff
changeset
|
544 { |
335
f6475949cd59
Implemented seek method.
Ryan C. Gordon <icculus@icculus.org>
parents:
306
diff
changeset
|
545 /* |
f6475949cd59
Implemented seek method.
Ryan C. Gordon <icculus@icculus.org>
parents:
306
diff
changeset
|
546 * VOCs don't lend themselves well to seeking, since you have to |
f6475949cd59
Implemented seek method.
Ryan C. Gordon <icculus@icculus.org>
parents:
306
diff
changeset
|
547 * parse each section, which is an arbitrary size. The best we can do |
f6475949cd59
Implemented seek method.
Ryan C. Gordon <icculus@icculus.org>
parents:
306
diff
changeset
|
548 * is rewind, set a flag saying not to write the waveforms to a buffer, |
f6475949cd59
Implemented seek method.
Ryan C. Gordon <icculus@icculus.org>
parents:
306
diff
changeset
|
549 * and decode to the point that we want. Ugh. Fortunately, there's |
f6475949cd59
Implemented seek method.
Ryan C. Gordon <icculus@icculus.org>
parents:
306
diff
changeset
|
550 * really no such thing as a large VOC, due to the era and hardware that |
f6475949cd59
Implemented seek method.
Ryan C. Gordon <icculus@icculus.org>
parents:
306
diff
changeset
|
551 * spawned them, so even though this is inefficient, this is still a |
f6475949cd59
Implemented seek method.
Ryan C. Gordon <icculus@icculus.org>
parents:
306
diff
changeset
|
552 * relatively fast operation in most cases. |
f6475949cd59
Implemented seek method.
Ryan C. Gordon <icculus@icculus.org>
parents:
306
diff
changeset
|
553 */ |
f6475949cd59
Implemented seek method.
Ryan C. Gordon <icculus@icculus.org>
parents:
306
diff
changeset
|
554 |
f6475949cd59
Implemented seek method.
Ryan C. Gordon <icculus@icculus.org>
parents:
306
diff
changeset
|
555 Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque; |
f6475949cd59
Implemented seek method.
Ryan C. Gordon <icculus@icculus.org>
parents:
306
diff
changeset
|
556 vs_t *v = (vs_t *) internal->decoder_private; |
f6475949cd59
Implemented seek method.
Ryan C. Gordon <icculus@icculus.org>
parents:
306
diff
changeset
|
557 int offset = __Sound_convertMsToBytePos(&sample->actual, ms); |
f6475949cd59
Implemented seek method.
Ryan C. Gordon <icculus@icculus.org>
parents:
306
diff
changeset
|
558 int origpos = SDL_RWtell(internal->rw); |
f6475949cd59
Implemented seek method.
Ryan C. Gordon <icculus@icculus.org>
parents:
306
diff
changeset
|
559 int origrest = v->rest; |
f6475949cd59
Implemented seek method.
Ryan C. Gordon <icculus@icculus.org>
parents:
306
diff
changeset
|
560 |
f6475949cd59
Implemented seek method.
Ryan C. Gordon <icculus@icculus.org>
parents:
306
diff
changeset
|
561 BAIL_IF_MACRO(!VOC_rewind(sample), NULL, 0); |
f6475949cd59
Implemented seek method.
Ryan C. Gordon <icculus@icculus.org>
parents:
306
diff
changeset
|
562 |
f6475949cd59
Implemented seek method.
Ryan C. Gordon <icculus@icculus.org>
parents:
306
diff
changeset
|
563 v->bufpos = 0; |
f6475949cd59
Implemented seek method.
Ryan C. Gordon <icculus@icculus.org>
parents:
306
diff
changeset
|
564 |
f6475949cd59
Implemented seek method.
Ryan C. Gordon <icculus@icculus.org>
parents:
306
diff
changeset
|
565 while (offset > 0) |
f6475949cd59
Implemented seek method.
Ryan C. Gordon <icculus@icculus.org>
parents:
306
diff
changeset
|
566 { |
f6475949cd59
Implemented seek method.
Ryan C. Gordon <icculus@icculus.org>
parents:
306
diff
changeset
|
567 Uint32 rc = voc_read_waveform(sample, 0, offset); |
468
cd46c97e58bc
Fixed broken VOC decoder...would always dereference NULL during VOC_open().
Ryan C. Gordon <icculus@icculus.org>
parents:
449
diff
changeset
|
568 if ( (rc == 0) || (!voc_get_block(sample, v)) ) |
335
f6475949cd59
Implemented seek method.
Ryan C. Gordon <icculus@icculus.org>
parents:
306
diff
changeset
|
569 { |
f6475949cd59
Implemented seek method.
Ryan C. Gordon <icculus@icculus.org>
parents:
306
diff
changeset
|
570 SDL_RWseek(internal->rw, origpos, SEEK_SET); |
f6475949cd59
Implemented seek method.
Ryan C. Gordon <icculus@icculus.org>
parents:
306
diff
changeset
|
571 v->rest = origrest; |
f6475949cd59
Implemented seek method.
Ryan C. Gordon <icculus@icculus.org>
parents:
306
diff
changeset
|
572 return(0); |
f6475949cd59
Implemented seek method.
Ryan C. Gordon <icculus@icculus.org>
parents:
306
diff
changeset
|
573 } /* if */ |
f6475949cd59
Implemented seek method.
Ryan C. Gordon <icculus@icculus.org>
parents:
306
diff
changeset
|
574 |
f6475949cd59
Implemented seek method.
Ryan C. Gordon <icculus@icculus.org>
parents:
306
diff
changeset
|
575 offset -= rc; |
f6475949cd59
Implemented seek method.
Ryan C. Gordon <icculus@icculus.org>
parents:
306
diff
changeset
|
576 } /* while */ |
f6475949cd59
Implemented seek method.
Ryan C. Gordon <icculus@icculus.org>
parents:
306
diff
changeset
|
577 |
f6475949cd59
Implemented seek method.
Ryan C. Gordon <icculus@icculus.org>
parents:
306
diff
changeset
|
578 return(1); |
306
c97be6e1bd27
Added framework for Sound_Seek() support.
Ryan C. Gordon <icculus@icculus.org>
parents:
301
diff
changeset
|
579 } /* VOC_seek */ |
c97be6e1bd27
Added framework for Sound_Seek() support.
Ryan C. Gordon <icculus@icculus.org>
parents:
301
diff
changeset
|
580 |
64
40006625142a
Changes in preparation of autoconf support.
Ryan C. Gordon <icculus@icculus.org>
parents:
62
diff
changeset
|
581 #endif /* SOUND_SUPPORTS_VOC */ |
14 | 582 |
583 /* end of voc.c ... */ |