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 }