////////////////////////////////////////////////////////////////////////////
//			     **** WAVPACK ****				  //
//		    Hybrid Lossless Wavefile Compressor			  //
//		Copyright (c) 1998 - 2004 Conifer Software.		  //
//			    All Rights Reserved.			  //
//      Distributed under the BSD Software License (see license.txt)      //
////////////////////////////////////////////////////////////////////////////

// float.c

#include "wavpack.h"

int read_float_info (WavpackStream *wps, WavpackMetadata *wpmd)
{
    int bytecnt = wpmd->byte_length;
    uchar *byteptr = wpmd->data;

    if (bytecnt != 4)
	return FALSE;

    wps->float_flags = *byteptr++;
    wps->float_shift = *byteptr++;
    wps->float_max_exp = *byteptr++;
    wps->float_norm_exp = *byteptr;
    return TRUE;
}

void float_values (WavpackStream *wps, long *values, long num_values)
{
    while (num_values--) {
	int shift_count = 0, exp = wps->float_max_exp;
	f32 outval = { 0, 0, 0 };

	if (*values) {
	    *values <<= wps->float_shift;

	    if (*values < 0) {
		*values = -*values;
		outval.sign = 1;
	    }

	    if (*values == 0x1000000)
		outval.exponent = 255;
	    else {
		if (exp)
		    while (!(*values & 0x800000) && --exp) {
			shift_count++;
			*values <<= 1;
		    }

		if (shift_count && (wps->float_flags & FLOAT_SHIFT_ONES))
		    *values |= ((1 << shift_count) - 1);

		outval.mantissa = *values;
		outval.exponent = exp;
	    }
	}

	* (f32 *) values++ = outval;
    }
}

void float_normalize (long *values, long num_values, int delta_exp)
{
    f32 *fvalues = (f32 *) values, fzero = { 0, 0, 0 };
    int exp;

    if (!delta_exp)
	return;

    while (num_values--) {
	if ((exp = fvalues->exponent) == 0 || exp + delta_exp <= 0)
	    *fvalues = fzero;
	else if (exp == 255 || (exp += delta_exp) >= 255) {
	    fvalues->exponent = 255;
	    fvalues->mantissa = 0;
	}
	else
	    fvalues->exponent = exp;

	fvalues++;
    }
}
