/**************************************************************************

This software module was originally developed by
Nokia in the course of development of the MPEG-2 AAC/MPEG-4 
Audio standard ISO/IEC13818-7, 14496-1, 2 and 3.
This software module is an implementation of a part
of one or more MPEG-2 AAC/MPEG-4 Audio tools as specified by the
MPEG-2 aac/MPEG-4 Audio standard. ISO/IEC  gives users of the
MPEG-2aac/MPEG-4 Audio standards free license to this software module
or modifications thereof for use in hardware or software products
claiming conformance to the MPEG-2 aac/MPEG-4 Audio  standards. Those
intending to use this software module in hardware or software products
are advised that this use may infringe existing patents. The original
developer of this software module, the subsequent
editors and their companies, and ISO/IEC have no liability for use of
this software module or modifications thereof in an
implementation. Copyright is not released for non MPEG-2 aac/MPEG-4
Audio conforming products. The original developer retains full right to
use the code for the developer's own purpose, assign or donate the code to a
third party and to inhibit third party from using the code for non
MPEG-2 aac/MPEG-4 Audio conforming products. This copyright notice
must be included in all copies or derivative works.
Copyright (c)1997.  

***************************************************************************/
/**************************************************************************
  nok_ltp_enc.c  -  Performs Long Term Prediction for the MPEG-4 
                    T/F Encoder.
  Author(s): Mikko Suonio, Juha Ojanperä
  	     Nokia Research Center, Speech and Audio Systems, 1997.
  *************************************************************************/


/**************************************************************************
  Version Control Information			Method: CVS
  Identifiers:
  $Revision: 1.4 $
  $Date: 1997/11/13 16:37:01 $ (check in)
  $Author: purnhage $
  *************************************************************************/



/**************************************************************************
  External Objects Needed
  *************************************************************************/
/*
  Standard library declarations.  */
#include <stdio.h>

/*
  Interface to related modules.  */
#include "tf_main.h"
#include "interface.h"
#include "bitstream.h"

/*
  Macro:	PRINT
  Purpose:	Interface to function for printing error messages.  */

/*
  Purpose:	Provided debug options.
  Explanation:	If element debug['p'] is true, we give debug information
  		on long term prediction.  */
extern int debug[];

/*
  Purpose:	Modified discrete cosine transform
  Input:	p_in_data[]	- input signal (length: 2*shift length)
		p_overlap[]	- buffer containing the previous frame
				  in OVERLAPPED-mode (length: 2*shift length)
		block_type	- selects the type of window to use
  		wfun_select	- select window function
  		nlong		- shift length for long windows
                nmed		- shift length for medium windows
		nshort		- shift length for short windows
		overlap_select	- OVERLAPPED-mode select
		num_short_win	- number of short windows to transform
		save_window	- if true, save the block_type
				  for future use
  Output:	p_out_mdct[]	- transformed signal (length: shift length)
		p_overlap[]	- a copy of p_in_data in OVERLAPPED-mode
  				  (length: shift length)
  Explanation:	-  */
extern void buffer2freq (double p_in_data[], double p_out_mdct[],
			 double p_overlap[], WINDOW_TYPE block_type,
			 Window_shape wfun_select, int nlong, int nmed,
			 int nshort, Mdct_in overlap_select,
			 int num_short_win, int save_window);

/*
  Purpose:	Inverse of modified discrete cosine transform
  Input:	p_in_data[]	- input signal (length: shift length)
		p_overlap[]	- the overlap buffer; does not have
				  an effect in NON_OVERLAPPED-mode,
				  but have to be allocated
				  (length: shift length)
		block_type	- selects the type of window to use
  		nlong		- shift length for long windows
                nmed		- shift length for medium windows
		nshort		- shift length for short windows
  		wfun_select	- select window function
		overlap_select	- OVERLAPPED-mode select
		num_short_win	- number of short windows to transform
 		save_window	- if true, save block_type for future use
  Output:	p_out_data[]	- transformed signal (length: 2*shift length)
		p_overlap[]	- the overlap buffer; always modified
				  (length: shift length)
  Explanation:	-  */
void freq2buffer (double p_in_data[], double p_out_data[], double p_overlap[],
		  WINDOW_TYPE block_type, int nlong, int nmed, int nshort,
		  Window_shape wfun_select, Window_shape fun_select_prev,
		  Imdct_out overlap_select, int num_short_win);	/* YB : 971113 */

/*
  Function:	BsPutBit
  Purpose:	Writes specified number of bits to the open
  		output bitstream.  */



/**************************************************************************
  External Objects Provided
  *************************************************************************/
#include "nok_ltp_enc.h"
#include "nok_pitch.h"



/**************************************************************************
  Internal Objects
  *************************************************************************/
/*
  Purpose:	Length of the bitstream element ltp_data_present.  */
#define	LEN_LTP_DATA_PRESENT 1

/*
  Purpose:	Length of the bitstream element ltp_lag.  */
#define	LEN_LTP_LAG 11

/*
  Purpose:	Length of the bitstream element ltp_coef.  */
#define	LEN_LTP_COEF 3

/*
  Purpose:	Length of the bitstream element ltp_short_used.  */
#define	LEN_LTP_SHORT_USED 1

/*
  Purpose:	Length of the bitstream element ltp_short_lag_present.  */
#define	LEN_LTP_SHORT_LAG_PRESENT 1

/*
  Purpose:	Length of the bitstream element ltp_short_lag.  */
#define	LEN_LTP_SHORT_LAG 5

/*
  Purpose:	Offset of the lags written in the bitstream.  */
#define	NOK_LTP_LAG_OFFSET 16

/*
  Purpose:	Length of the bitstream element ltp_long_used.  */
#define	LEN_LTP_LONG_USED 1

/*
  Purpose:	Upper limit for the number of scalefactor bands
   		which can use lt prediction with long windows.
  Explanation:	Bands 0..NOK_MAX_LT_PRED_SFB-1 can use lt prediction.  */
#define	NOK_MAX_LT_PRED_LONG_SFB 40

/*
  Purpose:	Upper limit for the number of scalefactor bands
   		which can use lt prediction with short windows.
  Explanation:	Bands 0..NOK_MAX_LT_PRED_SFB-1 can use lt prediction.  */
#define	NOK_MAX_LT_PRED_SHORT_SFB 13

/*
   Purpose:      Buffer offset to maintain block alignment.
   Explanation:  This is only used for a short window sequence.  */
#define SHORT_SQ_OFFSET (BLOCK_LEN_LONG-(BLOCK_LEN_SHORT*4+BLOCK_LEN_SHORT/2))

/*
  Purpose:	Number of codes for LTP weight. */
#define CODESIZE 8

/*
  Purpose:	Codebook for LTP weight coefficients.  */
static double codebook[CODESIZE] =
{
  {0.570829},
  {0.696616},
  {0.813004},
  {0.911304},
  {0.984900},
  {1.067894},
  {1.194601},
  {1.369533}
};


static short double_to_int (double sig_in);



/**************************************************************************
  Object Definitions
  *************************************************************************/



/**************************************************************************
  Title:	nok_init_lt_pred

  Purpose:	Initialize the history buffer for long term prediction

  Usage:        nok_init_lt_pred (lt_status)

  Input:	lt_status
  			- buffer: history buffer
                        - weight_idx : 
                          3 bit number indicating the LTP coefficient in 
                          the codebook 
                        - sbk_prediction_used: 
                          1 bit for each subblock indicating wheather
                          LTP is used in that subblock 
                        - sfb_prediction_used:
                          1 bit for each scalefactor band (sfb) where LTP 
                          can be used indicating whether LTP is switched 
                          on (1) /off (0) in that sfb.
                        - delay: LTP lag
                        - side_info: LTP side information

  Output:	lt_status
  			- buffer: filled with 0
                        - weight_idx : filled with 0
                        - sbk_prediction_used: filled with 0
                        - sfb_prediction_used: filled with 0
                        - delay: filled with 0
                        - side_info: filled with 1

  References:	-

  Explanation:	-

  Author(s):	Mikko Suonio
  *************************************************************************/
void
nok_init_lt_pred (NOK_LT_PRED_STATUS *lt_status)
{
  int i;

  for (i = 0; i < NOK_LT_BLEN; i++)
    lt_status->buffer[i] = 0;

  lt_status->weight_idx = 0;
  for(i=0; i<NSHORT; i++)
    lt_status->sbk_prediction_used[i] = lt_status->delay[i] = 0;

  for(i=0; i<MAXBANDS; i++)
    lt_status->sfb_prediction_used[i] = 0;

  lt_status->side_info = 1;
}



/**************************************************************************
  Title:	nok_ltp_enc

  Purpose:      Performs long term prediction.

  Usage:	nok_ltp_enc(p_spectrum, p_time_signal, win_type, win_shape, 
                            sfb_offset, num_of_sfb, lt_status, buffer_update)

  Input:        p_spectrum    - spectral coefficients
                p_time_signal - input samples
                win_type      - window sequence (frame, block) type
                win_shape     - shape of the mdct window
                sfb_offset    - scalefactor band boundraries
                num_of_sfb    - number of scalefactor bands 
                buffer_update - if set then the history buffer is updated

  Output:	p_spectrum    - error/reconstructed spectrum
                lt_status     - buffer: history buffer
                              - weight_idx : 
                                3 bit number indicating the LTP coefficient in 
                                the codebook 
                              - sbk_prediction_used: 
                                1 bit for each subblock indicating wheather
                                LTP is used in that subblock 
                              - sfb_prediction_used:
                                1 bit for each scalefactor band (sfb) where LTP 
                                can be used indicating whether LTP is switched 
                                on (1) /off (0) in that sfb.
                              - delay: LTP lag
                              - side_info: LTP side information
                        
  References:	1.) estimate_delay in nok_pitch.c
                2.) pitch in nok_pitch.c
                3.) buffer2freq
                4.) snr_pred in nok_pitch.c
                5.) freq2buffer
                6.) double_to_int

  Explanation:  When 'buffer_update' is 1 then the history buffer is updated
                and 'p_spectrum' is the reconstructed spectrum, otherwise
                'p_spectrum' is the error spectrum.

  Author(s):	Juha Ojanpera
  *************************************************************************/

int
nok_ltp_enc(double *p_spectrum, double *p_time_signal, WINDOW_TYPE win_type, 
            Window_shape win_shape, int *sfb_offset, int num_of_sfb,
            NOK_LT_PRED_STATUS *lt_status, int buffer_update)
{
    int i, j, sw, msw;
    int last_band, op_delay, max_side_info;
    int temp_weight_idx[MAX_SHORT_WINDOWS];
    double max_bits, total_bit;
    double *time_signal;
    double num_bit[MAX_SHORT_WINDOWS];
    double predicted_samples[2 * BLOCK_LEN_LONG];
    double overlap_buffer[2 * BLOCK_LEN_LONG];
    static double mdct_predicted[2 * BLOCK_LEN_LONG];
	static Window_shape win_shape_prev[2]={WS_FHG, WS_FHG};	/* YB : 971113 */


    switch(buffer_update)
    {
      case 0:        
        switch(win_type)
        {
          case ONLY_LONG_WINDOW:
	  case LONG_SHORT_WINDOW:
	  case SHORT_LONG_WINDOW:
            last_band = (num_of_sfb < NOK_MAX_LT_PRED_LONG_SFB) ? num_of_sfb : NOK_MAX_LT_PRED_LONG_SFB;

            lt_status->delay[0] = estimate_delay (p_time_signal, lt_status->buffer, 2 * BLOCK_LEN_LONG);

            /*fprintf(stdout, "(LTP) lag : %i ", lt_status->delay[0]);*/

            pitch (p_time_signal, predicted_samples, lt_status->buffer, 
                   &lt_status->weight_idx, lt_status->delay[0], 2 * BLOCK_LEN_LONG);

            /* Transform prediction to frequency domain. */
            buffer2freq (predicted_samples, mdct_predicted, NULL, win_type,
                         win_shape, BLOCK_LEN_LONG, BLOCK_LEN_MEDIUM,
                         BLOCK_LEN_SHORT, NON_OVERLAPPED, 1, 0);
          
            lt_status->side_info = 1 + last_band + LEN_LTP_LAG + LEN_LTP_COEF;
            
            num_bit[0] = snr_pred (p_spectrum, mdct_predicted,
                                   lt_status->sfb_prediction_used, sfb_offset, 
                                   win_type, lt_status->side_info, last_band);

            /*fprintf(stdout, " bit gain : %f\n", num_bit[0]);*/
          
            lt_status->global_pred_flag = (num_bit[0] == 0.0) ? 0 : 1;
	  
            if(lt_status->global_pred_flag)
              for (i = 0; i < sfb_offset[last_band]; i++)
                p_spectrum[i] -= mdct_predicted[i];
            else
              lt_status->side_info = 1;

            break;

          case ONLY_SHORT_WINDOW:
            last_band = (num_of_sfb < NOK_MAX_LT_PRED_SHORT_SFB) ? num_of_sfb : NOK_MAX_LT_PRED_SHORT_SFB;

            total_bit = 0;
            for (sw = 0; sw < MAX_SHORT_WINDOWS; sw++)
            {
              time_signal = p_time_signal + SHORT_SQ_OFFSET +  BLOCK_LEN_SHORT * sw;
              lt_status->delay[sw] = estimate_delay (time_signal, lt_status->buffer, 2 * BLOCK_LEN_SHORT);

              pitch (time_signal, predicted_samples, lt_status->buffer,
                     temp_weight_idx + sw, lt_status->delay[sw], 2 * BLOCK_LEN_SHORT);

              /* Transform prediction to frequency domain. */
              buffer2freq (predicted_samples, mdct_predicted, NULL, win_type,
                           win_shape, BLOCK_LEN_LONG, BLOCK_LEN_MEDIUM,
                           BLOCK_LEN_SHORT, NON_OVERLAPPED, 1, 0);

              lt_status->side_info = 1 + last_band + LEN_LTP_LAG + LEN_LTP_COEF;

              num_bit[sw] = snr_pred (p_spectrum + BLOCK_LEN_SHORT * sw, mdct_predicted,
                                      lt_status->sfb_prediction_used + last_band * sw, 
                                      sfb_offset, win_type, lt_status->side_info, last_band);

              total_bit += num_bit[sw];

              /*fprintf (stdout, "idealsubbits : %2i%5i%10f\n", sw, lt_status->delay[sw], num_bit[sw]);*/
            }

            /*fprintf (stdout, "total idealsubbits %f\n\n", total_bit);*/

            max_bits = 0;
            for (sw = 0; sw < MAX_SHORT_WINDOWS; sw++)
              if (max_bits <= num_bit[sw])
              {
                max_bits = num_bit[sw];
                msw = sw;
              }

            op_delay = lt_status->delay[msw];
            for (sw = 0; sw < MAX_SHORT_WINDOWS; sw++)
            {
              double temp;
              
              temp = op_delay - lt_status->delay[sw] + NOK_LTP_LAG_OFFSET;
              if (temp > (2 * NOK_LTP_LAG_OFFSET - 1) || temp < 0)
                lt_status->delay[sw] = op_delay;
            }

            for(i = 0; i < MAX_SHORT_WINDOWS; i++)
              lt_status->sbk_prediction_used[i] = 0;

            lt_status->weight_idx = temp_weight_idx[msw];
            max_side_info = 1;
            lt_status->global_pred_flag = 0;

            for (sw = 0; sw < MAX_SHORT_WINDOWS; sw++)
	    {
	      if (!lt_status->global_pred_flag)
		lt_status->side_info = last_band + LEN_LTP_LAG + LEN_LTP_COEF;
	      else
              {
                lt_status->side_info = last_band +  LEN_LTP_SHORT_LAG_PRESENT + LEN_LTP_COEF;
                if(lt_status->delay[sw-1] - lt_status->delay[sw])
                  lt_status->side_info += LEN_LTP_SHORT_LAG;
              }

	      prediction (lt_status->buffer, predicted_samples, &codebook[lt_status->weight_idx],
			  lt_status->delay[sw], 2 * BLOCK_LEN_SHORT);

              /* Transform prediction to frequency domain. */
              buffer2freq (predicted_samples, mdct_predicted + BLOCK_LEN_SHORT * sw, NULL, 
                           win_type, win_shape, BLOCK_LEN_LONG, BLOCK_LEN_MEDIUM,
                           BLOCK_LEN_SHORT, NON_OVERLAPPED, 1, 0);

              num_bit[sw] = snr_pred (p_spectrum + BLOCK_LEN_SHORT * sw, 
                                      mdct_predicted + BLOCK_LEN_SHORT * sw,
                                      lt_status->sfb_prediction_used + last_band * sw,
                                      sfb_offset, win_type, lt_status->side_info, last_band);

              /*fprintf (stdout, "subbits : %2i%10f\n", sw, num_bit[sw]);*/

              lt_status->sbk_prediction_used[sw] = 0;
	      if (num_bit[sw])
              {
                lt_status->global_pred_flag = 1;
                lt_status->sbk_prediction_used[sw] = 1;
                max_side_info +=lt_status->side_info;
              }

              if(lt_status->sbk_prediction_used[sw])
                for (i = 0; i < sfb_offset[last_band]; i++)
                  p_spectrum[sw * BLOCK_LEN_SHORT + i] -= mdct_predicted[sw * BLOCK_LEN_SHORT + i];
            }
            
            total_bit = 0.0;
            for (i = 0; i < MAX_SHORT_WINDOWS; i++)
              total_bit += num_bit[i];

            if (lt_status->global_pred_flag)
              lt_status->side_info = max_side_info + MAX_SHORT_WINDOWS;
            else
              lt_status->side_info = 1;

            /*fprintf (stdout, "total subbits %f\n\n", total_bit);*/

            break;
	default:
	  break;
        }
        break;
        
      case 1:

        switch(win_type)
        {
          case ONLY_LONG_WINDOW:
	  case LONG_SHORT_WINDOW:
	  case SHORT_LONG_WINDOW:
            last_band = (num_of_sfb < NOK_MAX_LT_PRED_LONG_SFB) ? num_of_sfb : NOK_MAX_LT_PRED_LONG_SFB;
    
            if(lt_status->global_pred_flag)
              for (i = 0; i < sfb_offset[last_band]; i++)
                p_spectrum[i] += mdct_predicted[i];

            /* Finally update the time domain history buffer. */
            freq2buffer (p_spectrum, predicted_samples, overlap_buffer, win_type,
                         BLOCK_LEN_LONG, BLOCK_LEN_MEDIUM, BLOCK_LEN_SHORT,
                         win_shape, win_shape_prev[0], NON_OVERLAPPED, 1);

            for (i = 0; i < NOK_LT_BLEN - BLOCK_LEN_LONG; i++)
              lt_status->buffer[i] = lt_status->buffer[i + BLOCK_LEN_LONG];

            j = NOK_LT_BLEN - 2 * BLOCK_LEN_LONG;
            for (i = 0; i < BLOCK_LEN_LONG; i++)
            {
              lt_status->buffer[i + j] =
                  double_to_int (predicted_samples[i] + lt_status->buffer[i + j]);
              lt_status->buffer[NOK_LT_BLEN - BLOCK_LEN_LONG + i] =
                  double_to_int (predicted_samples[i + BLOCK_LEN_LONG]);
            }
            break;

          case ONLY_SHORT_WINDOW:
            last_band = (num_of_sfb < NOK_MAX_LT_PRED_SHORT_SFB) ? num_of_sfb : NOK_MAX_LT_PRED_SHORT_SFB;

            for (i = 0; i < NOK_LT_BLEN - BLOCK_LEN_LONG; i++)
              lt_status->buffer[i] = lt_status->buffer[i + BLOCK_LEN_LONG];

            for (i = NOK_LT_BLEN - BLOCK_LEN_LONG; i < NOK_LT_BLEN; i++)
              lt_status->buffer[i] = 0;

            for(sw = 0; sw < MAX_SHORT_WINDOWS; sw++)
            {
              if(lt_status->sbk_prediction_used[sw])
                for (i = 0; i < sfb_offset[last_band]; i++)
                  p_spectrum[sw * BLOCK_LEN_SHORT + i] += mdct_predicted[sw * BLOCK_LEN_SHORT + i];
 
              /* Finally update the time domain history buffer. */
              freq2buffer (p_spectrum + sw * BLOCK_LEN_SHORT, predicted_samples, 
                           overlap_buffer, win_type, BLOCK_LEN_LONG, BLOCK_LEN_MEDIUM, 
                           BLOCK_LEN_SHORT, win_shape, win_shape_prev[0], NON_OVERLAPPED, 1);

              i = NOK_LT_BLEN - 2 * BLOCK_LEN_LONG + SHORT_SQ_OFFSET + sw * BLOCK_LEN_SHORT;
              for (j = 0; j < 2 * BLOCK_LEN_SHORT; j++)
                lt_status->buffer[i + j] = double_to_int (predicted_samples[j] + lt_status->buffer[i + j]);
            }
            break;
	default:
	  break;
        }
        break;
    }
    
    return (lt_status->global_pred_flag);
}


/**************************************************************************
  Title:	nok_ltp_encode

  Purpose:      Writes LTP parameters to the bit stream.

  Usage:	nok_ltp_encode (bs, win_type, num_of_sfb, lt_status)

  Input:        bs         - bit stream
                win_type   - window sequence (frame, block) type
                num_of_sfb - number of scalefactor bands
                lt_status  - side_info:
			     1, if prediction not used in this frame
			     >1 otherwise
                           - weight_idx : 
                             3 bit number indicating the LTP coefficient in 
                             the codebook 
                           - sfb_prediction_used:
                             1 bit for each scalefactor band (sfb) where LTP 
                             can be used indicating whether LTP is switched 
                             on (1) /off (0) in that sfb.
                           - delay: LTP lag

  Output:	-

  References:	1.) BsPutBit

  Explanation:  -

  Author(s):	Juha Ojanpera
  *************************************************************************/

void
nok_ltp_encode (BsBitStream *bs, WINDOW_TYPE win_type, int num_of_sfb, 
                NOK_LT_PRED_STATUS *lt_status)
{
  int i, j, last_band;
  int first_subblock;
  int prev_subblock;


  if (lt_status->side_info > 1)
  {
    BsPutBit (bs, 1, 1);    	/* LTP used */

    switch(win_type)
    {
      case ONLY_LONG_WINDOW:
      case LONG_SHORT_WINDOW:
      case SHORT_LONG_WINDOW:
        BsPutBit (bs, lt_status->delay[0], LEN_LTP_LAG);
        BsPutBit (bs, lt_status->weight_idx,  LEN_LTP_COEF);

        last_band = (num_of_sfb < NOK_MAX_LT_PRED_LONG_SFB) ? num_of_sfb : NOK_MAX_LT_PRED_LONG_SFB;
        for (i = 0; i < last_band; i++)
          BsPutBit (bs, lt_status->sfb_prediction_used[i], LEN_LTP_LONG_USED);
        break;
        
      case ONLY_SHORT_WINDOW:
        last_band = (num_of_sfb < NOK_MAX_LT_PRED_SHORT_SFB) ? num_of_sfb : NOK_MAX_LT_PRED_SHORT_SFB;
        for(i=0; i < MAX_SHORT_WINDOWS; i++)
        {
          if(lt_status->sbk_prediction_used[i])
          {
            first_subblock = i;
            break;
          }
        }
        BsPutBit (bs, lt_status->delay[first_subblock], LEN_LTP_LAG);
        BsPutBit (bs, lt_status->weight_idx,  LEN_LTP_COEF);

        prev_subblock = first_subblock;
        for(i = 0; i < MAX_SHORT_WINDOWS; i++)
        {
          BsPutBit (bs, lt_status->sbk_prediction_used[i], LEN_LTP_SHORT_USED);
          if(lt_status->sbk_prediction_used[i])
          {
            if(i > first_subblock)
            {
              int diff;
            
              diff = lt_status->delay[prev_subblock] - lt_status->delay[i];
              if(diff)
              {
                BsPutBit (bs, 1, 1);
                BsPutBit (bs, diff + NOK_LTP_LAG_OFFSET, LEN_LTP_SHORT_LAG);
              }
              else
                BsPutBit (bs, 0, 1);
            }
          }
        }  
        break;

      default:
        CommonExit(1, "nok_ltp_encode : unsupported window sequence %i", win_type);
        break;
    }
  }
  else
    BsPutBit (bs, 0, 1);    	/* LTP not used */
}


/**************************************************************************
  Title:	double_to_int

  Purpose:      Converts floating point format to integer (16-bit).

  Usage:	y = double_to_int(sig_in)

  Input:	sig_in  - floating point number

  Output:	y  - integer number

  References:	-

  Explanation:  -

  Author(s):	Juha Ojanpera
  *************************************************************************/

static short
double_to_int (double sig_in)
{
  short sig_out;


  if (sig_in > 32767)
    sig_out = 32767;
  else if (sig_in < -32768)
    sig_out = -32768;
  else if (sig_in > 0.0)
    sig_out = (short) (sig_in + 0.5);
  else if (sig_in <= 0.0)
    sig_out = (short) (sig_in - 0.5);

  return (sig_out);
}

