home *** CD-ROM | disk | FTP | other *** search
/ Chip 2004 November / CMCD1104.ISO / Software / Complet / ZynAddFX / Setup_ZynAddSubFX-2.1.1.exe / Chorus.C < prev    next >
Encoding:
C/C++ Source or Header  |  2004-07-12  |  6.3 KB  |  278 lines

  1. /*
  2.   ZynAddSubFX - a software synthesizer
  3.  
  4.   Chorus.C - Chorus and Flange effects
  5.   Copyright (C) 2002-2004 Nasca Octavian Paul
  6.   Author: Nasca Octavian Paul
  7.  
  8.   This program is free software; you can redistribute it and/or modify
  9.   it under the terms of version 2 of the GNU General Public License 
  10.   as published by the Free Software Foundation.
  11.  
  12.   This program is distributed in the hope that it will be useful,
  13.   but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.   GNU General Public License (version 2) for more details.
  16.  
  17.   You should have received a copy of the GNU General Public License (version 2)
  18.   along with this program; if not, write to the Free Software Foundation,
  19.   Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  20.  
  21. */
  22.  
  23. #include <math.h>
  24. #include "Chorus.h"
  25. #include <stdio.h>
  26.  
  27. Chorus::Chorus(int insertion_,REALTYPE *efxoutl_,REALTYPE *efxoutr_){
  28.     efxoutl=efxoutl_;
  29.     efxoutr=efxoutr_;
  30.     dlk=0;drk=0;
  31.     maxdelay=(int)(MAX_CHORUS_DELAY/1000.0*SAMPLE_RATE);
  32.     delayl=new REALTYPE[maxdelay];
  33.     delayr=new REALTYPE[maxdelay];
  34.     insertion=insertion_;
  35.  
  36.     filterpars=NULL;
  37.     Ppreset=0;
  38.     setpreset(Ppreset);
  39.  
  40.     lfo.effectlfoout(&lfol,&lfor);
  41.     dl2=getdelay(lfol);
  42.     dr2=getdelay(lfor);
  43.     cleanup();
  44. };
  45.  
  46. Chorus::~Chorus(){
  47.     delete [] delayl;
  48.     delete [] delayr;
  49. };
  50.  
  51. /*
  52.  * get the delay value in samples; xlfo is the current lfo value
  53.  */
  54. REALTYPE Chorus::getdelay(REALTYPE xlfo){
  55.     REALTYPE result;
  56.     if (Pflangemode==0){
  57.     result=(delay+xlfo*depth)*SAMPLE_RATE;
  58.     } else result=0;
  59.     
  60.     //check if it is too big delay(caused bu errornous setdelay() and setdepth()    
  61.     if ((result+0.5)>=maxdelay) {
  62.     fprintf(stderr,"%s","WARNING: Chorus.C::getdelay(..) too big delay (see setdelay and setdepth funcs.)\n");
  63.     result=maxdelay-1.0;
  64.     };
  65.     return(result);
  66. };
  67.  
  68. /*
  69.  * Apply the effect
  70.  */
  71. void Chorus::out(REALTYPE *smpsl,REALTYPE *smpsr){
  72.     int i;
  73.     dl1=dl2;dr1=dr2;
  74.     lfo.effectlfoout(&lfol,&lfor);
  75.     
  76.     dl2=getdelay(lfol);
  77.     dr2=getdelay(lfor);
  78.  
  79.     for (i=0;i<SOUND_BUFFER_SIZE;i++){    
  80.     REALTYPE inl=smpsl[i];
  81.     REALTYPE inr=smpsr[i];
  82.     //LRcross
  83.     REALTYPE l=inl;
  84.     REALTYPE r=inr;
  85.     inl=l*(1.0-lrcross)+r*lrcross;
  86.     inr=r*(1.0-lrcross)+l*lrcross;
  87.     
  88.     //Left channel
  89.  
  90.     //compute the delay in samples using linear interpolation between the lfo delays
  91.     mdel=(dl1*(SOUND_BUFFER_SIZE-i)+dl2*i)/SOUND_BUFFER_SIZE;
  92.     if (++dlk>=maxdelay) dlk=0;
  93.     REALTYPE tmp=dlk-mdel+maxdelay*2.0;//where should I get the sample from
  94.  
  95.     F2I(tmp,dlhi);
  96.     dlhi%=maxdelay;
  97.     
  98.     dlhi2=(dlhi-1+maxdelay)%maxdelay;
  99.     dllo=1.0-fmod(tmp,1.0);
  100.         efxoutl[i]=delayl[dlhi2]*dllo+delayl[dlhi]*(1.0-dllo);
  101.     delayl[dlk]=inl+efxoutl[i]*fb;
  102.  
  103.     //Right channel
  104.  
  105.     //compute the delay in samples using linear interpolation between the lfo delays
  106.     mdel=(dr1*(SOUND_BUFFER_SIZE-i)+dr2*i)/SOUND_BUFFER_SIZE;
  107.     if (++drk>=maxdelay) drk=0;
  108.     tmp=drk-mdel+maxdelay*2.0;//where should I get the sample from
  109.  
  110.     F2I(tmp,dlhi);
  111.     dlhi%=maxdelay;    
  112.     
  113.     dlhi2=(dlhi-1+maxdelay)%maxdelay;
  114.     dllo=1.0-fmod(tmp,1.0);
  115.         efxoutr[i]=delayr[dlhi2]*dllo+delayr[dlhi]*(1.0-dllo);
  116.     delayr[dlk]=inr+efxoutr[i]*fb;
  117.  
  118.     };
  119.  
  120.     if (Poutsub!=0)
  121.     for (i=0;i<SOUND_BUFFER_SIZE;i++){
  122.             efxoutl[i] *= -1.0;
  123.             efxoutr[i] *= -1.0;
  124.     };
  125.  
  126.  
  127.     for (int i=0;i<SOUND_BUFFER_SIZE;i++){
  128.     efxoutl[i]*=panning;
  129.     efxoutr[i]*=(1.0-panning);
  130.     };
  131. };
  132.  
  133. /*
  134.  * Cleanup the effect
  135.  */
  136. void Chorus::cleanup(){
  137.     for (int i=0;i<maxdelay;i++){
  138.     delayl[i]=0.0;
  139.     delayr[i]=0.0;
  140.     };
  141.         
  142. };
  143.  
  144. /*
  145.  * Parameter control
  146.  */
  147. void Chorus::setdepth(unsigned char Pdepth){
  148.     this->Pdepth=Pdepth;
  149.     depth=(pow(8.0,(Pdepth/127.0)*2.0)-1.0)/1000.0;//seconds
  150. };
  151.  
  152. void Chorus::setdelay(unsigned char Pdelay){
  153.     this->Pdelay=Pdelay;
  154.     delay=(pow(10.0,(Pdelay/127.0)*2.0)-1.0)/1000.0;//seconds
  155. };
  156.  
  157. void Chorus::setfb(unsigned char Pfb){
  158.     this->Pfb=Pfb;
  159.     fb=(Pfb-64.0)/64.1;
  160. };
  161. void Chorus::setvolume(unsigned char Pvolume){
  162.     this->Pvolume=Pvolume;
  163.     outvolume=Pvolume/127.0;
  164.     if (insertion==0) volume=1.0;
  165.     else volume=outvolume;
  166. };
  167.  
  168. void Chorus::setpanning(unsigned char Ppanning){
  169.     this->Ppanning=Ppanning;
  170.     panning=Ppanning/127.0;
  171. };
  172.  
  173. void Chorus::setlrcross(unsigned char Plrcross){
  174.     this->Plrcross=Plrcross;
  175.     lrcross=Plrcross/127.0;
  176. };
  177.  
  178. void Chorus::setpreset(unsigned char npreset){
  179.     const int PRESET_SIZE=12;
  180.     const int NUM_PRESETS=10;
  181.     unsigned char presets[NUM_PRESETS][PRESET_SIZE]={
  182.     //Chorus1
  183.     {64,64,50,0,0,90,40,85,64,119,0,0},
  184.     //Chorus2
  185.     {64,64,45,0,0,98,56,90,64,19,0,0},
  186.     //Chorus3
  187.     {64,64,29,0,1,42,97,95,90,127,0,0},
  188.     //Celeste1
  189.     {64,64,26,0,0,42,115,18,90,127,0,0},
  190.     //Celeste2
  191.     {64,64,29,117,0,50,115,9,31,127,0,1},
  192.     //Flange1
  193.     {64,64,57,0,0,60,23,3,62,0,0,0},
  194.     //Flange2
  195.     {64,64,33,34,1,40,35,3,109,0,0,0},
  196.     //Flange3
  197.     {64,64,53,34,1,94,35,3,54,0,0,1},
  198.     //Flange4
  199.     {64,64,40,0,1,62,12,19,97,0,0,0},
  200.     //Flange5
  201.     {64,64,55,105,0,24,39,19,17,0,0,1}};
  202.  
  203.     if (npreset>=NUM_PRESETS) npreset=NUM_PRESETS-1;
  204.     for (int n=0;n<PRESET_SIZE;n++) changepar(n,presets[npreset][n]);
  205.     Ppreset=npreset;
  206. };
  207.  
  208.  
  209. void Chorus::changepar(int npar,unsigned char value){
  210.     switch(npar){
  211.     case 0:    setvolume(value);
  212.             break;
  213.     case 1:    setpanning(value);
  214.             break;
  215.     case 2:    lfo.Pfreq=value;
  216.             lfo.updateparams();
  217.         break;    
  218.     case 3:    lfo.Prandomness=value;
  219.             lfo.updateparams();
  220.         break;    
  221.     case 4:    lfo.PLFOtype=value;
  222.             lfo.updateparams();
  223.         break;    
  224.     case 5:    lfo.Pstereo=value;
  225.             lfo.updateparams();
  226.         break;    
  227.     case 6:    setdepth(value);
  228.             break;
  229.     case 7:    setdelay(value);
  230.             break;
  231.     case 8:    setfb(value);
  232.             break;
  233.     case 9:    setlrcross(value);
  234.             break;
  235.     case 10:if (value>1) value=1;
  236.         Pflangemode=value;
  237.             break;
  238.     case 11:if (value>1) value=1;
  239.             Poutsub=value;
  240.         break;
  241.     };
  242. };
  243.  
  244. unsigned char Chorus::getpar(int npar){
  245.     switch (npar){
  246.     case 0:    return(Pvolume);
  247.         break;
  248.     case 1:    return(Ppanning);
  249.         break;
  250.     case 2:    return(lfo.Pfreq);
  251.         break;
  252.     case 3:    return(lfo.Prandomness);
  253.         break;
  254.     case 4:    return(lfo.PLFOtype);
  255.         break;
  256.     case 5:    return(lfo.Pstereo);
  257.         break;
  258.     case 6:    return(Pdepth);
  259.         break;
  260.     case 7:    return(Pdelay);
  261.         break;
  262.     case 8:    return(Pfb);
  263.         break;
  264.     case 9:    return(Plrcross);
  265.         break;
  266.     case 10:return(Pflangemode);
  267.         break;
  268.     case 11:return(Poutsub);
  269.         break;
  270.     default:return (0);
  271.     };
  272.     
  273. };
  274.  
  275.  
  276.  
  277.  
  278.