1 /*
2  * Allegro FLAC reader
3  * author: Ryan Dickie, (c) 2008
4  * streaming support by Elias Pschernig
5  */
6 
7 
8 #include "allegro5/allegro.h"
9 #include "allegro5/allegro_acodec.h"
10 #include "allegro5/allegro_audio.h"
11 #include "allegro5/internal/aintern.h"
12 #include "allegro5/internal/aintern_audio.h"
13 #include "allegro5/internal/aintern_exitfunc.h"
14 #include "allegro5/internal/aintern_system.h"
15 #include "acodec.h"
16 #include "helper.h"
17 
18 #ifndef ALLEGRO_CFG_ACODEC_FLAC
19    #error configuration problem, ALLEGRO_CFG_ACODEC_FLAC not set
20 #endif
21 
22 #include <FLAC/stream_decoder.h>
23 #include <stdio.h>
24 
25 ALLEGRO_DEBUG_CHANNEL("acodec")
26 
27 
28 typedef struct FLACFILE {
29    FLAC__StreamDecoder *decoder;
30    double sample_rate;
31    int sample_size;
32    int channels;
33 
34    /* The file buffer. */
35    uint64_t buffer_pos, buffer_size;
36    char *buffer;
37 
38    /* Number of samples in the complete FLAC. */
39    uint64_t total_samples;
40 
41    /* Sample position one past last decoded sample. */
42    uint64_t decoded_samples;
43 
44    /* Sample position one past last streamed sample. */
45    uint64_t streamed_samples;
46 
47    ALLEGRO_FILE *fh;
48    uint64_t loop_start, loop_end; /* in samples */
49 } FLACFILE;
50 
51 
52 /* dynamic loading support (Windows only currently) */
53 #ifdef ALLEGRO_CFG_ACODEC_FLAC_DLL
54 static void *flac_dll = NULL;
55 static bool flac_virgin = true;
56 #endif
57 
58 static struct
59 {
60    FLAC__StreamDecoder *(*FLAC__stream_decoder_new)(void);
61    void (*FLAC__stream_decoder_delete)(FLAC__StreamDecoder *decoder);
62    FLAC__StreamDecoderInitStatus (*FLAC__stream_decoder_init_stream)(
63       FLAC__StreamDecoder *decoder,
64       FLAC__StreamDecoderReadCallback read_callback,
65       FLAC__StreamDecoderSeekCallback seek_callback,
66       FLAC__StreamDecoderTellCallback tell_callback,
67       FLAC__StreamDecoderLengthCallback length_callback,
68       FLAC__StreamDecoderEofCallback eof_callback,
69       FLAC__StreamDecoderWriteCallback write_callback,
70       FLAC__StreamDecoderMetadataCallback metadata_callback,
71       FLAC__StreamDecoderErrorCallback error_callback,
72       void *client_data);
73    FLAC__bool (*FLAC__stream_decoder_process_single)(FLAC__StreamDecoder *decoder);
74    FLAC__bool (*FLAC__stream_decoder_process_until_end_of_metadata)(FLAC__StreamDecoder *decoder);
75    FLAC__bool (*FLAC__stream_decoder_process_until_end_of_stream)(FLAC__StreamDecoder *decoder);
76    FLAC__bool (*FLAC__stream_decoder_seek_absolute)(FLAC__StreamDecoder *decoder, FLAC__uint64 sample);
77    FLAC__bool (*FLAC__stream_decoder_flush)(FLAC__StreamDecoder *decoder);
78    FLAC__bool (*FLAC__stream_decoder_finish)(FLAC__StreamDecoder *decoder);
79 } lib;
80 
81 
82 #ifdef ALLEGRO_CFG_ACODEC_FLAC_DLL
shutdown_dynlib(void)83 static void shutdown_dynlib(void)
84 {
85    if (flac_dll) {
86       _al_close_library(flac_dll);
87       flac_dll = NULL;
88       flac_virgin = true;
89    }
90 }
91 #endif
92 
93 
init_dynlib(void)94 static bool init_dynlib(void)
95 {
96 #ifdef ALLEGRO_CFG_ACODEC_FLAC_DLL
97    if (flac_dll) {
98       return true;
99    }
100 
101    if (!flac_virgin) {
102       return false;
103    }
104 
105    flac_virgin = false;
106 
107    flac_dll = _al_open_library(ALLEGRO_CFG_ACODEC_FLAC_DLL);
108    if (!flac_dll) {
109       ALLEGRO_ERROR("Could not load " ALLEGRO_CFG_ACODEC_FLAC_DLL "\n");
110       return false;
111    }
112 
113    _al_add_exit_func(shutdown_dynlib, "shutdown_dynlib");
114 
115    #define INITSYM(x)                                                         \
116       do                                                                      \
117       {                                                                       \
118          lib.x = _al_import_symbol(flac_dll, #x);                             \
119          if (lib.x == 0) {                                                    \
120             ALLEGRO_ERROR("undefined symbol in lib structure: " #x "\n");     \
121             return false;                                                     \
122          }                                                                    \
123       } while(0)
124 #else
125    #define INITSYM(x)   (lib.x = (x))
126 #endif
127 
128    memset(&lib, 0, sizeof(lib));
129 
130    INITSYM(FLAC__stream_decoder_new);
131    INITSYM(FLAC__stream_decoder_delete);
132    INITSYM(FLAC__stream_decoder_init_stream);
133    INITSYM(FLAC__stream_decoder_process_single);
134    INITSYM(FLAC__stream_decoder_process_until_end_of_metadata);
135    INITSYM(FLAC__stream_decoder_process_until_end_of_stream);
136    INITSYM(FLAC__stream_decoder_seek_absolute);
137    INITSYM(FLAC__stream_decoder_flush);
138    INITSYM(FLAC__stream_decoder_finish);
139 
140    return true;
141 
142 #undef INITSYM
143 }
144 
145 
read_callback(const FLAC__StreamDecoder * decoder,FLAC__byte buffer[],size_t * bytes,void * dptr)146 static FLAC__StreamDecoderReadStatus read_callback(const FLAC__StreamDecoder *decoder,
147    FLAC__byte buffer[], size_t *bytes, void *dptr)
148 {
149    FLACFILE *ff = (FLACFILE *)dptr;
150    ALLEGRO_FILE *fh = ff->fh;
151    (void)decoder;
152    if (*bytes > 0) {
153       *bytes = al_fread(fh, buffer, *bytes);
154       if (al_ferror(fh))
155          return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
156       else if (*bytes == 0)
157          return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
158       else
159          return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
160    }
161    else
162       return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
163 }
164 
165 
seek_callback(const FLAC__StreamDecoder * decoder,FLAC__uint64 absolute_byte_offset,void * dptr)166 static FLAC__StreamDecoderSeekStatus seek_callback(
167    const FLAC__StreamDecoder *decoder,
168    FLAC__uint64 absolute_byte_offset, void *dptr)
169 {
170    FLACFILE *ff = (FLACFILE *)dptr;
171    ALLEGRO_FILE *fh = ff->fh;
172    (void)decoder;
173 
174    if (!al_fseek(fh, absolute_byte_offset, ALLEGRO_SEEK_SET))
175       return FLAC__STREAM_DECODER_SEEK_STATUS_ERROR;
176    else
177       return FLAC__STREAM_DECODER_SEEK_STATUS_OK;
178 }
179 
180 
tell_callback(const FLAC__StreamDecoder * decoder,FLAC__uint64 * absolute_byte_offset,void * dptr)181 static FLAC__StreamDecoderTellStatus tell_callback(
182    const FLAC__StreamDecoder *decoder,
183    FLAC__uint64 *absolute_byte_offset, void *dptr)
184 {
185    FLACFILE *ff = (FLACFILE *)dptr;
186    ALLEGRO_FILE *fh = ff->fh;
187    int64_t pos = 0;
188    (void)decoder;
189 
190    pos = al_ftell(fh);
191    if (pos == -1)
192       return FLAC__STREAM_DECODER_TELL_STATUS_ERROR;
193 
194    *absolute_byte_offset = (FLAC__uint64)pos;
195    return FLAC__STREAM_DECODER_TELL_STATUS_OK;
196 }
197 
198 
length_callback(const FLAC__StreamDecoder * decoder,FLAC__uint64 * stream_length,void * dptr)199 static FLAC__StreamDecoderLengthStatus length_callback(
200    const FLAC__StreamDecoder *decoder,
201    FLAC__uint64 *stream_length, void *dptr)
202 {
203    FLACFILE *ff = (FLACFILE *)dptr;
204    ALLEGRO_FILE *fh = ff->fh;
205    (void)decoder;
206 
207    /* XXX check error */
208    *stream_length = (FLAC__uint64)al_fsize(fh);
209 
210    return FLAC__STREAM_DECODER_LENGTH_STATUS_OK;
211 }
212 
213 
eof_callback(const FLAC__StreamDecoder * decoder,void * dptr)214 static FLAC__bool eof_callback(const FLAC__StreamDecoder *decoder, void *dptr)
215 {
216    FLACFILE *ff = (FLACFILE *)dptr;
217    ALLEGRO_FILE *fh = ff->fh;
218    (void)decoder;
219 
220    if (al_feof(fh))
221       return true;
222 
223    return false;
224 }
225 
226 
metadata_callback(const FLAC__StreamDecoder * decoder,const FLAC__StreamMetadata * metadata,void * client_data)227 static void metadata_callback(const FLAC__StreamDecoder *decoder,
228     const FLAC__StreamMetadata *metadata, void *client_data)
229 {
230    FLACFILE *out = (FLACFILE *)client_data;
231 
232    (void)decoder;
233 
234    if (metadata->type == FLAC__METADATA_TYPE_STREAMINFO) {
235       out->total_samples = metadata->data.stream_info.total_samples;
236       out->sample_rate = metadata->data.stream_info.sample_rate;
237       out->channels = metadata->data.stream_info.channels;
238       out->sample_size = metadata->data.stream_info.bits_per_sample / 8;
239    }
240 }
241 
242 
error_callback(const FLAC__StreamDecoder * decoder,FLAC__StreamDecoderErrorStatus status,void * client_data)243 static void error_callback(const FLAC__StreamDecoder *decoder,
244     FLAC__StreamDecoderErrorStatus status, void *client_data)
245 {
246    (void)decoder;
247    (void)client_data;
248 
249 #ifdef ALLEGRO_CFG_ACODEC_FLAC_DLL
250    (void)status;
251    ALLEGRO_ERROR("Got FLAC error callback\n"); /* lazy */
252 #else
253    ALLEGRO_ERROR("Got FLAC error callback: %s\n",
254       FLAC__StreamDecoderErrorStatusString[status]);
255 #endif
256 }
257 
258 
write_callback(const FLAC__StreamDecoder * decoder,const FLAC__Frame * frame,const FLAC__int32 * const buffer[],void * client_data)259 static FLAC__StreamDecoderWriteStatus write_callback(
260    const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame,
261    const FLAC__int32 * const buffer[], void *client_data)
262 {
263    FLACFILE *ff = (FLACFILE *) client_data;
264    long len = frame->header.blocksize;
265    long bytes = len * ff->channels * ff->sample_size;
266    FLAC__uint8 *buf8;
267    FLAC__int16 *buf16;
268    float *buf32;
269    int sample_index;
270    int channel_index;
271    int out_index;
272 
273    if (ff->buffer_pos + bytes > ff->buffer_size) {
274       ff->buffer = al_realloc(ff->buffer, ff->buffer_pos + bytes);
275       ff->buffer_size = ff->buffer_pos + bytes;
276    }
277 
278    /* FLAC returns FLAC__int32 and I need to convert it to my own format. */
279    buf8 = (FLAC__uint8 *) (ff->buffer + ff->buffer_pos);
280    buf16 = (FLAC__int16 *) buf8;
281    buf32 = (float *) buf8;
282 
283    (void)decoder;
284    (void)client_data;
285 
286    /* Flatten the array */
287    /* TODO: test this array flattening process on 5.1 and higher flac files */
288    out_index = 0;
289    switch (ff->sample_size) {
290       case 1:
291          for (sample_index = 0; sample_index < len; sample_index++) {
292              for (channel_index = 0;
293                   channel_index < ff->channels;
294                   channel_index++) {
295                 buf8[out_index++] =
296                    (FLAC__uint8) buffer[channel_index][sample_index];
297              }
298          }
299          break;
300 
301       case 2:
302          for (sample_index = 0; sample_index < len; sample_index++) {
303              for (channel_index = 0; channel_index < ff->channels;
304                    channel_index++) {
305                 buf16[out_index++] =
306                    (FLAC__int16) buffer[channel_index][sample_index];
307              }
308          }
309          break;
310 
311       case 3:
312          for (sample_index = 0; sample_index < len; sample_index++) {
313              for (channel_index = 0; channel_index < ff->channels;
314                 channel_index++)
315              {
316                 /* Little endian */
317                 /* FIXME: does this work? I only have 16-bit sound card mixer
318                  * garbages for other 24-bit codecs too.
319                  */
320                 buf8[out_index++] = (FLAC__uint8) (buffer[channel_index][sample_index] & 0xFF);
321                 buf8[out_index++] = (FLAC__uint8) ((buffer[channel_index][sample_index] & 0xFF00) >> 8);
322                 buf8[out_index++] = (FLAC__uint8) ((buffer[channel_index][sample_index] & 0xFF0000) >> 16);
323              }
324          }
325          break;
326 
327       case 4:
328          for (sample_index = 0; sample_index < len; sample_index++) {
329              for (channel_index = 0; channel_index < ff->channels;
330                    channel_index++) {
331                 buf32[out_index++] =
332                    (float) buffer[channel_index][sample_index];
333              }
334          }
335          break;
336 
337       default:
338          /* Word_size not supported. */
339          return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
340    }
341 
342    ff->decoded_samples += len;
343    ff->buffer_pos += bytes;
344    return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
345 }
346 
flac_close(FLACFILE * ff)347 static void flac_close(FLACFILE *ff)
348 {
349    lib.FLAC__stream_decoder_finish(ff->decoder);
350    lib.FLAC__stream_decoder_delete(ff->decoder);
351    /* Don't close ff->fh here. */
352    al_free(ff);
353 }
354 
355 /* In seconds. */
flac_stream_get_position(ALLEGRO_AUDIO_STREAM * stream)356 static double flac_stream_get_position(ALLEGRO_AUDIO_STREAM *stream)
357 {
358    FLACFILE *ff = (FLACFILE *)stream->extra;
359    return ff->streamed_samples / ff->sample_rate;
360 }
361 
362 
363 /*
364  *  Updates 'stream' with the next chunk of data.
365  *  Returns the actual number of bytes written.
366  */
flac_stream_update(ALLEGRO_AUDIO_STREAM * stream,void * data,size_t buf_size)367 static size_t flac_stream_update(ALLEGRO_AUDIO_STREAM *stream, void *data,
368    size_t buf_size)
369 {
370    int bytes_per_sample;
371    uint64_t wanted_samples;
372    uint64_t read_samples;
373    size_t written_bytes = 0;
374    size_t read_bytes;
375    FLACFILE *ff = (FLACFILE *)stream->extra;
376 
377    bytes_per_sample = ff->sample_size * ff->channels;
378    wanted_samples = buf_size / bytes_per_sample;
379 
380    if (ff->streamed_samples + wanted_samples > ff->loop_end) {
381       if (ff->loop_end > ff->streamed_samples)
382          wanted_samples = ff->loop_end - ff->streamed_samples;
383       else
384          return 0;
385    }
386 
387    while (wanted_samples > 0) {
388       read_samples = ff->decoded_samples - ff->streamed_samples;
389 
390       /* If the buffer size is small, we shouldn't read a new frame or our
391        * buffer keeps growing - so only refill when needed.
392        */
393       if (!read_samples) {
394          if (!lib.FLAC__stream_decoder_process_single(ff->decoder))
395             break;
396          read_samples = ff->decoded_samples - ff->streamed_samples;
397          if (!read_samples) {
398             break;
399          }
400       }
401 
402       if (read_samples > wanted_samples)
403          read_samples = wanted_samples;
404       ff->streamed_samples += read_samples;
405       wanted_samples -= read_samples;
406       read_bytes = read_samples * bytes_per_sample;
407       /* Copy data from the FLAC file buffer to the stream buffer. */
408       memcpy((uint8_t *)data + written_bytes, ff->buffer, read_bytes);
409       /* Make room in the FLACFILE buffer. */
410       memmove(ff->buffer, ff->buffer + read_bytes,
411          ff->buffer_pos - read_bytes);
412       ff->buffer_pos -= read_bytes;
413       written_bytes += read_bytes;
414    }
415 
416    return written_bytes;
417 }
418 
419 /* Called from al_destroy_audio_stream. */
flac_stream_close(ALLEGRO_AUDIO_STREAM * stream)420 static void flac_stream_close(ALLEGRO_AUDIO_STREAM *stream)
421 {
422    FLACFILE *ff = stream->extra;
423    _al_acodec_stop_feed_thread(stream);
424 
425    al_fclose(ff->fh);
426    al_free(ff->buffer);
427    flac_close(ff);
428 }
429 
real_seek(ALLEGRO_AUDIO_STREAM * stream,uint64_t sample)430 static bool real_seek(ALLEGRO_AUDIO_STREAM *stream, uint64_t sample)
431 {
432    FLACFILE *ff = stream->extra;
433 
434    /* We use ff->streamed_samples as the exact sample position for looping and
435     * returning the position. Therefore we also use it as reference position
436     * when seeking - that is, we call flush below to make the FLAC decoder
437     * discard any additional samples it may have buffered already.
438     * */
439    lib.FLAC__stream_decoder_flush(ff->decoder);
440    lib.FLAC__stream_decoder_seek_absolute(ff->decoder, sample);
441 
442    ff->buffer_pos = 0;
443    ff->streamed_samples = sample;
444    ff->decoded_samples = sample;
445    return true;
446 }
447 
flac_stream_seek(ALLEGRO_AUDIO_STREAM * stream,double time)448 static bool flac_stream_seek(ALLEGRO_AUDIO_STREAM *stream, double time)
449 {
450    FLACFILE *ff = stream->extra;
451    uint64_t sample = time * ff->sample_rate;
452    return real_seek(stream, sample);
453 }
454 
flac_stream_rewind(ALLEGRO_AUDIO_STREAM * stream)455 static bool flac_stream_rewind(ALLEGRO_AUDIO_STREAM *stream)
456 {
457    FLACFILE *ff = stream->extra;
458    return real_seek(stream, ff->loop_start);
459 }
460 
flac_stream_get_length(ALLEGRO_AUDIO_STREAM * stream)461 static double flac_stream_get_length(ALLEGRO_AUDIO_STREAM *stream)
462 {
463    FLACFILE *ff = stream->extra;
464    return ff->total_samples / ff->sample_rate;
465 }
466 
flac_stream_set_loop(ALLEGRO_AUDIO_STREAM * stream,double start,double end)467 static bool flac_stream_set_loop(ALLEGRO_AUDIO_STREAM *stream, double start,
468    double end)
469 {
470    FLACFILE *ff = stream->extra;
471    ff->loop_start = start * ff->sample_rate;
472    ff->loop_end = end * ff->sample_rate;
473    return true;
474 }
475 
flac_open(ALLEGRO_FILE * f)476 static FLACFILE *flac_open(ALLEGRO_FILE* f)
477 {
478    FLACFILE *ff;
479    FLAC__StreamDecoderInitStatus init_status;
480 
481    if (!init_dynlib()) {
482       return NULL;
483    }
484 
485    ff = al_calloc(1, sizeof *ff);
486 
487    ff->decoder = lib.FLAC__stream_decoder_new();
488    if (!ff->decoder) {
489       ALLEGRO_ERROR("Error allocating FLAC decoder\n");
490       goto error;
491    }
492 
493    ff->fh = f;
494    if (!ff->fh) {
495       ALLEGRO_ERROR("Error opening FLAC file\n");
496       goto error;
497    }
498 
499    init_status = lib.FLAC__stream_decoder_init_stream(ff->decoder, read_callback,
500       seek_callback, tell_callback, length_callback, eof_callback,
501       write_callback, metadata_callback, error_callback, ff);
502    if (init_status != FLAC__STREAM_DECODER_INIT_STATUS_OK) {
503 #ifdef ALLEGRO_CFG_ACODEC_FLAC_DLL
504       ALLEGRO_ERROR("Error initializing FLAC decoder\n"); /* lazy */
505 #else
506       ALLEGRO_ERROR("Error initializing FLAC decoder: %s\n",
507          FLAC__StreamDecoderInitStatusString[init_status]);
508 #endif
509       goto error;
510    }
511 
512    lib.FLAC__stream_decoder_process_until_end_of_metadata(ff->decoder);
513 
514    if (ff->sample_size == 0) {
515       ALLEGRO_ERROR("Error: don't support sub 8-bit sizes\n");
516       goto error;
517    }
518 
519    ALLEGRO_DEBUG("Loaded FLAC sample with properties:\n");
520    ALLEGRO_DEBUG("    channels %d\n", ff->channels);
521    ALLEGRO_DEBUG("    sample_size %d\n", ff->sample_size);
522    ALLEGRO_DEBUG("    rate %.f\n", ff->sample_rate);
523    ALLEGRO_DEBUG("    total_samples %ld\n", (long) ff->total_samples);
524 
525    return ff;
526 
527 error:
528    if (ff) {
529       if (ff->decoder)
530          lib.FLAC__stream_decoder_delete(ff->decoder);
531       al_free(ff);
532    }
533    return NULL;
534 }
535 
_al_load_flac(const char * filename)536 ALLEGRO_SAMPLE *_al_load_flac(const char *filename)
537 {
538    ALLEGRO_FILE *f;
539    ALLEGRO_SAMPLE *spl;
540    ASSERT(filename);
541 
542    f = al_fopen(filename, "rb");
543    if (!f) {
544       ALLEGRO_ERROR("Unable to open %s for reading.\n", filename);
545       return NULL;
546    }
547 
548    spl = _al_load_flac_f(f);
549 
550    al_fclose(f);
551 
552    return spl;
553 }
554 
_al_load_flac_f(ALLEGRO_FILE * f)555 ALLEGRO_SAMPLE *_al_load_flac_f(ALLEGRO_FILE *f)
556 {
557    ALLEGRO_SAMPLE *sample;
558    FLACFILE *ff;
559 
560    ff = flac_open(f);
561    if (!ff) {
562       return NULL;
563    }
564 
565    ff->buffer_size = ff->total_samples * ff->channels * ff->sample_size;
566    ff->buffer = al_malloc(ff->buffer_size);
567 
568    lib.FLAC__stream_decoder_process_until_end_of_stream(ff->decoder);
569 
570    sample = al_create_sample(ff->buffer, ff->total_samples, ff->sample_rate,
571       _al_word_size_to_depth_conf(ff->sample_size),
572       _al_count_to_channel_conf(ff->channels), true);
573 
574    if (!sample) {
575       ALLEGRO_ERROR("Failed to create a sample.\n");
576       al_free(ff->buffer);
577    }
578 
579    flac_close(ff);
580 
581    return sample;
582 }
583 
_al_load_flac_audio_stream(const char * filename,size_t buffer_count,unsigned int samples)584 ALLEGRO_AUDIO_STREAM *_al_load_flac_audio_stream(const char *filename,
585    size_t buffer_count, unsigned int samples)
586 {
587    ALLEGRO_FILE *f;
588    ALLEGRO_AUDIO_STREAM *stream;
589    ASSERT(filename);
590 
591    f = al_fopen(filename, "rb");
592    if (!f) {
593       ALLEGRO_ERROR("Unable to open %s for reading.\n", filename);
594       return NULL;
595    }
596 
597    stream = _al_load_flac_audio_stream_f(f, buffer_count, samples);
598    if (!stream) {
599       al_fclose(f);
600    }
601 
602    return stream;
603 }
604 
_al_load_flac_audio_stream_f(ALLEGRO_FILE * f,size_t buffer_count,unsigned int samples)605 ALLEGRO_AUDIO_STREAM *_al_load_flac_audio_stream_f(ALLEGRO_FILE* f,
606    size_t buffer_count, unsigned int samples)
607 {
608    ALLEGRO_AUDIO_STREAM *stream;
609    FLACFILE *ff;
610 
611    ff = flac_open(f);
612    if (!ff) {
613       return NULL;
614    }
615 
616    stream = al_create_audio_stream(buffer_count, samples, ff->sample_rate,
617       _al_word_size_to_depth_conf(ff->sample_size),
618       _al_count_to_channel_conf(ff->channels));
619 
620    if (stream) {
621       stream->extra = ff;
622       ff->loop_start = 0;
623       ff->loop_end = ff->total_samples;
624       stream->feeder = flac_stream_update;
625       stream->unload_feeder = flac_stream_close;
626       stream->rewind_feeder = flac_stream_rewind;
627       stream->seek_feeder = flac_stream_seek;
628       stream->get_feeder_position = flac_stream_get_position;
629       stream->get_feeder_length = flac_stream_get_length;
630       stream->set_feeder_loop = flac_stream_set_loop;
631       _al_acodec_start_feed_thread(stream);
632    }
633    else {
634       ALLEGRO_ERROR("Failed to create stream.\n");
635       al_fclose(ff->fh);
636       flac_close(ff);
637    }
638 
639    return stream;
640 }
641 
642 
643 /* vim: set sts=3 sw=3 et: */
644