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.

651 lines
17KB

  1. /*
  2. Copyright (C) 2006-2011 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 <FL/Fl.H>
  18. #include "globals.h"
  19. #include "Control.h"
  20. #include "XMLwrapper.h"
  21. using namespace std;
  22. Control::Control(){
  23. player=new Player();
  24. player->start();
  25. wavinfo.samplerate=44100;
  26. wavinfo.nsamples=0;
  27. wavinfo.intype=FILE_WAV;
  28. wav32bit=false;
  29. process.bufsize=16384;
  30. process.stretch=4.0;
  31. /// process.transient.enable=false;
  32. /// process.transient.amount=0.5;
  33. seek_pos=0.0;
  34. window_type=W_HANN;
  35. info.render_percent=-1.0;
  36. info.cancel_render=false;
  37. volume=1.0;
  38. gui_sliders.fftsize_s=0.5;
  39. gui_sliders.stretch_s=0.5;
  40. gui_sliders.mode_s=0;
  41. ///#warning test
  42. /// process.transient.enable=true;
  43. };
  44. Control::~Control(){
  45. // delete player; face crash daca il las
  46. };
  47. ///void Control::pre_analyse_whole_audio(InputS *ai){
  48. /// int inbufsize=1024;
  49. /// int readsize=inbufsize/2;
  50. ///
  51. /// short int *inbuf_i=new short int[readsize*2];
  52. ///
  53. ///// REALTYPE *inbuf_f=new REALTYPE[readsize];
  54. ///// for (int i=0;i<readsize;i++) inbuf_f[i]=0.0;
  55. ///
  56. /// REALTYPE *processbuf=new REALTYPE[inbufsize];
  57. /// for (int i=0;i<inbufsize;i++) processbuf[i]=0.0;
  58. ///
  59. /// FFT *infft=new FFT(inbufsize);
  60. ///
  61. /// int k=0;
  62. /// int fftsize=inbufsize/2;
  63. /// REALTYPE *oldfreq=new REALTYPE[fftsize];
  64. /// for (int i=0;i<fftsize;i++) oldfreq[i]=0.0;
  65. /// REALTYPE oldsumstart=0.0;
  66. /// int transient_data_n=0;
  67. /// int transient_data_max_n=10000;
  68. /// REALTYPE *transient_data=new REALTYPE [transient_data_max_n];
  69. /// while(!ai->eof){
  70. /// float in_pos=(REALTYPE) ai->info.currentsample/(REALTYPE)ai->info.nsamples;
  71. ///
  72. /// int readed=ai->read(readsize,inbuf_i);
  73. /// if (readed!=readsize) break;//do not process the last buffer from the audiofile
  74. /// const float inv_32768=1.0/32768.0;
  75. ///
  76. /// for (int i=0;i<inbufsize-readed;i++){
  77. /// processbuf[i]=processbuf[i+readed];
  78. /// };
  79. /// for (int i=0;i<readed;i++) {
  80. /// processbuf[i+inbufsize-readed]=(inbuf_i[i*2]*inv_32768+inbuf_i[i*2+1]*inv_32768);
  81. /// };
  82. ///
  83. ///
  84. /// for (int i=0;i<inbufsize;i++) infft->smp[i]=processbuf[i];
  85. ///
  86. ///
  87. /// infft->applywindow(W_HAMMING);
  88. /// infft->smp2freq();
  89. /// infft->freq[0]=0;
  90. /// REALTYPE *freq=infft->freq;
  91. ///
  92. /// REALTYPE sumstart=0.0;
  93. /// for (int i=0;i<fftsize;i++){
  94. /// REALTYPE x=freq[i]-oldfreq[i];
  95. /// if (x>0) sumstart+=x;
  96. /// };
  97. /// sumstart/=fftsize;
  98. /// const REALTYPE a=0.1;
  99. /// oldsumstart=oldsumstart*(1.0-a)+sumstart*a;
  100. /// sumstart-=1.5*oldsumstart;
  101. /// if (sumstart<0.0) sumstart=0.0;
  102. ///
  103. /// transient_data[transient_data_n]=sumstart;
  104. /// transient_data_n++;
  105. /// if (transient_data_n>=transient_data_max_n){
  106. /// transient_data_max_n+=100000;
  107. /// REALTYPE *new_transient_data=new REALTYPE[transient_data_max_n];
  108. /// for (int i=0;i<transient_data_n;i++) new_transient_data[i]=transient_data[i];
  109. /// delete [] transient_data;
  110. /// transient_data=new_transient_data;
  111. /// };
  112. ///
  113. /// for (int i=0;i<fftsize;i++) oldfreq[i]=freq[i];
  114. /// };
  115. /// ppar.set_transient_data(transient_data_n,transient_data);
  116. /// delete infft;
  117. /// delete []transient_data;
  118. ///
  119. /// delete []oldfreq;
  120. /// delete [] inbuf_i;
  121. /// //delete [] inbuf_f;
  122. /// delete [] processbuf;
  123. ///};
  124. bool Control::set_input_filename(string filename,FILE_TYPE intype){
  125. InputS *ai=NULL;
  126. if (intype==FILE_VORBIS) ai=new VorbisInputS;
  127. if (intype==FILE_MP3) ai=new MP3InputS;
  128. if (intype==FILE_WAV) ai=new AInputS;
  129. if (!ai) return false;
  130. wavinfo.filename=filename;
  131. wavinfo.intype=intype;
  132. bool result=ai->open(wavinfo.filename);
  133. if (result) {
  134. wavinfo.samplerate=ai->info.samplerate;
  135. wavinfo.nsamples=ai->info.nsamples;
  136. /// if (process.transient.enable) {
  137. /// pre_analyse_whole_audio(ai);
  138. /// };
  139. delete ai;
  140. }else{
  141. wavinfo.filename="";
  142. wavinfo.samplerate=0;
  143. wavinfo.nsamples=0;
  144. delete ai;
  145. };
  146. return result;
  147. };
  148. string Control::get_input_filename(){
  149. return wavinfo.filename;
  150. };
  151. string Control::get_input_filename_and_info(){
  152. int seconds=wavinfo.nsamples/wavinfo.samplerate;
  153. const int size=200;
  154. char tmp[size];tmp[size-1]=0;
  155. snprintf(tmp,size-1," ( samplerate=%d; duration=%02d:%02d:%02d )",wavinfo.samplerate,seconds/3600,(seconds/60)%60,seconds%60);
  156. string filename=wavinfo.filename;
  157. int len=filename.length();
  158. if (len>70)filename=filename.substr(0,25)+"..."+filename.substr(len-35);
  159. return filename+tmp;
  160. };
  161. /*string Control::get_recommanded_output_filename(){
  162. return "none";
  163. };
  164. */
  165. std::string Control::get_stretch_info(){
  166. const int size=200;
  167. char tmp[size];tmp[size-1]=0;
  168. if (wavinfo.nsamples==0) return "Stretch: ";
  169. double realduration=wavinfo.nsamples/wavinfo.samplerate*process.stretch;
  170. if (realduration>(365.25*86400.0*1.0e12)){//more than 1 trillion years
  171. double duration=(realduration/(365.25*86400.0*1.0e12));//my
  172. snprintf(tmp,size,"Stretch: %.7gx (%g trillion years)",process.stretch,duration);
  173. return tmp;
  174. };
  175. if (realduration>(365.25*86400.0*1.0e9)){//more than 1 billion years
  176. double duration=(realduration/(365.25*86400.0*1.0e9));//my
  177. snprintf(tmp,size,"Stretch: %.7gx (%g billion years)",process.stretch,duration);
  178. return tmp;
  179. };
  180. if (realduration>(365.25*86400.0*1.0e6)){//more than 1 million years
  181. double duration=(realduration/(365.25*86400.0*1.0e6));//my
  182. snprintf(tmp,size,"Stretch: %.7gx (%g million years)",process.stretch,duration);
  183. return tmp;
  184. };
  185. if (realduration>(365.25*86400.0*2000.0)){//more than two millenniums
  186. int duration=(int)(realduration/(365.25*86400.0));//years
  187. int years=duration%1000;
  188. int milleniums=duration/1000;
  189. char stryears[size];stryears[0]=0;
  190. if (years!=0){
  191. if (years==1) snprintf(stryears,size," 1 year");
  192. else snprintf(stryears,size," %d years",years);
  193. };
  194. snprintf(tmp,size,"Stretch: %.7gx (%d milleniums%s)",process.stretch,milleniums,stryears);
  195. return tmp;
  196. };
  197. if (realduration>(365.25*86400.0)){//more than 1 year
  198. int duration=(int) (realduration/3600.0);//hours
  199. int hours=duration%24;
  200. int days=(duration/24)%365;
  201. int years=duration/(365*24);
  202. char stryears[size];stryears[0]=0;
  203. if (years==1) snprintf(stryears,size,"1 year ");
  204. else snprintf(stryears,size,"%d years ",years);
  205. char strdays[size];strdays[0]=0;
  206. if (days>0){
  207. if (days==1) snprintf(strdays,size,"1 day");
  208. else snprintf(strdays,size,"%d days",days);
  209. };
  210. if (years>=10) hours=0;
  211. char strhours[size];strhours[0]=0;
  212. if (hours>0){
  213. snprintf(strhours,size," %d h",hours);
  214. };
  215. snprintf(tmp,size,"Stretch: %.7gx (%s%s%s)",process.stretch,stryears,strdays,strhours);
  216. return tmp;
  217. }else{//less than 1 year
  218. int duration=(int)(realduration);//seconds
  219. char strdays[size];strdays[0]=0;
  220. int days=duration/86400;
  221. if (days>0){
  222. if (days==1) snprintf(strdays,size,"1 day ");
  223. else snprintf(strdays,size,"%d days ",duration/86400);
  224. };
  225. REALTYPE stretch=process.stretch;
  226. if (stretch>=1.0){
  227. stretch=((int) (stretch*100.0))*0.01;
  228. };
  229. snprintf(tmp,size,"Stretch: %.7gx (%s%.2d:%.2d:%.2d)",
  230. stretch,strdays,(duration/3600)%24,(duration/60)%60,duration%60);
  231. return tmp;
  232. };
  233. return "";
  234. };
  235. string Control::get_fftsize_info(){
  236. const int size=200;
  237. char tmp[size];tmp[size-1]=0;
  238. string fftsizelabel;
  239. fftsizelabel+="Window size (samples): ";
  240. if (wavinfo.nsamples==0) return fftsizelabel;
  241. fftsizelabel+=getfftsizestr(process.bufsize);
  242. return fftsizelabel;
  243. };
  244. string Control::get_fftresolution_info(){
  245. string resolution="Resolution: ";
  246. if (wavinfo.nsamples==0) return resolution;
  247. //todo: unctime and uncfreq are correct computed? Need to check later.
  248. REALTYPE unctime=process.bufsize/(REALTYPE)wavinfo.samplerate*sqrt(2.0);
  249. REALTYPE uncfreq=1.0/unctime*sqrt(2.0);
  250. char tmp[100];
  251. snprintf(tmp,100,"%.5g seconds",unctime);resolution+=tmp;
  252. snprintf(tmp,100," (%.5g Hz)",uncfreq);resolution+=tmp;
  253. return resolution;
  254. };
  255. void Control::startplay(bool bypass){
  256. if ((!player->info.playing)||(player->info.samplerate!=wavinfo.samplerate)){
  257. stopplay();
  258. sleep(200);
  259. #ifdef HAVE_JACK
  260. JACKaudiooutputinit(player,wavinfo.samplerate);
  261. #else
  262. PAaudiooutputinit(player,wavinfo.samplerate);
  263. #endif
  264. };
  265. if (wavinfo.filename!="") player->startplay(wavinfo.filename,seek_pos,process.stretch,process.bufsize,wavinfo.intype,bypass,&ppar,&bbpar);
  266. // sleep(100);
  267. // update_process_parameters();
  268. };
  269. void Control::stopplay(){
  270. player->stop();
  271. player->seek(0.0);
  272. seek_pos=0;
  273. #ifdef HAVE_JACK
  274. JACKclose();
  275. #else
  276. PAfinish();
  277. #endif
  278. };
  279. void Control::pauseplay(){
  280. player->pause();
  281. };
  282. void Control::freezeplay(){
  283. player->freeze();
  284. };
  285. void Control::set_volume(REALTYPE vol){
  286. volume=vol;
  287. player->set_volume(vol);
  288. };
  289. void Control::set_seek_pos(REALTYPE x){
  290. seek_pos=x;
  291. player->seek(x);
  292. };
  293. REALTYPE Control::get_seek_pos(){
  294. if (player->getmode()==Player::MODE_PLAY) seek_pos=player->info.position;
  295. return seek_pos;
  296. };
  297. void Control::set_stretch_controls(double stretch_s,int mode,double fftsize_s){
  298. gui_sliders.stretch_s=stretch_s;
  299. gui_sliders.mode_s=mode;
  300. gui_sliders.fftsize_s=fftsize_s;
  301. double stretch=1.0;
  302. switch(mode){
  303. case 0:
  304. stretch_s=pow(stretch_s,1.2);
  305. stretch=pow(10.0,stretch_s*4.0);
  306. break;
  307. case 1:
  308. stretch_s=pow(stretch_s,1.5);
  309. stretch=pow(10.0,stretch_s*18.0);
  310. break;
  311. case 2:
  312. stretch=1.0/pow(10.0,stretch_s*3.0);
  313. if (stretch<0.1) stretch=0.1;
  314. break;
  315. };
  316. fftsize_s=pow(fftsize_s,1.5);
  317. double tmp=1.0;
  318. if (mode==2) tmp=1.0/stretch;
  319. int bufsize=(int)(pow(2.0,fftsize_s*12.0)*512.0*tmp);
  320. bufsize=optimizebufsize(bufsize);
  321. process.stretch=stretch;
  322. process.bufsize=bufsize;
  323. };
  324. double Control::get_stretch_control(double stretch,int mode){
  325. double result=1.0;
  326. switch(mode){
  327. case 0:
  328. if (stretch<1.0) return -1;
  329. stretch=(log(stretch)/log(10))*0.25;
  330. result=pow(stretch,1.0/1.2);
  331. break;
  332. case 1:
  333. if (stretch<1.0) return -1;
  334. stretch=(log(stretch)/log(10))/18.0;
  335. result=pow(stretch,1.0/1.5);
  336. break;
  337. case 2:
  338. if (stretch>1.0) return -1;
  339. result=3.0/(log(stretch)/log(10));
  340. break;
  341. };
  342. return result;
  343. };
  344. void Control::update_player_stretch(){
  345. player->setrap(process.stretch);
  346. };
  347. int abs_val(int x){
  348. if (x<0) return -x;
  349. else return x;
  350. };
  351. int Control::get_optimized_updown(int n,bool up){
  352. int orig_n=n;
  353. while(true){
  354. n=orig_n;
  355. #ifndef KISSFFT
  356. while (!(n%11)) n/=11;
  357. while (!(n%7)) n/=7;
  358. #endif
  359. while (!(n%5)) n/=5;
  360. while (!(n%3)) n/=3;
  361. while (!(n%2)) n/=2;
  362. if (n<2) break;
  363. if (up) orig_n++;
  364. else orig_n--;
  365. if (orig_n<4) return 4;
  366. };
  367. return orig_n;
  368. };
  369. int Control::optimizebufsize(int n){
  370. int n1=get_optimized_updown(n,false);
  371. int n2=get_optimized_updown(n,true);
  372. if ((n-n1)<(n2-n)) return n1;
  373. else return n2;
  374. };
  375. void Control::set_window_type(FFTWindow window){
  376. window_type=window;
  377. if (player) player->set_window_type(window);
  378. };
  379. string Control::Render(string inaudio,string outaudio,FILE_TYPE outtype,FILE_TYPE intype,REALTYPE pos1,REALTYPE pos2){
  380. if (pos2<pos1){
  381. REALTYPE tmp=pos2;
  382. pos2=pos1;
  383. pos1=tmp;
  384. };
  385. InputS *ai=NULL;
  386. switch(intype){
  387. case FILE_VORBIS:ai=new VorbisInputS;
  388. break;
  389. case FILE_MP3:ai=new MP3InputS;
  390. break;
  391. default:ai=new AInputS;
  392. };
  393. AOutputS ao;
  394. VorbisOutputS vorbisout;
  395. info.cancel_render=false;
  396. if (!ai->open(inaudio)){
  397. return "Error: Could not open audio file (or file format not recognized) :"+inaudio;
  398. };
  399. BinauralBeats bb(ai->info.samplerate);
  400. bb.pars=bbpar;
  401. if (outtype==FILE_WAV) ao.newfile(outaudio,ai->info.samplerate,wav32bit);
  402. if (outtype==FILE_VORBIS) vorbisout.newfile(outaudio,ai->info.samplerate);
  403. ai->seek(pos1);
  404. int inbufsize=process.bufsize;
  405. if (inbufsize<32) inbufsize=32;
  406. short int *inbuf_i=new short int[inbufsize*4];
  407. int outbufsize;
  408. struct{
  409. REALTYPE *l,*r;
  410. }inbuf;
  411. ProcessedStretch *stretchl=new ProcessedStretch(process.stretch,inbufsize,window_type,false,ai->info.samplerate,1);
  412. ProcessedStretch *stretchr=new ProcessedStretch(process.stretch,inbufsize,window_type,false,ai->info.samplerate,2);
  413. stretchl->set_parameters(&ppar);
  414. stretchr->set_parameters(&ppar);
  415. outbufsize=stretchl->out_bufsize;
  416. int *outbuf=new int[outbufsize*2];
  417. int poolsize=stretchl->poolsize;
  418. inbuf.l=new REALTYPE[poolsize];
  419. inbuf.r=new REALTYPE[poolsize];
  420. for (int i=0;i<poolsize;i++) inbuf.l[i]=inbuf.r[i]=0.0;
  421. int readsize=0;
  422. const int pause_max_write=65536;
  423. int pause_write=0;
  424. bool firstbuf=true;
  425. while(!ai->eof){
  426. float in_pos=(REALTYPE) ai->info.currentsample/(REALTYPE)ai->info.nsamples;
  427. if (firstbuf){
  428. readsize=stretchl->get_nsamples_for_fill();
  429. firstbuf=false;
  430. }else{
  431. readsize=stretchl->get_nsamples(in_pos*100.0);
  432. };
  433. int readed=0;
  434. if (readsize!=0) readed=ai->read(readsize,inbuf_i);
  435. for (int i=0;i<readed;i++) {
  436. inbuf.l[i]=inbuf_i[i*2]/32768.0;
  437. inbuf.r[i]=inbuf_i[i*2+1]/32768.0;
  438. };
  439. stretchl->process(inbuf.l,readed);
  440. stretchr->process(inbuf.r,readed);
  441. bb.process(stretchl->out_buf,stretchr->out_buf,outbufsize,in_pos*100.0);
  442. for (int i=0;i<outbufsize;i++) {
  443. stretchl->out_buf[i]*=volume;
  444. stretchr->out_buf[i]*=volume;
  445. };
  446. if (outtype==FILE_WAV){
  447. for (int i=0;i<outbufsize;i++) {
  448. REALTYPE l=stretchl->out_buf[i],r=stretchr->out_buf[i];
  449. if (l<-1.0) l=-1.0;
  450. else if (l>1.0) l=1.0;
  451. if (r<-1.0) r=-1.0;
  452. else if (r>1.0) r=1.0;
  453. outbuf[i*2]=(int)(l*32767.0*65536.0);
  454. outbuf[i*2+1]=(int)(r*32767.0*65536.0);
  455. };
  456. ao.write(outbufsize,outbuf);
  457. };
  458. if (outtype==FILE_VORBIS) vorbisout.write(outbufsize,stretchl->out_buf,stretchr->out_buf);
  459. REALTYPE totalf=ai->info.currentsample/(REALTYPE)ai->info.nsamples-pos1;
  460. if (totalf>(pos2-pos1)) break;
  461. info.render_percent=(totalf*100.0/(pos2-pos1+0.001));
  462. pause_write+=outbufsize;
  463. if (pause_write>pause_max_write){
  464. float tmp=outbufsize/1000000.0;
  465. if (tmp>0.1) tmp=0.1;
  466. Fl::wait(0.01+tmp);
  467. pause_write=0;
  468. if (info.cancel_render) break;
  469. };
  470. };
  471. delete stretchl;
  472. delete stretchr;
  473. delete []outbuf;
  474. delete []inbuf_i;
  475. delete []inbuf.l;
  476. delete []inbuf.r;
  477. info.render_percent=-1.0;
  478. return "";
  479. };
  480. string Control::getfftsizestr(int fftsize){
  481. int size=100;
  482. char tmp[size];tmp[size-1]=0;
  483. if (fftsize<1024.0) snprintf(tmp,size-1,"%d",fftsize);
  484. else if (fftsize<(1024.0*1024.0)) snprintf(tmp,size-1,"%.4gK",fftsize/1024.0);
  485. else if (fftsize<(1024.0*1024.0*1024.0)) snprintf(tmp,size-1,"%.4gM",fftsize/(1024.0*1024.0));
  486. else snprintf(tmp,size-1,"%.7gG",fftsize/(1024.0*1024.0*1024.0));
  487. return tmp;
  488. };
  489. void Control::update_process_parameters(){
  490. if (player) player->set_process_parameters(&ppar,&bbpar);
  491. };
  492. bool Control::save_parameters(const char *filename){
  493. XMLwrapper *xml=new XMLwrapper();
  494. xml->beginbranch("PAULSTRETCH");
  495. xml->beginbranch("STRETCH_PARAMETERS");
  496. xml->beginbranch("BASE");
  497. xml->addpar("bufsize",process.bufsize);
  498. xml->addparreal("stretch",process.stretch);
  499. xml->addparreal("fftsize_s",gui_sliders.fftsize_s);
  500. xml->addparreal("stretch_s",gui_sliders.stretch_s);
  501. xml->addpar("mode_s",gui_sliders.mode_s);
  502. xml->addpar("window_type",window_type);
  503. xml->addparreal("volume",volume);
  504. xml->endbranch();
  505. xml->beginbranch("PROCESS");
  506. ppar.add2XML(xml);
  507. xml->endbranch();
  508. xml->beginbranch("BINAURAL_BEATS");
  509. bbpar.add2XML(xml);
  510. xml->endbranch();
  511. xml->endbranch();
  512. xml->endbranch();
  513. int result=xml->saveXMLfile(filename);
  514. delete xml;
  515. return true;
  516. };
  517. bool Control::load_parameters(const char *filename){
  518. XMLwrapper *xml=new XMLwrapper();
  519. if (xml->loadXMLfile(filename)<0) {
  520. delete xml;
  521. return false;
  522. };
  523. if (xml->enterbranch("PAULSTRETCH")==0) {
  524. delete xml;
  525. return false;
  526. };
  527. if (xml->enterbranch("STRETCH_PARAMETERS")){
  528. if (xml->enterbranch("BASE")){
  529. process.bufsize=xml->getpar("bufsize",process.bufsize,16,2e9);
  530. process.stretch=xml->getparreal("stretch",process.stretch);
  531. gui_sliders.fftsize_s=xml->getparreal("fftsize_s",gui_sliders.fftsize_s);
  532. gui_sliders.stretch_s=xml->getparreal("stretch_s",gui_sliders.stretch_s);
  533. gui_sliders.mode_s=xml->getpar("mode_s",gui_sliders.mode_s,0,2);
  534. window_type=(FFTWindow)xml->getpar("window_type",window_type,0,4);
  535. volume=xml->getparreal("volume",1.0);
  536. xml->exitbranch();
  537. };
  538. if (xml->enterbranch("PROCESS")){
  539. ppar.getfromXML(xml);
  540. xml->exitbranch();
  541. };
  542. if (xml->enterbranch("BINAURAL_BEATS")){
  543. bbpar.getfromXML(xml);
  544. xml->exitbranch();
  545. };
  546. xml->exitbranch();
  547. };
  548. delete xml;
  549. set_stretch_controls(gui_sliders.stretch_s,gui_sliders.mode_s,gui_sliders.fftsize_s);
  550. set_window_type(window_type);
  551. set_volume(volume);
  552. update_process_parameters();
  553. return true;
  554. };