#ifndef FREQAEC_H_
#define FREQAEC_H_
/*---------------------------------------------------------------------------*/
/* freqaec.h                                                                 */
/* copyright (c) innovaphone 2013                                            */
/*                                                                           */
/*---------------------------------------------------------------------------*/

NAMESPACE_BEGIN

#define FREQAEC_ENABLE_NONLINEAR_PROCESSING     0x0010
#define FREQAEC_FREEZE_COEFFICIENTS             0x0020
#define FREQAEC_ENABLE_COMFORT_NOISE_GENERATION 0x0040

#define FREQAEC_MAX_FRAME_LENGTH_EXP    9
#define FREQAEC_MAX_FRAME_LENGTH        (1 << FREQAEC_MAX_FRAME_LENGTH_EXP)
#define FREQAEC_MAX_TAIL_FRAMES         16


typedef struct freqaec_s
{
    unsigned int frame_length;
    unsigned int tail_frames;
    word options;
    int32 rin_dc_offset;
    int32 sin_dc_offset;
	short rin_frame_buffer[FREQAEC_MAX_FRAME_LENGTH];
	short sin_frame_buffer[FREQAEC_MAX_FRAME_LENGTH];
	short sout_frame_buffer[FREQAEC_MAX_FRAME_LENGTH];
	short filter_result_buffer[FREQAEC_MAX_FRAME_LENGTH];
    union
    {
	    t_complex_short complex[2 * FREQAEC_MAX_FRAME_LENGTH];
        int32 scalar[2 * FREQAEC_MAX_FRAME_LENGTH];
    } fft_buffer_;
    t_complex_short filter_buffer[FREQAEC_MAX_TAIL_FRAMES * FREQAEC_MAX_FRAME_LENGTH];
    short filter_exp[FREQAEC_MAX_TAIL_FRAMES];
    short filter_freq_exp[FREQAEC_MAX_FRAME_LENGTH];
	t_complex_short rin_delay_buffer[FREQAEC_MAX_TAIL_FRAMES * FREQAEC_MAX_FRAME_LENGTH];
    short rin_delay_exp[FREQAEC_MAX_TAIL_FRAMES];
    word rin_energy_buffer[FREQAEC_MAX_TAIL_FRAMES * FREQAEC_MAX_FRAME_LENGTH];
    short rin_energy_exp[FREQAEC_MAX_TAIL_FRAMES * FREQAEC_MAX_FRAME_LENGTH];
    unsigned int rin_sample_counter;
	unsigned int rin_buffer_counter;
    t_complex_short eout_freq_buffer[FREQAEC_MAX_FRAME_LENGTH];
    word rin_energy_sum_buffer[FREQAEC_MAX_FRAME_LENGTH];
    short rin_energy_sum_exp[FREQAEC_MAX_FRAME_LENGTH];
    short eout_freq_exp[FREQAEC_MAX_FRAME_LENGTH];
    short eout_energy_exp[FREQAEC_MAX_FRAME_LENGTH];
    dword min_sqr_loss_enhance;
    dword max_sqr_loss_enhance;
    dword max_sqr_nlp_loss_enhance;
    word min_sqr_nlp_return_loss;
    dword sqr_loss_per_freq_buffer[FREQAEC_MAX_FRAME_LENGTH];
    word attenuations[FREQAEC_MAX_FRAME_LENGTH];
    word shaped_attenuations[FREQAEC_MAX_FRAME_LENGTH];
    word max_loop_gain;
    word last_attenuation;
    word nlp_attenuation;
    dword random_number_seed;
    dword filter_masking_schedule[FREQAEC_MAX_TAIL_FRAMES];
    byte last_dt[FREQAEC_MAX_FRAME_LENGTH];
    word noise_suppress_level;

    dword sout_energy;
    dword gauge_threshold;
    dword rin_energy;
    word rout_attenuation;
    dword rout_gain;

    unsigned int echo_peak_pos;
    dword echo_peak_amplitude;
    const char *trace_tag;
} t_freqaec;


void freqaec_init (t_freqaec *aec, word frame_length, word tail_frames, word options,
    dword nominal_return_loss, word max_loop_gain, word noise_suppress_level);
void freqaec_flush (t_freqaec *aec, word preserve_filter_frames);
short freqaec_exec (t_freqaec *aec, short Rin, short Sin);
short freqaec_r_exec (t_freqaec *aec, short Rin);

NAMESPACE_END

/*---------------------------------------------------------------------------*/
#endif /* FREQAEC_H_ */
