ProcessedStretch.cpp (14228B)
1 /* 2 Copyright (C) 2009 Nasca Octavian Paul 3 Author: Nasca Octavian Paul 4 5 This program is free software; you can redistribute it and/or modify 6 it under the terms of version 2 of the GNU General Public License 7 as published by the Free Software Foundation. 8 9 This program is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 GNU General Public License (version 2) for more details. 13 14 You should have received a copy of the GNU General Public License (version 2) 15 along with this program; if not, write to the Free Software Foundation, 16 Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 */ 18 19 #include <math.h> 20 #include <stdlib.h> 21 #include <stdio.h> 22 #include "ProcessedStretch.h" 23 24 void ProcessParameters::add2XML(XMLwrapper *xml){ 25 26 xml->addparbool("pitch_shift.enabled",pitch_shift.enabled); 27 xml->addparreal("pitch_shift.cents",pitch_shift.cents); 28 29 xml->addparbool("octave.enabled",octave.enabled); 30 xml->addparreal("octave.om2",octave.om2); 31 xml->addparreal("octave.om1",octave.om1); 32 xml->addparreal("octave.o0",octave.o0); 33 xml->addparreal("octave.o1",octave.o1); 34 xml->addparreal("octave.o15",octave.o15); 35 xml->addparreal("octave.o2",octave.o2); 36 37 xml->addparbool("freq_shift.enabled",freq_shift.enabled); 38 xml->addparreal("freq_shift.Hz",freq_shift.Hz); 39 40 xml->addparbool("compressor.enabled",compressor.enabled); 41 xml->addparreal("compressor.power",compressor.power); 42 43 xml->addparbool("filter.enabled",filter.enabled); 44 xml->addparbool("filter.stop",filter.stop); 45 xml->addparreal("filter.low",filter.low); 46 xml->addparreal("filter.high",filter.high); 47 xml->addparreal("filter.hdamp",filter.hdamp); 48 49 xml->addparbool("harmonics.enabled",harmonics.enabled); 50 xml->addparreal("harmonics.freq",harmonics.freq); 51 xml->addparreal("harmonics.bandwidth",harmonics.bandwidth); 52 xml->addpar("harmonic.nharmonics",harmonics.nharmonics); 53 54 xml->addparbool("harmonics.gauss",harmonics.gauss); 55 56 xml->addparbool("spread.enabled",spread.enabled); 57 xml->addparreal("spread.bandwidth",spread.bandwidth); 58 59 xml->addparbool("tonal_vs_noise.enabled",tonal_vs_noise.enabled); 60 xml->addparreal("tonal_vs_noise.bandwidth",tonal_vs_noise.bandwidth); 61 xml->addparreal("tonal_vs_noise.preserve",tonal_vs_noise.preserve); 62 63 xml->beginbranch("FREE_FILTER"); 64 free_filter.add2XML(xml); 65 xml->endbranch(); 66 67 xml->beginbranch("STRETCH_MULTIPLIER"); 68 stretch_multiplier.add2XML(xml); 69 xml->endbranch(); 70 71 }; 72 73 void ProcessParameters::getfromXML(XMLwrapper *xml){ 74 pitch_shift.enabled=xml->getparbool("pitch_shift.enabled",pitch_shift.enabled); 75 pitch_shift.cents=xml->getparreal("pitch_shift.cents",pitch_shift.cents); 76 77 octave.enabled=xml->getparbool("octave.enabled",octave.enabled); 78 octave.om2=xml->getparreal("octave.om2",octave.om2); 79 octave.om1=xml->getparreal("octave.om1",octave.om1); 80 octave.o0=xml->getparreal("octave.o0",octave.o0); 81 octave.o1=xml->getparreal("octave.o1",octave.o1); 82 octave.o15=xml->getparreal("octave.o15",octave.o15); 83 octave.o2=xml->getparreal("octave.o2",octave.o2); 84 85 freq_shift.enabled=xml->getparbool("freq_shift.enabled",freq_shift.enabled); 86 freq_shift.Hz=xml->getparreal("freq_shift.Hz",freq_shift.Hz); 87 88 compressor.enabled=xml->getparbool("compressor.enabled",compressor.enabled); 89 compressor.power=xml->getparreal("compressor.power",compressor.power); 90 91 filter.enabled=xml->getparbool("filter.enabled",filter.enabled); 92 filter.stop=xml->getparbool("filter.stop",filter.stop); 93 filter.low=xml->getparreal("filter.low",filter.low); 94 filter.high=xml->getparreal("filter.high",filter.high); 95 filter.hdamp=xml->getparreal("filter.hdamp",filter.hdamp); 96 97 harmonics.enabled=xml->getparbool("harmonics.enabled",harmonics.enabled); 98 harmonics.freq=xml->getparreal("harmonics.freq",harmonics.freq); 99 harmonics.bandwidth=xml->getparreal("harmonics.bandwidth",harmonics.bandwidth); 100 harmonics.nharmonics=xml->getpar("harmonic.nharmonics",harmonics.nharmonics,1,100); 101 102 harmonics.gauss=xml->getparbool("harmonics.gauss",harmonics.gauss); 103 104 spread.enabled=xml->getparbool("spread.enabled",spread.enabled); 105 spread.bandwidth=xml->getparreal("spread.bandwidth",spread.bandwidth); 106 107 tonal_vs_noise.enabled=xml->getparbool("tonal_vs_noise.enabled",tonal_vs_noise.enabled); 108 tonal_vs_noise.preserve=xml->getparreal("tonal_vs_noise.preserve",tonal_vs_noise.bandwidth); 109 tonal_vs_noise.bandwidth=xml->getparreal("tonal_vs_noise.bandwidth",tonal_vs_noise.bandwidth); 110 111 112 if (xml->enterbranch("FREE_FILTER")){ 113 free_filter.getfromXML(xml); 114 xml->exitbranch(); 115 }; 116 if (xml->enterbranch("STRETCH_MULTIPLIER")){ 117 stretch_multiplier.getfromXML(xml); 118 xml->exitbranch(); 119 }; 120 }; 121 122 ProcessedStretch::ProcessedStretch(REALTYPE rap_,int in_bufsize_,FFTWindow w,bool bypass_,REALTYPE samplerate_,int stereo_mode_):Stretch(rap_,in_bufsize_,w,bypass_,samplerate_,stereo_mode_){ 123 nfreq=bufsize; 124 infreq=new REALTYPE[nfreq]; 125 sumfreq=new REALTYPE[nfreq]; 126 tmpfreq1=new REALTYPE[nfreq]; 127 tmpfreq2=new REALTYPE[nfreq]; 128 //fbfreq=new REALTYPE[nfreq]; 129 free_filter_freqs=new REALTYPE[nfreq]; 130 for (int i=0;i<nfreq;i++) { 131 free_filter_freqs[i]=1.0; 132 // fbfreq[i]=0.0; 133 }; 134 }; 135 ProcessedStretch::~ProcessedStretch(){ 136 delete [] infreq; 137 delete [] sumfreq; 138 delete [] tmpfreq1; 139 delete [] tmpfreq2; 140 delete [] free_filter_freqs; 141 // delete [] fbfreq; 142 }; 143 144 void ProcessedStretch::set_parameters(ProcessParameters *ppar){ 145 pars=*ppar; 146 update_free_filter(); 147 }; 148 149 150 void ProcessedStretch::copy(REALTYPE *freq1,REALTYPE *freq2){ 151 for (int i=0;i<nfreq;i++) freq2[i]=freq1[i]; 152 }; 153 154 void ProcessedStretch::add(REALTYPE *freq2,REALTYPE *freq1,REALTYPE a){ 155 for (int i=0;i<nfreq;i++) freq2[i]+=freq1[i]*a; 156 }; 157 158 void ProcessedStretch::mul(REALTYPE *freq1,REALTYPE a){ 159 for (int i=0;i<nfreq;i++) freq1[i]*=a; 160 }; 161 162 void ProcessedStretch::zero(REALTYPE *freq1){ 163 for (int i=0;i<nfreq;i++) freq1[i]=0.0; 164 }; 165 166 REALTYPE ProcessedStretch::get_stretch_multiplier(REALTYPE pos_percents){ 167 REALTYPE result=1.0; 168 if (pars.stretch_multiplier.get_enabled()){ 169 result*=pars.stretch_multiplier.get_value(pos_percents); 170 }; 171 ///REALTYPE transient=pars.get_transient(pos_percents); 172 ///printf("\n%g\n",transient); 173 ///REALTYPE threshold=0.05; 174 ///REALTYPE power=1000.0; 175 ///transient-=threshold; 176 ///if (transient>0){ 177 /// transient*=power*(1.0+power); 178 /// result/=(1.0+transient); 179 ///}; 180 ///printf("tr=%g\n",result); 181 return result; 182 }; 183 184 void ProcessedStretch::process_spectrum(REALTYPE *freq){ 185 if (pars.harmonics.enabled) { 186 copy(freq,infreq); 187 do_harmonics(infreq,freq); 188 }; 189 190 if (pars.tonal_vs_noise.enabled){ 191 copy(freq,infreq); 192 do_tonal_vs_noise(infreq,freq); 193 }; 194 195 if (pars.freq_shift.enabled) { 196 copy(freq,infreq); 197 do_freq_shift(infreq,freq); 198 }; 199 if (pars.pitch_shift.enabled) { 200 copy(freq,infreq); 201 do_pitch_shift(infreq,freq,pow(2.0,pars.pitch_shift.cents/1200.0)); 202 }; 203 if (pars.octave.enabled){ 204 copy(freq,infreq); 205 do_octave(infreq,freq); 206 }; 207 208 209 if (pars.spread.enabled){ 210 copy(freq,infreq); 211 do_spread(infreq,freq); 212 }; 213 214 215 if (pars.filter.enabled){ 216 copy(freq,infreq); 217 do_filter(infreq,freq); 218 }; 219 220 if (pars.free_filter.get_enabled()){ 221 copy(freq,infreq); 222 do_free_filter(infreq,freq); 223 }; 224 225 if (pars.compressor.enabled){ 226 copy(freq,infreq); 227 do_compressor(infreq,freq); 228 }; 229 230 }; 231 232 //void ProcessedStretch::process_output(REALTYPE *smps,int nsmps){ 233 //}; 234 235 236 REALTYPE profile(REALTYPE fi, REALTYPE bwi){ 237 REALTYPE x=fi/bwi; 238 x*=x; 239 if (x>14.71280603) return 0.0; 240 return exp(-x);///bwi; 241 242 }; 243 244 void ProcessedStretch::do_harmonics(REALTYPE *freq1,REALTYPE *freq2){ 245 REALTYPE freq=pars.harmonics.freq; 246 REALTYPE bandwidth=pars.harmonics.bandwidth; 247 int nharmonics=pars.harmonics.nharmonics; 248 249 if (freq<10.0) freq=10.0; 250 251 REALTYPE *amp=tmpfreq1; 252 for (int i=0;i<nfreq;i++) amp[i]=0.0; 253 254 for (int nh=1;nh<=nharmonics;nh++){//for each harmonic 255 REALTYPE bw_Hz;//bandwidth of the current harmonic measured in Hz 256 REALTYPE bwi; 257 REALTYPE fi; 258 REALTYPE f=nh*freq; 259 260 if (f>=samplerate/2) break; 261 262 bw_Hz=(pow(2.0,bandwidth/1200.0)-1.0)*f; 263 bwi=bw_Hz/(2.0*samplerate); 264 fi=f/samplerate; 265 266 REALTYPE sum=0.0; 267 REALTYPE max=0.0; 268 for (int i=1;i<nfreq;i++){//todo: optimize here 269 REALTYPE hprofile; 270 hprofile=profile((i/(REALTYPE)nfreq*0.5)-fi,bwi); 271 amp[i]+=hprofile; 272 if (max<hprofile) max=hprofile; 273 sum+=hprofile; 274 }; 275 }; 276 277 REALTYPE max=0.0; 278 for (int i=1;i<nfreq;i++){ 279 if (amp[i]>max) max=amp[i]; 280 }; 281 if (max<1e-8) max=1e-8; 282 283 for (int i=1;i<nfreq;i++){ 284 REALTYPE c,s; 285 REALTYPE a=amp[i]/max; 286 if (!pars.harmonics.gauss) a=(a<0.368?0.0:1.0); 287 freq2[i]=freq1[i]*a; 288 }; 289 290 }; 291 292 293 void ProcessedStretch::do_freq_shift(REALTYPE *freq1,REALTYPE *freq2){ 294 zero(freq2); 295 int ifreq=(int)(pars.freq_shift.Hz/(samplerate*0.5)*nfreq); 296 for (int i=0;i<nfreq;i++){ 297 int i2=ifreq+i; 298 if ((i2>0)&&(i2<nfreq)) freq2[i2]=freq1[i]; 299 }; 300 }; 301 void ProcessedStretch::do_pitch_shift(REALTYPE *freq1,REALTYPE *freq2,REALTYPE rap){ 302 zero(freq2); 303 if (rap<1.0){//down 304 for (int i=0;i<nfreq;i++){ 305 int i2=(int)(i*rap); 306 if (i2>=nfreq) break; 307 freq2[i2]+=freq1[i]; 308 }; 309 }; 310 if (rap>=1.0){//up 311 rap=1.0/rap; 312 for (int i=0;i<nfreq;i++){ 313 freq2[i]=freq1[(int)(i*rap)]; 314 }; 315 316 }; 317 }; 318 void ProcessedStretch::do_octave(REALTYPE *freq1,REALTYPE *freq2){ 319 zero(sumfreq); 320 if (pars.octave.om2>1e-3){ 321 do_pitch_shift(freq1,tmpfreq1,0.25); 322 add(sumfreq,tmpfreq1,pars.octave.om2); 323 }; 324 if (pars.octave.om1>1e-3){ 325 do_pitch_shift(freq1,tmpfreq1,0.5); 326 add(sumfreq,tmpfreq1,pars.octave.om1); 327 }; 328 if (pars.octave.o0>1e-3){ 329 add(sumfreq,freq1,pars.octave.o0); 330 }; 331 if (pars.octave.o1>1e-3){ 332 do_pitch_shift(freq1,tmpfreq1,2.0); 333 add(sumfreq,tmpfreq1,pars.octave.o1); 334 }; 335 if (pars.octave.o15>1e-3){ 336 do_pitch_shift(freq1,tmpfreq1,3.0); 337 add(sumfreq,tmpfreq1,pars.octave.o15); 338 }; 339 if (pars.octave.o2>1e-3){ 340 do_pitch_shift(freq1,tmpfreq1,4.0); 341 add(sumfreq,tmpfreq1,pars.octave.o2); 342 }; 343 344 REALTYPE sum=0.01+pars.octave.om2+pars.octave.om1+pars.octave.o0+pars.octave.o1+pars.octave.o15+pars.octave.o2; 345 if (sum<0.5) sum=0.5; 346 for (int i=0;i<nfreq;i++) freq2[i]=sumfreq[i]/sum; 347 }; 348 349 void ProcessedStretch::do_filter(REALTYPE *freq1,REALTYPE *freq2){ 350 REALTYPE low=0,high=0; 351 if (pars.filter.low<pars.filter.high){//sort the low/high freqs 352 low=pars.filter.low; 353 high=pars.filter.high; 354 }else{ 355 high=pars.filter.low; 356 low=pars.filter.high; 357 }; 358 int ilow=(int) (low/samplerate*nfreq*2.0); 359 int ihigh=(int) (high/samplerate*nfreq*2.0); 360 REALTYPE dmp=1.0; 361 REALTYPE dmprap=1.0-pow(pars.filter.hdamp*0.5,4.0); 362 for (int i=0;i<nfreq;i++){ 363 REALTYPE a=0.0; 364 if ((i>=ilow)&&(i<ihigh)) a=1.0; 365 if (pars.filter.stop) a=1.0-a; 366 freq2[i]=freq1[i]*a*dmp; 367 dmp*=dmprap+1e-8; 368 }; 369 }; 370 371 void ProcessedStretch::update_free_filter(){ 372 pars.free_filter.update_curve(); 373 if (pars.free_filter.get_enabled()) { 374 for (int i=0;i<nfreq;i++){ 375 REALTYPE freq=(REALTYPE)i/(REALTYPE) nfreq*samplerate*0.5; 376 free_filter_freqs[i]=pars.free_filter.get_value(freq); 377 }; 378 }else{ 379 for (int i=0;i<nfreq;i++){ 380 free_filter_freqs[i]=1.0; 381 }; 382 }; 383 }; 384 void ProcessedStretch::do_free_filter(REALTYPE *freq1,REALTYPE *freq2){ 385 for (int i=0;i<nfreq;i++){ 386 freq2[i]=freq1[i]*free_filter_freqs[i]; 387 }; 388 }; 389 390 void ProcessedStretch::do_spread(REALTYPE *freq1,REALTYPE *freq2){ 391 spread(freq1,freq2,pars.spread.bandwidth); 392 }; 393 394 void ProcessedStretch::spread(REALTYPE *freq1,REALTYPE *freq2,REALTYPE spread_bandwidth){ 395 //convert to log spectrum 396 REALTYPE minfreq=20.0; 397 REALTYPE maxfreq=0.5*samplerate; 398 399 REALTYPE log_minfreq=log(minfreq); 400 REALTYPE log_maxfreq=log(maxfreq); 401 402 for (int i=0;i<nfreq;i++){ 403 REALTYPE freqx=i/(REALTYPE) nfreq; 404 REALTYPE x=exp(log_minfreq+freqx*(log_maxfreq-log_minfreq))/maxfreq*nfreq; 405 REALTYPE y=0.0; 406 int x0=(int)floor(x); if (x0>=nfreq) x0=nfreq-1; 407 int x1=x0+1; if (x1>=nfreq) x1=nfreq-1; 408 REALTYPE xp=x-x0; 409 if (x<nfreq){ 410 y=freq1[x0]*(1.0-xp)+freq1[x1]*xp; 411 }; 412 tmpfreq1[i]=y; 413 }; 414 415 //increase the bandwidth of each harmonic (by smoothing the log spectrum) 416 int n=2; 417 REALTYPE bandwidth=spread_bandwidth; 418 REALTYPE a=1.0-pow(2.0,-bandwidth*bandwidth*10.0); 419 a=pow(a,8192.0/nfreq*n); 420 421 for (int k=0;k<n;k++){ 422 tmpfreq1[0]=0.0; 423 for (int i=1;i<nfreq;i++){ 424 tmpfreq1[i]=tmpfreq1[i-1]*a+tmpfreq1[i]*(1.0-a); 425 }; 426 tmpfreq1[nfreq-1]=0.0; 427 for (int i=nfreq-2;i>0;i--){ 428 tmpfreq1[i]=tmpfreq1[i+1]*a+tmpfreq1[i]*(1.0-a); 429 }; 430 }; 431 432 freq2[0]=0; 433 REALTYPE log_maxfreq_d_minfreq=log(maxfreq/minfreq); 434 for (int i=1;i<nfreq;i++){ 435 REALTYPE freqx=i/(REALTYPE) nfreq; 436 REALTYPE x=log((freqx*maxfreq)/minfreq)/log_maxfreq_d_minfreq*nfreq; 437 REALTYPE y=0.0; 438 if ((x>0.0)&&(x<nfreq)){ 439 int x0=(int)floor(x); if (x0>=nfreq) x0=nfreq-1; 440 int x1=x0+1; if (x1>=nfreq) x1=nfreq-1; 441 REALTYPE xp=x-x0; 442 y=tmpfreq1[x0]*(1.0-xp)+tmpfreq1[x1]*xp; 443 }; 444 freq2[i]=y; 445 }; 446 447 448 }; 449 450 451 void ProcessedStretch::do_compressor(REALTYPE *freq1,REALTYPE *freq2){ 452 REALTYPE rms=0.0; 453 for (int i=0;i<nfreq;i++) rms+=freq1[i]*freq1[i]; 454 rms=sqrt(rms/nfreq)*0.1; 455 if (rms<1e-3) rms=1e-3; 456 457 REALTYPE rap=pow(rms,-pars.compressor.power); 458 for (int i=0;i<nfreq;i++) freq2[i]=freq1[i]*rap; 459 }; 460 461 void ProcessedStretch::do_tonal_vs_noise(REALTYPE *freq1,REALTYPE *freq2){ 462 spread(freq1,tmpfreq1,pars.tonal_vs_noise.bandwidth); 463 464 if (pars.tonal_vs_noise.preserve>=0.0){ 465 REALTYPE mul=(pow(10.0,pars.tonal_vs_noise.preserve)-1.0); 466 for (int i=0;i<nfreq;i++) { 467 REALTYPE x=freq1[i]; 468 REALTYPE smooth_x=tmpfreq1[i]+1e-6; 469 470 REALTYPE result=0.0; 471 result=x-smooth_x*mul; 472 if (result<0.0) result=0.0; 473 freq2[i]=result; 474 }; 475 }else{ 476 REALTYPE mul=(pow(5.0,1.0+pars.tonal_vs_noise.preserve)-1.0); 477 for (int i=0;i<nfreq;i++) { 478 REALTYPE x=freq1[i]; 479 REALTYPE smooth_x=tmpfreq1[i]+1e-6; 480 481 REALTYPE result=0.0; 482 result=x-smooth_x*mul+0.1*mul; 483 if (result<0.0) result=x; 484 else result=0.0; 485 486 freq2[i]=result; 487 }; 488 }; 489 490 }; 491