Logo Search packages:      
Sourcecode: rakarrack version File versions  Download package

Phaser.C

/*
  ZynAddSubFX - a software synthesizer
 
  Phaser.C - Phaser effect
  Copyright (C) 2002-2005 Nasca Octavian Paul
  Author: Nasca Octavian Paul

  Modified for rakarrack by 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 (version 2)
  along with this program; if not, write to the Free Software Foundation,
  Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA

*/

#include <math.h>
#include "Phaser.h"
#include <stdio.h>
#define PHASER_LFO_SHAPE 2

Phaser::Phaser (REALTYPE * efxoutl_, REALTYPE * efxoutr_)
{
  efxoutl = efxoutl_;
  efxoutr = efxoutr_;

  oldl = NULL;
  oldr = NULL;

  Ppreset = 0;
  setpreset (Ppreset);
  cleanup ();
};

Phaser::~Phaser ()
{
  if (oldl != NULL)
    delete[]oldl;
  if (oldr != NULL)
    delete[]oldr;
};


/*
 * Effect output
 */
void
Phaser::out (REALTYPE * smpsl, REALTYPE * smpsr)
{
  int i, j;
  REALTYPE lfol, lfor, lgain, rgain, tmp;

  lfo.effectlfoout (&lfol, &lfor);
  lgain = lfol;
  rgain = lfor;
  lgain =
    (expf (lgain * PHASER_LFO_SHAPE) - 1) / (expf (PHASER_LFO_SHAPE) - 1.0);
  rgain =
    (expf (rgain * PHASER_LFO_SHAPE) - 1) / (expf (PHASER_LFO_SHAPE) - 1.0);


  lgain = 1.0 - phase * (1.0 - depth) - (1.0 - phase) * lgain * depth;
  rgain = 1.0 - phase * (1.0 - depth) - (1.0 - phase) * rgain * depth;

  if (lgain > 1.0)
    lgain = 1.0;
  else if (lgain < 0.0)
    lgain = 0.0;
  if (rgain > 1.0)
    rgain = 1.0;
  else if (rgain < 0.0)
    rgain = 0.0;

  for (i = 0; i < PERIOD; i++)
    {
      REALTYPE x = (REALTYPE) i / PERIOD;
      REALTYPE x1 = 1.0 - x;
      REALTYPE gl = lgain * x + oldlgain * x1;
      REALTYPE gr = rgain * x + oldrgain * x1;
      REALTYPE inl = smpsl[i] * panning + fbl;
      REALTYPE inr = smpsr[i] * (1.0 - panning) + fbr;

      //Left channel
      for (j = 0; j < Pstages * 2; j++)
      {                 //Phasing routine
        tmp = oldl[j];
        oldl[j] = gl * tmp + inl;
        inl = tmp - gl * oldl[j];
      };
      //Right channel
      for (j = 0; j < Pstages * 2; j++)
      {                 //Phasing routine
        tmp = oldr[j];
        oldr[j] = (gr * tmp) + inr;
        inr = tmp - (gr * oldr[j]);
      };
      //Left/Right crossing
      REALTYPE l = inl;
      REALTYPE r = inr;
      inl = l * (1.0 - lrcross) + r * lrcross;
      inr = r * (1.0 - lrcross) + l * lrcross;

      fbl = inl * fb;
      fbr = inr * fb;
      efxoutl[i] = inl;
      efxoutr[i] = inr;

    };

  oldlgain = lgain;
  oldrgain = rgain;

  if (Poutsub != 0)
    for (i = 0; i < PERIOD; i++)
      {
      efxoutl[i] *= -1.0;
      efxoutr[i] *= -1.0;
      };

};

/*
 * Cleanup the effect
 */
void
Phaser::cleanup ()
{
  fbl = 0.0;
  fbr = 0.0;
  oldlgain = 0.0;
  oldrgain = 0.0;
  for (int i = 0; i < Pstages * 2; i++)
    {
      oldl[i] = 0.0;
      oldr[i] = 0.0;
    };
};

/*
 * Parameter control
 */
void
Phaser::setdepth (unsigned char Pdepth)
{
  this->Pdepth = Pdepth;
  depth = (Pdepth / 127.0);
};


void
Phaser::setfb (unsigned char Pfb)
{
  this->Pfb = Pfb;
  fb = (Pfb - 64.0) / 64.1;
};

void
Phaser::setvolume (unsigned char Pvolume)
{
  this->Pvolume = Pvolume;
  outvolume = Pvolume / 127.0;
};

void
Phaser::setpanning (unsigned char Ppanning)
{
  this->Ppanning = Ppanning;
  panning = Ppanning / 127.0;
};

void
Phaser::setlrcross (unsigned char Plrcross)
{
  this->Plrcross = Plrcross;
  lrcross = Plrcross / 127.0;
};

void
Phaser::setstages (unsigned char Pstages)
{
  if (oldl != NULL)
    delete[]oldl;
  if (oldr != NULL)
    delete[]oldr;
  if (Pstages >= MAX_PHASER_STAGES)
    Pstages = MAX_PHASER_STAGES - 1;
  this->Pstages = Pstages;
  oldl = new REALTYPE[Pstages * 2];
  oldr = new REALTYPE[Pstages * 2];
  cleanup ();
};

void
Phaser::setphase (unsigned char Pphase)
{
  this->Pphase = Pphase;
  phase = (Pphase / 127.0);
};


void
Phaser::setpreset (unsigned char npreset)
{
  const int PRESET_SIZE = 12;
  const int NUM_PRESETS = 6;
  unsigned char presets[NUM_PRESETS][PRESET_SIZE] = {
    //Phaser1
    {64, 64, 36, 0, 0, 64, 110, 64, 1, 0, 0, 20},
    //Phaser2
    {64, 64, 35, 0, 0, 88, 40, 64, 3, 0, 0, 20},
    //Phaser3
    {64, 64, 31, 0, 0, 66, 68, 107, 2, 0, 0, 20},
    //Phaser4
    {39, 64, 22, 0, 0, 66, 67, 10, 5, 0, 1, 20},
    //Phaser5
    {64, 64, 20, 0, 1, 110, 67, 78, 10, 0, 0, 20},
    //Phaser6
    {64, 64, 53, 100, 0, 58, 37, 78, 3, 0, 0, 20}
  };
  if (npreset >= NUM_PRESETS)
    npreset = NUM_PRESETS - 1;
  for (int n = 0; n < PRESET_SIZE; n++)
    changepar (n, presets[npreset][n]);
  Ppreset = npreset;
};


void
Phaser::changepar (int npar, unsigned char value)
{
  switch (npar)
    {
    case 0:
      setvolume (value);
      break;
    case 1:
      setpanning (value);
      break;
    case 2:
      lfo.Pfreq = value;
      lfo.updateparams ();
      break;
    case 3:
      lfo.Prandomness = value;
      lfo.updateparams ();
      break;
    case 4:
      lfo.PLFOtype = value;
      lfo.updateparams ();
      break;
    case 5:
      lfo.Pstereo = value;
      lfo.updateparams ();
      break;
    case 6:
      setdepth (value);
      break;
    case 7:
      setfb (value);
      break;
    case 8:
      setstages (value);
      break;
    case 9:
      setlrcross (value);
      break;
    case 10:
      if (value > 1)
      value = 1;
      Poutsub = value;
      break;
    case 11:
      setphase (value);
      break;
    };
};

unsigned char
Phaser::getpar (int npar)
{
  switch (npar)
    {
    case 0:
      return (Pvolume);
      break;
    case 1:
      return (Ppanning);
      break;
    case 2:
      return (lfo.Pfreq);
      break;
    case 3:
      return (lfo.Prandomness);
      break;
    case 4:
      return (lfo.PLFOtype);
      break;
    case 5:
      return (lfo.Pstereo);
      break;
    case 6:
      return (Pdepth);
      break;
    case 7:
      return (Pfb);
      break;
    case 8:
      return (Pstages);
      break;
    case 9:
      return (Plrcross);
      break;
    case 10:
      return (Poutsub);
      break;
    case 11:
      return (Pphase);
      break;
    default:
      return (0);
    };

};

Generated by  Doxygen 1.6.0   Back to index