1 /* libSoX file format: FLAC   (c) 2006-7 robs@users.sourceforge.net
2  *
3  * This library is free software; you can redistribute it and/or modify it
4  * under the terms of the GNU Lesser General Public License as published by
5  * the Free Software Foundation; either version 2.1 of the License, or (at
6  * your option) any later version.
7  *
8  * This library is distributed in the hope that it will be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser
11  * General Public License for more details.
12  *
13  * You should have received a copy of the GNU Lesser General Public License
14  * along with this library; if not, write to the Free Software Foundation,
15  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
16  */
17 
18 #include "sox_i.h"
19 
20 #include <string.h>
21 /* Next line for systems that don't define off_t when you #include
22    stdio.h; apparently OS/2 has this bug */
23 #include <sys/types.h>
24 
25 #include <FLAC/all.h>
26 
27 #define MAX_COMPRESSION 8
28 
29 
30 typedef struct {
31   /* Info: */
32   unsigned bits_per_sample;
33   unsigned channels;
34   unsigned sample_rate;
35   uint64_t total_samples;
36 
37   /* Decode buffer: */
38   sox_sample_t *req_buffer; /* this may be on the stack */
39   size_t number_of_requested_samples;
40   sox_sample_t *leftover_buf; /* heap */
41   unsigned number_of_leftover_samples;
42 
43   FLAC__StreamDecoder * decoder;
44   FLAC__bool eof;
45   sox_bool seek_pending;
46   uint64_t seek_offset;
47 
48   /* Encode buffer: */
49   FLAC__int32 * decoded_samples;
50   unsigned number_of_samples;
51 
52   FLAC__StreamEncoder * encoder;
53   FLAC__StreamMetadata * metadata[2];
54   unsigned num_metadata;
55 } priv_t;
56 
57 
decoder_read_callback(FLAC__StreamDecoder const * decoder UNUSED,FLAC__byte buffer[],size_t * bytes,void * ft_data)58 static FLAC__StreamDecoderReadStatus decoder_read_callback(FLAC__StreamDecoder const* decoder UNUSED, FLAC__byte buffer[], size_t* bytes, void* ft_data)
59 {
60   sox_format_t* ft = (sox_format_t*)ft_data;
61   if(*bytes > 0) {
62     *bytes = lsx_readbuf(ft, buffer, *bytes);
63     if(lsx_error(ft))
64       return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
65     else if(*bytes == 0)
66       return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
67     else
68       return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
69   }
70   else
71     return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
72 }
73 
decoder_seek_callback(FLAC__StreamDecoder const * decoder UNUSED,FLAC__uint64 absolute_byte_offset,void * ft_data)74 static FLAC__StreamDecoderSeekStatus decoder_seek_callback(FLAC__StreamDecoder const* decoder UNUSED, FLAC__uint64 absolute_byte_offset, void* ft_data)
75 {
76   sox_format_t* ft = (sox_format_t*)ft_data;
77   if(lsx_seeki(ft, (off_t)absolute_byte_offset, SEEK_SET) < 0)
78     return FLAC__STREAM_DECODER_SEEK_STATUS_ERROR;
79   else
80     return FLAC__STREAM_DECODER_SEEK_STATUS_OK;
81 }
82 
decoder_tell_callback(FLAC__StreamDecoder const * decoder UNUSED,FLAC__uint64 * absolute_byte_offset,void * ft_data)83 static FLAC__StreamDecoderTellStatus decoder_tell_callback(FLAC__StreamDecoder const* decoder UNUSED, FLAC__uint64* absolute_byte_offset, void* ft_data)
84 {
85   sox_format_t* ft = (sox_format_t*)ft_data;
86   off_t pos;
87   if((pos = lsx_tell(ft)) < 0)
88     return FLAC__STREAM_DECODER_TELL_STATUS_ERROR;
89   else {
90     *absolute_byte_offset = (FLAC__uint64)pos;
91     return FLAC__STREAM_DECODER_TELL_STATUS_OK;
92   }
93 }
94 
decoder_length_callback(FLAC__StreamDecoder const * decoder UNUSED,FLAC__uint64 * stream_length,void * ft_data)95 static FLAC__StreamDecoderLengthStatus decoder_length_callback(FLAC__StreamDecoder const* decoder UNUSED, FLAC__uint64* stream_length, void* ft_data)
96 {
97   sox_format_t* ft = (sox_format_t*)ft_data;
98   *stream_length = lsx_filelength(ft);
99   return FLAC__STREAM_DECODER_LENGTH_STATUS_OK;
100 }
101 
decoder_eof_callback(FLAC__StreamDecoder const * decoder UNUSED,void * ft_data)102 static FLAC__bool decoder_eof_callback(FLAC__StreamDecoder const* decoder UNUSED, void* ft_data)
103 {
104   sox_format_t* ft = (sox_format_t*)ft_data;
105   return lsx_eof(ft) ? 1 : 0;
106 }
107 
decoder_metadata_callback(FLAC__StreamDecoder const * const flac,FLAC__StreamMetadata const * const metadata,void * const client_data)108 static void decoder_metadata_callback(FLAC__StreamDecoder const * const flac, FLAC__StreamMetadata const * const metadata, void * const client_data)
109 {
110   sox_format_t * ft = (sox_format_t *) client_data;
111   priv_t * p = (priv_t *)ft->priv;
112 
113   (void) flac;
114 
115   if (metadata->type == FLAC__METADATA_TYPE_STREAMINFO) {
116     p->bits_per_sample = metadata->data.stream_info.bits_per_sample;
117     p->channels = metadata->data.stream_info.channels;
118     p->sample_rate = metadata->data.stream_info.sample_rate;
119     p->total_samples = metadata->data.stream_info.total_samples;
120   }
121   else if (metadata->type == FLAC__METADATA_TYPE_VORBIS_COMMENT) {
122     const FLAC__StreamMetadata_VorbisComment *vc = &metadata->data.vorbis_comment;
123     size_t i;
124 
125     if (vc->num_comments == 0)
126       return;
127 
128     if (ft->oob.comments != NULL) {
129       lsx_warn("multiple Vorbis comment block ignored");
130       return;
131     }
132 
133     for (i = 0; i < vc->num_comments; ++i)
134       if (vc->comments[i].entry)
135         sox_append_comment(&ft->oob.comments, (char const *) vc->comments[i].entry);
136   }
137 }
138 
139 
140 
decoder_error_callback(FLAC__StreamDecoder const * const flac,FLAC__StreamDecoderErrorStatus const status,void * const client_data)141 static void decoder_error_callback(FLAC__StreamDecoder const * const flac, FLAC__StreamDecoderErrorStatus const status, void * const client_data)
142 {
143   sox_format_t * ft = (sox_format_t *) client_data;
144 
145   (void) flac;
146 
147   lsx_fail_errno(ft, SOX_EINVAL, "%s", FLAC__StreamDecoderErrorStatusString[status]);
148 }
149 
150 
151 
decoder_write_callback(FLAC__StreamDecoder const * const flac,FLAC__Frame const * const frame,FLAC__int32 const * const buffer[],void * const client_data)152 static FLAC__StreamDecoderWriteStatus decoder_write_callback(FLAC__StreamDecoder const * const flac, FLAC__Frame const * const frame, FLAC__int32 const * const buffer[], void * const client_data)
153 {
154   sox_format_t * ft = (sox_format_t *) client_data;
155   priv_t * p = (priv_t *)ft->priv;
156   sox_sample_t * dst = p->req_buffer;
157   unsigned channel;
158   unsigned nsamples = frame->header.blocksize;
159   unsigned sample = 0;
160   size_t actual = nsamples * p->channels;
161 
162   (void) flac;
163 
164   if (frame->header.bits_per_sample != p->bits_per_sample || frame->header.channels != p->channels || frame->header.sample_rate != p->sample_rate) {
165     lsx_fail_errno(ft, SOX_EINVAL, "FLAC ERROR: parameters differ between frame and header");
166     return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
167   }
168   if (dst == NULL) {
169     lsx_warn("FLAC ERROR: entered write callback without a buffer (SoX bug)");
170     return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
171   }
172 
173   /* FLAC may give us too much data, prepare the leftover buffer */
174   if (actual > p->number_of_requested_samples) {
175     size_t to_stash = actual - p->number_of_requested_samples;
176 
177     p->leftover_buf = lsx_malloc(to_stash * sizeof(sox_sample_t));
178     p->number_of_leftover_samples = to_stash;
179     nsamples = p->number_of_requested_samples / p->channels;
180 
181     p->req_buffer += p->number_of_requested_samples;
182     p->number_of_requested_samples = 0;
183   } else {
184     p->req_buffer += actual;
185     p->number_of_requested_samples -= actual;
186   }
187 
188 leftover_copy:
189 
190   for (; sample < nsamples; sample++) {
191     for (channel = 0; channel < p->channels; channel++) {
192       FLAC__int32 d = buffer[channel][sample];
193       switch (p->bits_per_sample) {
194       case  8: *dst++ = SOX_SIGNED_8BIT_TO_SAMPLE(d,); break;
195       case 16: *dst++ = SOX_SIGNED_16BIT_TO_SAMPLE(d,); break;
196       case 24: *dst++ = SOX_SIGNED_24BIT_TO_SAMPLE(d,); break;
197       case 32: *dst++ = SOX_SIGNED_32BIT_TO_SAMPLE(d,); break;
198       }
199     }
200   }
201 
202   /* copy into the leftover buffer if we've prepared it */
203   if (sample < frame->header.blocksize) {
204     nsamples = frame->header.blocksize;
205     dst = p->leftover_buf;
206     goto leftover_copy;
207   }
208 
209   return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
210 }
211 
212 
213 
start_read(sox_format_t * const ft)214 static int start_read(sox_format_t * const ft)
215 {
216   priv_t * p = (priv_t *)ft->priv;
217   lsx_debug("API version %u", FLAC_API_VERSION_CURRENT);
218   p->decoder = FLAC__stream_decoder_new();
219   if (p->decoder == NULL) {
220     lsx_fail_errno(ft, SOX_ENOMEM, "FLAC ERROR creating the decoder instance");
221     return SOX_EOF;
222   }
223 
224   FLAC__stream_decoder_set_md5_checking(p->decoder, sox_true);
225   FLAC__stream_decoder_set_metadata_respond_all(p->decoder);
226   if (FLAC__stream_decoder_init_stream(
227       p->decoder,
228       decoder_read_callback,
229       ft->seekable ? decoder_seek_callback : NULL,
230       ft->seekable ? decoder_tell_callback : NULL,
231       ft->seekable ? decoder_length_callback : NULL,
232       ft->seekable ? decoder_eof_callback : NULL,
233       decoder_write_callback,
234       decoder_metadata_callback,
235       decoder_error_callback,
236       ft) != FLAC__STREAM_DECODER_INIT_STATUS_OK){
237     lsx_fail_errno(ft, SOX_EHDR, "FLAC ERROR initialising decoder");
238     return SOX_EOF;
239   }
240 
241   if (!FLAC__stream_decoder_process_until_end_of_metadata(p->decoder)) {
242     lsx_fail_errno(ft, SOX_EHDR, "FLAC ERROR whilst decoding metadata");
243     return SOX_EOF;
244   }
245 
246   if (FLAC__stream_decoder_get_state(p->decoder) > FLAC__STREAM_DECODER_END_OF_STREAM) {
247     lsx_fail_errno(ft, SOX_EHDR, "FLAC ERROR during metadata decoding");
248     return SOX_EOF;
249   }
250 
251   ft->encoding.encoding = SOX_ENCODING_FLAC;
252   ft->signal.rate = p->sample_rate;
253   ft->encoding.bits_per_sample = p->bits_per_sample;
254   ft->signal.channels = p->channels;
255   ft->signal.length = p->total_samples * p->channels;
256   return SOX_SUCCESS;
257 }
258 
259 
read_samples(sox_format_t * const ft,sox_sample_t * sampleBuffer,size_t const requested)260 static size_t read_samples(sox_format_t * const ft, sox_sample_t * sampleBuffer, size_t const requested)
261 {
262   priv_t * p = (priv_t *)ft->priv;
263   size_t prev_requested;
264 
265   if (p->seek_pending) {
266     p->seek_pending = sox_false;
267 
268     /* discard leftover decoded data */
269     free(p->leftover_buf);
270     p->leftover_buf = NULL;
271     p->number_of_leftover_samples = 0;
272 
273     p->req_buffer = sampleBuffer;
274     p->number_of_requested_samples = requested;
275 
276     /* calls decoder_write_callback */
277     if (!FLAC__stream_decoder_seek_absolute(p->decoder, (FLAC__uint64)(p->seek_offset / ft->signal.channels))) {
278       p->req_buffer = NULL;
279       return 0;
280     }
281   } else if (p->number_of_leftover_samples > 0) {
282 
283     /* small request, no need to decode more samples since we have leftovers */
284     if (requested < p->number_of_leftover_samples) {
285       size_t req_bytes = requested * sizeof(sox_sample_t);
286 
287       memcpy(sampleBuffer, p->leftover_buf, req_bytes);
288       p->number_of_leftover_samples -= requested;
289       memmove(p->leftover_buf, (char *)p->leftover_buf + req_bytes,
290               (size_t)p->number_of_leftover_samples * sizeof(sox_sample_t));
291       return requested;
292     }
293 
294     /* first, give them all of our leftover data: */
295     memcpy(sampleBuffer, p->leftover_buf,
296            p->number_of_leftover_samples * sizeof(sox_sample_t));
297 
298     p->req_buffer = sampleBuffer + p->number_of_leftover_samples;
299     p->number_of_requested_samples = requested - p->number_of_leftover_samples;
300 
301     free(p->leftover_buf);
302     p->leftover_buf = NULL;
303     p->number_of_leftover_samples = 0;
304 
305     /* continue invoking decoder below */
306   } else {
307     p->req_buffer = sampleBuffer;
308     p->number_of_requested_samples = requested;
309   }
310 
311   /* invoke the decoder, calls decoder_write_callback */
312   while ((prev_requested = p->number_of_requested_samples) && !p->eof) {
313     if (!FLAC__stream_decoder_process_single(p->decoder))
314       break; /* error, but maybe got earlier in the loop, though */
315 
316     /* number_of_requested_samples decrements as the decoder progresses */
317     if (p->number_of_requested_samples == prev_requested)
318       p->eof = sox_true;
319   }
320   p->req_buffer = NULL;
321 
322   return requested - p->number_of_requested_samples;
323 }
324 
325 
326 
stop_read(sox_format_t * const ft)327 static int stop_read(sox_format_t * const ft)
328 {
329   priv_t * p = (priv_t *)ft->priv;
330   if (!FLAC__stream_decoder_finish(p->decoder) && p->eof)
331     lsx_warn("decoder MD5 checksum mismatch.");
332   FLAC__stream_decoder_delete(p->decoder);
333 
334   free(p->leftover_buf);
335   p->leftover_buf = NULL;
336   p->number_of_leftover_samples = 0;
337   return SOX_SUCCESS;
338 }
339 
340 
341 
flac_stream_encoder_write_callback(FLAC__StreamEncoder const * const flac,const FLAC__byte buffer[],size_t const bytes,unsigned const samples,unsigned const current_frame,void * const client_data)342 static FLAC__StreamEncoderWriteStatus flac_stream_encoder_write_callback(FLAC__StreamEncoder const * const flac, const FLAC__byte buffer[], size_t const bytes, unsigned const samples, unsigned const current_frame, void * const client_data)
343 {
344   sox_format_t * const ft = (sox_format_t *) client_data;
345   (void) flac, (void) samples, (void) current_frame;
346 
347   return lsx_writebuf(ft, buffer, bytes) == bytes ? FLAC__STREAM_ENCODER_WRITE_STATUS_OK : FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR;
348 }
349 
350 
351 
flac_stream_encoder_metadata_callback(FLAC__StreamEncoder const * encoder,FLAC__StreamMetadata const * metadata,void * client_data)352 static void flac_stream_encoder_metadata_callback(FLAC__StreamEncoder const * encoder, FLAC__StreamMetadata const * metadata, void * client_data)
353 {
354   (void) encoder, (void) metadata, (void) client_data;
355 }
356 
357 
358 
flac_stream_encoder_seek_callback(FLAC__StreamEncoder const * encoder,FLAC__uint64 absolute_byte_offset,void * client_data)359 static FLAC__StreamEncoderSeekStatus flac_stream_encoder_seek_callback(FLAC__StreamEncoder const * encoder, FLAC__uint64 absolute_byte_offset, void * client_data)
360 {
361   sox_format_t * const ft = (sox_format_t *) client_data;
362   (void) encoder;
363   if (!ft->seekable)
364     return FLAC__STREAM_ENCODER_SEEK_STATUS_UNSUPPORTED;
365   else if (lsx_seeki(ft, (off_t)absolute_byte_offset, SEEK_SET) != SOX_SUCCESS)
366     return FLAC__STREAM_ENCODER_SEEK_STATUS_ERROR;
367   else
368     return FLAC__STREAM_ENCODER_SEEK_STATUS_OK;
369 }
370 
371 
372 
flac_stream_encoder_tell_callback(FLAC__StreamEncoder const * encoder,FLAC__uint64 * absolute_byte_offset,void * client_data)373 static FLAC__StreamEncoderTellStatus flac_stream_encoder_tell_callback(FLAC__StreamEncoder const * encoder, FLAC__uint64 * absolute_byte_offset, void * client_data)
374 {
375   sox_format_t * const ft = (sox_format_t *) client_data;
376   off_t pos;
377   (void) encoder;
378   if (!ft->seekable)
379     return FLAC__STREAM_ENCODER_TELL_STATUS_UNSUPPORTED;
380   else if ((pos = lsx_tell(ft)) < 0)
381     return FLAC__STREAM_ENCODER_TELL_STATUS_ERROR;
382   else {
383     *absolute_byte_offset = (FLAC__uint64)pos;
384     return FLAC__STREAM_ENCODER_TELL_STATUS_OK;
385   }
386 }
387 
388 
389 
start_write(sox_format_t * const ft)390 static int start_write(sox_format_t * const ft)
391 {
392   priv_t * p = (priv_t *)ft->priv;
393   FLAC__StreamEncoderInitStatus status;
394   unsigned compression_level = MAX_COMPRESSION; /* Default to "best" */
395 
396   if (ft->encoding.compression != HUGE_VAL) {
397     compression_level = ft->encoding.compression;
398     if (compression_level != ft->encoding.compression ||
399         compression_level > MAX_COMPRESSION) {
400       lsx_fail_errno(ft, SOX_EINVAL,
401                  "FLAC compression level must be a whole number from 0 to %i",
402                  MAX_COMPRESSION);
403       return SOX_EOF;
404     }
405   }
406 
407   p->encoder = FLAC__stream_encoder_new();
408   if (p->encoder == NULL) {
409     lsx_fail_errno(ft, SOX_ENOMEM, "FLAC ERROR creating the encoder instance");
410     return SOX_EOF;
411   }
412 
413   p->bits_per_sample = ft->encoding.bits_per_sample;
414   ft->signal.precision = ft->encoding.bits_per_sample;
415 
416   lsx_report("encoding at %i bits per sample", p->bits_per_sample);
417 
418   FLAC__stream_encoder_set_channels(p->encoder, ft->signal.channels);
419   FLAC__stream_encoder_set_bits_per_sample(p->encoder, p->bits_per_sample);
420   FLAC__stream_encoder_set_sample_rate(p->encoder, (unsigned)(ft->signal.rate + .5));
421 
422   { /* Check if rate is streamable: */
423     static const unsigned streamable_rates[] =
424       {8000, 16000, 22050, 24000, 32000, 44100, 48000, 96000};
425     size_t i;
426     sox_bool streamable = sox_false;
427     for (i = 0; !streamable && i < array_length(streamable_rates); ++i)
428        streamable = (streamable_rates[i] == ft->signal.rate);
429     if (!streamable) {
430       lsx_report("non-standard rate; output may not be streamable");
431       FLAC__stream_encoder_set_streamable_subset(p->encoder, sox_false);
432     }
433   }
434 
435 #if FLAC_API_VERSION_CURRENT >= 10
436   FLAC__stream_encoder_set_compression_level(p->encoder, compression_level);
437 #else
438   {
439     static struct {
440       unsigned blocksize;
441       FLAC__bool do_exhaustive_model_search;
442       FLAC__bool do_mid_side_stereo;
443       FLAC__bool loose_mid_side_stereo;
444       unsigned max_lpc_order;
445       unsigned max_residual_partition_order;
446       unsigned min_residual_partition_order;
447     } const options[MAX_COMPRESSION + 1] = {
448       {1152, sox_false, sox_false, sox_false, 0, 2, 2},
449       {1152, sox_false, sox_true, sox_true, 0, 2, 2},
450       {1152, sox_false, sox_true, sox_false, 0, 3, 0},
451       {4608, sox_false, sox_false, sox_false, 6, 3, 3},
452       {4608, sox_false, sox_true, sox_true, 8, 3, 3},
453       {4608, sox_false, sox_true, sox_false, 8, 3, 3},
454       {4608, sox_false, sox_true, sox_false, 8, 4, 0},
455       {4608, sox_true, sox_true, sox_false, 8, 6, 0},
456       {4608, sox_true, sox_true, sox_false, 12, 6, 0},
457     };
458 #define SET_OPTION(x) do {\
459   lsx_report(#x" = %i", options[compression_level].x); \
460   FLAC__stream_encoder_set_##x(p->encoder, options[compression_level].x);\
461 } while (0)
462     SET_OPTION(blocksize);
463     SET_OPTION(do_exhaustive_model_search);
464     SET_OPTION(max_lpc_order);
465     SET_OPTION(max_residual_partition_order);
466     SET_OPTION(min_residual_partition_order);
467     if (ft->signal.channels == 2) {
468       SET_OPTION(do_mid_side_stereo);
469       SET_OPTION(loose_mid_side_stereo);
470     }
471 #undef SET_OPTION
472   }
473 #endif
474 
475   if (ft->signal.length != 0) {
476     FLAC__stream_encoder_set_total_samples_estimate(p->encoder, (FLAC__uint64)(ft->signal.length / ft->signal.channels));
477 
478     p->metadata[p->num_metadata] = FLAC__metadata_object_new(FLAC__METADATA_TYPE_SEEKTABLE);
479     if (p->metadata[p->num_metadata] == NULL) {
480       lsx_fail_errno(ft, SOX_ENOMEM, "FLAC ERROR creating the encoder seek table template");
481       return SOX_EOF;
482     }
483     {
484       if (!FLAC__metadata_object_seektable_template_append_spaced_points_by_samples(p->metadata[p->num_metadata], (unsigned)(10 * ft->signal.rate + .5), (FLAC__uint64)(ft->signal.length/ft->signal.channels))) {
485         lsx_fail_errno(ft, SOX_ENOMEM, "FLAC ERROR creating the encoder seek table points");
486         return SOX_EOF;
487       }
488     }
489     p->metadata[p->num_metadata]->is_last = sox_false; /* the encoder will set this for us */
490     ++p->num_metadata;
491   }
492 
493   if (ft->oob.comments) {     /* Make the comment structure */
494     FLAC__StreamMetadata_VorbisComment_Entry entry;
495     int i;
496 
497     p->metadata[p->num_metadata] = FLAC__metadata_object_new(FLAC__METADATA_TYPE_VORBIS_COMMENT);
498     for (i = 0; ft->oob.comments[i]; ++i) {
499       static const char prepend[] = "Comment=";
500       char * text = lsx_calloc(strlen(prepend) + strlen(ft->oob.comments[i]) + 1, sizeof(*text));
501       /* Prepend `Comment=' if no field-name already in the comment */
502       if (!strchr(ft->oob.comments[i], '='))
503         strcpy(text, prepend);
504       entry.entry = (FLAC__byte *) strcat(text, ft->oob.comments[i]);
505       entry.length = strlen(text);
506       FLAC__metadata_object_vorbiscomment_append_comment(p->metadata[p->num_metadata], entry, /*copy= */ sox_true);
507       free(text);
508     }
509     ++p->num_metadata;
510   }
511 
512   if (p->num_metadata)
513     FLAC__stream_encoder_set_metadata(p->encoder, p->metadata, p->num_metadata);
514 
515   status = FLAC__stream_encoder_init_stream(p->encoder, flac_stream_encoder_write_callback,
516       flac_stream_encoder_seek_callback, flac_stream_encoder_tell_callback, flac_stream_encoder_metadata_callback, ft);
517 
518   if (status != FLAC__STREAM_ENCODER_INIT_STATUS_OK) {
519     lsx_fail_errno(ft, SOX_EINVAL, "%s", FLAC__StreamEncoderInitStatusString[status]);
520     return SOX_EOF;
521   }
522   return SOX_SUCCESS;
523 }
524 
525 
526 
write_samples(sox_format_t * const ft,sox_sample_t const * const sampleBuffer,size_t const len)527 static size_t write_samples(sox_format_t * const ft, sox_sample_t const * const sampleBuffer, size_t const len)
528 {
529   priv_t * p = (priv_t *)ft->priv;
530   unsigned i;
531 
532   /* allocate or grow buffer */
533   if (p->number_of_samples < len) {
534     p->number_of_samples = len;
535     free(p->decoded_samples);
536     p->decoded_samples = lsx_malloc(p->number_of_samples * sizeof(FLAC__int32));
537   }
538 
539   for (i = 0; i < len; ++i) {
540     SOX_SAMPLE_LOCALS;
541     long pcm = SOX_SAMPLE_TO_SIGNED_32BIT(sampleBuffer[i], ft->clips);
542     p->decoded_samples[i] = pcm >> (32 - p->bits_per_sample);
543     switch (p->bits_per_sample) {
544       case  8: p->decoded_samples[i] =
545           SOX_SAMPLE_TO_SIGNED_8BIT(sampleBuffer[i], ft->clips);
546         break;
547       case 16: p->decoded_samples[i] =
548           SOX_SAMPLE_TO_SIGNED_16BIT(sampleBuffer[i], ft->clips);
549         break;
550       case 24: p->decoded_samples[i] = /* sign extension: */
551           SOX_SAMPLE_TO_SIGNED_24BIT(sampleBuffer[i],ft->clips) << 8;
552         p->decoded_samples[i] >>= 8;
553         break;
554       case 32: p->decoded_samples[i] =
555           SOX_SAMPLE_TO_SIGNED_32BIT(sampleBuffer[i],ft->clips);
556         break;
557     }
558   }
559   FLAC__stream_encoder_process_interleaved(p->encoder, p->decoded_samples, (unsigned) len / ft->signal.channels);
560   return FLAC__stream_encoder_get_state(p->encoder) == FLAC__STREAM_ENCODER_OK ? len : 0;
561 }
562 
563 
564 
stop_write(sox_format_t * const ft)565 static int stop_write(sox_format_t * const ft)
566 {
567   priv_t * p = (priv_t *)ft->priv;
568   FLAC__StreamEncoderState state = FLAC__stream_encoder_get_state(p->encoder);
569   unsigned i;
570 
571   FLAC__stream_encoder_finish(p->encoder);
572   FLAC__stream_encoder_delete(p->encoder);
573   for (i = 0; i < p->num_metadata; ++i)
574     FLAC__metadata_object_delete(p->metadata[i]);
575   free(p->decoded_samples);
576   if (state != FLAC__STREAM_ENCODER_OK) {
577     lsx_fail_errno(ft, SOX_EINVAL, "FLAC ERROR: failed to encode to end of stream");
578     return SOX_EOF;
579   }
580   return SOX_SUCCESS;
581 }
582 
583 
584 
seek(sox_format_t * ft,uint64_t offset)585 static int seek(sox_format_t * ft, uint64_t offset)
586 {
587   priv_t * p = (priv_t *)ft->priv;
588   p->seek_offset = offset;
589   p->seek_pending = sox_true;
590   return ft->mode == 'r' ? SOX_SUCCESS : SOX_EOF;
591 }
592 
593 
594 
LSX_FORMAT_HANDLER(flac)595 LSX_FORMAT_HANDLER(flac)
596 {
597   static char const * const names[] = {"flac", NULL};
598   static unsigned const encodings[] = {SOX_ENCODING_FLAC, 8, 16, 24, 0, 0};
599   static sox_format_handler_t const handler = {SOX_LIB_VERSION_CODE,
600     "Free Lossless Audio CODEC compressed audio", names, 0,
601     start_read, read_samples, stop_read,
602     start_write, write_samples, stop_write,
603     seek, encodings, NULL, sizeof(priv_t)
604   };
605   return &handler;
606 }
607