/*
  rakarrack - a guitar effects software

 pan.C  -  Auto/Pan -  Extra Stereo
  Copyright (C) 2008-2010 Josep Andreu
  Author: Josep Andreu

 This program is free software; you can redistribute it and/or modify
 it under the terms of version 2 of the GNU General Public License
 as published by the Free Software Foundation.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License (version 2) for more details.

 You should have received a copy of the GNU General Public License
 (version2)  along with this program; if not, write to the Free Software
 Foundation,
 Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA

*/

#include "Pan_.h"

#ifdef SHR3D_SFX_CORE_RAKARRACK

Pan::Pan()
{
  setpreset(0);

  lfo.effectlfoout(lfol, lfor);
}

void Pan::processBlock(f32** inOutBlock, const i32 blockSize)
{
  if (PextraON)
  {
    for (i32 i = 0; i < blockSize; i++)
    {
      const f32 avg = (inOutBlock[0][i] + inOutBlock[1][i]) * 0.5f;
      const f32 ldiff = inOutBlock[0][i] - avg;
      const f32 rdiff = inOutBlock[1][i] - avg;

      f32 tmp = avg + ldiff * mul;
      inOutBlock[0][i] = tmp * cosf(dvalue);

      tmp = avg + rdiff * mul;
      inOutBlock[1][i] = tmp * sinf(dvalue);
    }
  }

  if (PAutoPan)
  {
    ll = lfol;
    lr = lfor;
    lfo.effectlfoout(lfol, lfor);
    const f32 coeff_PERIOD = 1.0 / fPERIOD;
    for (i32 i = 0; i < blockSize; i++)
    {
      const f32 fi = (f32)i;
      const f32 P_i = (f32)(blockSize - i);

      f32 pp = (ll * P_i + lfol * fi) * coeff_PERIOD;

      inOutBlock[0][i] *= pp * panning;

      pp = (lr * P_i + lfor * fi) * coeff_PERIOD;

      inOutBlock[1][i] *= pp * (1.0f - panning);
    }
  }
}

void Pan::setvolume(i32 Pvolume_)
{
  Pvolume = Pvolume_;
  outvolume = (f32)Pvolume_ / 127.0f;
}

void Pan::setpanning(i32 Ppanning_)
{
  Ppanning = Ppanning_;
  panning = ((f32)Ppanning_) / 127.0f;
  dvalue = panning * f32(M_PI_2);
}

void Pan::setextra(i32 Pextra_)
{
  Pextra = Pextra_;
  mul = 4.0f * (f32)Pextra_ / 127.0f;
}

void Pan::setpreset(i32 npreset)
{
  const i32 PRESET_SIZE = 9;
  i32 presets[][PRESET_SIZE] = {
    //AutoPan
    {64, 64, 26, 0, 0, 0, 0, 1, 0},
    //Extra Stereo
    {64, 64, 80, 0, 0, 0, 10, 0, 1}
  };

  for (i32 n = 0; n < PRESET_SIZE; n++)
    changepar(n, presets[npreset][n]);
}

void Pan::changepar(i32 npar, i32 value)
{
  switch (npar)
  {
  case 0:
    setvolume(value);
    return;
  case 1:
    setpanning(value);
    return;
  case 2:
    lfo.Pfreq = value;
    lfo.updateparams();
    return;
  case 3:
    lfo.Prandomness = value;
    lfo.updateparams();
    return;
  case 4:
    lfo.PLFOtype = value;
    lfo.updateparams();
    return;
  case 5:
    lfo.Pstereo = value;
    lfo.updateparams();
    return;
  case 6:
    setextra(value);
    return;
  case 7:
    PAutoPan = value;
    return;
  case 8:
    PextraON = value;
    return;
  }
  ASSERT(false);
}

i32 Pan::getpar(i32 npar)
{
  switch (npar)
  {
  case 0:
    return Pvolume;
  case 1:
    return Ppanning;
  case 2:
    return lfo.Pfreq;
  case 3:
    return lfo.Prandomness;
  case 4:
    return lfo.PLFOtype;
  case 5:
    return lfo.Pstereo;
  case 6:
    return Pextra;
  case 7:
    return PAutoPan;
  case 8:
    return PextraON;
  }
  ASSERT(false);
  return 0;
}

#endif // SHR3D_SFX_CORE_RAKARRACK
