comparison decoders/flac.c @ 166:d8904267d23c

Cleanups, fixes and enhancements by Torbj�rn Andersson.
author Ryan C. Gordon <icculus@icculus.org>
date Mon, 26 Nov 2001 04:32:55 +0000
parents 77482005beb6
children 3849438b735e
comparison
equal deleted inserted replaced
165:9b26ed9eaf04 166:d8904267d23c
77 { 77 {
78 FLAC__StreamDecoder *decoder; 78 FLAC__StreamDecoder *decoder;
79 SDL_RWops *rw; 79 SDL_RWops *rw;
80 Sound_Sample *sample; 80 Sound_Sample *sample;
81 Uint32 frame_size; 81 Uint32 frame_size;
82 Uint8 metadata_found; 82 Uint8 is_flac;
83 } flac_t; 83 } flac_t;
84
85
86 static void free_flac(flac_t *f)
87 {
88 FLAC__stream_decoder_finish(f->decoder);
89 FLAC__stream_decoder_delete(f->decoder);
90 free(f);
91 } /* free_flac */
84 92
85 93
86 static FLAC__StreamDecoderReadStatus FLAC_read_callback( 94 static FLAC__StreamDecoderReadStatus FLAC_read_callback(
87 const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], 95 const FLAC__StreamDecoder *decoder, FLAC__byte buffer[],
88 unsigned int *bytes, void *client_data) 96 unsigned int *bytes, void *client_data)
124 const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, 132 const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame,
125 const FLAC__int32 *buffer[], void *client_data) 133 const FLAC__int32 *buffer[], void *client_data)
126 { 134 {
127 flac_t *f = (flac_t *) client_data; 135 flac_t *f = (flac_t *) client_data;
128 Uint32 i, j; 136 Uint32 i, j;
137 Uint32 sample;
129 Uint8 *dst; 138 Uint8 *dst;
130 139
131 #if 0 140 #if 0
132 SNDDBG(("FLAC: Write callback.\n")); 141 SNDDBG(("FLAC: Write callback.\n"));
133 #endif 142 #endif
138 if (f->frame_size > f->sample->buffer_size) 147 if (f->frame_size > f->sample->buffer_size)
139 Sound_SetBufferSize(f->sample, f->frame_size); 148 Sound_SetBufferSize(f->sample, f->frame_size);
140 149
141 dst = f->sample->buffer; 150 dst = f->sample->buffer;
142 151
143 if (frame->header.bits_per_sample == 8) 152 /* If the sample is neither exactly 8-bit nor 16-bit, it will have to
144 { 153 * be converted. Unfortunately the buffer is read-only, so we either
145 for (i = 0; i < frame->header.blocksize; i++) 154 * have to check for each sample, or make a copy of the buffer. I'm
146 for (j = 0; j < frame->header.channels; j++) 155 * not sure which way is best, so I've arbitrarily picked the former.
147 *dst++ = buffer[j][i] & 0x000000ff; 156 */
148 } /* if */ 157 if (f->sample->actual.format == AUDIO_S8)
149 else
150 { 158 {
151 for (i = 0; i < frame->header.blocksize; i++) 159 for (i = 0; i < frame->header.blocksize; i++)
152 for (j = 0; j < frame->header.channels; j++) 160 for (j = 0; j < frame->header.channels; j++)
153 { 161 {
154 *dst++ = (buffer[j][i] & 0x0000ff00) >> 8; 162 sample = buffer[j][i];
155 *dst++ = buffer[j][i] & 0x000000ff; 163 if (frame->header.bits_per_sample < 8)
164 sample <<= (8 - frame->header.bits_per_sample);
165 *dst++ = sample & 0x00ff;
166 } /* for */
167 } /* if */
168 else
169 {
170 for (i = 0; i < frame->header.blocksize; i++)
171 for (j = 0; j < frame->header.channels; j++)
172 {
173 sample = buffer[j][i];
174 if (frame->header.bits_per_sample < 16)
175 sample <<= (16 - frame->header.bits_per_sample);
176 else if (frame->header.bits_per_sample > 16)
177 sample >>= (frame->header.bits_per_sample - 16);
178 *dst++ = (sample & 0xff00) >> 8;
179 *dst++ = sample & 0x00ff;
156 } /* for */ 180 } /* for */
157 } /* else */ 181 } /* else */
158 182
159 return(FLAC__STREAM_DECODER_WRITE_CONTINUE); 183 return(FLAC__STREAM_DECODER_WRITE_CONTINUE);
160 } /* FLAC_write_callback */ 184 } /* FLAC_write_callback */
166 { 190 {
167 flac_t *f = (flac_t *) client_data; 191 flac_t *f = (flac_t *) client_data;
168 192
169 SNDDBG(("FLAC: Metadata callback.\n")); 193 SNDDBG(("FLAC: Metadata callback.\n"));
170 194
195 /* There are several kinds of metadata, but STREAMINFO is the only
196 * one that always has to be there.
197 */
171 if (metadata->type == FLAC__METADATA_TYPE_STREAMINFO) 198 if (metadata->type == FLAC__METADATA_TYPE_STREAMINFO)
172 { 199 {
173 SNDDBG(("FLAC: Metadata is streaminfo.\n")); 200 SNDDBG(("FLAC: Metadata is streaminfo.\n"));
174 f->metadata_found = 1; 201
202 f->is_flac = 1;
175 f->sample->actual.channels = metadata->data.stream_info.channels; 203 f->sample->actual.channels = metadata->data.stream_info.channels;
176 f->sample->actual.rate = metadata->data.stream_info.sample_rate; 204 f->sample->actual.rate = metadata->data.stream_info.sample_rate;
177 205
178 /* !!! FIXME: I believe bits_per_sample may be anywhere between 206 if (metadata->data.stream_info.bits_per_sample > 8)
179 * 4 and 24. We can only handle 8 and 16 at present. 207 f->sample->actual.format = AUDIO_S16MSB;
180 */ 208 else
181 switch (metadata->data.stream_info.bits_per_sample) 209 f->sample->actual.format = AUDIO_S8;
182 {
183 case 8:
184 f->sample->actual.format = AUDIO_S8;
185 break;
186 case 16:
187 f->sample->actual.format = AUDIO_S16MSB;
188 break;
189 default:
190 Sound_SetError("FLAC: Unsupported sample width.");
191 f->sample->actual.format = 0;
192 break;
193 } /* switch */
194 } /* if */ 210 } /* if */
195 } /* FLAC_metadata_callback */ 211 } /* FLAC_metadata_callback */
196 212
197 213
198 void FLAC_error_callback( 214 void FLAC_error_callback(
199 const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, 215 const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status,
200 void *client_data) 216 void *client_data)
201 { 217 {
202 flac_t *f = (flac_t *) client_data; 218 flac_t *f = (flac_t *) client_data;
203 219
220 /* !!! FIXME: Is every error really fatal? I don't know... */
204 Sound_SetError(FLAC__StreamDecoderErrorStatusString[status]); 221 Sound_SetError(FLAC__StreamDecoderErrorStatusString[status]);
205 f->sample->flags |= SOUND_SAMPLEFLAG_ERROR; 222 f->sample->flags |= SOUND_SAMPLEFLAG_ERROR;
206 } /* FLAC_error_callback */ 223 } /* FLAC_error_callback */
207 224
208 225
222 { 239 {
223 Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque; 240 Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
224 SDL_RWops *rw = internal->rw; 241 SDL_RWops *rw = internal->rw;
225 FLAC__StreamDecoder *decoder; 242 FLAC__StreamDecoder *decoder;
226 flac_t *f; 243 flac_t *f;
244 int i;
227 245
228 f = (flac_t *) malloc(sizeof (flac_t)); 246 f = (flac_t *) malloc(sizeof (flac_t));
229 BAIL_IF_MACRO(f == NULL, ERR_OUT_OF_MEMORY, 0); 247 BAIL_IF_MACRO(f == NULL, ERR_OUT_OF_MEMORY, 0);
230 248
231 decoder = FLAC__stream_decoder_new(); 249 decoder = FLAC__stream_decoder_new();
243 FLAC__stream_decoder_set_client_data(decoder, f); 261 FLAC__stream_decoder_set_client_data(decoder, f);
244 262
245 f->rw = internal->rw; 263 f->rw = internal->rw;
246 f->sample = sample; 264 f->sample = sample;
247 f->decoder = decoder; 265 f->decoder = decoder;
248 266 f->sample->actual.format = 0;
267 f->is_flac = 0;
268
269 #if 0
270 /* !!! FIXME:
271 *
272 * It should be possible to play a FLAC stream starting at any frame,
273 * but we can only do that if we know for sure that it is a FLAC
274 * stream. Otherwise we have to check for metadata, and then we need
275 * the entire stream, from the beginning.
276 *
277 * But getting this to work right seems to be an enormous pain in the
278 * butt for what is, at the moment, a very small gain. Maybe later.
279 */
280 for (i = 0; extensions_flac[i] != NULL; i++)
281 if (__Sound_strcasecmp(ext, extensions_flac[i]) == 0)
282 {
283 f->is_flac = 1;
284 break;
285 } /* if */
286 #endif
287
288 internal->decoder_private = f;
249 FLAC__stream_decoder_init(decoder); 289 FLAC__stream_decoder_init(decoder);
250 internal->decoder_private = f; 290
251 291 /* If we are not sure this is a FLAC stream, check for the STREAMINFO
252 f->metadata_found = 0; 292 * metadata block. If not, we'd have to peek at the first audio frame
253 f->sample->actual.format = 0; 293 * and get the sound format from there but, as stated above, that is
254 FLAC__stream_decoder_process_metadata(decoder); 294 * not yet implemented.
255 295 */
256 if (f->sample->actual.format == 0) 296 if (!f->is_flac)
257 { 297 {
258 if (f->metadata_found == 0) 298 FLAC__stream_decoder_process_metadata(decoder);
259 Sound_SetError("FLAC: No metadata found."); 299
260 FLAC__stream_decoder_finish(decoder); 300 /* Still not FLAC? Give up. */
261 FLAC__stream_decoder_delete(decoder); 301 if (!f->is_flac)
262 free(f); 302 {
263 return(0); 303 Sound_SetError("FLAC: No metadata found. Not a FLAC stream?");
304 free_flac(f);
305 return(0);
306 } /* if */
264 } /* if */ 307 } /* if */
265 308
266 SNDDBG(("FLAC: Accepting data stream.\n")); 309 SNDDBG(("FLAC: Accepting data stream.\n"));
267 310
268 sample->flags = SOUND_SAMPLEFLAG_NONE; 311 sample->flags = SOUND_SAMPLEFLAG_NONE;
273 static void FLAC_close(Sound_Sample *sample) 316 static void FLAC_close(Sound_Sample *sample)
274 { 317 {
275 Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque; 318 Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
276 flac_t *f = (flac_t *) internal->decoder_private; 319 flac_t *f = (flac_t *) internal->decoder_private;
277 320
278 FLAC__stream_decoder_finish(f->decoder); 321 free_flac(f);
279 FLAC__stream_decoder_delete(f->decoder);
280 free(f);
281 } /* FLAC_close */ 322 } /* FLAC_close */
282 323
283 324
284 static Uint32 FLAC_read(Sound_Sample *sample) 325 static Uint32 FLAC_read(Sound_Sample *sample)
285 { 326 {