/* Copyright (C) 2006-2009 Nasca Octavian Paul Author: Nasca Octavian Paul This program is free software; you can redistribute it and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License (version 2) for more details. You should have received a copy of the GNU General Public License (version 2) along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include "Player.h" #include "globals.h" static int player_count=0; Player::Player():Thread(){ player_count++; if (player_count>1) { printf("Error: Player class multiples instances.\n"); exit(1); }; stretchl=NULL; stretchr=NULL; binaural_beats=NULL; ai=NULL; newtask.mode=TASK_NONE; newtask.startpos=0.0; newtask.rap=1.0; newtask.fftsize=4096; task=newtask; mode=MODE_STOP; outbuf.n=0; outbuf.datal=NULL; outbuf.datar=NULL; outbuf.size=0; outbuf.computek=0; outbuf.outk=0; outbuf.outpos=0; outbuf.nfresh=0; outbuf.in_position=0; inbuf_i=NULL; info.position=0; freeze_mode=false; bypass_mode=false; first_in_buf=true; window_type=W_HANN; inbuf.l=NULL; inbuf.r=NULL; paused=false; info.playing=false; info.samplerate=44100; info.eof=true; volume=1.0; onset_detection_sensitivity=0.0; }; Player::~Player(){ player_count--; stop(); if (stretchl) delete stretchl;stretchl=NULL; if (stretchr) delete stretchr;stretchr=NULL; if (outbuf.in_position) delete outbuf.in_position; if (inbuf.l) delete inbuf.l; if (inbuf.r) delete inbuf.r; if (inbuf_i) delete inbuf_i; if (ai) delete ai; if (binaural_beats) delete binaural_beats;binaural_beats=NULL; }; Player::ModeType Player::getmode(){ return mode; }; void Player::startplay(std::string filename, REALTYPE startpos,REALTYPE rap, int fftsize,FILE_TYPE intype,bool bypass,ProcessParameters *ppar,BinauralBeatsParameters *bbpar){ info.playing=false; info.eof=false; bypass_mode=bypass; if (bypass) freeze_mode=false; paused=false; taskmutex.lock(); newtask.mode=TASK_START; newtask.filename=filename; newtask.startpos=startpos; newtask.rap=rap; newtask.fftsize=fftsize; newtask.intype=intype; newtask.bypass=bypass; newtask.ppar=ppar; newtask.bbpar=bbpar; taskmutex.unlock(); }; void Player::stop(){ //pun 0 la outbuf info.playing=false; /* taskmutex.lock(); newtask.mode=TASK_STOP; taskmutex.unlock();*/ }; void Player::pause(){ paused=!paused; }; void Player::seek(REALTYPE pos){ taskmutex.lock(); newtask.mode=TASK_SEEK; newtask.startpos=pos; taskmutex.unlock(); }; void Player::freeze(){ freeze_mode=!freeze_mode; if (bypass_mode) freeze_mode=false; }; void Player::setrap(REALTYPE newrap){ taskmutex.lock(); newtask.mode=TASK_RAP; newtask.rap=newrap; taskmutex.unlock(); }; void Player::set_process_parameters(ProcessParameters *ppar,BinauralBeatsParameters *bbpar){ taskmutex.lock(); newtask.mode=TASK_PARAMETERS; newtask.ppar=ppar; newtask.bbpar=bbpar; taskmutex.unlock(); }; void Player::set_window_type(FFTWindow window){ window_type=window; }; void Player::set_volume(REALTYPE vol){ volume=vol; }; void Player::set_onset_detection_sensitivity(REALTYPE onset){ onset_detection_sensitivity=onset; }; void Player::getaudiobuffer(int nsamples, float *out){ if (mode==MODE_PREPARING){ for (int i=0;i=outbuf.size) { pos=0; k++; if (k>=outbuf.n) k=0; outbuf.nfresh--; //printf("%d %d\n",k,outbuf.nfresh); if (outbuf.nfresh<0){//Underflow outbuf.nfresh=0; for (int j=i;jopen(task.filename)){ info.samplerate=ai->info.samplerate; mode=MODE_PREPARING; ai->seek(task.startpos); bufmutex.lock(); if (stretchl) delete stretchl;stretchl=NULL; if (stretchr) delete stretchr;stretchr=NULL; stretchl=new ProcessedStretch(task.rap,task.fftsize,window_type,task.bypass,ai->info.samplerate,1); stretchr=new ProcessedStretch(task.rap,task.fftsize,window_type,task.bypass,ai->info.samplerate,2); if (binaural_beats) delete binaural_beats;binaural_beats=NULL; binaural_beats=new BinauralBeats(ai->info.samplerate); if (stretchl) stretchl->set_parameters(task.ppar); if (stretchr) stretchr->set_parameters(task.ppar); if (binaural_beats) binaural_beats->pars=*(task.bbpar); inbufsize=stretchl->get_max_bufsize(); if (inbuf.l) delete []inbuf.l;inbuf.l=NULL; if (inbuf.r) delete []inbuf.r;inbuf.r=NULL; inbuf.l=new REALTYPE[inbufsize]; inbuf.r=new REALTYPE[inbufsize]; for (int i=0;iget_bufsize(); int min_samples=ai->info.samplerate*2; int n=2*PA_SOUND_BUFFER_SIZE/outbuf.size; if (n<3) n=3;//min 3 buffers if (n<(min_samples/outbuf.size)) n=(min_samples/outbuf.size);//the internal buffers sums "min_samples" amount outbuf.n=n; outbuf.nfresh=0; outbuf.datal=new float *[outbuf.n]; outbuf.datar=new float *[outbuf.n]; outbuf.computek=0; outbuf.outk=0; outbuf.outpos=0; outbuf.in_position=new float[outbuf.n]; for (int j=0;jseek(task.startpos); first_in_buf=true; }; if (newmode==TASK_RAP){ if (stretchl) stretchl->set_rap(task.rap); if (stretchl) stretchr->set_rap(task.rap); }; if (newmode==TASK_PARAMETERS){ if (stretchl) stretchl->set_parameters(task.ppar); if (stretchr) stretchr->set_parameters(task.ppar); if (binaural_beats) binaural_beats->pars=*(task.bbpar); }; }; void Player::computesamples(){ bufmutex.lock(); bool exitnow=(outbuf.n==0); if (outbuf.nfresh>=(outbuf.n-1)) exitnow=true;//buffers are full bufmutex.unlock(); if (exitnow) { if (mode==MODE_PREPARING) { info.playing=true; mode=MODE_PLAY; }; sleep(10); return; }; bool eof=false; if (!ai) eof=true; else if (ai->eof) eof=true; if (eof){ for (int i=0;i=outbuf.n){ outbuf.computek=0; }; bufmutex.unlock(); info.eof=true; return; }; bool result=true; float in_pos_100=(REALTYPE) ai->info.currentsample/(REALTYPE)ai->info.nsamples*100.0; int readsize=stretchl->get_nsamples(in_pos_100); if (freeze_mode) readsize=0; if (first_in_buf) readsize=stretchl->get_nsamples_for_fill(); if (readsize) result=(ai->read(readsize,inbuf_i)==(readsize)); if (result){ float in_pos=(REALTYPE) ai->info.currentsample/(REALTYPE)ai->info.nsamples; if (ai->eof) in_pos=0.0; REALTYPE tmp=1.0/32768.0; for (int i=0;iwindow_type=window_type; stretchr->window_type=window_type; REALTYPE s_onset=onset_detection_sensitivity; stretchl->set_onset_detection_sensitivity(s_onset); stretchr->set_onset_detection_sensitivity(s_onset); REALTYPE onset_l=stretchl->process(inbuf.l,readsize); REALTYPE onset_r=stretchr->process(inbuf.r,readsize); REALTYPE onset=(onset_l>onset_r)?onset_l:onset_r; stretchl->here_is_onset(onset); stretchr->here_is_onset(onset); binaural_beats->process(stretchl->out_buf,stretchr->out_buf,stretchl->get_bufsize(),in_pos_100); // stretchl->process_output(stretchl->out_buf,stretchl->out_bufsize); // stretchr->process_output(stretchr->out_buf,stretchr->out_bufsize); int nskip=stretchl->get_skip_nsamples(); if (nskip>0) ai->skip(nskip); bufmutex.lock(); for (int i=0;iout_buf[i],r=stretchr->out_buf[i]; if (l<-1.0) l=-1.0; else if (l>1.0) l=1.0; if (r<-1.0) r=-1.0; else if (r>1.0) r=1.0; outbuf.datal[outbuf.computek][i]=l; outbuf.datar[outbuf.computek][i]=r; }; outbuf.in_position[outbuf.computek]=in_pos; outbuf.computek++; if (outbuf.computek>=outbuf.n){ outbuf.computek=0; }; bufmutex.unlock(); outbuf.nfresh++; }else{ info.eof=true; mode=MODE_STOP; stop(); }; };