1 #include "sms.h"
2 #include "real.h"
3 #include "utils.h"
4 #include "dBTable.h"
5 #include <stdlib.h>
6 #include <math.h>
7 #include <set>
8 using namespace std;
9 
10 namespace _sbsms_ {
11 
SMS(SMS * lo,int N,int band,int bandMax,int h,int res,int N0,int N1,int N2,int channels,audio * peak2)12 SMS :: SMS(SMS *lo, int N, int band, int bandMax, int h, int res, int N0, int N1, int N2, int channels, audio *peak2)
13 {
14   this->lo = lo;
15   if(lo) lo->hi = this;
16   hi = NULL;
17   this->band = band;
18   this->h = h;
19   this->h1 = (double)(h<<band);
20   this->res = res;
21   this->resMask = res - 1;
22   this->channels = channels;
23   this->N = N;
24   this->Nover2 = N/2;
25   float pad2 = (float)N/(float)N2;
26   float pad1 = (float)N/(float)N1;
27   float pad0 = (float)N/(float)N0;
28   M = (float)(1<<band);
29   peakThresh = 1e-8f;
30 
31   float maxDF2 = square(0.005f * (float)h) / M;
32   maxDF = sqrt(maxDF2);
33   maxCost2 = 0.5f * maxDF2;
34   dMCoeff2 = 0.002f * maxDF2;
35 
36   float maxDF2SplitMerge = square(0.001f * (float)h) / M;
37   maxDFSplitMerge = sqrt(maxDF2SplitMerge);
38   maxCost2SplitMerge = 1.0f * maxDF2SplitMerge;
39   dMCoeff2SplitMerge = 0.006f * maxDF2SplitMerge;
40 
41   maxDFMatch = .06f / M;
42   float maxDF2Match = square(maxDFMatch);
43   dMCoeff2Match = 0.0075f * maxDF2Match;
44   maxCost2Match = 0.8f * maxDF2Match;
45 
46   maxDFStereo = .04f / (float)M;
47   float maxDF2Stereo = square(maxDFStereo);
48   dMCoeff2Stereo = 0.005f * maxDF2Stereo;
49   maxCost2Stereo = 1.0f*maxDF2Stereo;
50 
51   peakWidth0 = lrintf(pad0*(float)N*0.0055f) + 1;
52   peakWidth1 = lrintf(pad1*(float)N*0.0055f) + 1;
53   peakWidth2 = lrintf(pad2*(float)N*0.0055f) + 1;
54   minTrackSize = max(384/(h<<band),N2/h/2);
55   minCutSep2 = max((int)lrintf(0.008f * (float)N),peakWidth1);
56   minCutSep1 = max((int)lrintf(0.011f * (float)N),peakWidth0);
57   if(band==bandMax) kLo = 1;
58   else kLo = max(1L,lrintf(floor(0.5f*(float)N/(float)lo->N*(float)lo->kHi-maxDFMatch*M/TWOPI*(float)N)));
59   if(band==0) kHi = Nover2;
60   else kHi = max(1L,lrintf(0.4785f * N)-peakWidth0*2);
61   kStart = max(1,kLo-peakWidth0);
62   kEnd = min(Nover2-1,kHi+peakWidth0*2);
63   float kNorm = TWOPI / (float)(M * N);
64   maxFHi = (float)kHi * kNorm + maxDF;
65   minFLo = (float)kLo * kNorm - maxDF;
66   if(lo) maxFMatchM = (float)lo->kHi * TWOPI / (float)(lo->N * M * 2) + maxDFMatch;
67   else maxFMatchM = 0.0f;
68   minFMatchL = (float)kLo * kNorm - maxDFMatch;
69   if(lo) maxFMid = (float)lo->kHi * TWOPI / (float)(lo->N * M * 2) + maxDF;
70   else maxFMid = 0.0f;
71   if(lo) lo->minFMid = (float)kLo * kNorm - lo->maxDF;
72   if(lo && lo->lo) {
73     minK = max(1L,(lrintf(0.25f * (float)N / (float)lo->lo->N * (float)lo->lo->kHi + peakWidth0)));
74   } else {
75     minK = 1;
76   }
77   maxK = min(kEnd,kHi + peakWidth0);
78   localFavorRatio = 1.1f;
79   mNorm = MScale * MScale * 16.061113032124002f * pad2 / square((float)N);
80   for(int c=0; c<channels; c++) {
81     bAssignDone[c] = false;
82     addtime[c] = 0;
83     assigntime[c] = 0;
84     trial2time[c] = 0;
85     trial1time[c] = 0;
86     synthtime[c] = 0;
87     for(int k=1; k<256; k++) {
88       trackIndex[c].push(k);
89     }
90     trial2Buf[c] = (float*)malloc(h*res*sizeof(float));
91     trial2RingBuf[c] = new ArrayRingBuffer<float>(0);
92     dmag1[c] = (float*)malloc(N*sizeof(float));
93     mag11[c] = (float*)malloc((Nover2+1)*sizeof(float));
94     x10[c] = (audio*)malloc(N*sizeof(audio));
95     x11[c] = (audio*)malloc(N*sizeof(audio));
96     trial1Buf[c] = (float*)malloc(h*res*sizeof(float));
97     trial1RingBuf[c] = new ArrayRingBuffer<float>(0);
98     dmag0[c] = (float*)malloc(N*sizeof(float));
99     mag01[c] = (float*)malloc((Nover2+1)*sizeof(float));
100     x00[c] = (audio*)malloc(N*sizeof(audio));
101     x01[c] = (audio*)malloc(N*sizeof(audio));
102     mag2[c] = (float*)malloc((Nover2+1)*sizeof(float));
103     dec2[c] = (float*)malloc(N*sizeof(float));
104     x2[c] = (audio*)malloc(N*sizeof(audio));
105 #ifdef MULTITHREADED
106     pthread_mutex_init(&renderMutex[c],NULL);
107     pthread_mutex_init(&trackMutex[c],NULL);
108     pthread_mutex_init(&sliceMutex[c],NULL);
109     pthread_mutex_init(&trial2Mutex[c],NULL);
110     pthread_mutex_init(&trial1Mutex[c],NULL);
111     pthread_mutex_init(&magMutex[c],NULL);
112 #endif
113   }
114   h2cum = 0.0;
115   adjust2time = 0;
116   adjust1time = 0;
117   trial2GrainBuf = new GrainBuf(N,h,N1,hannpoisson);
118   trial1GrainBuf = new GrainBuf(N,h,N0,hannpoisson);
119   peak20 = (float*)calloc(2*N,sizeof(float));
120   peak2N = peak20 + N;
121   for(int k=-Nover2;k<=Nover2;k++) {
122     peak2N[k] = norm2(peak2[(k+N)%N]);
123   }
124 }
125 
~SMS()126 SMS :: ~SMS()
127 {
128   for(int c=0;c<channels;c++) {
129     while(!mag1Queue[c].empty()) {
130       delete mag1Queue[c].front();
131       mag1Queue[c].pop();
132     }
133     while(!mag0Queue[c].empty()) {
134       delete mag0Queue[c].front();
135       mag0Queue[c].pop();
136     }
137     set<Track*> tracks;
138     for(list<Track*>::iterator i=assignTracks[c].begin();
139         i != assignTracks[c].end();
140         ++i ) {
141       tracks.insert(*i);
142     }
143     for(list<Track*>::iterator i=renderTracks[c].begin();
144         i != renderTracks[c].end();
145         ++i ) {
146       tracks.insert(*i);
147     }
148     for(set<Track*>::iterator i=tracks.begin();
149         i != tracks.end();
150         ++i ) {
151       delete *i;
152     }
153     set<Slice*> slices;
154     while(!adjust2SliceQueue[c].empty()) {
155       slices.insert(adjust2SliceQueue[c].front());
156       adjust2SliceQueue[c].pop();
157     }
158     while(!adjust1SliceQueue[c].empty()) {
159       slices.insert(adjust1SliceQueue[c].front());
160       adjust1SliceQueue[c].pop();
161     }
162     for(long k=sliceBuffer[c].readPos; k<sliceBuffer[c].writePos; k++) {
163       slices.insert(sliceBuffer[c].read(k));
164     }
165     for(set<Slice*>::iterator i = slices.begin();
166         i != slices.end();
167         ++i) {
168       Slice *s = *i;
169       TrackPoint *tp = s->bottom;
170       delete s;
171       while(tp) {
172         TrackPoint *tpn = tp->pn;
173         if(!tp->owner) tp->destroy();
174         tp = tpn;
175       }
176     }
177     free(trial2Buf[c]);
178     delete trial2RingBuf[c];
179     free(trial1Buf[c]);
180     delete trial1RingBuf[c];
181     free(dmag1[c]);
182     free(mag11[c]);
183     free(x10[c]);
184     free(x11[c]);
185     free(dmag0[c]);
186     free(mag01[c]);
187     free(x00[c]);
188     free(x01[c]);
189     free(mag2[c]);
190     free(x2[c]);
191     free(dec2[c]);
192   }
193   free(peak20);
194   delete trial2GrainBuf;
195   delete trial1GrainBuf;
196 }
197 
trial2Start(int c)198 void SMS :: trial2Start(int c)
199 {
200   if(band >= minTrial2Band) {
201     memset(trial2Buf[c],0,h*res*sizeof(float));
202   }
203 }
204 
trial2End(int c)205 void SMS :: trial2End(int c)
206 {
207   if(band < minTrial2Band) return;
208 #ifdef MULTITHREADED
209   pthread_mutex_lock(&trial2Mutex[c]);
210 #endif
211   trial2RingBuf[c]->write(trial2Buf[c],h*res);
212 #ifdef MULTITHREADED
213   pthread_mutex_unlock(&trial2Mutex[c]);
214 #endif
215 }
216 
trial2(int c)217 void SMS :: trial2(int c)
218 {
219 #ifdef MULTITHREADED
220   pthread_mutex_lock(&trackMutex[c]);
221 #endif
222   for(list<Track*>::iterator tt = renderTracks[c].begin();
223       tt != renderTracks[c].end();
224       ++tt) {
225     Track *t = (*tt);
226     if(trial2time[c] >= t->start) {
227       if(trial2time[c] > t->last) continue;
228       t->updateM(trial2time[c],synthModeTrial2);
229       if(hi && hi->band >= minTrial2Band) {
230         float f = 0.5f*M;
231         t->updateFPH(trial2time[c],synthModeTrial2,h<<1,f,f);
232         t->synth(hi->trial2Buf[c],trial2time[c],h<<1,synthModeTrial2,c);
233       }
234       if(lo && lo->band >= minTrial2Band) {
235         float f = 2.0f*M;
236         t->updateFPH(trial2time[c],synthModeTrial2,h>>1,f,f);
237         t->synth(lo->trial2Buf[c]+(trial2time[c]&(res*lo->res-1))*(h>>1),trial2time[c],h>>1,synthModeTrial2,c);
238       }
239       if(band >= minTrial2Band) {
240         float f = M;
241         t->updateFPH(trial2time[c],synthModeTrial2,h,f,f);
242       }
243     } else {
244       break;
245     }
246   }
247 #ifdef MULTITHREADED
248   pthread_mutex_unlock(&trackMutex[c]);
249 #endif
250   trial2time[c]++;
251 }
252 
trial1Start(int c)253 void SMS :: trial1Start(int c)
254 {
255   if(band >= minTrial1Band) {
256     memset(trial1Buf[c],0,h*res*sizeof(float));
257   }
258 }
259 
trial1End(int c)260 void SMS :: trial1End(int c)
261 {
262   if(band < minTrial1Band) return;
263 #ifdef MULTITHREADED
264   pthread_mutex_lock(&trial1Mutex[c]);
265 #endif
266   trial1RingBuf[c]->write(trial1Buf[c],h*res);
267 #ifdef MULTITHREADED
268   pthread_mutex_unlock(&trial1Mutex[c]);
269 #endif
270 }
271 
trial1(int c)272 void SMS :: trial1(int c)
273 {
274 #ifdef MULTITHREADED
275   pthread_mutex_lock(&trackMutex[c]);
276 #endif
277   for(list<Track*>::iterator tt = renderTracks[c].begin();
278       tt != renderTracks[c].end();
279       ++tt) {
280     Track *t = (*tt);
281     if(trial1time[c] >= t->start) {
282       if(trial1time[c] > t->last) continue;
283       t->updateM(trial1time[c],synthModeTrial1);
284       if(hi && hi->band >= minTrial1Band) {
285         float f = 0.5f*M;
286         t->updateFPH(trial1time[c],synthModeTrial1,h<<1,f,f);
287         t->synth(hi->trial1Buf[c],trial1time[c],h<<1,synthModeTrial1,c);
288       }
289       if(lo && lo->band >= minTrial1Band) {
290         float f = 2.0f*M;
291         t->updateFPH(trial1time[c],synthModeTrial1,h>>1,f,f);
292         t->synth(lo->trial1Buf[c]+(trial1time[c]&(res*lo->res-1))*(h>>1),trial1time[c],h>>1,synthModeTrial1,c);
293       }
294       if(band >= minTrial1Band) {
295         float f = M;
296         t->updateFPH(trial1time[c],synthModeTrial1,h,f,f);
297         t->synth(trial1Buf[c]+(trial1time[c]&resMask)*h,trial1time[c],h,synthModeTrial1,c);
298       }
299     } else {
300       break;
301     }
302   }
303 #ifdef MULTITHREADED
304   pthread_mutex_unlock(&trackMutex[c]);
305 #endif
306   trial1time[c]++;
307 }
308 
adjust2()309 void SMS :: adjust2()
310 {
311   Slice* slice[2];
312   for(int c=0; c<channels; c++) {
313 #ifdef MULTITHREADED
314     pthread_mutex_lock(&sliceMutex[c]);
315 #endif
316     slice[c] = adjust2SliceQueue[c].front(); adjust2SliceQueue[c].pop();
317 #ifdef MULTITHREADED
318     pthread_mutex_unlock(&sliceMutex[c]);
319 #endif
320   }
321   if(band >= minTrial2Band) {
322 #ifdef MULTITHREADED
323     for(int c=0; c<channels; c++) {
324       pthread_mutex_lock(&trial2Mutex[c]);
325     }
326 #endif
327     adjustInit(trial2RingBuf,trial2GrainBuf);
328 #ifdef MULTITHREADED
329     for(int c=channels-1; c>=0; c--) {
330       pthread_mutex_unlock(&trial2Mutex[c]);
331     }
332 #endif
333     adjust(trial2GrainBuf,mag1Queue,minCutSep1,mag11,dmag1,x11,adjust2time,slice);
334   }
335   if(channels == 2) {
336     for(int c=0; c<2; c++) {
337       for(TrackPoint *pc = slice[c]->bottom;
338           pc;
339           pc = pc->pn) {
340         pc->bOwned = false;
341         pc->cont = NULL;
342       }
343     }
344     for(int c=0; c<2; c++) {
345       int c2 = (c==0?1:0);
346       TrackPoint *begin = slice[c2]->bottom;
347       for(TrackPoint *pc = slice[c]->bottom;
348           pc;
349           pc = pc->pn) {
350         float F;
351         pc->cont = nearestForward(&begin,pc,&F,maxCost2Stereo,maxDFStereo,dMCoeff2Stereo);
352       }
353     }
354     for(TrackPoint *p0 = slice[0]->bottom;
355         p0;
356         p0 = p0->pn) {
357       TrackPoint *p1 = p0->cont;
358       if(p1 && p1->cont == p0) {
359         p0->dupStereo = p1;
360         p1->dupStereo = p0;
361       }
362     }
363   }
364   adjust2time++;
365 }
366 
adjust1(float stretch,float pitch0,float pitch1)367 void SMS :: adjust1(float stretch, float pitch0, float pitch1)
368 {
369   Slice* slice[2];
370   for(int c=0; c<channels; c++) {
371 #ifdef MULTITHREADED
372     pthread_mutex_lock(&sliceMutex[c]);
373 #endif
374     slice[c] = adjust1SliceQueue[c].front(); adjust1SliceQueue[c].pop();
375 #ifdef MULTITHREADED
376     pthread_mutex_unlock(&sliceMutex[c]);
377 #endif
378   }
379   if(band >= minTrial1Band) {
380 #ifdef MULTITHREADED
381     for(int c=0; c<channels; c++) {
382       pthread_mutex_lock(&trial1Mutex[c]);
383     }
384 #endif
385     adjustInit(trial1RingBuf,trial1GrainBuf);
386 #ifdef MULTITHREADED
387     for(int c=channels-1; c>=0; c--) {
388       pthread_mutex_unlock(&trial1Mutex[c]);
389     }
390 #endif
391     adjust(trial1GrainBuf,mag0Queue,minCutSep1,mag01,dmag0,x01,adjust1time,slice);
392   }
393   for(int c=0; c<channels; c++) {
394     delete slice[c];
395   }
396   double h2 = stretch * h1;
397   h2cum += h2;
398   int h2i = lrint(h2cum);
399   h2cum -= h2i;
400   for(int c=0; c<channels; c++) {
401 #ifdef MULTITHREADED
402     pthread_mutex_lock(&renderMutex[c]);
403 #endif
404     nRender[c].push(h2i);
405 #ifdef MULTITHREADED
406     pthread_mutex_unlock(&renderMutex[c]);
407 #endif
408   }
409   list<TrackPoint*> dupStereoPostponed;
410   for(int c=0; c<channels; c++) {
411 #ifdef MULTITHREADED
412     pthread_mutex_lock(&trackMutex[c]);
413 #endif
414     for(list<Track*>::iterator tt = renderTracks[c].begin();
415         tt != renderTracks[c].end();
416         ++tt) {
417       Track *t = (*tt);
418       if(adjust1time >= t->start) {
419         if(adjust1time <= t->last) {
420           TrackPoint *tp = t->updateFPH(adjust1time,synthModeOutput,h2i,pitch0,pitch1);
421           if(tp) dupStereoPostponed.push_back(tp);
422         }
423       } else {
424         break;
425       }
426     }
427 #ifdef MULTITHREADED
428     pthread_mutex_unlock(&trackMutex[c]);
429 #endif
430   }
431   for(list<TrackPoint*>::iterator tpi = dupStereoPostponed.begin();
432       tpi != dupStereoPostponed.end();
433       tpi++) {
434     TrackPoint *tp = (*tpi);
435     tp->phSynth = canon2PI(tp->dupStereo->phSynth + tp->ph - tp->dupStereo->ph);
436   }
437   adjust1time++;
438 }
439 
findCut(float * dmag,int k0,int maxK)440 int SMS :: findCut(float *dmag, int k0, int maxK)
441 {
442   int k;
443   for(k = max(1,k0); k <= maxK; k++) {
444     float dd0 = dmag[k+1] - dmag[k];
445     if(dd0 > 0.0f) {
446       float d02 = square(dmag[k+1] + dmag[k]);
447       if(dd0 * square(dmag[k] + dmag[k-1]) > (dmag[k] - dmag[k-1]) * d02
448          &&
449          dd0 * square(dmag[k+2] + dmag[k+1]) > (dmag[k+2] - dmag[k+1]) * d02) {
450         break;
451       }
452     }
453   }
454   return k;
455 }
456 
adjustInit(ArrayRingBuffer<float> ** trialRingBuf,GrainBuf * trialGrainBuf)457 void SMS :: adjustInit(ArrayRingBuffer<float> **trialRingBuf,
458                        GrainBuf *trialGrainBuf)
459 {
460   long n = trialRingBuf[0]->nReadable();
461   for(int c=1; c<channels; c++) {
462     n = min(n,trialRingBuf[c]->nReadable());
463   }
464   long ndone = 0;
465   while(n) {
466     audio abuf[512];
467     long ntodo = min(512L,n);
468     for(int c=0; c<channels; c++) {
469       float *fbuf = trialRingBuf[c]->getReadBuf();
470       for(int k=0; k<ntodo; k++) {
471         abuf[k][c] = fbuf[ndone+k];
472       }
473     }
474     for(int c=channels; c<2; c++) {
475       for(int k=0; k<ntodo; k++) {
476         abuf[k][c] = 0.0f;
477       }
478     }
479     trialGrainBuf->write(abuf,ntodo);
480     ndone += ntodo;
481     n -= ntodo;
482   }
483   for(int c=0; c<channels; c++) {
484     trialRingBuf[c]->advance(ndone);
485   }
486 }
487 
adjust(GrainBuf * trialGrainBuf,queue<float * > * magQueue,int minCutSep,float ** _mag1,float ** _dmag1,audio ** x1,const TimeType & time,Slice ** slices)488 void SMS :: adjust(GrainBuf *trialGrainBuf,
489                    queue<float*> *magQueue,
490                    int minCutSep,
491                    float **_mag1,
492                    float **_dmag1,
493                    audio **x1,
494                    const TimeType &time,
495                    Slice **slices)
496 {
497   grain *g = trialGrainBuf->read(trialGrainBuf->readPos);
498   g->analyze();
499   for(int c=0; c<channels; c++) {
500     Slice *slice = slices[c];
501     TrackPoint *p = slice->bottom;
502     if(c == 0) {
503       c2even(g->x, x1[0], N);
504     } else {
505       c2odd(g->x, x1[1], N);
506     }
507     float *mag1 = _mag1[c];
508     calcmags(mag1, x1[c]);
509 #ifdef MULTITHREADED
510     pthread_mutex_lock(&magMutex[c]);
511 #endif
512     float *mag0 = magQueue[c].front(); magQueue[c].pop();
513 #ifdef MULTITHREADED
514     pthread_mutex_unlock(&magMutex[c]);
515 #endif
516     if(p) {
517       float *dmag = _dmag1[c];
518       list<int> cuts;
519       int k3 = min(Nover2,maxK+2);
520       dmag[0] = mag1[0];
521       for(int k=max(1,minK-2); k<k3; k++) {
522         dmag[k] = mag1[k] - mag1[k-1];
523       }
524       int k = minK;
525       while(true) {
526         k = findCut(dmag,k+1,maxK);
527         if(k >= maxK) {
528           break;
529         } else  {
530           cuts.push_back(k);
531         }
532       }
533       bool bDone = false;
534       while(!bDone) {
535         bDone = true;
536         for(list<int>::iterator i = cuts.begin();
537             i != cuts.end();
538             ++i) {
539           int k0 = *i;
540           list<int>::iterator ibad = cuts.end();
541           list<int>::iterator i2 = i;
542           ++i2;
543           float maxY = 0.0f;
544           for(;
545               i2 != cuts.end();
546               ++i2) {
547             int k2 = *i2;
548             if(k2 - k0 >= minCutSep) break;
549             float y = mag0[k2] * mag1[k2];
550             if(y >= maxY) {
551               maxY = y;
552               ibad = i2;
553             }
554             k0 = k2;
555           }
556           if(ibad != cuts.end()) {
557             if(mag0[*i] * mag1[*i] > maxY) {
558               ibad = i;
559             }
560             cuts.erase(ibad);
561             bDone = false;
562             break;
563           }
564         }
565       }
566       cuts.push_front(minK);
567       cuts.push_back(maxK);
568       list<int>::iterator i = cuts.begin();
569       while(p) {
570         int k0 = *i;
571         ++i;
572         if(i == cuts.end()) break;
573         int k2 = *i;
574         if(p->x > k2) continue;
575         float m0 = 0.0f;
576         float m1 = 0.0f;
577         for(int k=k0;k<=k2;k++) {
578           m0 += mag0[k];
579           m1 += mag1[k];
580         }
581         float s = (m1>m0?sqrt(m0/m1):1.0f);
582         while(p && p->x <= k2) {
583           p->m *= s;
584           p = p->pn;
585         }
586       }
587     }
588     free(mag0);
589   }
590   trialGrainBuf->advance(1);
591 }
592 
render(int c,list<SBSMSRenderer * > & renderers)593 void SMS :: render(int c, list<SBSMSRenderer*> &renderers)
594 {
595 #ifdef MULTITHREADED
596   pthread_mutex_lock(&renderMutex[c]);
597 #endif
598   int n = nRender[c].front(); nRender[c].pop();
599 #ifdef MULTITHREADED
600   pthread_mutex_unlock(&renderMutex[c]);
601 #endif
602   TimeType time = synthtime[c];
603   for(list<SBSMSRenderer*>::iterator i = renderers.begin(); i != renderers.end(); ++i) {
604     SBSMSRenderer *renderer = *i;
605     renderer->startTime(c,time,n);
606   }
607 #ifdef MULTITHREADED
608   pthread_mutex_lock(&trackMutex[c]);
609 #endif
610   for(list<Track*>::iterator tt = renderTracks[c].begin();
611       tt != renderTracks[c].end();) {
612     Track *t = (*tt);
613     if(t->bEnded && time > t->last) {
614       list<Track*>::iterator eraseMe = tt;
615       ++tt;
616       renderTracks[c].erase(eraseMe);
617       delete t;
618     } else if(time >= t->start) {
619       if(time <= t->last) {
620         t->updateM(time,synthModeOutput);
621         for(list<SBSMSRenderer*>::iterator i = renderers.begin(); i != renderers.end(); ++i) {
622           SBSMSRenderer *renderer = *i;
623           renderer->render(c,t);
624         }
625         t->step(time);
626       }
627       ++tt;
628     } else {
629       break;
630     }
631   }
632 #ifdef MULTITHREADED
633   pthread_mutex_unlock(&trackMutex[c]);
634 #endif
635   for(list<SBSMSRenderer*>::iterator i = renderers.begin(); i != renderers.end(); ++i) {
636     SBSMSRenderer *renderer = *i;
637     renderer->endTime(c);
638   }
639   synthtime[c]++;
640 }
641 
nearestForward(TrackPoint ** begin,TrackPoint * tp0,float * minCost2,float maxCost2,float maxDF,float dMCoeff2,float dNCoeff2)642 TrackPoint *SMS :: nearestForward(TrackPoint **begin, TrackPoint *tp0, float *minCost2, float maxCost2, float maxDF, float dMCoeff2, float dNCoeff2)
643 {
644   *minCost2 = TrackPointNoCont;
645   float minF = tp0->f - maxDF;
646   float maxF = tp0->f + maxDF;
647   float maxDF2 = square(maxDF);
648   while((*begin) && (*begin)->f < minF) {
649     (*begin) = (*begin)->pn;
650   }
651   TrackPoint *mintp1 = NULL;
652   for(TrackPoint *tp1 = (*begin);
653       tp1;
654       tp1 = tp1->pn) {
655     if(tp1->bOwned) continue;
656     float df2 = square(tp1->f - tp0->f);
657     if(df2 > maxDF2) break;
658     float dM2 = dBApprox(tp1->m2,tp0->m2);
659     float cost2 = (df2+dMCoeff2*dM2);
660     if(cost2 > maxCost2) continue;
661     if(cost2 < (*minCost2)) {
662       (*minCost2) = cost2;
663       mintp1 = tp1;
664     }
665   }
666   return mintp1;
667 }
668 
nearestReverse(TrackPoint ** begin,TrackPoint * tp0,float * minCost2,float maxCost2,float maxDF,float dMCoeff2,float dNCoeff2)669 TrackPoint *SMS :: nearestReverse(TrackPoint **begin, TrackPoint *tp0, float *minCost2, float maxCost2, float maxDF, float dMCoeff2, float dNCoeff2)
670 {
671   *minCost2 = TrackPointNoCont;
672   float minF = tp0->f - maxDF;
673   float maxF = tp0->f + maxDF;
674   float maxDF2 = square(maxDF);
675   while((*begin) && (*begin)->f > maxF) {
676     (*begin) = (*begin)->pp;
677   }
678   TrackPoint *mintp1 = NULL;
679   for(TrackPoint *tp1 = (*begin);
680       tp1;
681       tp1 = tp1->pp) {
682     if(tp1->bOwned) continue;
683     float df2 = square(tp1->f - tp0->f);
684     if(df2 > maxDF2) break;
685     float dM2 = dBApprox(tp1->m2,tp0->m2);
686     float cost2 = (df2+dMCoeff2*dM2);
687     if(cost2 > maxCost2) continue;
688     if(cost2 < (*minCost2)) {
689       (*minCost2) = cost2;
690       mintp1 = tp1;
691     }
692   }
693   return mintp1;
694 }
695 
nearestForward2(TrackPoint ** begin,TrackPoint * tp0,float * minCost2,float maxCost2,float maxDF,float dMCoeff2,float dNCoeff2)696 TrackPoint *SMS :: nearestForward2(TrackPoint **begin, TrackPoint *tp0, float *minCost2, float maxCost2, float maxDF, float dMCoeff2, float dNCoeff2)
697 {
698   *minCost2 = TrackPointNoCont;
699   float minF = tp0->f - maxDF;
700   float maxF = tp0->f + maxDF;
701   float maxDF2 = square(maxDF);
702   while((*begin) && (*begin)->f < minF) {
703     (*begin) = (*begin)->pn;
704   }
705   TrackPoint *mintp1 = NULL;
706   for(TrackPoint *tp1 = (*begin);
707       tp1;
708       tp1 = tp1->pn) {
709     if(!tp1->owner) continue;
710     float df2 = square(tp1->f - tp0->f);
711     if(df2 > maxDF2) break;
712     float dM2 = dBApprox(0.25f*tp1->m2,tp0->m2);
713     float cost2 = (df2+dMCoeff2*dM2);
714     if(cost2 > maxCost2) continue;
715     if(cost2 < (*minCost2)) {
716       (*minCost2) = cost2;
717       mintp1 = tp1;
718     }
719   }
720   return mintp1;
721 }
722 
nearestReverse2(TrackPoint ** begin,TrackPoint * tp0,float * minCost2,float maxCost2,float maxDF,float dMCoeff2,float dNCoeff2)723 TrackPoint *SMS :: nearestReverse2(TrackPoint **begin, TrackPoint *tp0, float *minCost2, float maxCost2, float maxDF, float dMCoeff2, float dNCoeff2)
724 {
725   *minCost2 = TrackPointNoCont;
726   float minF = tp0->f - maxDF;
727   float maxF = tp0->f + maxDF;
728   float maxDF2 = square(maxDF);
729   while((*begin) && (*begin)->f > maxF) {
730     (*begin) = (*begin)->pp;
731   }
732   TrackPoint *mintp1 = NULL;
733   for(TrackPoint *tp1 = (*begin);
734       tp1;
735       tp1 = tp1->pp) {
736     if(!tp1->owner) continue;
737     float df2 = square(tp1->f - tp0->f);
738     if(df2 > maxDF2) break;
739     float dM2 = dBApprox(tp1->m2,tp0->m2);
740     float cost2 = (df2+dMCoeff2*dM2);
741     if(cost2 > maxCost2) continue;
742     if(cost2 < (*minCost2)) {
743       (*minCost2) = cost2;
744       mintp1 = tp1;
745     }
746   }
747   return mintp1;
748 }
749 
connect(TrackPoint * tp0,TrackPoint * tp1,int ilo,int c)750 void SMS :: connect(TrackPoint *tp0, TrackPoint *tp1, int ilo, int c)
751 {
752   TimeType time = assigntime[c];
753   if(tp0->slice->band == tp1->slice->band) {
754 #ifdef MULTITHREADED
755     pthread_mutex_lock(&trackMutex[c]);
756 #endif
757     tp0->owner->push_back(tp1);
758 #ifdef MULTITHREADED
759     pthread_mutex_unlock(&trackMutex[c]);
760 #endif
761   } else if(tp0->slice->band < tp1->slice->band) {
762     Track *precursor = tp0->owner;
763     if(ilo == 1) {
764 #ifdef MULTITHREADED
765       pthread_mutex_lock(&trackMutex[c]);
766 #endif
767       precursor->push_back(tp1);
768       precursor->endTrack(true);
769       TimeType time = precursor->end/res;
770 #ifdef MULTITHREADED
771       pthread_mutex_unlock(&trackMutex[c]);
772 #endif
773 #ifdef MULTITHREADED
774       pthread_mutex_lock(&lo->trackMutex[c]);
775 #endif
776       lo->createTrack(c,tp1,time,true);
777 #ifdef MULTITHREADED
778       pthread_mutex_unlock(&lo->trackMutex[c]);
779 #endif
780     } else {
781 #ifdef MULTITHREADED
782       pthread_mutex_lock(&trackMutex[c]);
783 #endif
784       TimeType time = precursor->end/res;
785       precursor->endTrack(true);
786       TrackPoint *last = precursor->back();
787 #ifdef MULTITHREADED
788       pthread_mutex_unlock(&trackMutex[c]);
789 #endif
790 #ifdef MULTITHREADED
791       pthread_mutex_lock(&lo->trackMutex[c]);
792 #endif
793       Track *t = lo->createTrack(c,last,time,true);
794       t->push_back(tp1);
795 #ifdef MULTITHREADED
796       pthread_mutex_unlock(&lo->trackMutex[c]);
797 #endif
798       last->owner = precursor;
799     }
800   } else {
801     Track *precursor = tp0->owner;
802 #ifdef MULTITHREADED
803     pthread_mutex_lock(&trackMutex[c]);
804 #endif
805     precursor->push_back(tp1);
806     precursor->endTrack(true);
807     TimeType time = precursor->end*hi->res;
808 #ifdef MULTITHREADED
809     pthread_mutex_unlock(&trackMutex[c]);
810 #endif
811 #ifdef MULTITHREADED
812     pthread_mutex_lock(&hi->trackMutex[c]);
813 #endif
814     hi->createTrack(c,tp1,time,true);
815 #ifdef MULTITHREADED
816     pthread_mutex_unlock(&hi->trackMutex[c]);
817 #endif
818   }
819   tp0->bConnected = true;
820   tp1->bConnected = true;
821   tp0->bOwned = true;
822   tp1->bOwned = true;
823   if(tp0->dupcont) {
824     TrackPoint *dup = tp0->dupcont;
825     if(!dup->owner) {
826       dup->bOwned = true;
827       dup->bDelete = true;
828     }
829   }
830   TrackPoint *dup2 = tp0->dup[2];
831   if(dup2 && dup2 != tp1 && !dup2->owner) {
832     dup2->bOwned = true;
833     dup2->bDelete = true;
834   }
835   for(int d=0;d<3;d++) {
836     TrackPoint *dup = tp1->dup[d];
837     if(dup && !dup->owner && (d<2 || dup->slice->band < tp1->slice->band)) {
838       dup->bOwned = true;
839       dup->bDelete = true;
840     }
841   }
842 }
843 
mark(long offset,int c)844 void SMS :: mark(long offset, int c)
845 {
846   mark(offset,0,c);
847   if(offset&resMask) {
848     mark(offset,1,c);
849   }
850 }
851 
mark(long offset,long offsetlo,int c)852 void SMS :: mark(long offset, long offsetlo, int c)
853 {
854   if(!lo) return;
855 #ifdef MULTITHREADED
856   pthread_mutex_lock(&lo->sliceMutex[c]);
857 #endif
858   Slice *sliceL1 = lo->sliceBuffer[c].read(lo->sliceBuffer[c].readPos+offset/res+offsetlo);
859 #ifdef MULTITHREADED
860   pthread_mutex_unlock(&lo->sliceMutex[c]);
861 #endif
862 #ifdef MULTITHREADED
863   pthread_mutex_lock(&sliceMutex[c]);
864 #endif
865   Slice *sliceM1 = sliceBuffer[c].read(sliceBuffer[c].readPos+offset);
866 #ifdef MULTITHREADED
867   pthread_mutex_unlock(&sliceMutex[c]);
868 #endif
869   bool b0 = !(offset&resMask);
870   bool bDone = false;
871   bool bLastDitch = false;
872   while(!bDone) {
873     int nToCont = 0;
874     int nCont = 0;
875     TrackPoint *rbegin = NULL;
876     TrackPoint *begin = sliceL1->bottom;
877     for(TrackPoint *tp = sliceM1->bottom;
878         tp;
879         tp = tp->pn) {
880       if(tp->bMarked) continue;
881       if(tp->f > maxFMatchM) {
882         break;
883       } else {
884         rbegin = tp;
885       }
886       float F;
887       tp->cont = nearestForward(&begin,tp,&F,maxCost2Match,maxDFMatch,dMCoeff2Match);
888       if(tp->cont) nToCont++;
889     }
890     if(sliceL1) {
891       for(TrackPoint *tp = sliceL1->top;
892           tp;
893           tp = tp->pp) {
894         if(tp->f < minFLo) break;
895         float F;
896         tp->cont = nearestReverse(&rbegin,tp,&F,maxCost2Match,maxDFMatch,dMCoeff2Match);
897       }
898     }
899     for(TrackPoint *tp0 = sliceM1->bottom;
900         tp0;
901         tp0 = tp0->pn) {
902       if(tp0->bMarked) continue;
903       if(tp0->f > maxFMatchM) {
904         break;
905       }
906       TrackPoint *tp1 = tp0->cont;
907       if(tp1) {
908         if(bLastDitch || tp1->cont == tp0) {
909           nCont++;
910           bool bAlreadyMarked = false;
911           if(b0) {
912             if(tp1->dup[1] || tp0->dup[1]) {
913               bAlreadyMarked = true;
914             }
915           } else {
916             if(tp1->dup[2-2*offsetlo] || tp0->dup[2*offsetlo]) {
917               bAlreadyMarked = true;
918             }
919           }
920           if(!bAlreadyMarked) {
921             if(b0) {
922               tp1->dup[1] = tp0;
923               tp0->dup[1] = tp1;
924             } else {
925               tp1->dup[2-2*offsetlo] = tp0;
926               tp0->dup[2*offsetlo] = tp1;
927             }
928           }
929           tp0->bMarked = true;
930         }
931       }
932     }
933     bDone = (nToCont == nCont);
934     bLastDitch = (!bDone && nCont==0);
935   }
936 }
937 
assignStart(long offset,int c)938 void SMS :: assignStart(long offset, int c)
939 {
940   bAssignDone[c] = false;
941 #ifdef MULTITHREADED
942   pthread_mutex_lock(&sliceMutex[c]);
943 #endif
944   sliceM0[c] = sliceBuffer[c].read(sliceBuffer[c].readPos+offset);
945   sliceM1[c] = sliceBuffer[c].read(sliceBuffer[c].readPos+offset+1);
946   if(res == 2) {
947     sliceM2[c] = sliceBuffer[c].read(sliceBuffer[c].readPos+offset+2);
948   } else {
949     sliceM2[c] = NULL;
950   }
951 #ifdef MULTITHREADED
952   pthread_mutex_unlock(&sliceMutex[c]);
953 #endif
954   for(TrackPoint *tp = sliceM0[c]->bottom;
955       tp;
956       tp = tp->pn) {
957     if(!tp->owner->bEnded) {
958       tp->owner->bEnd = true;
959       tp->bConnected = false;
960       tp->bOwned = false;
961     } else {
962       tp->bConnected = true;
963       tp->bOwned = true;
964     }
965   }
966 #ifdef MULTITHREADED
967   if(hi) pthread_mutex_lock(&hi->sliceMutex[c]);
968 #endif
969   sliceH0[c] = hi?hi->sliceBuffer[c].read(hi->sliceBuffer[c].readPos+(offset+1)*hi->res):NULL;
970   sliceH0[c] = NULL;
971   sliceH1[c] = hi?hi->sliceBuffer[c].read(hi->sliceBuffer[c].readPos+(offset+1)*hi->res):NULL;
972 #ifdef MULTITHREADED
973   if(hi) pthread_mutex_unlock(&hi->sliceMutex[c]);
974 #endif
975 #ifdef MULTITHREADED
976   if(lo) pthread_mutex_lock(&lo->sliceMutex[c]);
977 #endif
978   sliceL0[c] = lo?lo->sliceBuffer[c].read(lo->sliceBuffer[c].readPos+offset/res+1):NULL;
979   sliceL0[c] = NULL;
980   sliceL1[c] = lo?lo->sliceBuffer[c].read(lo->sliceBuffer[c].readPos+offset/res+1):NULL;
981 #ifdef MULTITHREADED
982 	if(lo) pthread_mutex_unlock(&lo->sliceMutex[c]);
983 #endif
984 }
985 
assignInit(long offset,int c)986 void SMS :: assignInit(long offset, int c)
987 {
988   for(TrackPoint *tp = sliceM1[c]->bottom;
989       tp;
990       tp = tp->pn) {
991     tp->cont = NULL;
992     tp->contF = TrackPointNoCont;
993   }
994   if(sliceM2[c]) {
995     for(TrackPoint *tp = sliceM2[c]->bottom;
996         tp;
997         tp = tp->pn) {
998       tp->cont = NULL;
999       tp->contF = TrackPointNoCont;
1000     }
1001   }
1002 }
1003 
assignFind(long offset,int c)1004 void SMS :: assignFind(long offset, int c)
1005 {
1006   if(bAssignDone[c]) return;
1007   Slice *sliceM0 = this->sliceM0[c];
1008   Slice *sliceM1 = this->sliceM1[c];
1009   Slice *sliceM2 = this->sliceM2[c];
1010   Slice *sliceL1 = this->sliceL1[c];
1011   Slice *sliceH1 = this->sliceH1[c];
1012   TrackPoint *begin;
1013   begin = sliceM0->bottom;
1014   for(TrackPoint *tp = sliceM1->bottom;
1015       tp;
1016       tp = tp->pn) {
1017     if(tp->bOwned) continue;
1018     float F;
1019     tp->bConnect = false;
1020     TrackPoint *minM = nearestForward(&begin,tp,&F,maxCost2,maxDF,dMCoeff2,dNCoeff2);
1021     if(minM && F < tp->contF) {
1022       tp->cont = minM;
1023       tp->contF = F;
1024     }
1025   }
1026   if(sliceL1) {
1027     TrackPoint *rbegin = sliceM0->top;
1028     for(TrackPoint *tp = sliceL1->top;
1029         tp;
1030         tp = tp->pp) {
1031       if(tp->bOwned) continue;
1032       if(tp->f < minFLo) break;
1033       float F;
1034       TrackPoint *minL = nearestReverse(&rbegin,tp,&F,maxCost2,maxDF,dMCoeff2,dNCoeff2);
1035       if(minL) {
1036         F *= localFavorRatio;
1037         if(F < tp->contF) {
1038           tp->cont = minL;
1039           tp->contF = F;
1040         }
1041       }
1042     }
1043   }
1044   begin = sliceM0->bottom;
1045   if(sliceH1) {
1046     for(TrackPoint *tp = sliceH1->bottom;
1047         tp;
1048         tp = tp->pn) {
1049       if(tp->bOwned) continue;
1050       if(tp->f > maxFHi) break;
1051       float F;
1052       TrackPoint *minH = nearestForward(&begin,tp,&F,maxCost2,maxDF,dMCoeff2,dNCoeff2);
1053       if(minH) {
1054         F *= localFavorRatio;
1055         if(F < tp->contF) {
1056           tp->cont = minH;
1057           tp->contF = F;
1058         }
1059       }
1060     }
1061   }
1062   if(sliceM2 && !(offset&resMask)) {
1063     begin = sliceM1->bottom;
1064     for(TrackPoint *tp = sliceM2->bottom;
1065         tp;
1066         tp = tp->pn) {
1067       if(tp->bOwned) continue;
1068       float F;
1069       tp->bConnect = false;
1070       TrackPoint *minM = nearestForward(&begin,tp,&F,maxCost2,maxDF,dMCoeff2);
1071       if(minM) {
1072         tp->cont = minM;
1073         tp->contF = F;
1074       }
1075     }
1076     if(sliceL1) {
1077       for(TrackPoint *tp = sliceM2->bottom;
1078           tp;
1079           tp = tp->pn) {
1080         if(tp->bOwned) continue;
1081         if(tp->f > maxFMid) break;
1082         float F;
1083         TrackPoint *rbegin = sliceL1->top;
1084         TrackPoint *minL = nearestReverse(&rbegin,tp,&F,maxCost2,maxDF,dMCoeff2);
1085         if(minL) {
1086           F *= localFavorRatio;
1087           if(F < tp->contF) {
1088             tp->cont = minL;
1089             tp->contF = F;
1090           }
1091         }
1092       }
1093     }
1094   }
1095 }
1096 
assignConnect(long offset,int c,bool bLastDitch)1097 bool SMS :: assignConnect(long offset, int c, bool bLastDitch)
1098 {
1099   if(bAssignDone[c]) return false;
1100   Slice *sliceM0 = this->sliceM0[c];
1101   Slice *sliceM1 = this->sliceM1[c];
1102   Slice *sliceL1 = this->sliceL1[c];
1103   Slice *sliceH1 = this->sliceH1[c];
1104   int nToCont = 0;
1105   int nCont = 0;
1106   bool b0 = !(offset&resMask);
1107   int ilo;
1108   if(res == 2 && b0) {
1109     ilo = 0;
1110   } else {
1111     ilo = 1;
1112   }
1113   TrackPoint *beginM1 = sliceM1->bottom;
1114   TrackPoint *beginH1;
1115   if(sliceH1) beginH1 = sliceH1->bottom;
1116   for(TrackPoint *tp = sliceM0->bottom;
1117       tp;
1118       tp = tp->pn) {
1119     if(tp->bOwned) continue;
1120     float FM1 = TrackPointNoCont;
1121     float FL1 = TrackPointNoCont;
1122     float FH1 = TrackPointNoCont;
1123     TrackPoint *minM1 = nearestForward(&beginM1,tp,&FM1,maxCost2,maxDF,dMCoeff2,dNCoeff2);
1124     TrackPoint *minL1 = NULL;
1125     if(sliceL1 && tp->f < maxFMid) {
1126       TrackPoint *rbeginL1 = sliceL1->top;
1127       minL1 = nearestReverse(&rbeginL1,tp,&FL1,maxCost2,maxDF,dMCoeff2,dNCoeff2);
1128       FL1 *= localFavorRatio;
1129     }
1130     TrackPoint *minH1 = NULL;
1131     if(sliceH1 && tp->f > minFMid) {
1132       minH1 = nearestForward(&beginH1,tp,&FH1,maxCost2,maxDF,dMCoeff2,dNCoeff2);
1133       FH1 *= localFavorRatio;
1134     }
1135     if(minM1 &&
1136        ((FM1<=FH1 && FM1<=FL1)
1137         ||(minL1 && FL1<=FH1 && FL1<=FM1 && minL1->dup[ilo] == minM1)
1138         ||(minH1 && FH1<=FL1 && FH1<=FM1 && minH1->dup[1] == minM1))) {
1139       if(ilo == 1 && minL1 && minL1->dup[1] == minM1) {
1140         tp->dupcont = minL1;
1141       } else if(minH1 && minH1->dup[1] == minM1) {
1142         tp->dupcont = minH1;
1143       } else {
1144         tp->dupcont = NULL;
1145       }
1146       tp->contF = FM1;
1147       tp->cont = minM1;
1148       nToCont++;
1149     } else if(minL1 && FL1<=FM1 && FL1<=FH1) {
1150       if(minM1 && minL1->dup[ilo] == minM1) {
1151         tp->dupcont = minM1;
1152       } else {
1153         tp->dupcont = NULL;
1154       }
1155       tp->contF = FL1;
1156       tp->cont = minL1;
1157       nToCont++;
1158     } else if(minH1 && FH1<=FM1 && FH1<=FL1) {
1159       if(minM1 && minH1->dup[1] == minM1) {
1160         tp->dupcont = minM1;
1161       } else {
1162         tp->dupcont = NULL;
1163       }
1164       tp->contF = FH1;
1165       tp->cont = minH1;
1166       nToCont++;
1167     } else {
1168       tp->cont = NULL;
1169     }
1170   }
1171   for(TrackPoint *tp0 = sliceM0->bottom;
1172       tp0;
1173       tp0 = tp0->pn) {
1174     if(tp0->bOwned) continue;
1175     tp0->bConnect = false;
1176     TrackPoint *tp1 = tp0->cont;
1177     TimeType time = assigntime[c];
1178     if(tp1 && !tp1->bOwned &&
1179        (bLastDitch ||
1180         (tp1->cont == tp0) ||
1181         ((tp1->cont && tp0->contF <= tp1->cont->contF) &&
1182          ((tp1->cont->dup[0] == tp0) ||
1183           (tp1->cont->dup[1] == tp0))))) {
1184       tp1->cont = tp0;
1185       tp0->bConnect = true;
1186       tp1->bConnect = true;
1187     }
1188   }
1189   for(TrackPoint *tp0 = sliceM0->bottom;
1190       tp0;
1191       tp0 = tp0->pn) {
1192     if(tp0->bOwned) continue;
1193     TrackPoint *tp1 = tp0->cont;
1194     if(tp0->bConnect && tp1 && !tp1->bOwned && tp1->bConnect && tp1->cont == tp0) {
1195       TrackPoint *dupcont = tp0->dupcont;
1196       if(dupcont && dupcont->bConnect) {
1197         if(!tp1->bConnected && !dupcont->bConnected) {
1198           if(!tp0->bConnected && (dupcont->cont == NULL || tp0->contF <= dupcont->cont->contF)) {
1199             nCont++;
1200             connect(tp0,tp1,ilo,c);
1201             tp0->owner->bEnd = false;
1202             dupcont->bConnect = false;
1203           } else if(dupcont->cont && !dupcont->cont->bConnected) {
1204             nCont++;
1205             connect(dupcont->cont,dupcont,ilo,c);
1206             dupcont->cont->owner->bEnd = false;
1207             tp1->bConnect = false;
1208           }
1209         }
1210       } else if(!tp0->bConnected && !tp1->bConnected) {
1211         nCont++;
1212         connect(tp0,tp1,ilo,c);
1213         tp0->owner->bEnd = false;
1214       }
1215     }
1216   }
1217   bAssignDone[c] = (nToCont == nCont || bLastDitch);
1218   return !(bAssignDone[c] || nCont == 0);
1219 }
1220 
start(long offset,int c)1221 void SMS :: start(long offset, int c)
1222 {
1223   started[c].clear();
1224   ended[c].clear();
1225 #ifdef MULTITHREADED
1226   pthread_mutex_lock(&trackMutex[c]);
1227 #endif
1228   for(list<Track*>::iterator tt = assignTracks[c].begin();
1229       tt != assignTracks[c].end(); ) {
1230     Track *t = (*tt);
1231     bool bKeep;
1232     if(t->bEnded) {
1233       bKeep = ((!t->bRender) && (t->bStitch || t->size() >= minTrackSize));
1234       if(assigntime[c] > t->last) {
1235         returnTrackIndex(c,t);
1236         list<Track*>::iterator eraseMe = tt;
1237         ++tt;
1238         assignTracks[c].erase(eraseMe);
1239       } else {
1240         ++tt;
1241       }
1242     } else if(t->bEnd) {
1243       bKeep = (t->bStitch || t->size() >= minTrackSize);
1244       if(bKeep) {
1245         bKeep = !t->bRender;
1246         t->endTrack(false);
1247         ended[c].push_back(t->back());
1248         ++tt;
1249       } else {
1250         list<Track*>::iterator eraseMe = tt;
1251         ++tt;
1252         assignTracks[c].erase(eraseMe);
1253         returnTrackIndex(c,t);
1254         t->absorb();
1255         delete t;
1256         continue;
1257       }
1258     } else {
1259       bKeep = ((!t->bRender) && (t->bStitch || t->size() >= minTrackSize));
1260       ++tt;
1261     }
1262     if(bKeep) {
1263       list<Track*>::reverse_iterator tt0 = renderTracks[c].rbegin();
1264       while(tt0 != renderTracks[c].rend()) {
1265         Track *t0 = *tt0;
1266         if(t->start >= t0->start) {
1267           break;
1268         }
1269         tt0++;
1270       }
1271       renderTracks[c].insert(tt0.base(),t);
1272       t->bRender = true;
1273     }
1274   }
1275 #ifdef MULTITHREADED
1276   pthread_mutex_unlock(&trackMutex[c]);
1277 #endif
1278 #ifdef MULTITHREADED
1279   pthread_mutex_lock(&sliceMutex[c]);
1280 #endif
1281   Slice *sliceM0 = sliceBuffer[c].read(sliceBuffer[c].readPos+offset);
1282   adjust2SliceQueue[c].push(sliceM0);
1283   adjust1SliceQueue[c].push(sliceM0);
1284 #ifdef MULTITHREADED
1285   pthread_mutex_unlock(&sliceMutex[c]);
1286 #endif
1287   for(TrackPoint *tp = sliceM0->bottom;
1288       tp;) {
1289     TrackPoint *tpn = tp->pn;
1290     if(tp->bOwned) {
1291       if(tp->bDelete) {
1292         tp->destroy();
1293       }
1294     } else {
1295       Track *t = createTrack(c,tp,assigntime[c],false);
1296       started[c].push_back(tp);
1297       for(int d=0;d<2;d++) {
1298         TrackPoint *dup = tp->dup[d];
1299         if(dup && !dup->owner) {
1300           dup->destroy();
1301         }
1302       }
1303     }
1304     tp = tpn;
1305   }
1306   assigntime[c]++;
1307 }
1308 
splitMerge(int c)1309 void SMS :: splitMerge(int c)
1310 {
1311   TimeType time = assigntime[c] - 1;
1312 #ifdef MULTITHREADED
1313   pthread_mutex_lock(&trackMutex[c]);
1314 #endif
1315   Slice *sliceM0 = this->sliceM0[c];
1316   Slice *sliceL0 = this->sliceL0[c];
1317   Slice *sliceH0 = this->sliceH0[c];
1318   Slice *sliceM1 = this->sliceM1[c];
1319   Slice *sliceL1 = this->sliceL1[c];
1320   Slice *sliceH1 = this->sliceH1[c];
1321   TrackPoint *rbeginL0 = sliceL0?sliceL0->top:NULL;
1322   TrackPoint *beginM0 = sliceM0->bottom;
1323   TrackPoint *beginH0 = sliceH0?sliceH0->bottom:NULL;
1324   for(list<TrackPoint*>::iterator i = started[c].begin();
1325       i != started[c].end();
1326       ++i) {
1327     TrackPoint *tp = *i;
1328     float F, FL, FH;
1329     tp->cont = nearestForward2(&beginM0,tp,&F,maxCost2SplitMerge,maxDFSplitMerge,dMCoeff2SplitMerge);
1330     TrackPoint *minL = nearestReverse2(&rbeginL0,tp,&FL,maxCost2SplitMerge,maxDFSplitMerge,dMCoeff2SplitMerge);
1331     if(minL) {
1332       FL *= localFavorRatio;
1333       if(FL < F) {
1334         tp->cont = minL;
1335         F = FL;
1336       }
1337     }
1338     TrackPoint *minH = nearestForward2(&beginH0,tp,&FH,maxCost2SplitMerge,maxDFSplitMerge,dMCoeff2SplitMerge);
1339     if(minH) {
1340       FH *= localFavorRatio;
1341       if(FH < F) {
1342         tp->cont = minH;
1343       }
1344     }
1345     if(tp->cont) {
1346       tp->owner->point.insert(tp->owner->point.begin(),tp->cont);
1347       tp->owner->first--;
1348       tp->owner->bStitch = true;
1349       tp->bSplit = true;
1350       tp->cont->bSplit = true;
1351       tp->owner->bSplit = true;
1352       tp->cont->refCount++;
1353       tp->cont->owner->bStitch = true;
1354     }
1355   }
1356 
1357   TrackPoint *rbeginL1 = sliceL1?sliceL1->top:NULL;
1358   TrackPoint *beginM1 = sliceM1->bottom;
1359   TrackPoint *beginH1 = sliceH1?sliceH1->bottom:NULL;
1360   for(list<TrackPoint*>::iterator i = ended[c].begin();
1361       i != ended[c].end();
1362       ++i) {
1363     TrackPoint *tp = *i;
1364     float F, FL, FH;
1365     tp->cont = nearestForward2(&beginM1,tp,&F,maxCost2SplitMerge,maxDFSplitMerge,dMCoeff2SplitMerge);
1366     TrackPoint *minL = nearestReverse2(&rbeginL1,tp,&FL,maxCost2SplitMerge,maxDFSplitMerge,dMCoeff2SplitMerge);
1367     if(minL) {
1368       FL *= localFavorRatio;
1369       if(FL < F) {
1370         tp->cont = minL;
1371         F = FL;
1372       }
1373     }
1374     TrackPoint *minH = nearestForward2(&beginH1,tp,&FH,maxCost2SplitMerge,maxDFSplitMerge,dMCoeff2SplitMerge);
1375     if(minH) {
1376       FH *= localFavorRatio;
1377       if(FH < F) {
1378         tp->cont = minH;
1379       }
1380     }
1381     if(tp->cont) {
1382       tp->owner->point.insert(tp->owner->point.end(),tp->cont);
1383       tp->owner->last++;
1384       tp->owner->bStitch = true;
1385       tp->bMerge = true;
1386       tp->cont->bMerge = true;
1387       tp->owner->bMerge = true;
1388       tp->cont->refCount++;
1389       tp->cont->owner->bStitch = true;
1390     }
1391   }
1392 #ifdef MULTITHREADED
1393   pthread_mutex_unlock(&trackMutex[c]);
1394 #endif
1395 }
1396 
advance(int c)1397 void SMS :: advance(int c)
1398 {
1399 #ifdef MULTITHREADED
1400   pthread_mutex_lock(&sliceMutex[c]);
1401 #endif
1402   sliceBuffer[c].advance(1);
1403 #ifdef MULTITHREADED
1404   pthread_mutex_unlock(&sliceMutex[c]);
1405 #endif
1406 }
1407 
add(grain * g0,grain * g1,grain * g2,int c)1408 void SMS :: add(grain *g0, grain *g1, grain *g2, int c)
1409 {
1410   if(c == 0) {
1411     if(band >= minTrial1Band) {
1412       c2even(g0->x, x00[0], N);
1413     }
1414     if(band >= minTrial2Band) {
1415       c2even(g1->x, x10[0], N);
1416     }
1417     c2even(g2->x, x2[0], N);
1418   } else {
1419     if(band >= minTrial1Band) {
1420       c2odd(g0->x, x00[1], N);
1421     }
1422     if(band >= minTrial2Band) {
1423       c2odd(g1->x, x10[1], N);
1424     }
1425     c2odd(g2->x, x2[1], N);
1426   }
1427 
1428   float *mag0;
1429   if(band >= minTrial1Band) {
1430     mag0 = (float*)malloc((Nover2+1)*sizeof(float));
1431     calcmags(mag0, x00[c]);
1432   }
1433   float *mag1;
1434   if(band >= minTrial2Band) {
1435     mag1 = (float*)malloc((Nover2+1)*sizeof(float));
1436     calcmags(mag1, x10[c]);
1437   }
1438   float mag2sum[1024];
1439   memset(mag2sum,0,1024*sizeof(float));
1440 
1441   float *mag2 = this->mag2[c];
1442   calcmags(mag2sum, g2->x);
1443   calcmags(mag2sum, x2[c]);
1444   calcmags(mag2, x2[c]);
1445 #ifdef MULTITHREADED
1446   pthread_mutex_lock(&magMutex[c]);
1447 #endif
1448   if(band >= minTrial1Band) mag0Queue[c].push(mag0);
1449   if(band >= minTrial2Band) mag1Queue[c].push(mag1);
1450 #ifdef MULTITHREADED
1451   pthread_mutex_unlock(&magMutex[c]);
1452 #endif
1453   float magmax = mag2[0];
1454   for(int k=1;k<=kEnd;k++) {
1455     if(magmax < mag2[k]) magmax = mag2[k];
1456   }
1457   float peakmin = magmax * peakThresh;
1458 
1459   float xt2 = 1.0f;
1460   bool bTroughN1 = false;
1461   bool bTroughN2 = false;
1462   float x0 = 1.0f;
1463   float y0 = mag2[1];
1464   float x1 = 0.0f;
1465   float y1 = 0.0f;
1466   bool bX0 = !lo;
1467   bool bX1 = false;
1468   TrackPoint *prev = NULL;
1469 
1470   Slice *slice = new Slice(band,addtime[c]);
1471 
1472   for(int k=1; k<=kEnd; k++) {
1473     if(mag2[k] > peakmin && mag2[k] > mag2[k-1] && mag2[k] >= mag2[k+1]) {
1474       if(k < kLo) {
1475         x0 = findExtremum(mag2,mag2,k,&y0);
1476         bX0 = true;
1477       } else if(k > kHi) {
1478         if(!bX1) {
1479           x1 = findExtremum(mag2,mag2,k,&y1);
1480           if(prev) {
1481             prev->x01 = x1;
1482             prev->y01 = y1;
1483           }
1484           bX1 = true;
1485         }
1486       } else {
1487         TrackPoint *p = new TrackPoint(slice,peak2N,x2[c],mag2,mag2,k,N,band);
1488 
1489         if(prev) {
1490           prev->pn = p;
1491           p->pp = prev;
1492         } else {
1493           slice->bottom = p;
1494         }
1495         slice->top = p;
1496         prev = p;
1497         p->xtn2 = (float)maxK;
1498         bTroughN1 = true;
1499         bTroughN2 = true;
1500         p->xtp2 = xt2;
1501         p->x01 = x0;
1502         p->y01 = y0;
1503       }
1504     } else if(mag2[k] <= mag2[k-1] && mag2[k] <= mag2[k+1]) {
1505       xt2 = findExtremum(mag2,mag2,k,NULL);
1506       xt2 = max(1.0f,xt2);
1507       xt2 = min((float)kEnd,xt2);
1508       if(bTroughN2) {
1509         prev->xtn2 = xt2;
1510         bTroughN2 = false;
1511       }
1512     }
1513   }
1514   if(bTroughN2) {
1515     prev->xtn2 = (float)kEnd;
1516   }
1517   if(!bX1 && !hi) {
1518     x1 = (float)kEnd;
1519     y1 = mag2[kEnd];
1520     bX1 = true;
1521   }
1522   float *dec2 = this->dec2[c];
1523   memset(dec2,0,(Nover2+1)*sizeof(float));
1524   if(bX0 && prev) {
1525     int k1 = lrintf(x0);
1526     int ko1 = k1 > x0 ? -1 : 1;
1527     float kf1 = k1 > x0 ? k1 - x0 : x0 - k1;
1528     int k3 = min(kEnd,k1+peakWidth2);
1529     for(int k=lrintf(slice->bottom->xtp2);k<=k3;k++) {
1530       float m = interp2(k-k1,ko1,kf1);
1531       dec2[k] += m * y0;
1532     }
1533   }
1534   if(bX1 && prev) {
1535     int k1 = lrintf(x1);
1536     int ko1 = k1 > x1 ? -1 : 1;
1537     float kf1 = k1 > x1 ? k1 - x1 : x1 - k1;
1538     int k3 = lrintf(slice->top->xtn2);
1539     for(int k=max(0,k1-peakWidth2);k<=k3;k++) {
1540       float m = interp2(k-k1,ko1,kf1);
1541       dec2[k] += m * y1;
1542     }
1543   }
1544   for(TrackPoint *p = slice->bottom;
1545       p;
1546       p = p->pn) {
1547     int k1 = lrintf(p->x);
1548     int ko1 = k1 > p->x ? -1 : 1;
1549     float kf1 = k1 > p->x ? k1 - p->x : p->x - k1;
1550     int k0 = lrintf(p->xtp2);
1551     float kf0 = (k0 > p->xtp2 ? k0 - p->xtp2 : p->xtp2 - k0);
1552     int k2 = lrintf(p->xtn2);
1553     float kf2 = (k2 > p->xtn2 ? k2 - p->xtn2 : p->xtn2 - k2);
1554     float m2 = 0.0f;
1555     if(k0 < p->xtp2) {
1556       m2 += (mag2[k0] + mag2[k0+1]) * 0.5f * (1.0f - kf0) + 0.5f * mag2[k0+1];
1557       int i = k0 - k1;
1558       float m = interp2(i,ko1,kf1) * p->y;
1559       m = min(m,mag2[k0]) * 0.5f * (1.0f + kf0);
1560       m2 += m;
1561       dec2[k0] += m;
1562       m = interp2(i+1,ko1,kf1) * p->y;
1563       m = min(m,mag2[k0+1]) * 0.5f * kf0;
1564       m2 += m;
1565       dec2[k0+1] += m;
1566       m = interp2(i-1,ko1,kf1) * p->y;
1567       m = min(m,mag2[k0-1]);
1568       m2 += m;
1569       dec2[k0-1] += m;
1570     } else {
1571       m2 += (mag2[k0] + mag2[k0-1]) * 0.5f * kf0 + 0.5f * mag2[k0] + mag2[k0+1];
1572       int i = k0 - k1;
1573       float m = interp2(i,ko1,kf1) * p->y;
1574       m = min(m,mag2[k0]) * 0.5f * (1.0f - kf0);
1575       m2 += m;
1576       dec2[k0] += m;
1577       m = interp2(i-1,ko1,kf1) * p->y;
1578       m = min(m,mag2[k0-1]) * 0.5f * (2.0f - kf0);
1579       m2 += m;
1580       dec2[k0-1] += m;
1581     }
1582     if(k2 < p->xtn2) {
1583       m2 += mag2[k2-1] + 0.5f * mag2[k2] + 0.5f * kf2 * (mag2[k2] + mag2[k2+1]);
1584       int i = k2 - k1;
1585       float m = interp2(i,ko1,kf1) * p->y;
1586       m = min(m,mag2[k2]) * 0.5f * (1.0f - kf2);
1587       m2 += m;
1588       dec2[k2] += m;
1589       m = interp2(i+1,ko1,kf1) * p->y;
1590       m = min(m,mag2[k2+1]) * 0.5f * (2.0f - kf2);
1591       m2 += m;
1592       dec2[k2+1] += m;
1593     } else {
1594       m2 += (mag2[k2-1] + mag2[k2]) * (1.0f - kf2) * 0.5f + 0.5f * mag2[k2-1];
1595       int i = k2 - k1;
1596       float m = interp2(i,ko1,kf1) * p->y;
1597       m = min(m,mag2[k2]) * 0.5f * (1.0f + kf2);
1598       m2 += m;
1599       dec2[k2] += m;
1600       m = interp2(i-1,ko1,kf1) * p->y;
1601       m = min(m,mag2[k2-1]) * 0.5f * kf2;
1602       m2 += m;
1603       dec2[k2-1] += m;
1604       m = interp2(i+1,ko1,kf1) * p->y;
1605       m = min(m,mag2[k2+1]);
1606       m2 += m;
1607       dec2[k2+1] += m;
1608     }
1609     for(int k=k0+2;k<k2-1;k++) {
1610       m2 += mag2[k];
1611     }
1612     if(k0 + 1 == k2 - 1) {
1613       m2 -= mag2[k0+1];
1614     }
1615     for(int k=max(0,k1-peakWidth2);k<k0-1;k++) {
1616       float m = interp2(k-k1,ko1,kf1) * p->y;
1617       m = min(m,mag2[k]);
1618       m2 += m;
1619       dec2[k] += m;
1620     }
1621     int k3 = min(kEnd,k1+peakWidth2);
1622     for(int k=k2+2;k<=k3;k++) {
1623       float m = interp2(k-k1,ko1,kf1) * p->y;
1624       m = min(m,mag2[k]);
1625       m2 += m;
1626       dec2[k] += m;
1627     }
1628     p->m2 = m2;
1629   }
1630   float m2max = 0.0f;
1631   for(TrackPoint *p = slice->bottom;
1632       p;
1633       p = p->pn) {
1634     int k1 = lrintf(p->x);
1635     int ko1 = k1 > p->x ? -1 : 1;
1636     float kf1 = k1 > p->x ? k1 - p->x : p->x - k1;
1637     int k0 = lrintf(p->xtp2);
1638     float kf0 = (k0 > p->xtp2 ? k0 - p->xtp2 : p->xtp2 - k0);
1639     int k2 = lrintf(p->xtn2);
1640     float kf2 = (k2 > p->xtn2 ? k2 - p->xtn2 : p->xtn2 - k2);
1641     float mdec = 0.0f;
1642     if(k0 < p->xtp2) {
1643       mdec += (dec2[k0] + dec2[k0+1]) * 0.5f * (1.0f - kf0) + 0.5f * dec2[k0+1];
1644     } else {
1645       mdec += (dec2[k0] + dec2[k0-1]) * 0.5f * kf0 + 0.5f * dec2[k0] + dec2[k0+1];
1646     }
1647     if(k2 < p->xtn2) {
1648       mdec += dec2[k2-1] + 0.5f * dec2[k2] + 0.5f * kf2 * (dec2[k2] + dec2[k2+1]);
1649     } else {
1650       mdec += (dec2[k2-1] + dec2[k2]) * (1.0f - kf2) * 0.5f + 0.5f * dec2[k2-1];
1651     }
1652     for(int k=k0+2;k<k2-1;k++) {
1653       mdec += dec2[k];
1654     }
1655     if(k0 + 1 == k2 - 1) {
1656       mdec -= dec2[k0+1];
1657     }
1658 
1659     p->m2 -= mdec;
1660     p->m2 *= mNorm;
1661     if(p->m2 > m2max) {
1662       m2max = p->m2;
1663     }
1664   }
1665   float m2min = m2max * peakThresh;
1666   for(TrackPoint *p = slice->bottom;
1667       p; ) {
1668     TrackPoint *pn = p->pn;
1669     if(p->m2 < m2min) {
1670       if(p->m2 < 0) { p->m2 = 0; }
1671       p->absorb();
1672       delete p;
1673     }
1674     p = pn;
1675   }
1676 
1677 #ifdef MULTITHREADED
1678   pthread_mutex_lock(&sliceMutex[c]);
1679 #endif
1680   sliceBuffer[c].write(slice);
1681 #ifdef MULTITHREADED
1682   pthread_mutex_unlock(&sliceMutex[c]);
1683 #endif
1684   addtime[c]++;
1685 }
1686 
prepad1(audio * buf,long n)1687 void SMS :: prepad1(audio *buf, long n)
1688 {
1689   if(band >= minTrial2Band) {
1690     trial2GrainBuf->write(buf,n);
1691   }
1692 }
1693 
prepad0(audio * buf,long n)1694 void SMS :: prepad0(audio *buf, long n)
1695 {
1696   if(band >= minTrial1Band) {
1697     trial1GrainBuf->write(buf,n);
1698   }
1699 }
1700 
getTrial2Latency()1701 int SMS :: getTrial2Latency()
1702 {
1703   return minTrackSize;
1704 }
1705 
createTrack(int c,TrackPoint * tp,const TimeType & time,bool bStitch)1706 Track *SMS :: createTrack(int c, TrackPoint *tp, const TimeType &time, bool bStitch)
1707 {
1708   TrackIndexType index;
1709   if(trackIndex[c].empty()) {
1710     index = trackIndexNone;
1711   } else {
1712     index = trackIndex[c].front();
1713     trackIndex[c].pop();
1714   }
1715   Track *t = new Track(h1,index,tp,time,bStitch);
1716   assignTracks[c].push_back(t);
1717   return t;
1718 }
1719 
returnTrackIndex(int c,Track * t)1720 void SMS :: returnTrackIndex(int c, Track *t)
1721 {
1722   if(t->index != trackIndexNone) {
1723     trackIndex[c].push(t->index);
1724     t->index = trackIndexNone;
1725   }
1726 }
1727 
interp2(int k,int ko,float kf)1728 float SMS :: interp2(int k, int ko, float kf) {
1729   return (1.0f-kf)*peak2N[k] + kf*peak2N[k+ko];
1730 }
1731 
findExtremum(float * mag,float * mag2,int k,float * y)1732 float SMS :: findExtremum(float *mag, float *mag2, int k, float *y)
1733 {
1734   float y0 = mag[k-1];
1735   float y1 = mag[k];
1736   float y2 = mag[k+1];
1737   float d = (y0 + y2 - y1 - y1);
1738   float x = (d==0.0f?k:k + 0.5f * (y0 - y2) / d);
1739   if(y) {
1740     int ki = lrintf(x);
1741     float kf = ki<x?x-ki:ki-x;
1742     int ki1 = ki<k?ki+1:ki-1;
1743     *y = ((1.0f-kf)*mag2[ki] + kf*mag2[ki1]);
1744   }
1745   return x;
1746 }
1747 
calcmags(float * mag,audio * x)1748 void SMS :: calcmags(float *mag, audio *x) {
1749   for(int k=0;k<=Nover2;k++) {
1750     mag[k] = norm2(x[k]);
1751   }
1752 }
1753 
SynthRenderer(int channels,int h)1754 SynthRenderer :: SynthRenderer(int channels, int h)
1755 {
1756   this->channels = channels;
1757   for(int c=0; c<channels; c++) {
1758     sines[c] = new ArrayRingBuffer<float>(0);
1759     synthBufLength[c] = h << 4;
1760     synthBuf[c] = (float*)malloc(synthBufLength[c]*sizeof(float));
1761   }
1762 #ifdef MULTITHREADED
1763   pthread_mutex_init(&bufferMutex,NULL);
1764 #endif
1765 }
1766 
~SynthRenderer()1767 SynthRenderer :: ~SynthRenderer()
1768 {
1769   for(int c=0; c<channels; c++) {
1770     delete sines[c];
1771     free(synthBuf[c]);
1772   }
1773 }
1774 
startTime(int c,const TimeType & time,int n)1775 void SynthRenderer :: startTime(int c, const TimeType &time, int n)
1776 {
1777   if(n > synthBufLength[c]) {
1778     free(synthBuf[c]);
1779     synthBufLength[c] = n << 1;
1780     synthBuf[c] = (float*)malloc(synthBufLength[c]*sizeof(float));
1781   }
1782   this->n[c] = n;
1783   this->time[c] = time;
1784   memset(synthBuf[c],0,n*sizeof(float));
1785 }
1786 
render(int c,SBSMSTrack * t)1787 void SynthRenderer :: render(int c, SBSMSTrack *t)
1788 {
1789   ((Track*)t)->synth(synthBuf[c],time[c],n[c],synthModeOutput,c);
1790 }
1791 
endTime(int c)1792 void SynthRenderer :: endTime(int c)
1793 {
1794 #ifdef MULTITHREADED
1795   pthread_mutex_lock(&bufferMutex);
1796 #endif
1797   int n = this->n[c];
1798   sines[c]->grow(n);
1799   long j = sines[c]->writePos;
1800   float *dest = sines[c]->buf;
1801   float *src = synthBuf[c];
1802   for(int k=0; k<n; k++) {
1803     dest[j++] += src[k];
1804   }
1805   sines[c]->writePos += n;
1806 #ifdef MULTITHREADED
1807   pthread_mutex_unlock(&bufferMutex);
1808 #endif
1809 }
1810 
read(audio * out,long n)1811 long SynthRenderer :: read(audio *out, long n)
1812 {
1813 #ifdef MULTITHREADED
1814   pthread_mutex_lock(&bufferMutex);
1815 #endif
1816   n = min(n,sines[0]->nReadable());
1817   for(int c=1; c<channels; c++) {
1818     n = min(n,sines[c]->nReadable());
1819   }
1820   for(int c=0; c<channels; c++) {
1821     float *buf = sines[c]->getReadBuf();
1822     for(int k=0; k<n; k++) {
1823       out[k][c] = buf[k];
1824     }
1825     sines[c]->advance(n);
1826   }
1827 #ifdef MULTITHREADED
1828   pthread_mutex_unlock(&bufferMutex);
1829 #endif
1830   return n;
1831 }
1832 
1833 }
1834