diff --git a/src/libFLAC/bitbuffer.c b/src/libFLAC/bitbuffer.c index 041b8357..22bd9088 100644 --- a/src/libFLAC/bitbuffer.c +++ b/src/libFLAC/bitbuffer.c @@ -567,6 +567,67 @@ bool FLAC__bitbuffer_write_symmetric_rice_signed_guarded(FLAC__BitBuffer *bb, in return true; } +static unsigned silog21_(int v) +{ +doit_: + if(v == 0) { + return 0; + } + else if(v > 0) { + unsigned l = 0; + while(v) { + l++; + v >>= 1; + } + return l+1; + } + else if(v == -1) { + return 2; + } + else { + v = -(++v); + goto doit_; + } +} + +bool FLAC__bitbuffer_write_symmetric_rice_signed_escape(FLAC__BitBuffer *bb, int val, unsigned parameter) +{ + unsigned total_bits, val_bits; + uint32 pattern; +unsigned x; + + assert(bb != 0); + assert(bb->buffer != 0); + assert(parameter <= 31); + + val_bits = silog21_(val); + total_bits = 2 + parameter + 5 + val_bits; + +x=bb->total_bits; + if(total_bits <= 32) { + pattern = 3; + pattern <<= (parameter + 5); + pattern |= val_bits; + pattern <<= val_bits; + pattern |= (val & ((1 << val_bits) - 1)); + if(!FLAC__bitbuffer_write_raw_uint32(bb, pattern, total_bits)) + return false; + } + else { + /* write the '-0' escape code first */ + if(!FLAC__bitbuffer_write_raw_uint32(bb, 3u << parameter, 2+parameter)) + return false; + /* write the length */ + if(!FLAC__bitbuffer_write_raw_uint32(bb, val_bits, 5)) + return false; + /* write the value */ + if(!FLAC__bitbuffer_write_raw_int32(bb, val, val_bits)) + return false; + } +fprintf(stderr,"wrote %u bits\n",bb->total_bits-x); + return true; +} + bool FLAC__bitbuffer_write_rice_signed(FLAC__BitBuffer *bb, int val, unsigned parameter) { unsigned total_bits, interesting_bits, msbs, uval; diff --git a/src/libFLAC/encoder.c b/src/libFLAC/encoder.c index 533c31ff..fbbd65ae 100644 --- a/src/libFLAC/encoder.c +++ b/src/libFLAC/encoder.c @@ -1054,19 +1054,45 @@ unsigned encoder_find_best_partition_order_(const int32 residual[], uint32 abs_r return best_residual_bits; } -static unsigned iilog2_(unsigned v) +static unsigned silog21_(int v) +{ +doit_: + if(v == 0) { + return 0; + } + else if(v > 0) { + unsigned l = 0; + while(v) { + l++; + v >>= 1; + } + return l+1; + } + else if(v == -1) { + return 2; + } + else { + v = -(++v); + goto doit_; + } +} + +static unsigned uilog21_(unsigned v) { unsigned l = 0; - assert(v > 0); - while(v >>= 1) + while(v) { l++; + v >>= 1; + } return l; } +const double smult = 3.0; +const unsigned rpdec = 0; + static uint32 get_thresh_(const int32 residual[], const unsigned residual_samples) { double sum, sos, r, stddev, mean; - const double smult = 2.0; unsigned i; uint32 thresh; @@ -1079,7 +1105,7 @@ static uint32 get_thresh_(const int32 residual[], const unsigned residual_sample mean = sum / residual_samples; stddev = sqrt((sos - (sum * sum / residual_samples)) / (residual_samples-1)); thresh = mean+smult*stddev; - thresh = iilog2_(thresh); + thresh = (1u << uilog21_(thresh)) - 1; return thresh; } @@ -1094,11 +1120,10 @@ bool encoder_set_partitioned_rice_(const int32 residual[], const uint32 abs_resi if(partition_order == 0) { unsigned i; +#ifdef SYMMETRIC_RICE uint32 thresh = get_thresh_(residual, residual_samples); - const unsigned rpdec = 1; bool cross = false; -#ifdef SYMMETRIC_RICE for(i=0;i= thresh) { cross = true; @@ -1124,10 +1149,16 @@ bool encoder_set_partitioned_rice_(const int32 residual[], const uint32 abs_resi for(i = 0; i < residual_samples; i++) { #ifdef VARIABLE_RICE_BITS #ifdef SYMMETRIC_RICE - if(cross && abs_residual[i] >= thresh) - bits_ += VARIABLE_RICE_BITS(0, rice_parameter) + 5 + iilog2_(abs_residual) + 1; - else + if(cross) { + unsigned escbits, normbits; + escbits = /* VARIABLE_RICE_BITS(0, rice_parameter) == 0 */ 5 + silog21_(residual[i]); + normbits = VARIABLE_RICE_BITS(abs_residual[i], rice_parameter); + bits += min(escbits, normbits); + } + else { + /*@@@ old way */ bits_ += VARIABLE_RICE_BITS(abs_residual[i], rice_parameter); + } #else bits_ += VARIABLE_RICE_BITS(abs_residual[i], rice_parameter_estimate); #endif diff --git a/src/libFLAC/encoder_framing.c b/src/libFLAC/encoder_framing.c index 244b6825..6a9eba30 100644 --- a/src/libFLAC/encoder_framing.c +++ b/src/libFLAC/encoder_framing.c @@ -19,6 +19,7 @@ #include #include +#include #include "private/encoder_framing.h" #include "private/crc.h" @@ -319,16 +320,100 @@ bool subframe_add_entropy_coding_method_(FLAC__BitBuffer *bb, const FLAC__Entrop return true; } +static unsigned silog21_(int v) +{ +doit_: + if(v == 0) { + return 0; + } + else if(v > 0) { + unsigned l = 0; + while(v) { + l++; + v >>= 1; + } + return l+1; + } + else if(v == -1) { + return 2; + } + else { + v = -(++v); + goto doit_; + } +} + +static unsigned uilog21_(unsigned v) +{ + unsigned l = 0; + while(v) { + l++; + v >>= 1; + } + return l; +} + +extern const double smult; + +static uint32 get_thresh_(const int32 residual[], const unsigned residual_samples) +{ + double sum, sos, r, stddev, mean; + unsigned i; + uint32 thresh; + + sum = sos = 0.0; + for(i = 0; i < residual_samples; i++) { + r = (double)residual[i]; + sum += r; + sos += r*r; + } + mean = sum / residual_samples; + stddev = sqrt((sos - (sum * sum / residual_samples)) / (residual_samples-1)); + thresh = mean+smult*stddev; + thresh = (1u << uilog21_(thresh)) - 1; + return thresh; +} + bool subframe_add_residual_partitioned_rice_(FLAC__BitBuffer *bb, const int32 residual[], const unsigned residual_samples, const unsigned predictor_order, const unsigned rice_parameters[], const unsigned partition_order) { if(partition_order == 0) { unsigned i; +#ifdef SYMMETRIC_RICE + uint32 thresh = get_thresh_(residual, residual_samples); + bool cross = false; + + for(i=0;i= thresh) { + cross = true; + break; + } + } +#endif + if(!FLAC__bitbuffer_write_raw_uint32(bb, rice_parameters[0], FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_PARAMETER_LEN)) return false; for(i = 0; i < residual_samples; i++) { #ifdef SYMMETRIC_RICE - if(!FLAC__bitbuffer_write_symmetric_rice_signed(bb, residual[i], rice_parameters[0])) - return false; + if(cross) { + unsigned escbits, normbits; + uint32 a = (residual[i] < 0? -residual[i] : residual[i]); + escbits = 5 + silog21_(residual[i]); + normbits = a >> rice_parameters[0]; + if(escbits < normbits) { +fprintf(stderr,"ESCAPE, k=%u, r=%d, saved %u bits\n", rice_parameters[0], residual[i], normbits-escbits); + if(!FLAC__bitbuffer_write_symmetric_rice_signed_escape(bb, residual[i], rice_parameters[0])) + return false; + } + else { + if(!FLAC__bitbuffer_write_symmetric_rice_signed(bb, residual[i], rice_parameters[0])) + return false; + } + } + else { + if(!FLAC__bitbuffer_write_symmetric_rice_signed(bb, residual[i], rice_parameters[0])) + return false; + } #else if(!FLAC__bitbuffer_write_rice_signed(bb, residual[i], rice_parameters[0])) return false;