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.

440 lines
10KB

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