You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

492 lines
14KB

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