+static float wv_get_value_float(WavpackContext *s, uint32_t *crc, int S)
+{
+ union {
+ float f;
+ uint32_t u;
+ } value;
+
+ int sign;
+ int exp = s->float_max_exp;
+
+ if(s->got_extra_bits){
+ const int max_bits = 1 + 23 + 8 + 1;
+ const int left_bits = s->gb_extra_bits.size_in_bits - get_bits_count(&s->gb_extra_bits);
+
+ if(left_bits + 8 * FF_INPUT_BUFFER_PADDING_SIZE < max_bits)
+ return 0.0;
+ }
+
+ if(S){
+ S <<= s->float_shift;
+ sign = S < 0;
+ if(sign)
+ S = -S;
+ if(S >= 0x1000000){
+ if(s->got_extra_bits && get_bits1(&s->gb_extra_bits)){
+ S = get_bits(&s->gb_extra_bits, 23);
+ }else{
+ S = 0;
+ }
+ exp = 255;
+ }else if(exp){
+ int shift = 23 - av_log2(S);
+ exp = s->float_max_exp;
+ if(exp <= shift){
+ shift = --exp;
+ }
+ exp -= shift;
+
+ if(shift){
+ S <<= shift;
+ if((s->float_flag & WV_FLT_SHIFT_ONES) ||
+ (s->got_extra_bits && (s->float_flag & WV_FLT_SHIFT_SAME) && get_bits1(&s->gb_extra_bits)) ){
+ S |= (1 << shift) - 1;
+ } else if(s->got_extra_bits && (s->float_flag & WV_FLT_SHIFT_SENT)){
+ S |= get_bits(&s->gb_extra_bits, shift);
+ }
+ }
+ }else{
+ exp = s->float_max_exp;
+ }
+ S &= 0x7fffff;
+ }else{
+ sign = 0;
+ exp = 0;
+ if(s->got_extra_bits && (s->float_flag & WV_FLT_ZERO_SENT)){
+ if(get_bits1(&s->gb_extra_bits)){
+ S = get_bits(&s->gb_extra_bits, 23);
+ if(s->float_max_exp >= 25)
+ exp = get_bits(&s->gb_extra_bits, 8);
+ sign = get_bits1(&s->gb_extra_bits);
+ }else{
+ if(s->float_flag & WV_FLT_ZERO_SIGN)
+ sign = get_bits1(&s->gb_extra_bits);
+ }
+ }
+ }
+
+ *crc = *crc * 27 + S * 9 + exp * 3 + sign;
+
+ value.u = (sign << 31) | (exp << 23) | S;
+ return value.f;
+}
+