/*---------------------------------------------------------------------------*/
/*
  File: gain.h

  Gain linear and decibel.
*/
/*---------------------------------------------------------------------------*/

#ifndef GAIN_H_
#define GAIN_H_

#ifdef __cplusplus
extern "C" {
#endif
/*---------------------------------------------------------------------------*/

void gain_exec(dword gain, word limit, const short *in_samples, short *out_samples, word sample_count);

typedef struct gain_peak_limited_s
{
    t_peak_limiter limiter;
    dword gain;
    word limit;
} t_gain_peak_limited;

void gain_peak_limited_init(t_gain_peak_limited * p_gainlim, dword gain, word limit);
void gain_peak_limited_exec(t_gain_peak_limited * p_gainlim, const short *in_samples, short *out_samples, word sample_count);

typedef struct gain_dynamic_compressed_s
{
    t_dynamic_compressor compressor;
    dword gain;
    word threshold;
    word norm;
} t_gain_dynamic_compressed;

void gain_dynamic_compressed_init(t_gain_dynamic_compressed * p_gaincompr, dword gain, word threshold, bool noise_suppress);
void gain_dynamic_compressed_exec(t_gain_dynamic_compressed * p_gaincompr, const short *in_samples, short *out_samples, word sample_count);

extern char gain_db_exp_table[0x80];
extern word gain_db_mant_coarse_table[0x100];
extern word gain_db_mant_fine_table[0x100];

#define GAIN_DB_EXP(db_256th) (gain_db_exp_table[((db_256th) >> 9) + 0x40])
#define GAIN_DB_MANT_COARSE(db_256th) (gain_db_mant_coarse_table[((db_256th) >> 8) + 0x80])
#define GAIN_DB_MANT(db_256th) ((word)(((dword)(((dword)(GAIN_DB_MANT_COARSE(db_256th))) * ((dword)(gain_db_mant_fine_table[(db_256th) & 0xff])))) >> 15))

void gain_db_exec(short db_256th, short limit_db_256th, const short *in_samples, short *out_samples, word sample_count);

typedef struct gain_db_peak_limited_s
{
    t_peak_limiter limiter;
    short db_256th;
    short limit_db_256th;
} t_gain_db_peak_limited;

void gain_db_peak_limited_init(t_gain_db_peak_limited * p_gainlim, short db_256th, short limit_db_256th);
void gain_db_peak_limited_exec(t_gain_db_peak_limited * p_gainlim, const short *in_samples, short *out_samples, word sample_count);

typedef struct gain_db_dynamic_compressed_s
{
    t_dynamic_compressor compressor;
    short db_256th;
    short threshold_db_256th;
    word norm;
} t_gain_db_dynamic_compressed;

void gain_db_dynamic_compressed_init(t_gain_db_dynamic_compressed * p_gaincompr, short db_256th, short threshold_db_256th, bool noise_suppress);
void gain_db_dynamic_compressed_exec(t_gain_db_dynamic_compressed * p_gaincompr, const short *in_samples, short *out_samples, word sample_count);

/*---------------------------------------------------------------------------*/
#ifdef __cplusplus
}
#endif

#endif

/*---------------------------------------------------------------------------*/
