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.

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