#include "track.h" #include #include "utils.h" #include "real.h" #include "sbsms.h" #include "sms.h" #include #include #include using namespace std; namespace _sbsms_ { #define SBSMS_TRACK_BLOCK 2048 TrackAllocator :: TrackAllocator(bool bManageIndex) { this-> bManageIndex = bManageIndex; } TrackAllocator :: TrackAllocator(bool bManageIndex, unsigned short maxtrackindex) { this-> bManageIndex = bManageIndex; gTrack.resize(maxtrackindex); init(); } TrackAllocator :: ~TrackAllocator() { } void TrackAllocator :: init() { for(unsigned short k=0;kindex = index; gTrack[index] = t; return t; } track *TrackAllocator :: create(track *precursor, sms *owner, int res) { #ifdef MULTITHREADED pthread_mutex_lock(&taMutex); #endif if(gTrackIndex.empty()) { unsigned short n = gTrack.size(); gTrack.resize(n+SBSMS_TRACK_BLOCK); for(int k=n+SBSMS_TRACK_BLOCK-1;k>=n;k--) { gTrackIndex.push(k); gTrack[k] = NULL; } } unsigned short index = gTrackIndex.top(); gTrackIndex.pop(); #ifdef MULTITHREADED pthread_mutex_unlock(&taMutex); #endif return create(precursor, owner, res, index); } void TrackAllocator :: destroy(track *t) { #ifdef MULTITHREADED pthread_mutex_lock(&taMutex); #endif gTrack[t->index] = NULL; if(bManageIndex) gTrackIndex.push(t->index); delete t; #ifdef MULTITHREADED pthread_mutex_unlock(&taMutex); #endif } track :: track(track *precursor, sms *owner, int res) { this->owner = owner; this->res = res; this->descendant = NULL; this->precursor = precursor; this->end = LONG_MAX; this->rise = 0.3f; this->fall = 0.5f; tailEnd = 0; tailStart = 0; m_p = 0.0; currtime = 0; } void track :: endTrack(bool bTail) { end = back()->time; if(bTail) { this->fall = min(1.5f,.25 + back()->y / point[point.size()-2]->y); tailEnd = 1; end++; trackpoint *f = new trackpoint(back()); f->time = back()->time + 1; point.push_back(f); } } real track :: advance(long synthtime, int steps) { long k = synthtime - start; tpoint *tp0 = point[k]; tpoint *tp1 = point[k+1]; real w0 = tp0->f; real w1 = tp1->f; real ph0 = tp0->ph; real ph1 = tp1->ph; real h = tp0->h; real dp = ph1 - ph0; if(dp>PI) dp-=TWOPI; else if(dp<-PI) dp+=TWOPI; real dp0 = 0.5f*h*(w0 + w1); real deltadp = canon(dp - dp0); if(k==0) { if(precursor) { m_p = precursor->m_pDescendant; } else { deltadp = 0; } } dp = (real)steps/h*(dp0+deltadp); return dp; } void track :: synth(SampleBuf *out, long writePos, int c, long synthtime, int steps) { if(point.size()==0) return; long k = synthtime - start; if(k>=(long)point.size()-1) return; currtime = synthtime; if(k<0) return; int k1 = k + 1; tpoint *tp0 = point[k]; tpoint *tp1 = point[k1]; real w0 = tp0->f; real w1 = tp1->f; real dp = advance(synthtime,steps); real dt = (real)steps; w1 = 2.0f/dt*dp - w0; real b = (w1 - w0)/(2.0f*dt); bool bEnd = (k1==(long)point.size()-1); bool bStart = (k==0); if(bStart && tailStart) { real ph = m_p; int rise = round2int(this->rise * (real)steps); real dm = tp1->y/(real)rise; real m = tp1->y - dm; for(int i=steps-1;i>=steps-rise+1;i--) { ph -= w0; if(ph>PI) ph -= TWOPI; else if(ph<-PI) ph += TWOPI; out->buf[writePos+i][c] += m * COS(ph); m -= dm; } } else if(bEnd && tailEnd) { real ph = m_p; int fall = round2int(this->fall * (real)steps); real dm = tp0->y/(real)fall; real m = tp0->y; for(int i=0;ibuf[writePos+i][c] += m * COS(ph); ph += w0; if(ph>PI) ph -= TWOPI; else if(ph<-PI) ph += TWOPI; m -= dm; } } else { real m = tp0->y; real dm; dm = (tp1->y0 - tp0->y)/dt; real ph = m_p; real b2tt1 = b; real b2 = 2.0f*b; audio *o = &(out->buf[writePos]); for(int i=0;iPI) ph -= TWOPI; else if(ph<-PI) ph += TWOPI; b2tt1 += b2; m += dm; o++; } } //} if(bEnd) { if(descendant && descendant->back()->M < tp0->M) { m_pDescendant = canon(m_p + dp/dt*(real)(descendant->owner->samplePos/2 + 0.5f*(descendant->owner->samplePos%2) - owner->samplePos)); } } else if(bStart && tailStart) { } else { m_p = canon(m_p + dp); if(descendant && descendant->back()->M > tp0->M && (k1+res==(long)point.size()-1)) { m_pDescendant = canon(m_p + dp/dt*(real)(descendant->owner->samplePos*2 - (owner->samplePos+steps))); } } } bool track :: isEnded() { return (end!=LONG_MAX); } void track :: push_back_tpoint(tpoint *p) { point.push_back(p); } void track :: push_back(trackpoint *p) { point.push_back(p); p->owner = this; } void track :: startTrack(trackpoint *p, bool bTail) { push_back(p); start = p->time; m_pDescendant = p->ph; if(bTail) { tailStart = 1; start--; trackpoint *s = new trackpoint(p); s->time = p->time - 1; point.insert(point.begin(),s); m_p = p->ph; } currtime = p->time-1; } trackpoint *track :: back() { return (trackpoint*)point.back(); } trackpoint *track :: getTrackPoint(long time) { long k = time-start; if(k<0 || k >= (long)point.size()) return NULL; else return (trackpoint*)point[k]; } bool track :: isStart(long synthtime) { return (synthtime == start); } bool track :: isEnd(long synthtime) { return (synthtime == end); } bool track :: isDone() { return (currtime-start+1 >= (long)point.size()-1); } long track :: size() { return 1+end-start-tailEnd-tailStart; } track :: ~track() { static long i = 0; if(precursor) precursor->descendant = NULL; if(descendant) descendant->precursor = NULL; for(vector::iterator i = point.begin(); i != point.end(); i++) { delete (*i); } } }