zynaddsubfx

ZynAddSubFX open source synthesizer
Log | Files | Refs | Submodules | LICENSE

FormantFilter.cpp (6496B)


      1 /*
      2   ZynAddSubFX - a software synthesizer
      3 
      4   FormantFilter.cpp - formant filters
      5   Copyright (C) 2002-2005 Nasca Octavian Paul
      6   Author: Nasca Octavian Paul
      7 
      8   This program is free software; you can redistribute it and/or
      9   modify it under the terms of the GNU General Public License
     10   as published by the Free Software Foundation; either version 2
     11   of the License, or (at your option) any later version.
     12 */
     13 
     14 #include <cmath>
     15 #include <cstdio>
     16 #include "../Misc/Util.h"
     17 #include "../Misc/Allocator.h"
     18 #include "FormantFilter.h"
     19 #include "AnalogFilter.h"
     20 #include "../Params/FilterParams.h"
     21 
     22 namespace zyn {
     23 
     24 FormantFilter::FormantFilter(const FilterParams *pars, Allocator *alloc, unsigned int srate, int bufsize)
     25     :Filter(srate, bufsize), memory(*alloc)
     26 {
     27     numformants = pars->Pnumformants;
     28     for(int i = 0; i < numformants; ++i)
     29         formant[i] = memory.alloc<AnalogFilter>(4 /*BPF*/, 1000.0f, 10.0f, pars->Pstages, srate, bufsize);
     30     cleanup();
     31 
     32     for(int j = 0; j < FF_MAX_VOWELS; ++j)
     33         for(int i = 0; i < numformants; ++i) {
     34             formantpar[j][i].freq = pars->getformantfreq(
     35                 pars->Pvowels[j].formants[i].freq);
     36             formantpar[j][i].amp = pars->getformantamp(
     37                 pars->Pvowels[j].formants[i].amp);
     38             formantpar[j][i].q = pars->getformantq(
     39                 pars->Pvowels[j].formants[i].q);
     40         }
     41 
     42     for(int i = 0; i < FF_MAX_FORMANTS; ++i)
     43     {
     44         formant_amp_smoothing[i].sample_rate(srate);
     45         formant_amp_smoothing[i].reset(1.0f);
     46     }
     47 
     48     for(int i = 0; i < numformants; ++i) {
     49         currentformants[i].freq = 1000.0f;
     50         currentformants[i].amp  = 1.0f;
     51         currentformants[i].q    = 2.0f;
     52     }
     53 
     54     formantslowness = powf(1.0f - (pars->Pformantslowness / 128.0f), 3.0f);
     55 
     56     sequencesize = pars->Psequencesize;
     57     if(sequencesize == 0)
     58         sequencesize = 1;
     59     for(int k = 0; k < sequencesize; ++k)
     60         sequence[k].nvowel = pars->Psequence[k].nvowel;
     61 
     62     vowelclearness = powf(10.0f, (pars->Pvowelclearness - 32.0f) / 48.0f);
     63 
     64     sequencestretch = powf(0.1f, (pars->Psequencestretch - 32.0f) / 48.0f);
     65     if(pars->Psequencereversed)
     66         sequencestretch *= -1.0f;
     67 
     68     outgain = dB2rap(pars->getgain());
     69 
     70     oldinput   = -1.0f;
     71     Qfactor = pars->getq();
     72     oldQfactor = Qfactor;
     73     firsttime  = true;
     74 }
     75 
     76 FormantFilter::~FormantFilter()
     77 {
     78     for(int i = 0; i < numformants; ++i)
     79         memory.dealloc(formant[i]);
     80 }
     81 
     82 void FormantFilter::cleanup()
     83 {
     84     for(int i = 0; i < numformants; ++i)
     85         formant[i]->cleanup();
     86 }
     87 
     88 inline float log_2(float x)
     89 {
     90     return logf(x) / logf(2.0f);
     91 }
     92 
     93 void FormantFilter::setpos(float frequency)
     94 {
     95     int p1, p2;
     96 
     97     //Convert form real freq[Hz]
     98     const float input = log_2(frequency) - 9.96578428f; //log2(1000)=9.95748f.
     99 
    100     if(firsttime)
    101         slowinput = input;
    102     else
    103         slowinput = slowinput
    104                     * (1.0f - formantslowness) + input * formantslowness;
    105 
    106     if((fabsf(oldinput - input) < 0.001f) && (fabsf(slowinput - input) < 0.001f)
    107        && (fabsf(Qfactor - oldQfactor) < 0.001f)) {
    108         //      oldinput=input; setting this will cause problems at very slow changes
    109         firsttime = false;
    110         return;
    111     }
    112     else
    113         oldinput = input;
    114 
    115     float pos = input * sequencestretch;
    116     pos -= floorf(pos);
    117 
    118     F2I(pos * sequencesize, p2);
    119     p1 = p2 - 1;
    120     if(p1 < 0)
    121         p1 += sequencesize;
    122 
    123     pos = pos * sequencesize;
    124     pos -= floorf(pos);
    125     pos =
    126         (atanf((pos * 2.0f
    127                 - 1.0f)
    128                * vowelclearness) / atanf(vowelclearness) + 1.0f) * 0.5f;
    129 
    130     p1 = sequence[p1].nvowel;
    131     p2 = sequence[p2].nvowel;
    132 
    133     if(firsttime) {
    134         for(int i = 0; i < numformants; ++i) {
    135             currentformants[i].freq =
    136                 formantpar[p1][i].freq
    137                 * (1.0f - pos) + formantpar[p2][i].freq * pos;
    138             currentformants[i].amp =
    139                 formantpar[p1][i].amp
    140                 * (1.0f - pos) + formantpar[p2][i].amp * pos;
    141             currentformants[i].q =
    142                 formantpar[p1][i].q * (1.0f - pos) + formantpar[p2][i].q * pos;
    143             formant[i]->setfreq_and_q(currentformants[i].freq,
    144                                       currentformants[i].q * Qfactor);
    145         }
    146         firsttime = false;
    147     }
    148     else
    149         for(int i = 0; i < numformants; ++i) {
    150             currentformants[i].freq =
    151                 currentformants[i].freq * (1.0f - formantslowness)
    152                 + (formantpar[p1][i].freq
    153                    * (1.0f - pos) + formantpar[p2][i].freq * pos)
    154                 * formantslowness;
    155 
    156             currentformants[i].amp =
    157                 currentformants[i].amp * (1.0f - formantslowness)
    158                 + (formantpar[p1][i].amp * (1.0f - pos)
    159                    + formantpar[p2][i].amp * pos) * formantslowness;
    160 
    161             currentformants[i].q = currentformants[i].q
    162                                    * (1.0f - formantslowness)
    163                                    + (formantpar[p1][i].q * (1.0f - pos)
    164                                       + formantpar[p2][i].q
    165                                       * pos) * formantslowness;
    166 
    167 
    168             formant[i]->setfreq_and_q(currentformants[i].freq,
    169                                       currentformants[i].q * Qfactor);
    170         }
    171 
    172     oldQfactor = Qfactor;
    173 }
    174 
    175 void FormantFilter::setfreq(float frequency)
    176 {
    177     setpos(frequency);
    178 }
    179 
    180 void FormantFilter::setq(float q_)
    181 {
    182     Qfactor = q_;
    183     for(int i = 0; i < numformants; ++i)
    184         formant[i]->setq(Qfactor * currentformants[i].q);
    185 }
    186 
    187 void FormantFilter::setgain(float /*dBgain*/)
    188 {}
    189 
    190 void FormantFilter::setfreq_and_q(float frequency, float q_)
    191 {
    192     Qfactor = q_;
    193     setpos(frequency);
    194 }
    195 
    196 
    197 void FormantFilter::filterout(float *smp)
    198 {
    199     float inbuffer[buffersize];
    200 
    201     memcpy(inbuffer, smp, bufferbytes);
    202     memset(smp, 0, bufferbytes);
    203 
    204     float formantbuf[buffersize];
    205 
    206     for(int j = 0; j < numformants; ++j) {
    207 
    208         float tmpbuf[buffersize];
    209 
    210         for(int i = 0; i < buffersize; ++i)
    211             tmpbuf[i] = inbuffer[i] * outgain;
    212 
    213         formant[j]->filterout(tmpbuf);
    214 
    215         if ( formant_amp_smoothing[j].apply( formantbuf, buffersize, currentformants[j].amp ) )
    216         {
    217             for(int i = 0; i < buffersize; ++i)
    218                 smp[i] += tmpbuf[i] * formantbuf[i];
    219         }
    220         else
    221         {
    222             for(int i = 0; i < buffersize; ++i)
    223                 smp[i] += tmpbuf[i] * currentformants[j].amp;
    224         }
    225     }
    226 }
    227 
    228 }