#ifndef VALIB_RESAMPLE_H
#define VALIB_RESAMPLE_H

#include "../filter.h"
#if RESAMPLE_PERF
#include "../win32\cpu.h"
#endif

class Resample : public NullFilter
{
protected:
  
  double a;   
  double q;   

  int fs;     
  int fd;     
  int nch;    
  double rate;

  
  int g;      
  int l, m;   
  int l1, l2; 
  int m1, m2; 

  
  int n1, n1x, n1y; 
  int c1, c1x, c1y; 
  sample_t **f1;    
  sample_t *f1_raw; 
  int *order;       

  
  int n2, n2b;      
  int c2;           
  sample_t *f2;     

  
  int      *fft_ip;
  sample_t *fft_w;

  
  int pos_l, pos_m;            
  int pos1;                    
  sample_t *buf1[NCHANNELS];   
  sample_t *buf2[NCHANNELS];   
  sample_t *delay2[NCHANNELS]; 
  int shift;                   
  int pre_samples;             
  int post_samples;            

  int init_resample(int _nch, int _fs, int _fd);
  void uninit_resample();

  
  
  
  inline int stage1_in(int n)  const { return (n + pos_l) * m1 / l1 - pos_m; }
  inline int stage1_out(int n) const { return ((pos_m + n) * l1 + m1 - 1) / m1 - (pos_m * l1 + m1 - 1) / m1; }

  inline void do_stage1(sample_t *in[], sample_t *out[], int n_in, int n_out);
  inline void do_stage2();
  inline void drop_pre_samples();

  void reset_resample();
  int process_resample(sample_t *in_buf[], int nsamples);
  bool flush_resample();

protected:
  int sample_rate;       

  Speakers  out_spk;     
  samples_t out_samples; 
  int       out_size;    

#if RESAMPLE_PERF
public:
  CPUMeter stage1;
  CPUMeter stage2;
#endif

public:
  Resample();
  Resample(int sample_rate, double a = 100, double q = 0.99);
  ~Resample();

  
  

  bool set(int sample_rate, double a = 100, double q = 0.99);
  void get(int *sample_rate, double *a = 0, double *q = 0);

  bool set_sample_rate(int _sample_rate) { return set(_sample_rate, a, q); }
  int get_sample_rate() const { return sample_rate; };

  bool set_attenuation(double _a) { return set(sample_rate, _a, q); }
  double get_attenuation() const { return a; }

  bool set_quality(double _q) { return set(sample_rate, a, _q); }
  double get_quality() const { return q; }

  
  

  virtual void reset();
  virtual bool set_input(Speakers spk);
  virtual Speakers get_output() const;
  virtual bool get_chunk(Chunk *chunk);
};

#endif
