ref: 7438be46b4c1874cda7f1c23d67427bd9ad42b27
parent: 72751915968c8dbcef0252c5fda7a07b4eb4026e
author: robs <robs>
date: Thu Jan 24 15:06:28 EST 2008
Fix and support for FLAC 1.2.x; further fixes needed in sox.c tho'
--- a/src/flac.c
+++ b/src/flac.c
@@ -44,7 +44,9 @@
#define FLAC__stream_decoder_seek_absolute FLAC__file_decoder_seek_absolute
#endif
+#define MAX_COMPRESSION 8
+
typedef struct {
/* Info: */
unsigned bits_per_sample;
@@ -309,7 +311,19 @@
{
Encoder * encoder = (Encoder *) ft->priv;
FLAC__StreamEncoderState status;
+ unsigned compression_level = MAX_COMPRESSION; /* Default to "best" */
+ if (ft->signal.compression != HUGE_VAL) {
+ compression_level = ft->signal.compression;
+ if (compression_level != ft->signal.compression ||
+ compression_level > MAX_COMPRESSION) {
+ sox_fail_errno(ft, SOX_EINVAL,
+ "FLAC compression level must be a whole number from 0 to %i",
+ MAX_COMPRESSION);
+ return SOX_EOF;
+ }
+ }
+
memset(encoder, 0, sizeof(*encoder));
encoder->flac = FLAC__stream_encoder_new();
if (encoder->flac == NULL) {
@@ -318,7 +332,36 @@
}
encoder->decoded_samples = xmalloc(sox_globals.bufsiz * sizeof(FLAC__int32));
- { /* Select and set FLAC encoder options: */
+ /* FIXME: FLAC should not need to know about this oddity */
+ if (ft->signal.encoding < SOX_ENCODING_SIZE_IS_WORD)
+ ft->signal.size = SOX_SIZE_16BIT;
+ ft->signal.encoding = SOX_ENCODING_FLAC;
+
+ encoder->bits_per_sample = (ft->signal.size > 4 ? 4 : ft->signal.size) << 3;
+
+ sox_report("encoding at %i bits per sample", encoder->bits_per_sample);
+
+ FLAC__stream_encoder_set_channels(encoder->flac, ft->signal.channels);
+ FLAC__stream_encoder_set_bits_per_sample(encoder->flac, encoder->bits_per_sample);
+ FLAC__stream_encoder_set_sample_rate(encoder->flac, ft->signal.rate);
+
+ { /* Check if rate is streamable: */
+ static const unsigned streamable_rates[] =
+ {8000, 16000, 22050, 24000, 32000, 44100, 48000, 96000};
+ size_t i;
+ sox_bool streamable = sox_false;
+ for (i = 0; !streamable && i < array_length(streamable_rates); ++i)
+ streamable = (streamable_rates[i] == ft->signal.rate);
+ if (!streamable) {
+ sox_report("non-standard rate; output may not be streamable");
+ FLAC__stream_encoder_set_streamable_subset(encoder->flac, sox_false);
+ }
+ }
+
+#if FLAC_API_VERSION_CURRENT >= 10
+ FLAC__stream_encoder_set_compression_level(encoder->flac, compression_level);
+#else
+ {
static struct {
unsigned blocksize;
FLAC__bool do_exhaustive_model_search;
@@ -327,7 +370,7 @@
unsigned max_lpc_order;
unsigned max_residual_partition_order;
unsigned min_residual_partition_order;
- } const options[] = {
+ } const options[MAX_COMPRESSION + 1] = {
{1152, sox_false, sox_false, sox_false, 0, 2, 2},
{1152, sox_false, sox_true, sox_true, 0, 2, 2},
{1152, sox_false, sox_true, sox_false, 0, 3, 0},
@@ -338,21 +381,8 @@
{4608, sox_true, sox_true, sox_false, 8, 6, 0},
{4608, sox_true, sox_true, sox_false, 12, 6, 0},
};
- unsigned compression_level = array_length(options) - 1; /* Default to "best" */
-
- if (ft->signal.compression != HUGE_VAL) {
- compression_level = ft->signal.compression;
- if (compression_level != ft->signal.compression ||
- compression_level >= array_length(options)) {
- sox_fail_errno(ft, SOX_EINVAL,
- "FLAC compression level must be a whole number from 0 to %i",
- array_length(options) - 1);
- return SOX_EOF;
- }
- }
-
#define SET_OPTION(x) do {\
- sox_report("FLAC "#x" = %i", options[compression_level].x); \
+ sox_report(#x" = %i", options[compression_level].x); \
FLAC__stream_encoder_set_##x(encoder->flac, options[compression_level].x);\
} while (0)
SET_OPTION(blocksize);
@@ -366,33 +396,8 @@
}
#undef SET_OPTION
}
+#endif
- /* FIXME: FLAC should not need to know about this oddity */
- if (ft->signal.encoding < SOX_ENCODING_SIZE_IS_WORD)
- ft->signal.size = SOX_SIZE_16BIT;
- ft->signal.encoding = SOX_ENCODING_FLAC;
-
- encoder->bits_per_sample = (ft->signal.size > 4 ? 4 : ft->signal.size) << 3;
-
- sox_report("FLAC encoding at %i bits per sample", encoder->bits_per_sample);
-
- FLAC__stream_encoder_set_channels(encoder->flac, ft->signal.channels);
- FLAC__stream_encoder_set_bits_per_sample(encoder->flac, encoder->bits_per_sample);
- FLAC__stream_encoder_set_sample_rate(encoder->flac, ft->signal.rate);
-
- { /* Check if rate is streamable: */
- static const unsigned streamable_rates[] =
- {8000, 16000, 22050, 24000, 32000, 44100, 48000, 96000};
- size_t i;
- sox_bool streamable = sox_false;
- for (i = 0; !streamable && i < array_length(streamable_rates); ++i)
- streamable = (streamable_rates[i] == ft->signal.rate);
- if (!streamable) {
- sox_report("FLAC: non-standard rate; output may not be streamable");
- FLAC__stream_encoder_set_streamable_subset(encoder->flac, sox_false);
- }
- }
-
if (ft->length != 0) {
FLAC__stream_encoder_set_total_samples_estimate(encoder->flac, (FLAC__uint64)ft->length);
@@ -479,11 +484,22 @@
unsigned i;
for (i = 0; i < len; ++i) {
+ long pcm = SOX_SAMPLE_TO_SIGNED_32BIT(sampleBuffer[i], ft->clips);
+ encoder->decoded_samples[i] = pcm >> (32 - encoder->bits_per_sample);
switch (encoder->bits_per_sample) {
- case 8: encoder->decoded_samples[i] = SOX_SAMPLE_TO_SIGNED_8BIT(sampleBuffer[i], ft->clips); break;
- case 16: encoder->decoded_samples[i] = SOX_SAMPLE_TO_SIGNED_16BIT(sampleBuffer[i], ft->clips); break;
- case 24: encoder->decoded_samples[i] = SOX_SAMPLE_TO_SIGNED_24BIT(sampleBuffer[i],ft->clips); break;
- case 32: encoder->decoded_samples[i] = SOX_SAMPLE_TO_SIGNED_32BIT(sampleBuffer[i],ft->clips); break;
+ case 8: encoder->decoded_samples[i] =
+ SOX_SAMPLE_TO_SIGNED_8BIT(sampleBuffer[i], ft->clips);
+ break;
+ case 16: encoder->decoded_samples[i] =
+ SOX_SAMPLE_TO_SIGNED_16BIT(sampleBuffer[i], ft->clips);
+ break;
+ case 24: encoder->decoded_samples[i] = /* sign extension: */
+ SOX_SAMPLE_TO_SIGNED_24BIT(sampleBuffer[i],ft->clips) << 8;
+ encoder->decoded_samples[i] >>= 8;
+ break;
+ case 32: encoder->decoded_samples[i] =
+ SOX_SAMPLE_TO_SIGNED_32BIT(sampleBuffer[i],ft->clips);
+ break;
}
}
FLAC__stream_encoder_process_interleaved(encoder->flac, encoder->decoded_samples, len / ft->signal.channels);
@@ -512,6 +528,10 @@
+/*
+ * N.B. Do not call this function with offset=0 when file-pointer
+ * is already 0 or a block of decoded FLAC data will be discarded.
+ */
static int seek(sox_format_t * ft, sox_size_t offset)
{
Decoder * decoder = (Decoder *) ft->priv;