

#ifndef VALIB_MIXER_H
#define VALIB_MIXER_H

#include "../filter.h"
#include "../data.h"


typedef sample_t matrix_t[NCHANNELS][NCHANNELS];





class Mixer : public NullFilter
{
protected:
  
  Speakers out_spk;                  

  
  SampleBuf buf;                     
  size_t nsamples;                   
                                  
  
  bool     auto_matrix;              
  bool     normalize_matrix;         
  bool     voice_control;            
  bool     expand_stereo;            
                                  
  
  sample_t clev;                     
  sample_t slev;                     
  sample_t lfelev;                   

  
  sample_t gain;                     
  sample_t input_gains[NCHANNELS];   
  sample_t output_gains[NCHANNELS];  

  
  matrix_t matrix;                   
  matrix_t m;                        

  void prepare_matrix();

public:
  Mixer(size_t nsamples);

  
  

  virtual bool set_input(Speakers spk);
  virtual Speakers get_output() const;
  virtual bool get_chunk(Chunk *out);

  
  

  
  bool set_output(Speakers spk);

  
  inline bool   is_buffered() const;
  inline size_t get_buffer() const;
  inline void   set_buffer(size_t nsamples);

  
  void calc_matrix();

  
  inline void     get_matrix(matrix_t *matrix);
  inline bool     get_auto_matrix();
  inline bool     get_normalize_matrix();
  inline bool     get_voice_control();
  inline bool     get_expand_stereo();
  inline sample_t get_clev();
  inline sample_t get_slev();
  inline sample_t get_lfelev();
  inline sample_t get_gain();
  inline void     get_input_gains(sample_t input_gains[NCHANNELS]);
  inline void     get_output_gains(sample_t output_gains[NCHANNELS]);

  inline void     set_matrix(matrix_t *matrix);
  inline void     set_auto_matrix(bool auto_matrix);
  inline void     set_normalize_matrix(bool normalize_matrix);
  inline void     set_voice_control(bool voice_control);
  inline void     set_expand_stereo(bool expand_stereo);
  inline void     set_clev(sample_t clev);
  inline void     set_slev(sample_t slev);
  inline void     set_lfelev(sample_t lfelev);
  inline void     set_gain(sample_t gain);
  inline void     set_input_gains(sample_t input_gains[NCHANNELS]);
  inline void     set_output_gains(sample_t output_gains[NCHANNELS]);

  
  void io_mix11(samples_t input, samples_t output, size_t nsamples);
  void io_mix12(samples_t input, samples_t output, size_t nsamples);
  void io_mix13(samples_t input, samples_t output, size_t nsamples);
  void io_mix14(samples_t input, samples_t output, size_t nsamples);
  void io_mix15(samples_t input, samples_t output, size_t nsamples);
  void io_mix16(samples_t input, samples_t output, size_t nsamples);
  void io_mix21(samples_t input, samples_t output, size_t nsamples);
  void io_mix22(samples_t input, samples_t output, size_t nsamples);
  void io_mix23(samples_t input, samples_t output, size_t nsamples);
  void io_mix24(samples_t input, samples_t output, size_t nsamples);
  void io_mix25(samples_t input, samples_t output, size_t nsamples);
  void io_mix26(samples_t input, samples_t output, size_t nsamples);
  void io_mix31(samples_t input, samples_t output, size_t nsamples);
  void io_mix32(samples_t input, samples_t output, size_t nsamples);
  void io_mix33(samples_t input, samples_t output, size_t nsamples);
  void io_mix34(samples_t input, samples_t output, size_t nsamples);
  void io_mix35(samples_t input, samples_t output, size_t nsamples);
  void io_mix36(samples_t input, samples_t output, size_t nsamples);
  void io_mix41(samples_t input, samples_t output, size_t nsamples);
  void io_mix42(samples_t input, samples_t output, size_t nsamples);
  void io_mix43(samples_t input, samples_t output, size_t nsamples);
  void io_mix44(samples_t input, samples_t output, size_t nsamples);
  void io_mix45(samples_t input, samples_t output, size_t nsamples);
  void io_mix46(samples_t input, samples_t output, size_t nsamples);
  void io_mix51(samples_t input, samples_t output, size_t nsamples);
  void io_mix52(samples_t input, samples_t output, size_t nsamples);
  void io_mix53(samples_t input, samples_t output, size_t nsamples);
  void io_mix54(samples_t input, samples_t output, size_t nsamples);
  void io_mix55(samples_t input, samples_t output, size_t nsamples);
  void io_mix56(samples_t input, samples_t output, size_t nsamples);
  void io_mix61(samples_t input, samples_t output, size_t nsamples);
  void io_mix62(samples_t input, samples_t output, size_t nsamples);
  void io_mix63(samples_t input, samples_t output, size_t nsamples);
  void io_mix64(samples_t input, samples_t output, size_t nsamples);
  void io_mix65(samples_t input, samples_t output, size_t nsamples);
  void io_mix66(samples_t input, samples_t output, size_t nsamples);

  void ip_mix11(samples_t samples, size_t nsamples);
  void ip_mix12(samples_t samples, size_t nsamples);
  void ip_mix13(samples_t samples, size_t nsamples);
  void ip_mix14(samples_t samples, size_t nsamples);
  void ip_mix15(samples_t samples, size_t nsamples);
  void ip_mix16(samples_t samples, size_t nsamples);
  void ip_mix21(samples_t samples, size_t nsamples);
  void ip_mix22(samples_t samples, size_t nsamples);
  void ip_mix23(samples_t samples, size_t nsamples);
  void ip_mix24(samples_t samples, size_t nsamples);
  void ip_mix25(samples_t samples, size_t nsamples);
  void ip_mix26(samples_t samples, size_t nsamples);
  void ip_mix31(samples_t samples, size_t nsamples);
  void ip_mix32(samples_t samples, size_t nsamples);
  void ip_mix33(samples_t samples, size_t nsamples);
  void ip_mix34(samples_t samples, size_t nsamples);
  void ip_mix35(samples_t samples, size_t nsamples);
  void ip_mix36(samples_t samples, size_t nsamples);
  void ip_mix41(samples_t samples, size_t nsamples);
  void ip_mix42(samples_t samples, size_t nsamples);
  void ip_mix43(samples_t samples, size_t nsamples);
  void ip_mix44(samples_t samples, size_t nsamples);
  void ip_mix45(samples_t samples, size_t nsamples);
  void ip_mix46(samples_t samples, size_t nsamples);
  void ip_mix51(samples_t samples, size_t nsamples);
  void ip_mix52(samples_t samples, size_t nsamples);
  void ip_mix53(samples_t samples, size_t nsamples);
  void ip_mix54(samples_t samples, size_t nsamples);
  void ip_mix55(samples_t samples, size_t nsamples);
  void ip_mix56(samples_t samples, size_t nsamples);
  void ip_mix61(samples_t samples, size_t nsamples);
  void ip_mix62(samples_t samples, size_t nsamples);
  void ip_mix63(samples_t samples, size_t nsamples);
  void ip_mix64(samples_t samples, size_t nsamples);
  void ip_mix65(samples_t samples, size_t nsamples);
  void ip_mix66(samples_t samples, size_t nsamples);
};







inline bool
Mixer::is_buffered() const
{
  return out_spk.nch() > spk.nch();
}

inline size_t
Mixer::get_buffer() const
{
  return nsamples;
}

inline void 
Mixer::set_buffer(size_t _nsamples)
{
  nsamples = _nsamples;
  if (is_buffered())
    buf.allocate(out_spk.nch(), _nsamples);
}



inline void 
Mixer::get_matrix(matrix_t *_matrix)
{ memcpy(_matrix, matrix, sizeof(matrix_t)); }

inline bool 
Mixer::get_auto_matrix()
{ return auto_matrix; }

inline bool 
Mixer::get_normalize_matrix()
{ return normalize_matrix; }

inline bool 
Mixer::get_voice_control()
{ return voice_control; }

inline bool 
Mixer::get_expand_stereo()
{ return expand_stereo; }

inline sample_t 
Mixer::get_clev()
{ return clev; }

inline sample_t 
Mixer::get_slev()
{ return slev; }

inline sample_t 
Mixer::get_lfelev()
{ return lfelev; }

inline sample_t 
Mixer::get_gain()
{ return gain; }

inline void 
Mixer::get_input_gains(sample_t _input_gains[NCHANNELS])
{ memcpy(_input_gains, input_gains, sizeof(input_gains)); }

inline void 
Mixer::get_output_gains(sample_t _output_gains[NCHANNELS])
{ memcpy(_output_gains, output_gains, sizeof(output_gains)); }


inline void 
Mixer::set_matrix(matrix_t *_matrix)
{
  if (!auto_matrix)
  {
    memcpy(matrix, _matrix, sizeof(matrix_t));
    prepare_matrix();
  }
}

inline void 
Mixer::set_auto_matrix(bool _auto_matrix)
{
  auto_matrix = _auto_matrix;
  if (auto_matrix) calc_matrix();
}

inline void 
Mixer::set_normalize_matrix(bool _normalize_matrix)
{
  normalize_matrix = _normalize_matrix;
  if (auto_matrix) calc_matrix();
}

inline void 
Mixer::set_voice_control(bool _voice_control)
{
  voice_control = _voice_control;
  if (auto_matrix) calc_matrix();
}

inline void 
Mixer::set_expand_stereo(bool _expand_stereo)
{
  expand_stereo = _expand_stereo;
  if (auto_matrix) calc_matrix();
}

inline void 
Mixer::set_clev(sample_t _clev)
{
  clev = _clev;
  if (auto_matrix) calc_matrix();
}

inline void 
Mixer::set_slev(sample_t _slev)
{
  slev = _slev;
  if (auto_matrix) calc_matrix();
}

inline void 
Mixer::set_lfelev(sample_t _lfelev)
{
  lfelev = _lfelev;
  if (auto_matrix) calc_matrix();
}
inline void 
Mixer::set_gain(sample_t _gain)
{
  gain = _gain;
  prepare_matrix();
}

inline void 
Mixer::set_input_gains(sample_t _input_gains[NCHANNELS])
{
  memcpy(input_gains, _input_gains, sizeof(input_gains));
  prepare_matrix();
}

inline void 
Mixer::set_output_gains(sample_t _output_gains[NCHANNELS])
{
  memcpy(output_gains, _output_gains, sizeof(output_gains));
  prepare_matrix();
}

#endif
