add support for specifying which apodization functions to use to window data before...
authorJosh Coalson <jcoalson@users.sourceforce.net>
Tue, 25 Apr 2006 06:38:43 +0000 (06:38 +0000)
committerJosh Coalson <jcoalson@users.sourceforce.net>
Tue, 25 Apr 2006 06:38:43 +0000 (06:38 +0000)
22 files changed:
doc/html/changelog.html
include/FLAC/file_encoder.h
include/FLAC/format.h
include/FLAC/seekable_stream_encoder.h
include/FLAC/stream_encoder.h
include/OggFLAC/file_encoder.h
include/OggFLAC/seekable_stream_encoder.h
include/OggFLAC/stream_encoder.h
src/flac/encode.c
src/flac/encode.h
src/flac/main.c
src/libFLAC/Makefile.lite
src/libFLAC/file_encoder.c
src/libFLAC/format.c
src/libFLAC/include/private/lpc.h
src/libFLAC/include/protected/stream_encoder.h
src/libFLAC/lpc.c
src/libFLAC/seekable_stream_encoder.c
src/libFLAC/stream_encoder.c
src/libOggFLAC/file_encoder.c
src/libOggFLAC/seekable_stream_encoder.c
src/libOggFLAC/stream_encoder.c

index 99283d4..4c6af3e 100644 (file)
                                        <li>
                                                libFLAC:
                                                <ul>
+                                                       <li><b>Added</b> FLAC__*_encoder_set_apodization()</li>
                                                        <li><b>Added</b> FLAC__metadata_object_cuesheet_calculate_cddb_id()</li>
                                                        <li><b>Added</b> FLAC__metadata_get_cuesheet()</li>
                                                </ul>
                                        <li>
                                                libFLAC++:
                                                <ul>
+                                                       <li><b>Added</b> FLAC::*::Encoder::set_apodization()</li>
                                                        <li><b>Added</b> FLAC::Metadata::CueSheet::calculate_cddb_id()</li>
                                                        <li><b>Added</b> FLAC::Metadata::get_cuesheet()</li>
                                                </ul>
index fbbfadb..9b07f54 100644 (file)
@@ -315,6 +315,21 @@ FLAC_API FLAC__bool FLAC__file_encoder_set_sample_rate(FLAC__FileEncoder *encode
 FLAC_API FLAC__bool FLAC__file_encoder_set_blocksize(FLAC__FileEncoder *encoder, unsigned value);
 
 /** This is inherited from FLAC__SeekableStreamEncoder; see
+ *  FLAC__seekable_stream_encoder_set_apodization().
+ *
+ * \default \c 0
+ * \param  encoder        An encoder instance to set.
+ * \param  specification  See above.
+ * \assert
+ *    \code encoder != NULL \endcode
+ *    \code specification != NULL \endcode
+ * \retval FLAC__bool
+ *    \c false if the encoder is already initialized, else \c true.
+ */
+/* @@@@add to unit tests*/
+FLAC_API FLAC__bool FLAC__file_encoder_set_apodization(FLAC__FileEncoder *encoder, const char *specification);
+
+/** This is inherited from FLAC__SeekableStreamEncoder; see
  *  FLAC__seekable_stream_encoder_set_max_lpc_order().
  *
  * \default \c 0
index 934586d..d1c8a87 100644 (file)
@@ -315,6 +315,10 @@ typedef struct {
 
        const FLAC__int32 *residual;
        /**< The residual signal, length == (blocksize minus order) samples. */
+
+#ifdef WINDOW_DEBUG_OUTPUT
+       char window_type[64]; //@@@@@@
+#endif
 } FLAC__Subframe_LPC;
 
 extern FLAC_API const unsigned FLAC__SUBFRAME_LPC_QLP_COEFF_PRECISION_LEN; /**< == 4 (bits) */
index 4efeb42..f59e924 100644 (file)
@@ -417,6 +417,21 @@ FLAC_API FLAC__bool FLAC__seekable_stream_encoder_set_sample_rate(FLAC__Seekable
 FLAC_API FLAC__bool FLAC__seekable_stream_encoder_set_blocksize(FLAC__SeekableStreamEncoder *encoder, unsigned value);
 
 /** This is inherited from FLAC__StreamEncoder; see
+ *  FLAC__stream_encoder_set_apodization().
+ *
+ * \default \c 0
+ * \param  encoder        An encoder instance to set.
+ * \param  specification  See above.
+ * \assert
+ *    \code encoder != NULL \endcode
+ *    \code specification != NULL \endcode
+ * \retval FLAC__bool
+ *    \c false if the encoder is already initialized, else \c true.
+ */
+/* @@@@add to unit tests*/
+FLAC_API FLAC__bool FLAC__seekable_stream_encoder_set_apodization(FLAC__SeekableStreamEncoder *encoder, const char *specification);
+
+/** This is inherited from FLAC__StreamEncoder; see
  *  FLAC__stream_encoder_set_max_lpc_order().
  *
  * \default \c 0
index 0ac18a3..4f82fda 100644 (file)
@@ -498,6 +498,52 @@ FLAC_API FLAC__bool FLAC__stream_encoder_set_sample_rate(FLAC__StreamEncoder *en
  */
 FLAC_API FLAC__bool FLAC__stream_encoder_set_blocksize(FLAC__StreamEncoder *encoder, unsigned value);
 
+/** Sets the apodization function(s) the encoder will use when windowing
+ *  audio data for LPC analysis.
+ *
+ * The \a specification is a plain ASCII string which specifies exactly
+ * which functions to use.  There may be more than one (up to 32),
+ * separated by \c ';' characters.  Some functions take one or more
+ * comma-separated arguments in parentheses.
+ *
+ * The available functions are \c bartlett, \c bartlett_hann,
+ * \c blackman, \c blackman_harris_4term_92db, \c connes, \c flattop,
+ * \c gauss(STDDEV), \c hamming, \c hann, \c kaiser_bessel, \c nuttall,
+ * \c rectangle, \c triangle, \c tukey(P), \c welch.
+ *
+ * For \c gauss(STDDEV), STDDEV specifies the standard deviation
+ * (0<STDDEV<=0.5).
+ *
+ * For \c tukey(P), P specifies the fraction of the window that is
+ * tapered (0<=P<=1).  P=0 corresponds to \c rectangle and P=1
+ * corresponds to \c hann.
+ *
+ * Example specifications are \c "blackman" or
+ * \c "hann;triangle;tukey(0.5);tukey(0.25);tukey(0.125)"
+ *
+ * Any function that is specified erroneously is silently dropped.  Up
+ * to 32 functions are kept, the rest are dropped.  If the specification
+ * is empty the encoder defaults to \c "hann".
+ *
+ * When more than one function is specified, then for every subframe the
+ * encoder will try each of them separately and choose the window that
+ * results in the smallest compressed subframe.
+ *
+ * Note that each function specified causes the encoder to occupy a
+ * floating point array in which to store the window.
+ *
+ * \default \c "hann"
+ * \param  encoder        An encoder instance to set.
+ * \param  specification  See above.
+ * \assert
+ *    \code encoder != NULL \endcode
+ *    \code specification != NULL \endcode
+ * \retval FLAC__bool
+ *    \c false if the encoder is already initialized, else \c true.
+ */
+/* @@@@add to unit tests*/
+FLAC_API FLAC__bool FLAC__stream_encoder_set_apodization(FLAC__StreamEncoder *encoder, const char *specification);
+
 /** Set the maximum LPC order, or \c 0 to use only the fixed predictors.
  *
  * \default \c 0
index 0f0024e..89547a2 100644 (file)
@@ -299,6 +299,20 @@ OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_sample_rate(OggFLAC__FileEncode
 OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_blocksize(OggFLAC__FileEncoder *encoder, unsigned value);
 
 /** This is inherited from OggFLAC__SeekableStreamEncoder; see
+ *  OggFLAC__seekable_stream_encoder_set_apodization().
+ *
+ * \default \c 0
+ * \param  encoder        An encoder instance to set.
+ * \param  specification  See above.
+ * \assert
+ *    \code encoder != NULL \endcode
+ *    \code specification != NULL \endcode
+ * \retval FLAC__bool
+ *    \c false if the encoder is already initialized, else \c true.
+ */
+OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_apodization(OggFLAC__FileEncoder *encoder, const char *specification);
+
+/** This is inherited from OggFLAC__SeekableStreamEncoder; see
  *  OggFLAC__seekable_stream_encoder_set_max_lpc_order().
  *
  * \default \c 0
index 5109154..c4bf86b 100644 (file)
@@ -376,6 +376,19 @@ OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_sample_rate(OggFLAC_
  */
 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_blocksize(OggFLAC__SeekableStreamEncoder *encoder, unsigned value);
 
+/** This is inherited from FLAC__StreamEncoder; see FLAC__stream_encoder_set_apodization()
+ *
+ * \default \c 0
+ * \param  encoder        An encoder instance to set.
+ * \param  specification  See above.
+ * \assert
+ *    \code encoder != NULL \endcode
+ *    \code specification != NULL \endcode
+ * \retval FLAC__bool
+ *    \c false if the encoder is already initialized, else \c true.
+ */
+OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_apodization(OggFLAC__SeekableStreamEncoder *encoder, const char *specification);
+
 /** This is inherited from FLAC__StreamEncoder; see FLAC__stream_encoder_set_max_lpc_order()
  *
  * \default \c 0
index 11025c1..7a0a4ed 100644 (file)
@@ -312,6 +312,19 @@ OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_sample_rate(OggFLAC__StreamEn
  */
 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_blocksize(OggFLAC__StreamEncoder *encoder, unsigned value);
 
+/** This is inherited from FLAC__StreamEncoder; see FLAC__stream_encoder_set_apodization()
+ *
+ * \default \c 0
+ * \param  encoder        An encoder instance to set.
+ * \param  specification  See above.
+ * \assert
+ *    \code encoder != NULL \endcode
+ *    \code specification != NULL \endcode
+ * \retval FLAC__bool
+ *    \c false if the encoder is already initialized, else \c true.
+ */
+OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_apodization(OggFLAC__StreamEncoder *encoder, const char *specification);
+
 /** This is inherited from FLAC__StreamEncoder; see FLAC__stream_encoder_set_max_lpc_order()
  *
  * \default \c 0
index 55bcb4d..bd346bb 100644 (file)
@@ -1427,6 +1427,7 @@ FLAC__bool EncoderSession_init_encoder(EncoderSession *e, encode_options_t optio
                        OggFLAC__stream_encoder_set_bits_per_sample(e->encoder.ogg.stream, bps);
                        OggFLAC__stream_encoder_set_sample_rate(e->encoder.ogg.stream, sample_rate);
                        OggFLAC__stream_encoder_set_blocksize(e->encoder.ogg.stream, options.blocksize);
+                       OggFLAC__stream_encoder_set_apodization(e->encoder.ogg.stream, options.apodizations);
                        OggFLAC__stream_encoder_set_max_lpc_order(e->encoder.ogg.stream, options.max_lpc_order);
                        OggFLAC__stream_encoder_set_qlp_coeff_precision(e->encoder.ogg.stream, options.qlp_coeff_precision);
                        OggFLAC__stream_encoder_set_do_qlp_coeff_prec_search(e->encoder.ogg.stream, options.do_qlp_coeff_prec_search);
@@ -1463,6 +1464,7 @@ FLAC__bool EncoderSession_init_encoder(EncoderSession *e, encode_options_t optio
                        OggFLAC__file_encoder_set_bits_per_sample(e->encoder.ogg.file, bps);
                        OggFLAC__file_encoder_set_sample_rate(e->encoder.ogg.file, sample_rate);
                        OggFLAC__file_encoder_set_blocksize(e->encoder.ogg.file, options.blocksize);
+                       OggFLAC__file_encoder_set_apodization(e->encoder.ogg.file, options.apodizations);
                        OggFLAC__file_encoder_set_max_lpc_order(e->encoder.ogg.file, options.max_lpc_order);
                        OggFLAC__file_encoder_set_qlp_coeff_precision(e->encoder.ogg.file, options.qlp_coeff_precision);
                        OggFLAC__file_encoder_set_do_qlp_coeff_prec_search(e->encoder.ogg.file, options.do_qlp_coeff_prec_search);
@@ -1499,6 +1501,7 @@ FLAC__bool EncoderSession_init_encoder(EncoderSession *e, encode_options_t optio
                FLAC__stream_encoder_set_bits_per_sample(e->encoder.flac.stream, bps);
                FLAC__stream_encoder_set_sample_rate(e->encoder.flac.stream, sample_rate);
                FLAC__stream_encoder_set_blocksize(e->encoder.flac.stream, options.blocksize);
+               FLAC__stream_encoder_set_apodization(e->encoder.flac.stream, options.apodizations);
                FLAC__stream_encoder_set_max_lpc_order(e->encoder.flac.stream, options.max_lpc_order);
                FLAC__stream_encoder_set_qlp_coeff_precision(e->encoder.flac.stream, options.qlp_coeff_precision);
                FLAC__stream_encoder_set_do_qlp_coeff_prec_search(e->encoder.flac.stream, options.do_qlp_coeff_prec_search);
@@ -1534,6 +1537,7 @@ FLAC__bool EncoderSession_init_encoder(EncoderSession *e, encode_options_t optio
                FLAC__file_encoder_set_bits_per_sample(e->encoder.flac.file, bps);
                FLAC__file_encoder_set_sample_rate(e->encoder.flac.file, sample_rate);
                FLAC__file_encoder_set_blocksize(e->encoder.flac.file, options.blocksize);
+               FLAC__file_encoder_set_apodization(e->encoder.flac.file, options.apodizations);
                FLAC__file_encoder_set_max_lpc_order(e->encoder.flac.file, options.max_lpc_order);
                FLAC__file_encoder_set_qlp_coeff_precision(e->encoder.flac.file, options.qlp_coeff_precision);
                FLAC__file_encoder_set_do_qlp_coeff_prec_search(e->encoder.flac.file, options.do_qlp_coeff_prec_search);
@@ -2141,7 +2145,7 @@ FLAC__bool fskip_ahead(FILE *f, FLAC__uint64 offset)
                long need = (long)min(offset, LONG_MAX);
                if(fseek(f, need, SEEK_CUR) < 0) {
                        need = (long)min(offset, sizeof(dump));
-                       if(fread(dump, 1, need, f) < need)
+                       if((long)fread(dump, 1, need, f) < need)
                                return false;
                }
                offset -= need;
index 773a154..4dad1c9 100644 (file)
@@ -43,6 +43,7 @@ typedef struct {
        unsigned min_residual_partition_order;
        unsigned max_residual_partition_order;
        unsigned rice_parameter_search_dist;
+       char *apodizations;
        unsigned max_lpc_order;
        unsigned blocksize;
        unsigned qlp_coeff_precision;
index a1e4338..e84d32a 100644 (file)
@@ -147,6 +147,7 @@ static struct share__option long_options_[] = {
        { "blocksize"                 , share__required_argument, 0, 'b' },
        { "exhaustive-model-search"   , share__no_argument, 0, 'e' },
        { "max-lpc-order"             , share__required_argument, 0, 'l' },
+       { "apodization"               , share__required_argument, 0, 'A' },
        { "mid-side"                  , share__no_argument, 0, 'm' },
        { "adaptive-mid-side"         , share__no_argument, 0, 'M' },
        { "qlp-coeff-precision-search", share__no_argument, 0, 'p' },
@@ -232,6 +233,7 @@ static struct {
        const char *output_prefix;
        analysis_options aopts;
        int padding;
+       char apodizations[1000]; /* bad MAGIC NUMBER but buffer overflow is checked */
        unsigned max_lpc_order;
        unsigned qlp_coeff_precision;
        const char *skip_specification;
@@ -247,7 +249,7 @@ static struct {
        int min_residual_partition_order;
        int max_residual_partition_order;
        int rice_parameter_search_dist;
-       char requested_seek_points[50000]; /* bad MAGIC NUMBER but buffer overflow is checked */
+       char requested_seek_points[5000]; /* bad MAGIC NUMBER but buffer overflow is checked */
        int num_requested_seek_points; /* -1 => no -S options were given, 0 => -S- was given */
        const char *cuesheet_filename;
        FLAC__bool cued_seekpoints;
@@ -577,6 +579,7 @@ FLAC__bool init_options()
        option_values.aopts.do_residual_text = false;
        option_values.aopts.do_residual_gnuplot = false;
        option_values.padding = 4096;
+       option_values.apodizations[0] = '\0';
        option_values.max_lpc_order = 8;
        option_values.qlp_coeff_precision = 0;
        option_values.skip_specification = 0;
@@ -615,7 +618,7 @@ int parse_options(int argc, char *argv[])
        int short_option;
        int option_index = 1;
        FLAC__bool had_error = false;
-       const char *short_opts = "0123456789ab:cdefFhHl:mMo:pP:q:r:sS:tT:vV";
+       const char *short_opts = "0123456789aA:b:cdefFhHl:mMo:pP:q:r:sS:tT:vV";
 
        while ((short_option = share__getopt_long(argc, argv, short_opts, long_options_, &option_index)) != -1) {
                switch (short_option) {
@@ -1030,6 +1033,16 @@ int parse_option(int short_option, const char *long_option, const char *option_a
                                FLAC__ASSERT(0 != option_argument);
                                option_values.max_lpc_order = atoi(option_argument);
                                break;
+                       case 'A':
+                               FLAC__ASSERT(0 != option_argument);
+                               if(strlen(option_values.apodizations)+strlen(option_argument)+2 >= sizeof(option_values.apodizations)) {
+                                       return usage_error("ERROR: too many apodization functions requested\n");
+                               }
+                               else {
+                                       strcat(option_values.apodizations, option_argument);
+                                       strcat(option_values.apodizations, ";");
+                               }
+                               break;
                        case 'm':
                                option_values.do_mid_side = true;
                                option_values.loose_mid_side = false;
@@ -1210,6 +1223,7 @@ void show_help()
        printf("  -m, --mid-side                     Try mid-side coding for each frame\n");
        printf("  -M, --adaptive-mid-side            Adaptive mid-side coding for all frames\n");
        printf("  -e, --exhaustive-model-search      Do exhaustive model search (expensive!)\n");
+       printf("  -A, --apodization=\"function\"       Window audio data with given the function\n");
        printf("  -l, --max-lpc-order=#              Max LPC order; 0 => only fixed predictors\n");
        printf("  -p, --qlp-coeff-precision-search   Exhaustively search LP coeff quantization\n");
        printf("  -q, --qlp-coeff-precision=#        Specify precision in bits\n");
@@ -1422,6 +1436,16 @@ void show_explain()
        printf("  -M, --adaptive-mid-side            Adaptive mid-side coding for all frames\n");
        printf("                                     (stereo only)\n");
        printf("  -e, --exhaustive-model-search      Do exhaustive model search (expensive!)\n");
+       printf("  -A, --apodization=\"function\"       Window audio data with given the function.\n");
+       printf("                                     The functions are: bartlett, bartlett_hann,\n");
+       printf("                                     blackman, blackman_harris_4term_92db,\n");
+       printf("                                     connes, flattop, gauss(STDDEV), hamming,\n");
+       printf("                                     hann, kaiser_bessel, nuttall, rectangle,\n");
+       printf("                                     triangle, tukey(P), welch.  More than one\n");
+       printf("                                     may be specified but encoding time is a\n");
+       printf("                                     multiple of the number of functions since\n");
+       printf("                                     they are each tried in turn.  The default\n");
+       printf("                                     is \"hann\". \n");
        printf("  -l, --max-lpc-order=#              Max LPC order; 0 => only fixed predictors\n");
        printf("  -p, --qlp-coeff-precision-search   Do exhaustive search of LP coefficient\n");
        printf("                                     quantization (expensive!); overrides -q;\n");
@@ -1606,6 +1630,7 @@ int encode_file(const char *infilename, FLAC__bool is_first_file, FLAC__bool is_
        common_options.min_residual_partition_order = option_values.min_residual_partition_order;
        common_options.max_residual_partition_order = option_values.max_residual_partition_order;
        common_options.rice_parameter_search_dist = option_values.rice_parameter_search_dist;
+       common_options.apodizations = option_values.apodizations;
        common_options.max_lpc_order = option_values.max_lpc_order;
        common_options.blocksize = (unsigned)option_values.blocksize;
        common_options.qlp_coeff_precision = option_values.qlp_coeff_precision;
index 38da8f3..ac03c3c 100644 (file)
@@ -79,7 +79,8 @@ SRCS_C = \
        seekable_stream_encoder.c \
        stream_decoder.c \
        stream_encoder.c \
-       stream_encoder_framing.c
+       stream_encoder_framing.c \
+       window.c
 
 include $(topdir)/build/lib.mk
 
index db4c421..8f19693 100644 (file)
@@ -314,6 +314,17 @@ FLAC_API FLAC__bool FLAC__file_encoder_set_blocksize(FLAC__FileEncoder *encoder,
        return FLAC__seekable_stream_encoder_set_blocksize(encoder->private_->seekable_stream_encoder, value);
 }
 
+FLAC_API FLAC__bool FLAC__file_encoder_set_apodization(FLAC__FileEncoder *encoder, const char *specification)
+{
+       FLAC__ASSERT(0 != encoder);
+       FLAC__ASSERT(0 != encoder->private_);
+       FLAC__ASSERT(0 != encoder->protected_);
+       FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
+       if(encoder->protected_->state != FLAC__FILE_ENCODER_UNINITIALIZED)
+               return false;
+       return FLAC__seekable_stream_encoder_set_apodization(encoder->private_->seekable_stream_encoder, specification);
+}
+
 FLAC_API FLAC__bool FLAC__file_encoder_set_max_lpc_order(FLAC__FileEncoder *encoder, unsigned value)
 {
        FLAC__ASSERT(0 != encoder);
index 8052b0f..503a8a8 100644 (file)
@@ -56,9 +56,10 @@ FLAC_API const char *FLAC__VERSION_STRING = VERSION;
 
 #if defined _MSC_VER || defined __MINW32__
 /* yet one more hack because of MSVC6: */
-FLAC_API const char *FLAC__VENDOR_STRING = "reference libFLAC 1.1.2 20050205";
+/*@@@@@@WAS:FLAC_API const char *FLAC__VENDOR_STRING = "reference libFLAC 1.1.2 20050205";*/
+FLAC_API const char *FLAC__VENDOR_STRING = "reference libFLAC CVS 20060425";
 #else
-FLAC_API const char *FLAC__VENDOR_STRING = "reference libFLAC " VERSION " 20050205";
+FLAC_API const char *FLAC__VENDOR_STRING = "reference libFLAC " VERSION " 20060425";
 #endif
 
 FLAC_API const FLAC__byte FLAC__STREAM_SYNC_STRING[4] = { 'f','L','a','C' };
index 37286f5..26f060b 100644 (file)
 #ifndef FLAC__INTEGER_ONLY_LIBRARY
 
 /*
+ *     FLAC__lpc_window_data()
+ *     --------------------------------------------------------------------
+ *     Applies the given window to the data.
+ *  @@@@@@ asm optimize
+ *
+ *     IN in[0,data_len-1]
+ *     IN window[0,data_len-1]
+ *     OUT out[0,lag-1]
+ *     IN data_len
+ */
+void FLAC__lpc_window_data(const FLAC__real in[], const FLAC__real window[], FLAC__real out[], unsigned data_len);
+
+/*
  *     FLAC__lpc_compute_autocorrelation()
  *     --------------------------------------------------------------------
  *     Compute the autocorrelation for lags between 0 and lag-1.
index 86495cc..d2410be 100644 (file)
 
 #include "FLAC/stream_encoder.h"
 
+#ifndef FLAC__INTEGER_ONLY_LIBRARY
+
+#include "private/float.h"
+
+#define FLAC__MAX_APODIZATION_FUNCTIONS 32
+
+typedef enum {
+       FLAC__APODIZATION_BARTLETT,
+       FLAC__APODIZATION_BARTLETT_HANN,
+       FLAC__APODIZATION_BLACKMAN,
+       FLAC__APODIZATION_BLACKMAN_HARRIS_4TERM_92DB_SIDELOBE,
+       FLAC__APODIZATION_CONNES,
+       FLAC__APODIZATION_FLATTOP,
+       FLAC__APODIZATION_GAUSS,
+       FLAC__APODIZATION_HAMMING,
+       FLAC__APODIZATION_HANN,
+       FLAC__APODIZATION_KAISER_BESSEL,
+       FLAC__APODIZATION_NUTTALL,
+       FLAC__APODIZATION_RECTANGLE,
+       FLAC__APODIZATION_TRIANGLE,
+       FLAC__APODIZATION_TUKEY,
+       FLAC__APODIZATION_WELCH
+} FLAC__ApodizationFunction;
+
+typedef struct {
+       FLAC__ApodizationFunction type;
+       union {
+               struct {
+                       FLAC__real stddev;
+               } gauss;
+               struct {
+                       FLAC__real p;
+               } tukey;
+       } parameters;
+} FLAC__ApodizationSpecification;
+
+#endif // #ifndef FLAC__INTEGER_ONLY_LIBRARY
+
 typedef struct FLAC__StreamEncoderProtected {
        FLAC__StreamEncoderState state;
        FLAC__bool verify;
@@ -44,6 +82,10 @@ typedef struct FLAC__StreamEncoderProtected {
        unsigned bits_per_sample;
        unsigned sample_rate;
        unsigned blocksize;
+#ifndef FLAC__INTEGER_ONLY_LIBRARY
+       unsigned num_apodizations;
+       FLAC__ApodizationSpecification apodizations[FLAC__MAX_APODIZATION_FUNCTIONS];
+#endif
        unsigned max_lpc_order;
        unsigned qlp_coeff_precision;
        FLAC__bool do_qlp_coeff_prec_search;
index b846db5..7884383 100644 (file)
 #define M_LN2 0.69314718055994530942
 #endif
 
+void FLAC__lpc_window_data(const FLAC__real in[], const FLAC__real window[], FLAC__real out[], unsigned data_len)
+{
+       unsigned i;
+       for(i = 0; i < data_len; i++)
+               out[i] = in[i] * window[i];
+}
+
 void FLAC__lpc_compute_autocorrelation(const FLAC__real data[], unsigned data_len, unsigned lag, FLAC__real autoc[])
 {
        /* a readable, but slower, version */
index 18291a8..9fe15c4 100644 (file)
@@ -318,6 +318,17 @@ FLAC_API FLAC__bool FLAC__seekable_stream_encoder_set_blocksize(FLAC__SeekableSt
        return FLAC__stream_encoder_set_blocksize(encoder->private_->stream_encoder, value);
 }
 
+FLAC_API FLAC__bool FLAC__seekable_stream_encoder_set_apodization(FLAC__SeekableStreamEncoder *encoder, const char *specification)
+{
+       FLAC__ASSERT(0 != encoder);
+       FLAC__ASSERT(0 != encoder->private_);
+       FLAC__ASSERT(0 != encoder->protected_);
+       FLAC__ASSERT(0 != encoder->private_->stream_encoder);
+       if(encoder->protected_->state != FLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
+               return false;
+       return FLAC__stream_encoder_set_apodization(encoder->private_->stream_encoder, specification);
+}
+
 FLAC_API FLAC__bool FLAC__seekable_stream_encoder_set_max_lpc_order(FLAC__SeekableStreamEncoder *encoder, unsigned value)
 {
        FLAC__ASSERT(0 != encoder);
index 8ae4ba4..cee1e10 100644 (file)
@@ -29,6 +29,9 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+/*@@@@@@*/
+#define WINDOW_DEBUG_OUTPUT
+
 #include <limits.h>
 #include <stdio.h>
 #include <stdlib.h> /* for malloc() */
@@ -46,6 +49,7 @@
 #include "private/md5.h"
 #include "private/memory.h"
 #include "private/stream_encoder_framing.h"
+#include "private/window.h"
 
 #ifdef HAVE_CONFIG_H
 #include <config.h>
@@ -108,6 +112,9 @@ static FLAC__bool process_subframe_(
        FLAC__int32 *residual[2],
        unsigned *best_subframe,
        unsigned *best_bits
+#ifdef WINDOW_DEBUG_OUTPUT
+       ,unsigned subframe_number
+#endif
 );
 
 static FLAC__bool add_subframe_(
@@ -116,6 +123,9 @@ static FLAC__bool add_subframe_(
        unsigned subframe_bps,
        const FLAC__Subframe *subframe,
        FLAC__BitBuffer *frame
+#ifdef WINDOW_DEBUG_OUTPUT
+,unsigned subframe_bits
+#endif
 );
 
 static unsigned evaluate_constant_subframe_(
@@ -165,6 +175,11 @@ static unsigned evaluate_lpc_subframe_(
        unsigned rice_parameter_search_dist,
        FLAC__Subframe *subframe,
        FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents
+#ifdef WINDOW_DEBUG_OUTPUT
+       ,unsigned frame_number
+       ,unsigned subframe_number
+       ,FLAC__ApodizationSpecification aspec
+#endif
 );
 #endif
 
@@ -308,6 +323,25 @@ static void verify_error_callback_(
        void *client_data
 );
 
+#ifdef WINDOW_DEBUG_OUTPUT
+static const char * const winstr[] = {
+       "bartlett",
+       "bartlett_hann",
+       "blackman",
+       "blackman_harris_4term_92db_sidelobe",
+       "connes",
+       "flattop",
+       "gauss",
+       "hamming",
+       "hann",
+       "kaiser_bessel",
+       "nuttall",
+       "rectangular",
+       "triangle",
+       "tukey",
+       "welch"
+};
+#endif
 
 /***********************************************************************
  *
@@ -322,6 +356,8 @@ typedef struct FLAC__StreamEncoderPrivate {
 #ifndef FLAC__INTEGER_ONLY_LIBRARY
        FLAC__real *real_signal[FLAC__MAX_CHANNELS];      /* the floating-point version of the input signal */
        FLAC__real *real_signal_mid_side[2];              /* the floating-point version of the mid-side input signal (stereo only) */
+       FLAC__real *window[FLAC__MAX_APODIZATION_FUNCTIONS]; /* the pre-computed floating-point window for each apodization function */
+       FLAC__real *windowed_signal;                      /* the real_signal[] * current window[] */
 #endif
        unsigned subframe_bps[FLAC__MAX_CHANNELS];        /* the effective bits per sample of the input signal (stream bps - wasted bits) */
        unsigned subframe_bps_mid_side[2];                /* the effective bits per sample of the mid-side input signal (stream bps - wasted bits + 0/1) */
@@ -378,6 +414,8 @@ typedef struct FLAC__StreamEncoderPrivate {
 #ifndef FLAC__INTEGER_ONLY_LIBRARY
        FLAC__real *real_signal_unaligned[FLAC__MAX_CHANNELS];
        FLAC__real *real_signal_mid_side_unaligned[2];
+       FLAC__real *window_unaligned[FLAC__MAX_APODIZATION_FUNCTIONS];
+       FLAC__real *windowed_signal_unaligned;
 #endif
        FLAC__int32 *residual_workspace_unaligned[FLAC__MAX_CHANNELS][2];
        FLAC__int32 *residual_workspace_mid_side_unaligned[2][2];
@@ -723,6 +761,11 @@ FLAC_API FLAC__StreamEncoderState FLAC__stream_encoder_init(FLAC__StreamEncoder
                encoder->private_->real_signal_mid_side_unaligned[i] = encoder->private_->real_signal_mid_side[i] = 0;
 #endif
        }
+#ifndef FLAC__INTEGER_ONLY_LIBRARY
+       for(i = 0; i < encoder->protected_->num_apodizations; i++)
+               encoder->private_->window_unaligned[i] = encoder->private_->window[i] = 0;
+       encoder->private_->windowed_signal_unaligned = encoder->private_->windowed_signal = 0;
+#endif
        for(i = 0; i < encoder->protected_->channels; i++) {
                encoder->private_->residual_workspace_unaligned[i][0] = encoder->private_->residual_workspace[i][0] = 0;
                encoder->private_->residual_workspace_unaligned[i][1] = encoder->private_->residual_workspace[i][1] = 0;
@@ -1063,6 +1106,77 @@ FLAC_API FLAC__bool FLAC__stream_encoder_set_blocksize(FLAC__StreamEncoder *enco
        return true;
 }
 
+FLAC_API FLAC__bool FLAC__stream_encoder_set_apodization(FLAC__StreamEncoder *encoder, const char *specification)
+{
+       FLAC__ASSERT(0 != encoder);
+       FLAC__ASSERT(0 != specification);
+       if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
+               return false;
+#ifdef FLAC__INTEGER_ONLY_LIBRARY
+       (void)specification; /* silently ignore since we haven't integerized; will always use a rectangular window */
+#else
+       encoder->protected_->num_apodizations = 0;
+       while(1) {
+               const char *s = strchr(specification, ';');
+               const size_t n = s? (size_t)(s - specification) : strlen(specification);
+               if     (n==8  && 0 == strncmp("bartlett"     , specification, n))
+                       encoder->protected_->apodizations[encoder->protected_->num_apodizations++].type = FLAC__APODIZATION_BARTLETT;
+               else if(n==13 && 0 == strncmp("bartlett_hann", specification, n))
+                       encoder->protected_->apodizations[encoder->protected_->num_apodizations++].type = FLAC__APODIZATION_BARTLETT_HANN;
+               else if(n==8  && 0 == strncmp("blackman"     , specification, n))
+                       encoder->protected_->apodizations[encoder->protected_->num_apodizations++].type = FLAC__APODIZATION_BLACKMAN;
+               else if(n==26 && 0 == strncmp("blackman_harris_4term_92db", specification, n))
+                       encoder->protected_->apodizations[encoder->protected_->num_apodizations++].type = FLAC__APODIZATION_BLACKMAN_HARRIS_4TERM_92DB_SIDELOBE;
+               else if(n==6  && 0 == strncmp("connes"       , specification, n))
+                       encoder->protected_->apodizations[encoder->protected_->num_apodizations++].type = FLAC__APODIZATION_CONNES;
+               else if(n==7  && 0 == strncmp("flattop"      , specification, n))
+                       encoder->protected_->apodizations[encoder->protected_->num_apodizations++].type = FLAC__APODIZATION_FLATTOP;
+               else if(n>7   && 0 == strncmp("gauss("       , specification, 6)) {
+                       FLAC__real stddev = (FLAC__real)strtod(specification+6, 0);
+                       if (stddev > 0.0 && stddev <= 0.5) {
+                               encoder->protected_->apodizations[encoder->protected_->num_apodizations].parameters.gauss.stddev = stddev;
+                               encoder->protected_->apodizations[encoder->protected_->num_apodizations++].type = FLAC__APODIZATION_GAUSS;
+                       }
+               }
+               else if(n==7  && 0 == strncmp("hamming"      , specification, n))
+                       encoder->protected_->apodizations[encoder->protected_->num_apodizations++].type = FLAC__APODIZATION_HAMMING;
+               else if(n==4  && 0 == strncmp("hann"         , specification, n))
+                       encoder->protected_->apodizations[encoder->protected_->num_apodizations++].type = FLAC__APODIZATION_HANN;
+               else if(n==13 && 0 == strncmp("kaiser_bessel", specification, n))
+                       encoder->protected_->apodizations[encoder->protected_->num_apodizations++].type = FLAC__APODIZATION_KAISER_BESSEL;
+               else if(n==7  && 0 == strncmp("nuttall"      , specification, n))
+                       encoder->protected_->apodizations[encoder->protected_->num_apodizations++].type = FLAC__APODIZATION_NUTTALL;
+               else if(n==9  && 0 == strncmp("rectangle"    , specification, n))
+                       encoder->protected_->apodizations[encoder->protected_->num_apodizations++].type = FLAC__APODIZATION_RECTANGLE;
+               else if(n==8  && 0 == strncmp("triangle"     , specification, n))
+                       encoder->protected_->apodizations[encoder->protected_->num_apodizations++].type = FLAC__APODIZATION_TRIANGLE;
+               else if(n>7   && 0 == strncmp("tukey("       , specification, 6)) {
+                       FLAC__real p = (FLAC__real)strtod(specification+6, 0);
+                       if (p >= 0.0 && p <= 1.0) {
+                               encoder->protected_->apodizations[encoder->protected_->num_apodizations].parameters.tukey.p = p;
+                               encoder->protected_->apodizations[encoder->protected_->num_apodizations++].type = FLAC__APODIZATION_TUKEY;
+                       }
+               }
+               else if(n==5  && 0 == strncmp("welch"        , specification, n))
+                       encoder->protected_->apodizations[encoder->protected_->num_apodizations++].type = FLAC__APODIZATION_WELCH;
+               if (encoder->protected_->num_apodizations == 32)
+                       break;
+               if (s)
+                       specification = s+1;
+               else
+                       break;
+       }
+       if(encoder->protected_->num_apodizations == 0) {
+               encoder->protected_->num_apodizations = 1;
+               encoder->protected_->apodizations[0].type = FLAC__APODIZATION_HANN;
+       }
+#ifdef WINDOW_DEBUG_OUTPUT
+{unsigned n;for(n=0;n<encoder->protected_->num_apodizations;n++)fprintf(stderr,"@@@@@@ parsed apodization[%zu]: %s\n",n,winstr[encoder->protected_->apodizations[n].type]);}
+#endif
+#endif
+       return true;
+}
+
 FLAC_API FLAC__bool FLAC__stream_encoder_set_max_lpc_order(FLAC__StreamEncoder *encoder, unsigned value)
 {
        FLAC__ASSERT(0 != encoder);
@@ -1648,6 +1762,10 @@ void set_defaults_(FLAC__StreamEncoder *encoder)
        encoder->protected_->bits_per_sample = 16;
        encoder->protected_->sample_rate = 44100;
        encoder->protected_->blocksize = 1152;
+#ifndef FLAC__INTEGER_ONLY_LIBRARY
+       encoder->protected_->num_apodizations = 1;
+       encoder->protected_->apodizations[0].type = FLAC__APODIZATION_HANN;
+#endif
        encoder->protected_->max_lpc_order = 0;
        encoder->protected_->qlp_coeff_precision = 0;
        encoder->protected_->do_qlp_coeff_prec_search = false;
@@ -1697,6 +1815,18 @@ void free_(FLAC__StreamEncoder *encoder)
                }
 #endif
        }
+#ifndef FLAC__INTEGER_ONLY_LIBRARY
+       for(i = 0; i < encoder->protected_->num_apodizations; i++) {
+               if(0 != encoder->private_->window_unaligned[i]) {
+                       free(encoder->private_->window_unaligned[i]);
+                       encoder->private_->window_unaligned[i] = 0;
+               }
+       }
+       if(0 != encoder->private_->windowed_signal_unaligned) {
+               free(encoder->private_->windowed_signal_unaligned);
+               encoder->private_->windowed_signal_unaligned = 0;
+       }
+#endif
        for(channel = 0; channel < encoder->protected_->channels; channel++) {
                for(i = 0; i < 2; i++) {
                        if(0 != encoder->private_->residual_workspace_unaligned[channel][i]) {
@@ -1775,6 +1905,13 @@ FLAC__bool resize_buffers_(FLAC__StreamEncoder *encoder, unsigned new_size)
                memset(encoder->private_->integer_signal_mid_side[i], 0, sizeof(FLAC__int32)*4);
                encoder->private_->integer_signal_mid_side[i] += 4;
        }
+#ifndef FLAC__INTEGER_ONLY_LIBRARY
+       if(ok && encoder->protected_->max_lpc_order > 0) {
+               for(i = 0; ok && i < encoder->protected_->num_apodizations; i++)
+                       ok = ok && FLAC__memory_alloc_aligned_real_array(new_size, &encoder->private_->window_unaligned[i], &encoder->private_->window[i]);
+               ok = ok && FLAC__memory_alloc_aligned_real_array(new_size, &encoder->private_->windowed_signal_unaligned, &encoder->private_->windowed_signal);
+       }
+#endif
        for(channel = 0; ok && channel < encoder->protected_->channels; channel++) {
                for(i = 0; ok && i < 2; i++) {
                        ok = ok && FLAC__memory_alloc_aligned_int32_array(new_size, &encoder->private_->residual_workspace_unaligned[channel][i], &encoder->private_->residual_workspace[channel][i]);
@@ -1796,6 +1933,65 @@ FLAC__bool resize_buffers_(FLAC__StreamEncoder *encoder, unsigned new_size)
        else
                encoder->protected_->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR;
 
+#ifndef FLAC__INTEGER_ONLY_LIBRARY
+       if(ok && encoder->protected_->max_lpc_order > 0) {
+               for(i = 0; ok && i < encoder->protected_->num_apodizations; i++) {
+                       switch(encoder->protected_->apodizations[i].type) {
+                               case FLAC__APODIZATION_BARTLETT:
+                                       FLAC__window_bartlett(encoder->private_->window[i], new_size);
+                                       break;
+                               case FLAC__APODIZATION_BARTLETT_HANN:
+                                       FLAC__window_bartlett_hann(encoder->private_->window[i], new_size);
+                                       break;
+                               case FLAC__APODIZATION_BLACKMAN:
+                                       FLAC__window_blackman(encoder->private_->window[i], new_size);
+                                       break;
+                               case FLAC__APODIZATION_BLACKMAN_HARRIS_4TERM_92DB_SIDELOBE:
+                                       FLAC__window_blackman_harris_4term_92db_sidelobe(encoder->private_->window[i], new_size);
+                                       break;
+                               case FLAC__APODIZATION_CONNES:
+                                       FLAC__window_connes(encoder->private_->window[i], new_size);
+                                       break;
+                               case FLAC__APODIZATION_FLATTOP:
+                                       FLAC__window_flattop(encoder->private_->window[i], new_size);
+                                       break;
+                               case FLAC__APODIZATION_GAUSS:
+                                       FLAC__window_gauss(encoder->private_->window[i], new_size, encoder->protected_->apodizations[i].parameters.gauss.stddev);
+                                       break;
+                               case FLAC__APODIZATION_HAMMING:
+                                       FLAC__window_hamming(encoder->private_->window[i], new_size);
+                                       break;
+                               case FLAC__APODIZATION_HANN:
+                                       FLAC__window_hann(encoder->private_->window[i], new_size);
+                                       break;
+                               case FLAC__APODIZATION_KAISER_BESSEL:
+                                       FLAC__window_kaiser_bessel(encoder->private_->window[i], new_size);
+                                       break;
+                               case FLAC__APODIZATION_NUTTALL:
+                                       FLAC__window_nuttall(encoder->private_->window[i], new_size);
+                                       break;
+                               case FLAC__APODIZATION_RECTANGLE:
+                                       FLAC__window_rectangle(encoder->private_->window[i], new_size);
+                                       break;
+                               case FLAC__APODIZATION_TRIANGLE:
+                                       FLAC__window_triangle(encoder->private_->window[i], new_size);
+                                       break;
+                               case FLAC__APODIZATION_TUKEY:
+                                       FLAC__window_tukey(encoder->private_->window[i], new_size, encoder->protected_->apodizations[i].parameters.tukey.p);
+                                       break;
+                               case FLAC__APODIZATION_WELCH:
+                                       FLAC__window_welch(encoder->private_->window[i], new_size);
+                                       break;
+                               default:
+                                       FLAC__ASSERT(0);
+                                       /* double protection */
+                                       FLAC__window_rectangle(encoder->private_->window[i], new_size);
+                                       break;
+                       }
+               }
+       }
+#endif
+
        return ok;
 }
 
@@ -1994,6 +2190,9 @@ FLAC__bool process_subframes_(FLAC__StreamEncoder *encoder, FLAC__bool is_last_f
                                        encoder->private_->residual_workspace[channel],
                                        encoder->private_->best_subframe+channel,
                                        encoder->private_->best_subframe_bits+channel
+#ifdef WINDOW_DEBUG_OUTPUT
+                                       ,channel
+#endif
                                )
                        )
                                return false;
@@ -2024,6 +2223,9 @@ FLAC__bool process_subframes_(FLAC__StreamEncoder *encoder, FLAC__bool is_last_f
                                        encoder->private_->residual_workspace_mid_side[channel],
                                        encoder->private_->best_subframe_mid_side+channel,
                                        encoder->private_->best_subframe_bits_mid_side+channel
+#ifdef WINDOW_DEBUG_OUTPUT
+                                       ,channel
+#endif
                                )
                        )
                                return false;
@@ -2037,6 +2239,9 @@ FLAC__bool process_subframes_(FLAC__StreamEncoder *encoder, FLAC__bool is_last_f
                unsigned left_bps = 0, right_bps = 0; /* initialized only to prevent superfluous compiler warning */
                FLAC__Subframe *left_subframe = 0, *right_subframe = 0; /* initialized only to prevent superfluous compiler warning */
                FLAC__ChannelAssignment channel_assignment;
+#ifdef WINDOW_DEBUG_OUTPUT
+               unsigned left_bits = 0, right_bits = 0;
+#endif
 
                FLAC__ASSERT(encoder->protected_->channels == 2);
 
@@ -2075,18 +2280,34 @@ FLAC__bool process_subframes_(FLAC__StreamEncoder *encoder, FLAC__bool is_last_f
                        case FLAC__CHANNEL_ASSIGNMENT_INDEPENDENT:
                                left_subframe  = &encoder->private_->subframe_workspace         [0][encoder->private_->best_subframe         [0]];
                                right_subframe = &encoder->private_->subframe_workspace         [1][encoder->private_->best_subframe         [1]];
+#ifdef WINDOW_DEBUG_OUTPUT
+                               left_bits      = encoder->private_->best_subframe_bits          [0];
+                               right_bits     = encoder->private_->best_subframe_bits          [1];
+#endif
                                break;
                        case FLAC__CHANNEL_ASSIGNMENT_LEFT_SIDE:
                                left_subframe  = &encoder->private_->subframe_workspace         [0][encoder->private_->best_subframe         [0]];
                                right_subframe = &encoder->private_->subframe_workspace_mid_side[1][encoder->private_->best_subframe_mid_side[1]];
+#ifdef WINDOW_DEBUG_OUTPUT
+                               left_bits      = encoder->private_->best_subframe_bits          [0];
+                               right_bits     = encoder->private_->best_subframe_bits_mid_side [1];
+#endif
                                break;
                        case FLAC__CHANNEL_ASSIGNMENT_RIGHT_SIDE:
                                left_subframe  = &encoder->private_->subframe_workspace_mid_side[1][encoder->private_->best_subframe_mid_side[1]];
                                right_subframe = &encoder->private_->subframe_workspace         [1][encoder->private_->best_subframe         [1]];
+#ifdef WINDOW_DEBUG_OUTPUT
+                               left_bits      = encoder->private_->best_subframe_bits_mid_side [1];
+                               right_bits     = encoder->private_->best_subframe_bits          [1];
+#endif
                                break;
                        case FLAC__CHANNEL_ASSIGNMENT_MID_SIDE:
                                left_subframe  = &encoder->private_->subframe_workspace_mid_side[0][encoder->private_->best_subframe_mid_side[0]];
                                right_subframe = &encoder->private_->subframe_workspace_mid_side[1][encoder->private_->best_subframe_mid_side[1]];
+#ifdef WINDOW_DEBUG_OUTPUT
+                               left_bits      = encoder->private_->best_subframe_bits_mid_side [0];
+                               right_bits     = encoder->private_->best_subframe_bits_mid_side [1];
+#endif
                                break;
                        default:
                                FLAC__ASSERT(0);
@@ -2114,10 +2335,17 @@ FLAC__bool process_subframes_(FLAC__StreamEncoder *encoder, FLAC__bool is_last_f
                }
 
                /* note that encoder_add_subframe_ sets the state for us in case of an error */
+#ifdef WINDOW_DEBUG_OUTPUT
+               if(!add_subframe_(encoder, &frame_header, left_bps , left_subframe , encoder->private_->frame, left_bits))
+                       return false;
+               if(!add_subframe_(encoder, &frame_header, right_bps, right_subframe, encoder->private_->frame, right_bits))
+                       return false;
+#else
                if(!add_subframe_(encoder, &frame_header, left_bps , left_subframe , encoder->private_->frame))
                        return false;
                if(!add_subframe_(encoder, &frame_header, right_bps, right_subframe, encoder->private_->frame))
                        return false;
+#endif
        }
        else {
                if(!FLAC__frame_add_header(&frame_header, encoder->protected_->streamable_subset, encoder->private_->frame)) {
@@ -2126,7 +2354,7 @@ FLAC__bool process_subframes_(FLAC__StreamEncoder *encoder, FLAC__bool is_last_f
                }
 
                for(channel = 0; channel < encoder->protected_->channels; channel++) {
-                       if(!add_subframe_(encoder, &frame_header, encoder->private_->subframe_bps[channel], &encoder->private_->subframe_workspace[channel][encoder->private_->best_subframe[channel]], encoder->private_->frame)) {
+                       if(!add_subframe_(encoder, &frame_header, encoder->private_->subframe_bps[channel], &encoder->private_->subframe_workspace[channel][encoder->private_->best_subframe[channel]], encoder->private_->frame, encoder->private_->best_subframe_bits[channel])) {
                                /* the above function sets the state for us in case of an error */
                                return false;
                        }
@@ -2160,6 +2388,9 @@ FLAC__bool process_subframe_(
        FLAC__int32 *residual[2],
        unsigned *best_subframe,
        unsigned *best_bits
+#ifdef WINDOW_DEBUG_OUTPUT
+       ,unsigned subframe_number
+#endif
 )
 {
 #ifndef FLAC__INTEGER_ONLY_LIBRARY
@@ -2277,67 +2508,76 @@ FLAC__bool process_subframe_(
                                else
                                        max_lpc_order = encoder->protected_->max_lpc_order;
                                if(max_lpc_order > 0) {
-                                       encoder->private_->local_lpc_compute_autocorrelation(real_signal, frame_header->blocksize, max_lpc_order+1, autoc);
-                                       /* if autoc[0] == 0.0, the signal is constant and we usually won't get here, but it can happen */
-                                       if(autoc[0] != 0.0) {
-                                               FLAC__lpc_compute_lp_coefficients(autoc, max_lpc_order, encoder->private_->lp_coeff, lpc_error);
-                                               if(encoder->protected_->do_exhaustive_model_search) {
-                                                       min_lpc_order = 1;
-                                               }
-                                               else {
-                                                       unsigned guess_lpc_order = FLAC__lpc_compute_best_order(lpc_error, max_lpc_order, frame_header->blocksize, subframe_bps);
-                                                       min_lpc_order = max_lpc_order = guess_lpc_order;
-                                               }
-                                               for(lpc_order = min_lpc_order; lpc_order <= max_lpc_order; lpc_order++) {
-                                                       lpc_residual_bits_per_sample = FLAC__lpc_compute_expected_bits_per_residual_sample(lpc_error[lpc_order-1], frame_header->blocksize-lpc_order);
-                                                       if(lpc_residual_bits_per_sample >= (FLAC__double)subframe_bps)
-                                                               continue; /* don't even try */
-                                                       rice_parameter = (lpc_residual_bits_per_sample > 0.0)? (unsigned)(lpc_residual_bits_per_sample+0.5) : 0; /* 0.5 is for rounding */
-                                                       rice_parameter++; /* to account for the signed->unsigned conversion during rice coding */
-                                                       if(rice_parameter >= FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER) {
-#ifdef DEBUG_VERBOSE
-                                                               fprintf(stderr, "clipping rice_parameter (%u -> %u) @1\n", rice_parameter, FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER - 1);
-#endif
-                                                               rice_parameter = FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER - 1;
-                                                       }
-                                                       if(encoder->protected_->do_qlp_coeff_prec_search) {
-                                                               min_qlp_coeff_precision = FLAC__MIN_QLP_COEFF_PRECISION;
-                                                               /* ensure a 32-bit datapath throughout for 16bps or less */
-                                                               if(subframe_bps <= 16)
-                                                                       max_qlp_coeff_precision = min(32 - subframe_bps - lpc_order, FLAC__MAX_QLP_COEFF_PRECISION);
-                                                               else
-                                                                       max_qlp_coeff_precision = FLAC__MAX_QLP_COEFF_PRECISION;
+                                       unsigned a;
+                                       for (a = 0; a < encoder->protected_->num_apodizations; a++) {
+                                               FLAC__lpc_apply_apodization(real_signal, encoder->private_->window[a], encoder->private_->windowed_signal, frame_header->blocksize);
+                                               encoder->private_->local_lpc_compute_autocorrelation(encoder->private_->windowed_signal, frame_header->blocksize, max_lpc_order+1, autoc);
+                                               /* if autoc[0] == 0.0, the signal is constant and we usually won't get here, but it can happen */
+                                               if(autoc[0] != 0.0) {
+                                                       FLAC__lpc_compute_lp_coefficients(autoc, max_lpc_order, encoder->private_->lp_coeff, lpc_error);
+                                                       if(encoder->protected_->do_exhaustive_model_search) {
+                                                               min_lpc_order = 1;
                                                        }
                                                        else {
-                                                               min_qlp_coeff_precision = max_qlp_coeff_precision = encoder->protected_->qlp_coeff_precision;
+                                                               unsigned guess_lpc_order = FLAC__lpc_compute_best_order(lpc_error, max_lpc_order, frame_header->blocksize, subframe_bps);
+                                                               min_lpc_order = max_lpc_order = guess_lpc_order;
                                                        }
-                                                       for(qlp_coeff_precision = min_qlp_coeff_precision; qlp_coeff_precision <= max_qlp_coeff_precision; qlp_coeff_precision++) {
-                                                               _candidate_bits =
-                                                                       evaluate_lpc_subframe_(
-                                                                               encoder,
-                                                                               integer_signal,
-                                                                               residual[!_best_subframe],
-                                                                               encoder->private_->abs_residual,
-                                                                               encoder->private_->abs_residual_partition_sums,
-                                                                               encoder->private_->raw_bits_per_partition,
-                                                                               encoder->private_->lp_coeff[lpc_order-1],
-                                                                               frame_header->blocksize,
-                                                                               subframe_bps,
-                                                                               lpc_order,
-                                                                               qlp_coeff_precision,
-                                                                               rice_parameter,
-                                                                               min_partition_order,
-                                                                               max_partition_order,
-                                                                               precompute_partition_sums,
-                                                                               encoder->protected_->do_escape_coding,
-                                                                               encoder->protected_->rice_parameter_search_dist,
-                                                                               subframe[!_best_subframe],
-                                                                               partitioned_rice_contents[!_best_subframe]
-                                                                       );
-                                                               if(_candidate_bits > 0) { /* if == 0, there was a problem quantizing the lpcoeffs */
-                                                                       if(_candidate_bits < _best_bits) {
-                                                                               _best_subframe = !_best_subframe;
-                                                                               _best_bits = _candidate_bits;
+                                                       for(lpc_order = min_lpc_order; lpc_order <= max_lpc_order; lpc_order++) {
+                                                               lpc_residual_bits_per_sample = FLAC__lpc_compute_expected_bits_per_residual_sample(lpc_error[lpc_order-1], frame_header->blocksize-lpc_order);
+                                                               if(lpc_residual_bits_per_sample >= (FLAC__double)subframe_bps)
+                                                                       continue; /* don't even try */
+                                                               rice_parameter = (lpc_residual_bits_per_sample > 0.0)? (unsigned)(lpc_residual_bits_per_sample+0.5) : 0; /* 0.5 is for rounding */
+                                                               rice_parameter++; /* to account for the signed->unsigned conversion during rice coding */
+                                                               if(rice_parameter >= FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER) {
+       #ifdef DEBUG_VERBOSE
+                                                                       fprintf(stderr, "clipping rice_parameter (%u -> %u) @1\n", rice_parameter, FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER - 1);
+       #endif
+                                                                       rice_parameter = FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER - 1;
+                                                               }
+                                                               if(encoder->protected_->do_qlp_coeff_prec_search) {
+                                                                       min_qlp_coeff_precision = FLAC__MIN_QLP_COEFF_PRECISION;
+                                                                       /* ensure a 32-bit datapath throughout for 16bps or less */
+                                                                       if(subframe_bps <= 16)
+                                                                               max_qlp_coeff_precision = min(32 - subframe_bps - lpc_order, FLAC__MAX_QLP_COEFF_PRECISION);
+                                                                       else
+                                                                               max_qlp_coeff_precision = FLAC__MAX_QLP_COEFF_PRECISION;
+                                                               }
+                                                               else {
+                                                                       min_qlp_coeff_precision = max_qlp_coeff_precision = encoder->protected_->qlp_coeff_precision;
+                                                               }
+                                                               for(qlp_coeff_precision = min_qlp_coeff_precision; qlp_coeff_precision <= max_qlp_coeff_precision; qlp_coeff_precision++) {
+                                                                       _candidate_bits =
+                                                                               evaluate_lpc_subframe_(
+                                                                                       encoder,
+                                                                                       integer_signal,
+                                                                                       residual[!_best_subframe],
+                                                                                       encoder->private_->abs_residual,
+                                                                                       encoder->private_->abs_residual_partition_sums,
+                                                                                       encoder->private_->raw_bits_per_partition,
+                                                                                       encoder->private_->lp_coeff[lpc_order-1],
+                                                                                       frame_header->blocksize,
+                                                                                       subframe_bps,
+                                                                                       lpc_order,
+                                                                                       qlp_coeff_precision,
+                                                                                       rice_parameter,
+                                                                                       min_partition_order,
+                                                                                       max_partition_order,
+                                                                                       precompute_partition_sums,
+                                                                                       encoder->protected_->do_escape_coding,
+                                                                                       encoder->protected_->rice_parameter_search_dist,
+                                                                                       subframe[!_best_subframe],
+                                                                                       partitioned_rice_contents[!_best_subframe]
+#ifdef WINDOW_DEBUG_OUTPUT
+                                                                                       ,frame_header->number.frame_number
+                                                                                       ,subframe_number
+                                                                                       ,encoder->protected_->apodizations[a]
+#endif
+                                                                               );
+                                                                       if(_candidate_bits > 0) { /* if == 0, there was a problem quantizing the lpcoeffs */
+                                                                               if(_candidate_bits < _best_bits) {
+                                                                                       _best_subframe = !_best_subframe;
+                                                                                       _best_bits = _candidate_bits;
+                                                                               }
                                                                        }
                                                                }
                                                        }
@@ -2367,6 +2607,9 @@ FLAC__bool add_subframe_(
        unsigned subframe_bps,
        const FLAC__Subframe *subframe,
        FLAC__BitBuffer *frame
+#ifdef WINDOW_DEBUG_OUTPUT
+,unsigned subframe_bits
+#endif
 )
 {
        switch(subframe->type) {
@@ -2383,6 +2626,9 @@ FLAC__bool add_subframe_(
                        }
                        break;
                case FLAC__SUBFRAME_TYPE_LPC:
+#ifdef WINDOW_DEBUG_OUTPUT
+                       fprintf(stderr, "WIN:\tframe=%u\tsubframe=?\torder=%u\twindow=%s\tbits=%u\n", frame_header->number.frame_number, subframe->data.lpc.order, subframe->data.lpc.window_type, subframe_bits);
+#endif
                        if(!FLAC__subframe_add_lpc(&(subframe->data.lpc), frame_header->blocksize - subframe->data.lpc.order, subframe_bps, subframe->wasted_bits, frame)) {
                                encoder->protected_->state = FLAC__STREAM_ENCODER_FATAL_ERROR_WHILE_ENCODING;
                                return false;
@@ -2490,6 +2736,11 @@ unsigned evaluate_lpc_subframe_(
        unsigned rice_parameter_search_dist,
        FLAC__Subframe *subframe,
        FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents
+#ifdef WINDOW_DEBUG_OUTPUT
+       ,unsigned frame_number
+       ,unsigned subframe_number
+       ,FLAC__ApodizationSpecification aspec
+#endif
 )
 {
        FLAC__int32 qlp_coeff[FLAC__MAX_LPC_ORDER];
@@ -2504,6 +2755,15 @@ unsigned evaluate_lpc_subframe_(
                qlp_coeff_precision = min(qlp_coeff_precision, 32 - subframe_bps - FLAC__bitmath_ilog2(order));
        }
 
+#ifdef WINDOW_DEBUG_OUTPUT
+       if (aspec.type == FLAC__APODIZATION_GAUSS)
+               snprintf(subframe->data.lpc.window_type, sizeof subframe->data.lpc.window_type, "%s(%0.5f)", winstr[aspec.type], aspec.parameters.gauss.stddev);
+       else if (aspec.type == FLAC__APODIZATION_TUKEY)
+               snprintf(subframe->data.lpc.window_type, sizeof subframe->data.lpc.window_type, "%s(%0.5f)", winstr[aspec.type], aspec.parameters.tukey.p);
+       else
+               strncpy(subframe->data.lpc.window_type, winstr[aspec.type], sizeof subframe->data.lpc.window_type);
+#endif
+
        ret = FLAC__lpc_quantize_coefficients(lp_coeff, order, qlp_coeff_precision, qlp_coeff, &quantization);
        if(ret != 0)
                return 0; /* this is a hack to indicate to the caller that we can't do lp at this order on this subframe */
@@ -2547,6 +2807,9 @@ unsigned evaluate_lpc_subframe_(
        for(i = 0; i < order; i++)
                subframe->data.lpc.warmup[i] = signal[i];
 
+#ifdef WINDOW_DEBUG_OUTPUT
+       fprintf(stderr, "SWIN:\tframe=%u\tsubframe=%u\torder=%u\twindow=%s\tbits=%u\n", frame_number, subframe_number, order, subframe->data.lpc.window_type, FLAC__SUBFRAME_ZERO_PAD_LEN + FLAC__SUBFRAME_TYPE_LEN + FLAC__SUBFRAME_WASTED_BITS_FLAG_LEN + FLAC__SUBFRAME_LPC_QLP_COEFF_PRECISION_LEN + FLAC__SUBFRAME_LPC_QLP_SHIFT_LEN + (order * (qlp_coeff_precision + subframe_bps)) + residual_bits);
+#endif
        return FLAC__SUBFRAME_ZERO_PAD_LEN + FLAC__SUBFRAME_TYPE_LEN + FLAC__SUBFRAME_WASTED_BITS_FLAG_LEN + FLAC__SUBFRAME_LPC_QLP_COEFF_PRECISION_LEN + FLAC__SUBFRAME_LPC_QLP_SHIFT_LEN + (order * (qlp_coeff_precision + subframe_bps)) + residual_bits;
 }
 #endif
index 4567685..f32003b 100644 (file)
@@ -328,6 +328,17 @@ OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_blocksize(OggFLAC__FileEncoder
        return OggFLAC__seekable_stream_encoder_set_blocksize(encoder->private_->seekable_stream_encoder, value);
 }
 
+OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_apodization(OggFLAC__FileEncoder *encoder, const char *specification)
+{
+       FLAC__ASSERT(0 != encoder);
+       FLAC__ASSERT(0 != encoder->private_);
+       FLAC__ASSERT(0 != encoder->protected_);
+       FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
+       if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED)
+               return false;
+       return OggFLAC__seekable_stream_encoder_set_apodization(encoder->private_->seekable_stream_encoder, specification);
+}
+
 OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_max_lpc_order(OggFLAC__FileEncoder *encoder, unsigned value)
 {
        FLAC__ASSERT(0 != encoder);
index 0aa6e72..341b068 100644 (file)
@@ -335,6 +335,17 @@ OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_blocksize(OggFLAC__S
        return FLAC__stream_encoder_set_blocksize(encoder->private_->FLAC_stream_encoder, value);
 }
 
+OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_apodization(OggFLAC__SeekableStreamEncoder *encoder, const char *specification)
+{
+       FLAC__ASSERT(0 != encoder);
+       FLAC__ASSERT(0 != encoder->private_);
+       FLAC__ASSERT(0 != encoder->protected_);
+       FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
+       if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
+               return false;
+       return FLAC__stream_encoder_set_apodization(encoder->private_->FLAC_stream_encoder, specification);
+}
+
 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_max_lpc_order(OggFLAC__SeekableStreamEncoder *encoder, unsigned value)
 {
        FLAC__ASSERT(0 != encoder);
index 2552101..33b1e93 100644 (file)
@@ -290,6 +290,17 @@ OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_blocksize(OggFLAC__StreamEnco
        return FLAC__stream_encoder_set_blocksize(encoder->private_->FLAC_stream_encoder, value);
 }
 
+OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_apodization(OggFLAC__StreamEncoder *encoder, const char *specification)
+{
+       FLAC__ASSERT(0 != encoder);
+       FLAC__ASSERT(0 != encoder->private_);
+       FLAC__ASSERT(0 != encoder->protected_);
+       FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
+       if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED)
+               return false;
+       return FLAC__stream_encoder_set_apodization(encoder->private_->FLAC_stream_encoder, specification);
+}
+
 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_max_lpc_order(OggFLAC__StreamEncoder *encoder, unsigned value)
 {
        FLAC__ASSERT(0 != encoder);