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.

454 lines
11KB

  1. /*
  2. Copyright (C) 2006-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 <stdlib.h>
  16. #include <stdio.h>
  17. #include <unistd.h>
  18. #include <math.h>
  19. #include "Player.h"
  20. #include "globals.h"
  21. static int player_count=0;
  22. Player::Player():Thread(){
  23. player_count++;
  24. if (player_count>1) {
  25. printf("Error: Player class multiples instances.\n");
  26. exit(1);
  27. };
  28. stretchl=NULL;
  29. stretchr=NULL;
  30. binaural_beats=NULL;
  31. ai=NULL;
  32. newtask.mode=TASK_NONE;
  33. newtask.startpos=0.0;
  34. newtask.rap=1.0;
  35. newtask.fftsize=4096;
  36. task=newtask;
  37. mode=MODE_STOP;
  38. outbuf.n=0;
  39. outbuf.datal=NULL;
  40. outbuf.datar=NULL;
  41. outbuf.size=0;
  42. outbuf.computek=0;
  43. outbuf.outk=0;
  44. outbuf.outpos=0;
  45. outbuf.nfresh=0;
  46. outbuf.in_position=0;
  47. inbuf_i=NULL;
  48. info.position=0;
  49. freeze_mode=false;
  50. bypass_mode=false;
  51. first_in_buf=true;
  52. window_type=W_HANN;
  53. inbuf.l=NULL;
  54. inbuf.r=NULL;
  55. paused=false;
  56. info.playing=false;
  57. info.samplerate=44100;
  58. info.eof=true;
  59. volume=1.0;
  60. onset_detection_sensitivity=0.0;
  61. };
  62. Player::~Player(){
  63. player_count--;
  64. stop();
  65. if (stretchl) delete stretchl;stretchl=NULL;
  66. if (stretchr) delete stretchr;stretchr=NULL;
  67. if (outbuf.in_position) delete outbuf.in_position;
  68. if (inbuf.l) delete inbuf.l;
  69. if (inbuf.r) delete inbuf.r;
  70. if (inbuf_i) delete inbuf_i;
  71. if (ai) delete ai;
  72. if (binaural_beats) delete binaural_beats;binaural_beats=NULL;
  73. };
  74. Player::ModeType Player::getmode(){
  75. return mode;
  76. };
  77. void Player::startplay(std::string filename, REALTYPE startpos,REALTYPE rap, int fftsize,FILE_TYPE intype,bool bypass,ProcessParameters *ppar,BinauralBeatsParameters *bbpar){
  78. info.playing=false;
  79. info.eof=false;
  80. bypass_mode=bypass;
  81. if (bypass) freeze_mode=false;
  82. paused=false;
  83. taskmutex.lock();
  84. newtask.mode=TASK_START;
  85. newtask.filename=filename;
  86. newtask.startpos=startpos;
  87. newtask.rap=rap;
  88. newtask.fftsize=fftsize;
  89. newtask.intype=intype;
  90. newtask.bypass=bypass;
  91. newtask.ppar=ppar;
  92. newtask.bbpar=bbpar;
  93. taskmutex.unlock();
  94. };
  95. void Player::stop(){
  96. //pun 0 la outbuf
  97. info.playing=false;
  98. /* taskmutex.lock();
  99. newtask.mode=TASK_STOP;
  100. taskmutex.unlock();*/
  101. };
  102. void Player::pause(){
  103. paused=!paused;
  104. };
  105. void Player::seek(REALTYPE pos){
  106. taskmutex.lock();
  107. newtask.mode=TASK_SEEK;
  108. newtask.startpos=pos;
  109. taskmutex.unlock();
  110. };
  111. void Player::freeze(){
  112. freeze_mode=!freeze_mode;
  113. if (bypass_mode) freeze_mode=false;
  114. };
  115. void Player::setrap(REALTYPE newrap){
  116. taskmutex.lock();
  117. newtask.mode=TASK_RAP;
  118. newtask.rap=newrap;
  119. taskmutex.unlock();
  120. };
  121. void Player::set_process_parameters(ProcessParameters *ppar,BinauralBeatsParameters *bbpar){
  122. taskmutex.lock();
  123. newtask.mode=TASK_PARAMETERS;
  124. newtask.ppar=ppar;
  125. newtask.bbpar=bbpar;
  126. taskmutex.unlock();
  127. };
  128. void Player::set_window_type(FFTWindow window){
  129. window_type=window;
  130. };
  131. void Player::set_volume(REALTYPE vol){
  132. volume=vol;
  133. };
  134. void Player::set_onset_detection_sensitivity(REALTYPE onset){
  135. onset_detection_sensitivity=onset;
  136. };
  137. void Player::getaudiobuffer(int nsamples, float *out){
  138. if (mode==MODE_PREPARING){
  139. for (int i=0;i<nsamples*2;i++){
  140. out[i]=0.0;
  141. };
  142. return;
  143. };
  144. if (paused){
  145. for (int i=0;i<nsamples*2;i++){
  146. out[i]=0.0;
  147. };
  148. return;
  149. };
  150. bufmutex.lock();
  151. if ((outbuf.n==0)||(outbuf.nfresh==0)){
  152. bufmutex.unlock();
  153. for (int i=0;i<nsamples*2;i++){
  154. out[i]=0.0;
  155. };
  156. return;
  157. };
  158. int k=outbuf.outk,pos=outbuf.outpos;
  159. // printf("%d in_pos=%g\n",info.eof,outbuf.in_position[k]);
  160. if (info.eof) mode=MODE_STOP;
  161. else info.position=outbuf.in_position[k];
  162. for (int i=0;i<nsamples;i++){
  163. out[i*2]=outbuf.datal[k][pos]*volume;
  164. out[i*2+1]=outbuf.datar[k][pos]*volume;
  165. pos++;
  166. if (pos>=outbuf.size) {
  167. pos=0;
  168. k++;
  169. if (k>=outbuf.n) k=0;
  170. outbuf.nfresh--;
  171. //printf("%d %d\n",k,outbuf.nfresh);
  172. if (outbuf.nfresh<0){//Underflow
  173. outbuf.nfresh=0;
  174. for (int j=i;j<nsamples;j++){
  175. out[j*2]=0.0;
  176. out[j*2+1]=0.0;
  177. };
  178. break;
  179. };
  180. };
  181. };
  182. outbuf.outk=k;
  183. outbuf.outpos=pos;
  184. bufmutex.unlock();
  185. };
  186. void Player::run(){
  187. while(1){
  188. newtaskcheck();
  189. if (mode==MODE_STOP) sleep(10);
  190. if ((mode==MODE_PLAY)||(mode==MODE_PREPARING)){
  191. computesamples();
  192. };
  193. task.mode=TASK_NONE;
  194. };
  195. };
  196. void Player::newtaskcheck(){
  197. TaskMode newmode=TASK_NONE;
  198. taskmutex.lock();
  199. if (task.mode!=newtask.mode) {
  200. newmode=newtask.mode;
  201. task=newtask;
  202. };
  203. newtask.mode=TASK_NONE;
  204. taskmutex.unlock();
  205. if (newmode==TASK_START){
  206. if (current_filename!=task.filename){
  207. current_filename=task.filename;
  208. task.startpos=0.0;
  209. };
  210. switch (task.intype){
  211. case FILE_VORBIS:ai=new VorbisInputS;
  212. break;
  213. case FILE_MP3:ai=new MP3InputS;
  214. break;
  215. default: ai=new AInputS;
  216. };
  217. if (ai->open(task.filename)){
  218. info.samplerate=ai->info.samplerate;
  219. mode=MODE_PREPARING;
  220. ai->seek(task.startpos);
  221. bufmutex.lock();
  222. if (stretchl) delete stretchl;stretchl=NULL;
  223. if (stretchr) delete stretchr;stretchr=NULL;
  224. stretchl=new ProcessedStretch(task.rap,task.fftsize,window_type,task.bypass,ai->info.samplerate,1);
  225. stretchr=new ProcessedStretch(task.rap,task.fftsize,window_type,task.bypass,ai->info.samplerate,2);
  226. if (binaural_beats) delete binaural_beats;binaural_beats=NULL;
  227. binaural_beats=new BinauralBeats(ai->info.samplerate);
  228. if (stretchl) stretchl->set_parameters(task.ppar);
  229. if (stretchr) stretchr->set_parameters(task.ppar);
  230. if (binaural_beats) binaural_beats->pars=*(task.bbpar);
  231. inbufsize=stretchl->get_max_bufsize();
  232. if (inbuf.l) delete []inbuf.l;inbuf.l=NULL;
  233. if (inbuf.r) delete []inbuf.r;inbuf.r=NULL;
  234. inbuf.l=new REALTYPE[inbufsize];
  235. inbuf.r=new REALTYPE[inbufsize];
  236. for (int i=0;i<inbufsize;i++) inbuf.l[i]=inbuf.r[i]=0.0;
  237. if (outbuf.datal){
  238. for (int j=0;j<outbuf.n;j++){
  239. delete [] outbuf.datal[j];
  240. };
  241. delete [] outbuf.datal;
  242. outbuf.datal=NULL;
  243. };
  244. if (outbuf.datar){
  245. for (int j=0;j<outbuf.n;j++){
  246. delete [] outbuf.datar[j];
  247. };
  248. delete [] outbuf.datar;
  249. outbuf.datar=NULL;
  250. };
  251. delete[] inbuf_i;
  252. if (outbuf.in_position) {
  253. delete outbuf.in_position;
  254. outbuf.in_position=NULL;
  255. };
  256. inbuf_i=new short int[inbufsize*2];//for left and right
  257. for (int i=0;i<inbufsize;i++){
  258. inbuf_i[i*2]=inbuf_i[i*2+1]=0;
  259. };
  260. first_in_buf=true;
  261. outbuf.size=stretchl->get_bufsize();
  262. int min_samples=ai->info.samplerate*2;
  263. int n=2*PA_SOUND_BUFFER_SIZE/outbuf.size;
  264. if (n<3) n=3;//min 3 buffers
  265. if (n<(min_samples/outbuf.size)) n=(min_samples/outbuf.size);//the internal buffers sums "min_samples" amount
  266. outbuf.n=n;
  267. outbuf.nfresh=0;
  268. outbuf.datal=new float *[outbuf.n];
  269. outbuf.datar=new float *[outbuf.n];
  270. outbuf.computek=0;
  271. outbuf.outk=0;
  272. outbuf.outpos=0;
  273. outbuf.in_position=new float[outbuf.n];
  274. for (int j=0;j<outbuf.n;j++){
  275. outbuf.datal[j]=new float[outbuf.size];
  276. for (int i=0;i<outbuf.size;i++) outbuf.datal[j][i]=0.0;
  277. outbuf.datar[j]=new float[outbuf.size];
  278. for (int i=0;i<outbuf.size;i++) outbuf.datar[j][i]=0.0;
  279. outbuf.in_position[j]=0.0;
  280. };
  281. bufmutex.unlock();
  282. };
  283. };
  284. if (newmode==TASK_SEEK){
  285. if (ai) ai->seek(task.startpos);
  286. first_in_buf=true;
  287. };
  288. if (newmode==TASK_RAP){
  289. if (stretchl) stretchl->set_rap(task.rap);
  290. if (stretchl) stretchr->set_rap(task.rap);
  291. };
  292. if (newmode==TASK_PARAMETERS){
  293. if (stretchl) stretchl->set_parameters(task.ppar);
  294. if (stretchr) stretchr->set_parameters(task.ppar);
  295. if (binaural_beats) binaural_beats->pars=*(task.bbpar);
  296. };
  297. };
  298. void Player::computesamples(){
  299. bufmutex.lock();
  300. bool exitnow=(outbuf.n==0);
  301. if (outbuf.nfresh>=(outbuf.n-1)) exitnow=true;//buffers are full
  302. bufmutex.unlock();
  303. if (exitnow) {
  304. if (mode==MODE_PREPARING) {
  305. info.playing=true;
  306. mode=MODE_PLAY;
  307. };
  308. sleep(10);
  309. return;
  310. };
  311. bool eof=false;
  312. if (!ai) eof=true;
  313. else if (ai->eof) eof=true;
  314. if (eof){
  315. for (int i=0;i<inbufsize;i++){
  316. inbuf_i[i*2]=inbuf_i[i*2+1]=0;
  317. };
  318. outbuf.nfresh++;
  319. bufmutex.lock();
  320. for (int i=0;i<outbuf.size;i++){
  321. outbuf.datal[outbuf.computek][i]=0.0;
  322. outbuf.datar[outbuf.computek][i]=0.0;
  323. };
  324. outbuf.computek++;
  325. if (outbuf.computek>=outbuf.n){
  326. outbuf.computek=0;
  327. };
  328. bufmutex.unlock();
  329. info.eof=true;
  330. return;
  331. };
  332. bool result=true;
  333. float in_pos_100=(REALTYPE) ai->info.currentsample/(REALTYPE)ai->info.nsamples*100.0;
  334. int readsize=stretchl->get_nsamples(in_pos_100);
  335. if (first_in_buf) readsize=stretchl->get_nsamples_for_fill();
  336. else if (freeze_mode) readsize=0;
  337. if (readsize) result=(ai->read(readsize,inbuf_i)==(readsize));
  338. if (result){
  339. float in_pos=(REALTYPE) ai->info.currentsample/(REALTYPE)ai->info.nsamples;
  340. if (ai->eof) in_pos=0.0;
  341. REALTYPE tmp=1.0/32768.0;
  342. for (int i=0;i<readsize;i++){
  343. inbuf.l[i]=inbuf_i[i*2]*tmp;
  344. inbuf.r[i]=inbuf_i[i*2+1]*tmp;
  345. };
  346. stretchl->window_type=window_type;
  347. stretchr->window_type=window_type;
  348. REALTYPE s_onset=onset_detection_sensitivity;
  349. stretchl->set_onset_detection_sensitivity(s_onset);
  350. stretchr->set_onset_detection_sensitivity(s_onset);
  351. bool freezing=freeze_mode&&(!first_in_buf);
  352. stretchl->set_freezing(freezing);
  353. stretchr->set_freezing(freezing);
  354. REALTYPE onset_l=stretchl->process(inbuf.l,readsize);
  355. REALTYPE onset_r=stretchr->process(inbuf.r,readsize);
  356. REALTYPE onset=(onset_l>onset_r)?onset_l:onset_r;
  357. stretchl->here_is_onset(onset);
  358. stretchr->here_is_onset(onset);
  359. binaural_beats->process(stretchl->out_buf,stretchr->out_buf,stretchl->get_bufsize(),in_pos_100);
  360. // stretchl->process_output(stretchl->out_buf,stretchl->out_bufsize);
  361. // stretchr->process_output(stretchr->out_buf,stretchr->out_bufsize);
  362. int nskip=stretchl->get_skip_nsamples();
  363. if (nskip>0) ai->skip(nskip);
  364. first_in_buf=false;
  365. bufmutex.lock();
  366. for (int i=0;i<outbuf.size;i++){
  367. REALTYPE l=stretchl->out_buf[i],r=stretchr->out_buf[i];
  368. if (l<-1.0) l=-1.0;
  369. else if (l>1.0) l=1.0;
  370. if (r<-1.0) r=-1.0;
  371. else if (r>1.0) r=1.0;
  372. outbuf.datal[outbuf.computek][i]=l;
  373. outbuf.datar[outbuf.computek][i]=r;
  374. };
  375. outbuf.in_position[outbuf.computek]=in_pos;
  376. outbuf.computek++;
  377. if (outbuf.computek>=outbuf.n){
  378. outbuf.computek=0;
  379. };
  380. bufmutex.unlock();
  381. outbuf.nfresh++;
  382. }else{
  383. info.eof=true;
  384. mode=MODE_STOP;
  385. stop();
  386. };
  387. };