-r now takes min,max and is called min/max_residual_partition order, new -R option...
authorJosh Coalson <jcoalson@users.sourceforce.net>
Wed, 25 Apr 2001 02:16:36 +0000 (02:16 +0000)
committerJosh Coalson <jcoalson@users.sourceforce.net>
Wed, 25 Apr 2001 02:16:36 +0000 (02:16 +0000)
doc/documentation.html
include/FLAC/encoder.h
man/flac.sgml
src/flac/encode.c
src/flac/encode.h
src/flac/main.c
src/libFLAC/encoder.c

index 34c09e5..842b240 100644 (file)
                                -9
                        </TD>
                        <TD>
-                               Synonymous with -l 32 -b 4608 -m -e -r 99 -p.  This is painfully slow but gives you the maximum compression <B><TT>flac</TT></B> can do for a given blocksize.
+                               Synonymous with -l 32 -b 4608 -m -e -r 16 -p.  This is painfully slow but gives you the maximum compression <B><TT>flac</TT></B> can do for a given blocksize.
                        </TD>
                </TR>
                <TR>
                                -r #
                        </TD>
                        <TD>
-                               Do Rice parameter optimization.  By default the encoder uses a single Rice parameter for the subframe's entire residual.  With this option, the residual is partitioned into 2^n pieces, each with its own Rice parameter.  Higher values of n yield diminishing returns.  The most bang for the buck is usually with <B><TT>-r 2</TT></B> (more for higher blocksizes).  This usually shaves off another 1.5%.  The technique tends to peak out about when blocksize/(2^n)=128.  Use <B><TT>-r 99</TT></B> to force the highest degree of optimization.
+                               Do Rice parameter optimization.  By default the encoder uses a single Rice parameter for the subframe's entire residual.  With this option, the residual is partitioned into 2^n pieces, each with its own Rice parameter.  Higher values of n yield diminishing returns.  The most bang for the buck is usually with <B><TT>-r 2</TT></B> (more for higher blocksizes).  This usually shaves off another 1.5%.  The technique tends to peak out about when blocksize/(2^n)=128.  Use <B><TT>-r 16</TT></B> to force the highest degree of optimization.
                        </TD>
                </TR>
                <TR>
index decef04..ff12fab 100644 (file)
@@ -68,7 +68,9 @@ typedef struct {
                                              /* qlp_coeff_precision+bits_per_sample must be < 32 */
        bool     do_qlp_coeff_prec_search;    /* 0 => use qlp_coeff_precision, 1 => search around qlp_coeff_precision, take best */
        bool     do_exhaustive_model_search;  /* 0 => use estimated bits per residual for scoring, 1 => generate all, take shortest */
-       unsigned rice_optimization_level;     /* 0 => estimate Rice parameter based on residual variance, 1-8 => partition residual, use parameter for each */
+       unsigned min_residual_partition_order; /* 0 => estimate Rice parameter based on residual variance; >0 => partition residual, use parameter for each */
+       unsigned max_residual_partition_order; /*      based on mean; min_ and max_ specify the min and max Rice partition order */
+       unsigned rice_parameter_search_dist;  /* 0 => try only calc'd parameter k; else try all [k-dist..k+dist] parameters, use best */
        uint64   total_samples_estimate;      /* may be 0 if unknown.  this will be a placeholder in the metadata block until the actual total is calculated */
        const FLAC__StreamMetaData_SeekTable *seek_table; /* optional seek_table to prepend, 0 => no seek table */
        unsigned padding;                     /* size of PADDING block to add (goes after seek table); 0 => do not add a PADDING block */
index bc2daf6..fd23320 100644 (file)
                      <term><option>-9</option></term>
                      
                      <listitem>
-                       <para>Synonymous with -l 32 -m -e -r 99 -p
+                       <para>Synonymous with -l 32 -m -e -r 16 -p
                          (very slow!)</para>
                      </listitem>
                    </varlistentry>
                <term><option>-r</option> <replaceable>level</replaceable></term>
 
                <listitem>
-                 <para>Rice parameter optimization level (0..99). 0
+                 <para>Residual partition order (0..16). 0
                    => none, default is 0, above 4 doesn't usually
                    help much)</para>
                </listitem>
index bc65fc4..a11f632 100644 (file)
@@ -91,7 +91,7 @@ static int32 *input[FLAC__MAX_CHANNELS];
 
 /* local routines */
 static bool init(encoder_wrapper_struct *encoder_wrapper);
-static bool init_encoder(bool lax, bool do_mid_side, bool loose_mid_side, bool do_exhaustive_model_search, bool do_qlp_coeff_prec_search, unsigned rice_optimization_level, unsigned max_lpc_order, unsigned blocksize, unsigned qlp_coeff_precision, unsigned channels, unsigned bps, unsigned sample_rate, unsigned padding, char *requested_seek_points, int num_requested_seek_points, encoder_wrapper_struct *encoder_wrapper);
+static bool init_encoder(bool lax, bool do_mid_side, bool loose_mid_side, bool do_exhaustive_model_search, bool do_qlp_coeff_prec_search, unsigned min_residual_partition_order, unsigned max_residual_partition_order, unsigned rice_parameter_search_dist, unsigned max_lpc_order, unsigned blocksize, unsigned qlp_coeff_precision, unsigned channels, unsigned bps, unsigned sample_rate, unsigned padding, char *requested_seek_points, int num_requested_seek_points, encoder_wrapper_struct *encoder_wrapper);
 static bool convert_to_seek_table(char *requested_seek_points, int num_requested_seek_points, uint64 stream_samples, unsigned blocksize, FLAC__StreamMetaData_SeekTable *seek_table);
 static void append_point_to_seek_table(FLAC__StreamMetaData_SeekTable *seek_table, uint64 sample, uint64 stream_samples, uint64 blocksize);
 static int seekpoint_compare(const FLAC__StreamMetaData_SeekPoint *l, const FLAC__StreamMetaData_SeekPoint *r);
@@ -108,7 +108,7 @@ static bool read_little_endian_uint32(FILE *f, uint32 *val, bool eof_ok);
 static bool write_big_endian_uint16(FILE *f, uint16 val);
 static bool write_big_endian_uint64(FILE *f, uint64 val);
 
-int encode_wav(const char *infile, const char *outfile, bool verbose, uint64 skip, bool verify, bool lax, bool do_mid_side, bool loose_mid_side, bool do_exhaustive_model_search, bool do_qlp_coeff_prec_search, unsigned rice_optimization_level, unsigned max_lpc_order, unsigned blocksize, unsigned qlp_coeff_precision, unsigned padding, char *requested_seek_points, int num_requested_seek_points)
+int encode_wav(const char *infile, const char *outfile, bool verbose, uint64 skip, bool verify, bool lax, bool do_mid_side, bool loose_mid_side, bool do_exhaustive_model_search, bool do_qlp_coeff_prec_search, unsigned min_residual_partition_order, unsigned max_residual_partition_order, unsigned rice_parameter_search_dist, unsigned max_lpc_order, unsigned blocksize, unsigned qlp_coeff_precision, unsigned padding, char *requested_seek_points, int num_requested_seek_points)
 {
        encoder_wrapper_struct encoder_wrapper;
        FILE *fin;
@@ -262,7 +262,7 @@ int encode_wav(const char *infile, const char *outfile, bool verbose, uint64 ski
        encoder_wrapper.total_samples_to_encode = data_bytes / bytes_per_wide_sample - skip;
        encoder_wrapper.unencoded_size = encoder_wrapper.total_samples_to_encode * bytes_per_wide_sample + 44; /* 44 for the size of the WAV headers */
 
-       if(!init_encoder(lax, do_mid_side, loose_mid_side, do_exhaustive_model_search, do_qlp_coeff_prec_search, rice_optimization_level, max_lpc_order, blocksize, qlp_coeff_precision, channels, bps, sample_rate, padding, requested_seek_points, num_requested_seek_points, &encoder_wrapper))
+       if(!init_encoder(lax, do_mid_side, loose_mid_side, do_exhaustive_model_search, do_qlp_coeff_prec_search, min_residual_partition_order, max_residual_partition_order, rice_parameter_search_dist, max_lpc_order, blocksize, qlp_coeff_precision, channels, bps, sample_rate, padding, requested_seek_points, num_requested_seek_points, &encoder_wrapper))
                goto wav_abort_;
 
        encoder_wrapper.verify_fifo.into_frames = true;
@@ -345,7 +345,7 @@ wav_abort_:
        return 1;
 }
 
-int encode_raw(const char *infile, const char *outfile, bool verbose, uint64 skip, bool verify, bool lax, bool do_mid_side, bool loose_mid_side, bool do_exhaustive_model_search, bool do_qlp_coeff_prec_search, unsigned rice_optimization_level, unsigned max_lpc_order, unsigned blocksize, unsigned qlp_coeff_precision, unsigned padding, char *requested_seek_points, int num_requested_seek_points, bool is_big_endian, bool is_unsigned_samples, unsigned channels, unsigned bps, unsigned sample_rate)
+int encode_raw(const char *infile, const char *outfile, bool verbose, uint64 skip, bool verify, bool lax, bool do_mid_side, bool loose_mid_side, bool do_exhaustive_model_search, bool do_qlp_coeff_prec_search, unsigned min_residual_partition_order, unsigned max_residual_partition_order, unsigned rice_parameter_search_dist, unsigned max_lpc_order, unsigned blocksize, unsigned qlp_coeff_precision, unsigned padding, char *requested_seek_points, int num_requested_seek_points, bool is_big_endian, bool is_unsigned_samples, unsigned channels, unsigned bps, unsigned sample_rate)
 {
        encoder_wrapper_struct encoder_wrapper;
        FILE *fin;
@@ -423,7 +423,7 @@ int encode_raw(const char *infile, const char *outfile, bool verbose, uint64 ski
                fseek(fin, 0, SEEK_SET);
        }
 
-       if(!init_encoder(lax, do_mid_side, loose_mid_side, do_exhaustive_model_search, do_qlp_coeff_prec_search, rice_optimization_level, max_lpc_order, blocksize, qlp_coeff_precision, channels, bps, sample_rate, padding, requested_seek_points, num_requested_seek_points, &encoder_wrapper))
+       if(!init_encoder(lax, do_mid_side, loose_mid_side, do_exhaustive_model_search, do_qlp_coeff_prec_search, min_residual_partition_order, max_residual_partition_order, rice_parameter_search_dist, max_lpc_order, blocksize, qlp_coeff_precision, channels, bps, sample_rate, padding, requested_seek_points, num_requested_seek_points, &encoder_wrapper))
                goto raw_abort_;
 
        encoder_wrapper.verify_fifo.into_frames = true;
@@ -517,7 +517,7 @@ bool init(encoder_wrapper_struct *encoder_wrapper)
        return true;
 }
 
-bool init_encoder(bool lax, bool do_mid_side, bool loose_mid_side, bool do_exhaustive_model_search, bool do_qlp_coeff_prec_search, unsigned rice_optimization_level, unsigned max_lpc_order, unsigned blocksize, unsigned qlp_coeff_precision, unsigned channels, unsigned bps, unsigned sample_rate, unsigned padding, char *requested_seek_points, int num_requested_seek_points, encoder_wrapper_struct *encoder_wrapper)
+bool init_encoder(bool lax, bool do_mid_side, bool loose_mid_side, bool do_exhaustive_model_search, bool do_qlp_coeff_prec_search, unsigned min_residual_partition_order, unsigned max_residual_partition_order, unsigned rice_parameter_search_dist, unsigned max_lpc_order, unsigned blocksize, unsigned qlp_coeff_precision, unsigned channels, unsigned bps, unsigned sample_rate, unsigned padding, char *requested_seek_points, int num_requested_seek_points, encoder_wrapper_struct *encoder_wrapper)
 {
        unsigned i;
 
@@ -565,7 +565,9 @@ bool init_encoder(bool lax, bool do_mid_side, bool loose_mid_side, bool do_exhau
        encoder_wrapper->encoder->loose_mid_side_stereo = loose_mid_side;
        encoder_wrapper->encoder->do_exhaustive_model_search = do_exhaustive_model_search;
        encoder_wrapper->encoder->do_qlp_coeff_prec_search = do_qlp_coeff_prec_search;
-       encoder_wrapper->encoder->rice_optimization_level = rice_optimization_level;
+       encoder_wrapper->encoder->min_residual_partition_order = min_residual_partition_order;
+       encoder_wrapper->encoder->max_residual_partition_order = max_residual_partition_order;
+       encoder_wrapper->encoder->rice_parameter_search_dist = rice_parameter_search_dist;
        encoder_wrapper->encoder->total_samples_estimate = encoder_wrapper->total_samples_to_encode;
        encoder_wrapper->encoder->seek_table = (encoder_wrapper->seek_table.num_points > 0)? &encoder_wrapper->seek_table : 0;
        encoder_wrapper->encoder->padding = padding;
index ea7075a..3b581ce 100644 (file)
@@ -21,7 +21,7 @@
 
 #include "FLAC/ordinals.h"
 
-int encode_wav(const char *infile, const char *outfile, bool verbose, uint64 skip, bool verify, bool lax, bool do_mid_side, bool loose_mid_side, bool do_exhaustive_model_search, bool do_qlp_coeff_prec_search, unsigned rice_optimization_level, unsigned max_lpc_order, unsigned blocksize, unsigned qlp_coeff_precision, unsigned padding, char *requested_seek_points, int num_requested_seek_points);
-int encode_raw(const char *infile, const char *outfile, bool verbose, uint64 skip, bool verify, bool lax, bool do_mid_side, bool loose_mid_side, bool do_exhaustive_model_search, bool do_qlp_coeff_prec_search, unsigned rice_optimization_level, unsigned max_lpc_order, unsigned blocksize, unsigned qlp_coeff_precision, unsigned padding, char *requested_seek_points, int num_requested_seek_points, bool is_big_endian, bool is_unsigned_samples, unsigned channels, unsigned bps, unsigned sample_rate);
+int encode_wav(const char *infile, const char *outfile, bool verbose, uint64 skip, bool verify, bool lax, bool do_mid_side, bool loose_mid_side, bool do_exhaustive_model_search, bool do_qlp_coeff_prec_search, unsigned min_residual_partition_order, unsigned max_residual_partition_order, unsigned rice_parameter_search_dist, unsigned max_lpc_order, unsigned blocksize, unsigned qlp_coeff_precision, unsigned padding, char *requested_seek_points, int num_requested_seek_points);
+int encode_raw(const char *infile, const char *outfile, bool verbose, uint64 skip, bool verify, bool lax, bool do_mid_side, bool loose_mid_side, bool do_exhaustive_model_search, bool do_qlp_coeff_prec_search, unsigned min_residual_partition_order, unsigned max_residual_partition_order, unsigned rice_parameter_search_dist, unsigned max_lpc_order, unsigned blocksize, unsigned qlp_coeff_precision, unsigned padding, char *requested_seek_points, int num_requested_seek_points, bool is_big_endian, bool is_unsigned_samples, unsigned channels, unsigned bps, unsigned sample_rate);
 
 #endif
index f19057a..a0a1ae7 100644 (file)
@@ -41,7 +41,7 @@ int main(int argc, char *argv[])
        uint64 skip = 0;
        int format_is_wave = -1, format_is_big_endian = -1, format_is_unsigned_samples = false;
        int format_channels = -1, format_bps = -1, format_sample_rate = -1;
-       int blocksize = -1, rice_optimization_level = -1;
+       int blocksize = -1, min_residual_partition_order = -1, max_residual_partition_order = -1, rice_parameter_search_dist = -1;
        char requested_seek_points[50000]; /* @@@ bad MAGIC NUMBER */
        int num_requested_seek_points = -1; /* -1 => no -S options were given, 0 => -S- was given */
 
@@ -110,8 +110,19 @@ int main(int argc, char *argv[])
                        padding = atoi(argv[++i]);
                else if(0 == strcmp(argv[i], "-q"))
                        qlp_coeff_precision = atoi(argv[++i]);
-               else if(0 == strcmp(argv[i], "-r"))
-                       rice_optimization_level = atoi(argv[++i]);
+               else if(0 == strcmp(argv[i], "-r")) {
+                       char *p = strchr(argv[++i], ',');
+                       if(0 == p) {
+                               min_residual_partition_order = 0;
+                               max_residual_partition_order = atoi(argv[i]);
+                       }
+                       else {
+                               min_residual_partition_order = atoi(argv[i]);
+                               max_residual_partition_order = atoi(++p);
+                       }
+               }
+               else if(0 == strcmp(argv[i], "-R"))
+                       rice_parameter_search_dist = atoi(argv[++i]);
                else if(0 == strcmp(argv[i], "-V"))
                        verify = true;
                else if(0 == strcmp(argv[i], "-V-"))
@@ -141,7 +152,8 @@ int main(int argc, char *argv[])
                        do_mid_side = false;
                        loose_mid_side = false;
                        qlp_coeff_precision = 0;
-                       rice_optimization_level = 0;
+                       min_residual_partition_order = max_residual_partition_order = 0;
+                       rice_parameter_search_dist = 0;
                        max_lpc_order = 0;
                }
                else if(0 == strcmp(argv[i], "-1")) {
@@ -149,7 +161,8 @@ int main(int argc, char *argv[])
                        do_mid_side = true;
                        loose_mid_side = true;
                        qlp_coeff_precision = 0;
-                       rice_optimization_level = 0;
+                       min_residual_partition_order = max_residual_partition_order = 0;
+                       rice_parameter_search_dist = 0;
                        max_lpc_order = 0;
                }
                else if(0 == strcmp(argv[i], "-2")) {
@@ -157,6 +170,7 @@ int main(int argc, char *argv[])
                        do_mid_side = true;
                        loose_mid_side = false;
                        qlp_coeff_precision = 0;
+                       rice_parameter_search_dist = 0;
                        max_lpc_order = 0;
                }
                else if(0 == strcmp(argv[i], "-4")) {
@@ -164,7 +178,8 @@ int main(int argc, char *argv[])
                        do_mid_side = false;
                        loose_mid_side = false;
                        qlp_coeff_precision = 0;
-                       rice_optimization_level = 0;
+                       min_residual_partition_order = max_residual_partition_order = 0;
+                       rice_parameter_search_dist = 0;
                        max_lpc_order = 8;
                }
                else if(0 == strcmp(argv[i], "-5")) {
@@ -172,7 +187,8 @@ int main(int argc, char *argv[])
                        do_mid_side = true;
                        loose_mid_side = true;
                        qlp_coeff_precision = 0;
-                       rice_optimization_level = 0;
+                       min_residual_partition_order = max_residual_partition_order = 0;
+                       rice_parameter_search_dist = 0;
                        max_lpc_order = 8;
                }
                else if(0 == strcmp(argv[i], "-6")) {
@@ -180,6 +196,7 @@ int main(int argc, char *argv[])
                        do_mid_side = true;
                        loose_mid_side = false;
                        qlp_coeff_precision = 0;
+                       rice_parameter_search_dist = 0;
                        max_lpc_order = 8;
                }
                else if(0 == strcmp(argv[i], "-8")) {
@@ -187,6 +204,7 @@ int main(int argc, char *argv[])
                        do_mid_side = true;
                        loose_mid_side = false;
                        qlp_coeff_precision = 0;
+                       rice_parameter_search_dist = 0;
                        max_lpc_order = 32;
                }
                else if(0 == strcmp(argv[i], "-9")) {
@@ -194,7 +212,9 @@ int main(int argc, char *argv[])
                        do_mid_side = true;
                        loose_mid_side = false;
                        do_qlp_coeff_prec_search = true;
-                       rice_optimization_level = 99;
+                       min_residual_partition_order = 0;
+                       max_residual_partition_order = 16;
+                       rice_parameter_search_dist = 32;
                        max_lpc_order = 32;
                }
                else if(isdigit((int)(argv[i][1]))) {
@@ -225,15 +245,19 @@ int main(int argc, char *argv[])
                        else
                                blocksize = 4608;
                }
-               if(rice_optimization_level < 0) {
+               if(min_residual_partition_order < 0) {
+                       min_residual_partition_order = 0;
                        if(blocksize <= 1152)
-                               rice_optimization_level = 4;
+                               max_residual_partition_order = 4;
                        else if(blocksize <= 2304)
-                               rice_optimization_level = 4;
+                               max_residual_partition_order = 4;
                        else if(blocksize <= 4608)
-                               rice_optimization_level = 4;
+                               max_residual_partition_order = 4;
                        else
-                               rice_optimization_level = 5;
+                               max_residual_partition_order = 5;
+               }
+               if(rice_parameter_search_dist < 0) {
+                       rice_parameter_search_dist = 0;
                }
        }
        else {
@@ -287,10 +311,11 @@ int main(int argc, char *argv[])
                printf("welcome to redistribute it under certain conditions.  Type `flac' for details.\n\n");
 
                if(!mode_decode) {
-                       printf("options:%s -P %u -b %u%s -l %u%s%s -q %u -r %u%s\n",
+                       printf("options:%s -P %u -b %u%s -l %u%s%s -q %u -r %u,%u -R %u%s\n",
                                lax?" --lax":"", padding, (unsigned)blocksize, loose_mid_side?" -M":do_mid_side?" -m":"", max_lpc_order,
                                do_exhaustive_model_search?" -e":"", do_qlp_coeff_prec_search?" -p":"",
-                               qlp_coeff_precision, (unsigned)rice_optimization_level,
+                               qlp_coeff_precision,
+                               (unsigned)min_residual_partition_order, (unsigned)max_residual_partition_order, (unsigned)rice_parameter_search_dist,
                                verify? " -V":""
                        );
                }
@@ -303,9 +328,9 @@ int main(int argc, char *argv[])
                        return decode_raw(argv[i], test_only? 0 : argv[i+1], analyze, aopts, verbose, skip, format_is_big_endian, format_is_unsigned_samples);
        else
                if(format_is_wave)
-                       return encode_wav(argv[i], argv[i+1], verbose, skip, verify, lax, do_mid_side, loose_mid_side, do_exhaustive_model_search, do_qlp_coeff_prec_search, rice_optimization_level, max_lpc_order, (unsigned)blocksize, qlp_coeff_precision, padding, requested_seek_points, num_requested_seek_points);
+                       return encode_wav(argv[i], argv[i+1], verbose, skip, verify, lax, do_mid_side, loose_mid_side, do_exhaustive_model_search, do_qlp_coeff_prec_search, min_residual_partition_order, max_residual_partition_order, rice_parameter_search_dist, max_lpc_order, (unsigned)blocksize, qlp_coeff_precision, padding, requested_seek_points, num_requested_seek_points);
                else
-                       return encode_raw(argv[i], argv[i+1], verbose, skip, verify, lax, do_mid_side, loose_mid_side, do_exhaustive_model_search, do_qlp_coeff_prec_search, rice_optimization_level, max_lpc_order, (unsigned)blocksize, qlp_coeff_precision, padding, requested_seek_points, num_requested_seek_points, format_is_big_endian, format_is_unsigned_samples, format_channels, format_bps, format_sample_rate);
+                       return encode_raw(argv[i], argv[i+1], verbose, skip, verify, lax, do_mid_side, loose_mid_side, do_exhaustive_model_search, do_qlp_coeff_prec_search, min_residual_partition_order, max_residual_partition_order, rice_parameter_search_dist, max_lpc_order, (unsigned)blocksize, qlp_coeff_precision, padding, requested_seek_points, num_requested_seek_points, format_is_big_endian, format_is_unsigned_samples, format_channels, format_bps, format_sample_rate);
 
        return 0;
 }
@@ -390,22 +415,23 @@ int usage(const char *message, ...)
        printf("             these are synonyms for other options:\n");
        printf("  -0   : synonymous with -l 0 -b 1152\n");
        printf("  -1   : synonymous with -l 0 -b 1152 -M\n");
-       printf("  -2   : synonymous with -l 0 -b 1152 -m -r 2\n");
+       printf("  -2   : synonymous with -l 0 -b 1152 -m -r 4\n");
        printf("  -3   : reserved\n");
        printf("  -4   : synonymous with -l 8 -b 4608 \n");
        printf("  -5   : synonymous with -l 8 -b 4608 -M\n");
        printf("  -6   : synonymous with -l 8 -b 4608 -m -r 4\n");
        printf("  -7   : reserved\n");
        printf("  -8   : synonymous with -l 32 -b 4608 -m -r 4\n");
-       printf("  -9   : synonymous with -l 32 -m -e -r 99 -p (very slow!)\n");
+       printf("  -9   : synonymous with -l 32 -m -e -r 16 -R 32 -p (very slow!)\n");
        printf("  -e   : do exhaustive model search (expensive!)\n");
        printf("  -l # : specify max LPC order; 0 => use only fixed predictors\n");
        printf("  -p   : do exhaustive search of LP coefficient quantization (expensive!);\n");
        printf("         overrides -q, does nothing if using -l 0\n");
        printf("  -q # : specify precision in bits of quantized linear-predictor coefficients;\n");
        printf("         0 => let encoder decide (min is %u, default is -q 0)\n", FLAC__MIN_QLP_COEFF_PRECISION);
-       printf("  -r # : rice parameter optimization level (# is 0..99, 0 => none, default is\n");
-       printf("         -r 0, above 4 doesn't usually help much)\n");
+       printf("  -r [#,]# : [min,]max residual partition order (# is 0..16; min defaults to 0;\n");
+       printf("         default is -r 0; above 4 doesn't usually help much)\n");
+       printf("  -R # : Rice parameter search distance (# is 0..32; above 2 doesn't help much\n");
        printf("  -V   : verify a correct encoding by decoding the output in parallel and\n");
        printf("         comparing to the original\n");
        printf("  -S-, -m-, -M-, -e-, -p-, -V-, --lax- can all be used to turn off a particular\n");
index 5ce2bf3..c189038 100644 (file)
@@ -81,17 +81,17 @@ typedef struct FLAC__EncoderPrivate {
 static bool encoder_resize_buffers_(FLAC__Encoder *encoder, unsigned new_size);
 static bool encoder_process_frame_(FLAC__Encoder *encoder, bool is_last_frame);
 static bool encoder_process_subframes_(FLAC__Encoder *encoder, bool is_last_frame);
-static bool encoder_process_subframe_(FLAC__Encoder *encoder, unsigned max_partition_order, bool verbatim_only, const FLAC__FrameHeader *frame_header, unsigned subframe_bps, const int32 integer_signal[], const real real_signal[], FLAC__Subframe *subframe[2], int32 *residual[2], unsigned *best_subframe, unsigned *best_bits);
+static bool encoder_process_subframe_(FLAC__Encoder *encoder, unsigned min_partition_order, unsigned max_partition_order, bool verbatim_only, const FLAC__FrameHeader *frame_header, unsigned subframe_bps, const int32 integer_signal[], const real real_signal[], FLAC__Subframe *subframe[2], int32 *residual[2], unsigned *best_subframe, unsigned *best_bits);
 static bool encoder_add_subframe_(FLAC__Encoder *encoder, const FLAC__FrameHeader *frame_header, unsigned subframe_bps, const FLAC__Subframe *subframe, FLAC__BitBuffer *frame);
 static unsigned encoder_evaluate_constant_subframe_(const int32 signal, unsigned subframe_bps, FLAC__Subframe *subframe);
-static unsigned encoder_evaluate_fixed_subframe_(const int32 signal[], int32 residual[], uint32 abs_residual[], uint32 abs_residual_partition_sums[], unsigned raw_bits_per_partition[], unsigned blocksize, unsigned subframe_bps, unsigned order, unsigned rice_parameter, unsigned max_partition_order, FLAC__Subframe *subframe);
-static unsigned encoder_evaluate_lpc_subframe_(const int32 signal[], int32 residual[], uint32 abs_residual[], uint32 abs_residual_partition_sums[], unsigned raw_bits_per_partition[], const real lp_coeff[], unsigned blocksize, unsigned subframe_bps, unsigned order, unsigned qlp_coeff_precision, unsigned rice_parameter, unsigned max_partition_order, FLAC__Subframe *subframe);
+static unsigned encoder_evaluate_fixed_subframe_(const int32 signal[], int32 residual[], uint32 abs_residual[], uint32 abs_residual_partition_sums[], unsigned raw_bits_per_partition[], unsigned blocksize, unsigned subframe_bps, unsigned order, unsigned rice_parameter, unsigned min_partition_order, unsigned max_partition_order, unsigned rice_parameter_search_dist, FLAC__Subframe *subframe);
+static unsigned encoder_evaluate_lpc_subframe_(const int32 signal[], int32 residual[], uint32 abs_residual[], uint32 abs_residual_partition_sums[], unsigned raw_bits_per_partition[], const real lp_coeff[], unsigned blocksize, unsigned subframe_bps, unsigned order, unsigned qlp_coeff_precision, unsigned rice_parameter, unsigned min_partition_order, unsigned max_partition_order, unsigned rice_parameter_search_dist, FLAC__Subframe *subframe);
 static unsigned encoder_evaluate_verbatim_subframe_(const int32 signal[], unsigned blocksize, unsigned subframe_bps, FLAC__Subframe *subframe);
-static unsigned encoder_find_best_partition_order_(const int32 residual[], uint32 abs_residual[], uint32 abs_residual_partition_sums[], unsigned raw_bits_per_partition[], unsigned residual_samples, unsigned predictor_order, unsigned rice_parameter, unsigned max_partition_order, unsigned *best_partition_order, unsigned best_parameters[], unsigned best_raw_bits[]);
+static unsigned encoder_find_best_partition_order_(const int32 residual[], uint32 abs_residual[], uint32 abs_residual_partition_sums[], unsigned raw_bits_per_partition[], unsigned residual_samples, unsigned predictor_order, unsigned rice_parameter, unsigned min_partition_order, unsigned max_partition_order, unsigned rice_parameter_search_dist, unsigned *best_partition_order, unsigned best_parameters[], unsigned best_raw_bits[]);
 #if (defined FLAC__PRECOMPUTE_PARTITION_SUMS) || (defined FLAC__SEARCH_FOR_ESCAPES)
-static unsigned encoder_precompute_partition_info_(const int32 residual[], uint32 abs_residual[], uint32 abs_residual_partition_sums[], unsigned raw_bits_per_partition[], unsigned residual_samples, unsigned predictor_order, unsigned max_partition_order);
+static unsigned encoder_precompute_partition_info_(const int32 residual[], uint32 abs_residual[], uint32 abs_residual_partition_sums[], unsigned raw_bits_per_partition[], unsigned residual_samples, unsigned predictor_order, unsigned min_partition_order, unsigned max_partition_order);
 #endif
-static bool encoder_set_partitioned_rice_(const uint32 abs_residual[], const uint32 abs_residual_partition_sums[], const unsigned raw_bits_per_partition[], const unsigned residual_samples, const unsigned predictor_order, unsigned rice_parameter, const unsigned partition_order, unsigned parameters[], unsigned raw_bits[], unsigned *bits);
+static bool encoder_set_partitioned_rice_(const uint32 abs_residual[], const uint32 abs_residual_partition_sums[], const unsigned raw_bits_per_partition[], const unsigned residual_samples, const unsigned predictor_order, unsigned rice_parameter, const unsigned rice_parameter_search_dist, const unsigned partition_order, unsigned parameters[], unsigned raw_bits[], unsigned *bits);
 static unsigned encoder_get_wasted_bits_(int32 signal[], unsigned samples);
 
 const char *FLAC__EncoderWriteStatusString[] = {
@@ -353,8 +353,10 @@ FLAC__EncoderState FLAC__encoder_init(FLAC__Encoder *encoder, FLAC__EncoderWrite
                        return encoder->state = FLAC__ENCODER_NOT_STREAMABLE;
        }
 
-       if(encoder->rice_optimization_level >= (1u << FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ORDER_LEN))
-               encoder->rice_optimization_level = (1u << FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ORDER_LEN) - 1;
+       if(encoder->max_residual_partition_order >= (1u << FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ORDER_LEN))
+               encoder->max_residual_partition_order = (1u << FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ORDER_LEN) - 1;
+       if(encoder->min_residual_partition_order >= encoder->max_residual_partition_order)
+               encoder->min_residual_partition_order = encoder->max_residual_partition_order;
 
        encoder->guts = (FLAC__EncoderPrivate*)malloc(sizeof(FLAC__EncoderPrivate));
        if(encoder->guts == 0)
@@ -690,11 +692,11 @@ bool encoder_process_frame_(FLAC__Encoder *encoder, bool is_last_frame)
 bool encoder_process_subframes_(FLAC__Encoder *encoder, bool is_last_frame)
 {
        FLAC__FrameHeader frame_header;
-       unsigned channel, max_partition_order;
+       unsigned channel, min_partition_order, max_partition_order;
        bool do_independent, do_mid_side;
 
        /*
-        * Calculate the max Rice partition order
+        * Calculate the min,max Rice partition orders
         */
        if(is_last_frame) {
                max_partition_order = 0;
@@ -705,8 +707,9 @@ bool encoder_process_subframes_(FLAC__Encoder *encoder, bool is_last_frame)
                        limit++;
                        b >>= 1;
                }
-               max_partition_order = min(encoder->rice_optimization_level, limit);
+               max_partition_order = min(encoder->max_residual_partition_order, limit);
        }
+       min_partition_order = min(min_partition_order, max_partition_order);
 
        /*
         * Setup the frame
@@ -778,7 +781,7 @@ bool encoder_process_subframes_(FLAC__Encoder *encoder, bool is_last_frame)
         */
        if(do_independent) {
                for(channel = 0; channel < encoder->channels; channel++) {
-                       if(!encoder_process_subframe_(encoder, max_partition_order, false, &frame_header, encoder->guts->subframe_bps[channel], encoder->guts->integer_signal[channel], encoder->guts->real_signal[channel], encoder->guts->subframe_workspace_ptr[channel], encoder->guts->residual_workspace[channel], encoder->guts->best_subframe+channel, encoder->guts->best_subframe_bits+channel))
+                       if(!encoder_process_subframe_(encoder, min_partition_order, max_partition_order, false, &frame_header, encoder->guts->subframe_bps[channel], encoder->guts->integer_signal[channel], encoder->guts->real_signal[channel], encoder->guts->subframe_workspace_ptr[channel], encoder->guts->residual_workspace[channel], encoder->guts->best_subframe+channel, encoder->guts->best_subframe_bits+channel))
                                return false;
                }
        }
@@ -790,7 +793,7 @@ bool encoder_process_subframes_(FLAC__Encoder *encoder, bool is_last_frame)
                assert(encoder->channels == 2);
 
                for(channel = 0; channel < 2; channel++) {
-                       if(!encoder_process_subframe_(encoder, max_partition_order, false, &frame_header, encoder->guts->subframe_bps_mid_side[channel], encoder->guts->integer_signal_mid_side[channel], encoder->guts->real_signal_mid_side[channel], encoder->guts->subframe_workspace_ptr_mid_side[channel], encoder->guts->residual_workspace_mid_side[channel], encoder->guts->best_subframe_mid_side+channel, encoder->guts->best_subframe_bits_mid_side+channel))
+                       if(!encoder_process_subframe_(encoder, min_partition_order, max_partition_order, false, &frame_header, encoder->guts->subframe_bps_mid_side[channel], encoder->guts->integer_signal_mid_side[channel], encoder->guts->real_signal_mid_side[channel], encoder->guts->subframe_workspace_ptr_mid_side[channel], encoder->guts->residual_workspace_mid_side[channel], encoder->guts->best_subframe_mid_side+channel, encoder->guts->best_subframe_bits_mid_side+channel))
                                return false;
                }
        }
@@ -909,7 +912,7 @@ bool encoder_process_subframes_(FLAC__Encoder *encoder, bool is_last_frame)
        return true;
 }
 
-bool encoder_process_subframe_(FLAC__Encoder *encoder, unsigned max_partition_order, bool verbatim_only, const FLAC__FrameHeader *frame_header, unsigned subframe_bps, const int32 integer_signal[], const real real_signal[], FLAC__Subframe *subframe[2], int32 *residual[2], unsigned *best_subframe, unsigned *best_bits)
+bool encoder_process_subframe_(FLAC__Encoder *encoder, unsigned min_partition_order, unsigned max_partition_order, bool verbatim_only, const FLAC__FrameHeader *frame_header, unsigned subframe_bps, const int32 integer_signal[], const real real_signal[], FLAC__Subframe *subframe[2], int32 *residual[2], unsigned *best_subframe, unsigned *best_bits)
 {
        real fixed_residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1];
        real lpc_residual_bits_per_sample;
@@ -968,7 +971,7 @@ bool encoder_process_subframe_(FLAC__Encoder *encoder, unsigned max_partition_or
 #endif
                                if(rice_parameter >= (1u << FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_PARAMETER_LEN))
                                        rice_parameter = (1u << FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_PARAMETER_LEN) - 1;
-                               _candidate_bits = encoder_evaluate_fixed_subframe_(integer_signal, residual[!_best_subframe], encoder->guts->abs_residual, encoder->guts->abs_residual_partition_sums, encoder->guts->raw_bits_per_partition, frame_header->blocksize, subframe_bps, fixed_order, rice_parameter, max_partition_order, subframe[!_best_subframe]);
+                               _candidate_bits = encoder_evaluate_fixed_subframe_(integer_signal, residual[!_best_subframe], encoder->guts->abs_residual, encoder->guts->abs_residual_partition_sums, encoder->guts->raw_bits_per_partition, frame_header->blocksize, subframe_bps, fixed_order, rice_parameter, min_partition_order, max_partition_order, encoder->rice_parameter_search_dist, subframe[!_best_subframe]);
                                if(_candidate_bits < _best_bits) {
                                        _best_subframe = !_best_subframe;
                                        _best_bits = _candidate_bits;
@@ -1011,7 +1014,7 @@ bool encoder_process_subframe_(FLAC__Encoder *encoder, unsigned max_partition_or
                                                        if(rice_parameter >= (1u << FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_PARAMETER_LEN))
                                                                rice_parameter = (1u << FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_PARAMETER_LEN) - 1;
                                                        for(qlp_coeff_precision = min_qlp_coeff_precision; qlp_coeff_precision <= max_qlp_coeff_precision; qlp_coeff_precision++) {
-                                                               _candidate_bits = encoder_evaluate_lpc_subframe_(integer_signal, residual[!_best_subframe], encoder->guts->abs_residual, encoder->guts->abs_residual_partition_sums, encoder->guts->raw_bits_per_partition, lp_coeff[lpc_order-1], frame_header->blocksize, subframe_bps, lpc_order, qlp_coeff_precision, rice_parameter, max_partition_order, subframe[!_best_subframe]);
+                                                               _candidate_bits = encoder_evaluate_lpc_subframe_(integer_signal, residual[!_best_subframe], encoder->guts->abs_residual, encoder->guts->abs_residual_partition_sums, encoder->guts->raw_bits_per_partition, lp_coeff[lpc_order-1], frame_header->blocksize, subframe_bps, lpc_order, qlp_coeff_precision, rice_parameter, min_partition_order, max_partition_order, encoder->rice_parameter_search_dist, subframe[!_best_subframe]);
                                                                if(_candidate_bits > 0) { /* if == 0, there was a problem quantizing the lpcoeffs */
                                                                        if(_candidate_bits < _best_bits) {
                                                                                _best_subframe = !_best_subframe;
@@ -1074,7 +1077,7 @@ unsigned encoder_evaluate_constant_subframe_(const int32 signal, unsigned subfra
        return FLAC__SUBFRAME_ZERO_PAD_LEN + FLAC__SUBFRAME_TYPE_LEN + FLAC__SUBFRAME_WASTED_BITS_FLAG_LEN + subframe_bps;
 }
 
-unsigned encoder_evaluate_fixed_subframe_(const int32 signal[], int32 residual[], uint32 abs_residual[], uint32 abs_residual_partition_sums[], unsigned raw_bits_per_partition[], unsigned blocksize, unsigned subframe_bps, unsigned order, unsigned rice_parameter, unsigned max_partition_order, FLAC__Subframe *subframe)
+unsigned encoder_evaluate_fixed_subframe_(const int32 signal[], int32 residual[], uint32 abs_residual[], uint32 abs_residual_partition_sums[], unsigned raw_bits_per_partition[], unsigned blocksize, unsigned subframe_bps, unsigned order, unsigned rice_parameter, unsigned min_partition_order, unsigned max_partition_order, unsigned rice_parameter_search_dist, FLAC__Subframe *subframe)
 {
        unsigned i, residual_bits;
        const unsigned residual_samples = blocksize - order;
@@ -1086,7 +1089,7 @@ unsigned encoder_evaluate_fixed_subframe_(const int32 signal[], int32 residual[]
        subframe->data.fixed.entropy_coding_method.type = FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE;
        subframe->data.fixed.residual = residual;
 
-       residual_bits = encoder_find_best_partition_order_(residual, abs_residual, abs_residual_partition_sums, raw_bits_per_partition, residual_samples, order, rice_parameter, max_partition_order, &subframe->data.fixed.entropy_coding_method.data.partitioned_rice.order, subframe->data.fixed.entropy_coding_method.data.partitioned_rice.parameters, subframe->data.fixed.entropy_coding_method.data.partitioned_rice.raw_bits);
+       residual_bits = encoder_find_best_partition_order_(residual, abs_residual, abs_residual_partition_sums, raw_bits_per_partition, residual_samples, order, rice_parameter, min_partition_order, max_partition_order, rice_parameter_search_dist, &subframe->data.fixed.entropy_coding_method.data.partitioned_rice.order, subframe->data.fixed.entropy_coding_method.data.partitioned_rice.parameters, subframe->data.fixed.entropy_coding_method.data.partitioned_rice.raw_bits);
 
        subframe->data.fixed.order = order;
        for(i = 0; i < order; i++)
@@ -1095,7 +1098,7 @@ unsigned encoder_evaluate_fixed_subframe_(const int32 signal[], int32 residual[]
        return FLAC__SUBFRAME_ZERO_PAD_LEN + FLAC__SUBFRAME_TYPE_LEN + FLAC__SUBFRAME_WASTED_BITS_FLAG_LEN + (order * subframe_bps) + residual_bits;
 }
 
-unsigned encoder_evaluate_lpc_subframe_(const int32 signal[], int32 residual[], uint32 abs_residual[], uint32 abs_residual_partition_sums[], unsigned raw_bits_per_partition[], const real lp_coeff[], unsigned blocksize, unsigned subframe_bps, unsigned order, unsigned qlp_coeff_precision, unsigned rice_parameter, unsigned max_partition_order, FLAC__Subframe *subframe)
+unsigned encoder_evaluate_lpc_subframe_(const int32 signal[], int32 residual[], uint32 abs_residual[], uint32 abs_residual_partition_sums[], unsigned raw_bits_per_partition[], const real lp_coeff[], unsigned blocksize, unsigned subframe_bps, unsigned order, unsigned qlp_coeff_precision, unsigned rice_parameter, unsigned min_partition_order, unsigned max_partition_order, unsigned rice_parameter_search_dist, FLAC__Subframe *subframe)
 {
        int32 qlp_coeff[FLAC__MAX_LPC_ORDER];
        unsigned i, residual_bits;
@@ -1113,7 +1116,7 @@ unsigned encoder_evaluate_lpc_subframe_(const int32 signal[], int32 residual[],
        subframe->data.lpc.entropy_coding_method.type = FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE;
        subframe->data.lpc.residual = residual;
 
-       residual_bits = encoder_find_best_partition_order_(residual, abs_residual, abs_residual_partition_sums, raw_bits_per_partition, residual_samples, order, rice_parameter, max_partition_order, &subframe->data.lpc.entropy_coding_method.data.partitioned_rice.order, subframe->data.lpc.entropy_coding_method.data.partitioned_rice.parameters, subframe->data.lpc.entropy_coding_method.data.partitioned_rice.raw_bits);
+       residual_bits = encoder_find_best_partition_order_(residual, abs_residual, abs_residual_partition_sums, raw_bits_per_partition, residual_samples, order, rice_parameter, min_partition_order, max_partition_order, rice_parameter_search_dist, &subframe->data.lpc.entropy_coding_method.data.partitioned_rice.order, subframe->data.lpc.entropy_coding_method.data.partitioned_rice.parameters, subframe->data.lpc.entropy_coding_method.data.partitioned_rice.raw_bits);
 
        subframe->data.lpc.order = order;
        subframe->data.lpc.qlp_coeff_precision = qlp_coeff_precision;
@@ -1134,7 +1137,7 @@ unsigned encoder_evaluate_verbatim_subframe_(const int32 signal[], unsigned bloc
        return FLAC__SUBFRAME_ZERO_PAD_LEN + FLAC__SUBFRAME_TYPE_LEN + FLAC__SUBFRAME_WASTED_BITS_FLAG_LEN + (blocksize * subframe_bps);
 }
 
-unsigned encoder_find_best_partition_order_(const int32 residual[], uint32 abs_residual[], uint32 abs_residual_partition_sums[], unsigned raw_bits_per_partition[], unsigned residual_samples, unsigned predictor_order, unsigned rice_parameter, unsigned max_partition_order, unsigned *best_partition_order, unsigned best_parameters[], unsigned best_raw_bits[])
+unsigned encoder_find_best_partition_order_(const int32 residual[], uint32 abs_residual[], uint32 abs_residual_partition_sums[], unsigned raw_bits_per_partition[], unsigned residual_samples, unsigned predictor_order, unsigned rice_parameter, unsigned min_partition_order, unsigned max_partition_order, unsigned rice_parameter_search_dist, unsigned *best_partition_order, unsigned best_parameters[], unsigned best_raw_bits[])
 {
        int32 r;
 #if (defined FLAC__PRECOMPUTE_PARTITION_SUMS) || (defined FLAC__SEARCH_FOR_ESCAPES)
@@ -1154,10 +1157,11 @@ unsigned encoder_find_best_partition_order_(const int32 residual[], uint32 abs_r
        }
 
 #if (defined FLAC__PRECOMPUTE_PARTITION_SUMS) || (defined FLAC__SEARCH_FOR_ESCAPES)
-       max_partition_order = encoder_precompute_partition_info_(residual, abs_residual, abs_residual_partition_sums, raw_bits_per_partition, residual_samples, predictor_order, max_partition_order);
+       max_partition_order = encoder_precompute_partition_info_(residual, abs_residual, abs_residual_partition_sums, raw_bits_per_partition, residual_samples, predictor_order, min_partition_order, max_partition_order);
+       min_partition_order = min(min_partition_order, max_partition_order);
 
-       for(partition_order = (int)max_partition_order, sum = 0; partition_order >= 0; partition_order--) {
-               if(!encoder_set_partitioned_rice_(abs_residual, abs_residual_partition_sums+sum, raw_bits_per_partition+sum, residual_samples, predictor_order, rice_parameter, (unsigned)partition_order, parameters[!best_parameters_index], raw_bits[!best_parameters_index], &residual_bits)) {
+       for(partition_order = (int)max_partition_order, sum = 0; partition_order >= (int)min_partition_order; partition_order--) {
+               if(!encoder_set_partitioned_rice_(abs_residual, abs_residual_partition_sums+sum, raw_bits_per_partition+sum, residual_samples, predictor_order, rice_parameter, rice_parameter_search_dist, (unsigned)partition_order, parameters[!best_parameters_index], raw_bits[!best_parameters_index], &residual_bits)) {
                        assert(0); /* encoder_precompute_partition_info_ should keep this from ever happening */
                }
                sum += 1u << partition_order;
@@ -1168,8 +1172,8 @@ unsigned encoder_find_best_partition_order_(const int32 residual[], uint32 abs_r
                }
        }
 #else
-       for(partition_order = 0; partition_order <= max_partition_order; partition_order++) {
-               if(!encoder_set_partitioned_rice_(abs_residual, 0, 0, residual_samples, predictor_order, rice_parameter, partition_order, parameters[!best_parameters_index], raw_bits[!best_parameters_index], &residual_bits)) {
+       for(partition_order = min_partition_order; partition_order <= max_partition_order; partition_order++) {
+               if(!encoder_set_partitioned_rice_(abs_residual, 0, 0, residual_samples, predictor_order, rice_parameter, rice_parameter_search_dist, partition_order, parameters[!best_parameters_index], raw_bits[!best_parameters_index], &residual_bits)) {
                        assert(best_residual_bits != 0);
                        break;
                }
@@ -1187,7 +1191,7 @@ unsigned encoder_find_best_partition_order_(const int32 residual[], uint32 abs_r
 }
 
 #if (defined FLAC__PRECOMPUTE_PARTITION_SUMS) || (defined FLAC__SEARCH_FOR_ESCAPES)
-unsigned encoder_precompute_partition_info_(const int32 residual[], uint32 abs_residual[], uint32 abs_residual_partition_sums[], unsigned raw_bits_per_partition[], unsigned residual_samples, unsigned predictor_order, unsigned max_partition_order)
+unsigned encoder_precompute_partition_info_(const int32 residual[], uint32 abs_residual[], uint32 abs_residual_partition_sums[], unsigned raw_bits_per_partition[], unsigned residual_samples, unsigned predictor_order, unsigned min_partition_order, unsigned max_partition_order)
 {
        int partition_order;
        unsigned from_partition, to_partition = 0;
@@ -1251,7 +1255,7 @@ unsigned encoder_precompute_partition_info_(const int32 residual[], uint32 abs_r
        }
 
        /* now merge for lower orders */
-       for(from_partition = 0; partition_order >= 0; partition_order--) {
+       for(from_partition = 0; partition_order >= min_partition_order; partition_order--) {
 #ifdef FLAC__PRECOMPUTE_PARTITION_SUMS
                uint32 s;
 #endif
@@ -1288,9 +1292,10 @@ unsigned encoder_precompute_partition_info_(const int32 residual[], uint32 abs_r
 #endif
 #define VARIABLE_RICE_BITS(value, parameter) ((value) >> (parameter))
 
-bool encoder_set_partitioned_rice_(const uint32 abs_residual[], const uint32 abs_residual_partition_sums[], const unsigned raw_bits_per_partition[], const unsigned residual_samples, const unsigned predictor_order, unsigned rice_parameter, const unsigned partition_order, unsigned parameters[], unsigned raw_bits[], unsigned *bits)
+bool encoder_set_partitioned_rice_(const uint32 abs_residual[], const uint32 abs_residual_partition_sums[], const unsigned raw_bits_per_partition[], const unsigned residual_samples, const unsigned predictor_order, unsigned rice_parameter, const unsigned rice_parameter_search_dist, const unsigned partition_order, unsigned parameters[], unsigned raw_bits[], unsigned *bits)
 {
        unsigned partition_bits;
+       unsigned min_rice_parameter, max_rice_parameter;
 #ifdef FLAC__SEARCH_FOR_ESCAPES
        unsigned flat_bits;
 #endif
@@ -1302,8 +1307,22 @@ bool encoder_set_partitioned_rice_(const uint32 abs_residual[], const uint32 abs
        if(partition_order == 0) {
                unsigned i;
 
-               partition_bits = 0;
+#if 0
+               /*@@@ pending @@@*/
+               if(rice_parameter_search_dist) {
+                       if(rice_parameter < rice_parameter_search_dist)
+                               min_rice_parameter = 0;
+                       else
+                               min_rice_parameter = rice_parameter - rice_parameter_search_dist;
+                       max_rice_parameter = rice_parameter + rice_parameter_search_dist;
+                       if(max_rice_parameter >= FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER)
+                               max_rice_parameter = FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER - 1;
+               }
+               else
+                       min_rice_parameter = max_rice_parameter = rice_parameter;
+#endif
 
+               partition_bits = 0;
                {
 #ifdef VARIABLE_RICE_BITS
 #ifdef FLAC__SYMMETRIC_RICE
@@ -1380,6 +1399,22 @@ mean>>=1;
                                parameter = max_parameter;
                        if(parameter >= FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER)
                                parameter = FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER - 1;
+
+#if 0
+                       /*@@@ pending @@@*/
+                       if(rice_parameter_search_dist) {
+                               if(parameter < rice_parameter_search_dist)
+                                       min_rice_parameter = 0;
+                               else
+                                       min_rice_parameter = parameter - rice_parameter_search_dist;
+                               max_rice_parameter = parameter + rice_parameter_search_dist;
+                               if(max_rice_parameter >= FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER)
+                                       max_rice_parameter = FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER - 1;
+                       }
+                       else
+                               min_rice_parameter = max_rice_parameter = rice_parameter;
+#endif
+
                        parameters[i] = parameter;
                        partition_bits += FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_PARAMETER_LEN;
 #ifdef VARIABLE_RICE_BITS