1 #include "config.h"
2 #include "sbsms.h"
3 #include "real.h"
4 #include "subband.h"
5 #ifdef MULTITHREADED
6 #include <pthread.h>
7 #endif
8 #include <stdlib.h>
9 #include <string.h>
10 #include <algorithm>
11 using namespace std;
12 
13 namespace _sbsms_ {
14 
15 const SBSMSQualityParams SBSMSQualityStandard = {
16   8,3,
17   {512,512,384,384,384,384,384,384,0,0},
18   {168,144,128,96,64,36,24,14,0,0},
19   {384,288,256,168,128,84,52,28,0,0},
20   {512,448,360,288,192,128,84,44,0,0},
21   {1,1,2,1,1,2,1,1,0,0}
22 };
23 
24 
SBSMSQuality(const SBSMSQualityParams * params)25 SBSMSQuality :: SBSMSQuality(const SBSMSQualityParams *params)
26 {
27   this->params = *params;
28 }
29 
getFrameSize()30 long SBSMSQuality :: getFrameSize()
31 {
32   return (1<<(params.bands-1)) * params.H;
33 }
34 
getMaxPresamples()35 long SBSMSQuality :: getMaxPresamples()
36 {
37   long prepad = 0;
38   for(int i=0; i<params.bands; i++) {
39     prepad = max(prepad,(long)((1<<i) * (params.N2[i]>>1)));
40   }
41   prepad += ((1<<(params.bands-1)) - 1) * (NDownSample>>1);
42   long framesize = (1<<(params.bands-1)) * params.H;
43   long frames = prepad / framesize;
44   if(prepad%framesize) frames++;
45   frames++;
46   prepad = frames * framesize;
47   return prepad;
48 }
49 
50 #ifdef MULTITHREADED
51 class ThreadInterface;
52 #endif
53 
54 class SBSMSImp {
55 public:
56   SBSMSImp(int channels, SBSMSQuality *quality, bool bSynthesize);
57   ~SBSMSImp();
58   inline long read(SBSMSInterface *iface, audio *buf, long n);
59   inline void addRenderer(SBSMSRenderer *renderer);
60   inline void removeRenderer(SBSMSRenderer *renderer);
61   inline long renderFrame(SBSMSInterface *iface);
62   SubBand *top;
63 #ifdef MULTITHREADED
64   friend class ThreadInterface;
65   ThreadInterface *threadInterface;
66 #endif
67   friend class SBSMS;
68 protected:
69   inline void reset();
70   float getInputTime(SBSMSInterface *iface);
71   long write(SBSMSInterface *);
72   FILE *fpIn;
73   FILE *fpOut;
74   SBSMSError error;
75   long nPrepad;
76   long nPrepadDone;
77   long nPresamplesDone;
78   SampleCountType nSamplesInputed;
79   SampleCountType nSamplesOutputed;
80   int channels;
81   SBSMSQuality *quality;
82   audio *ina;
83 };
84 
85 #ifdef MULTITHREADED
86 
87 struct channel_thread_data {
88   int c;
89   ThreadInterface *threadInterface;
90 };
91 
92 struct analyze_thread_data {
93   int i;
94   ThreadInterface *threadInterface;
95 };
96 
97 class ThreadInterface {
98 public:
99   friend class SBSMSImp;
100   ThreadInterface(SBSMSImp *sbsms, bool bSynthesize);
101   ~ThreadInterface();
102   void signalReadWrite();
103   void signalAnalyze();
104   void signalExtract(int c);
105   void signalMark(int c);
106   void signalAssign(int c);
107   void signalTrial2(int c);
108   void signalAdjust2();
109   void signalTrial1(int c);
110   void signalAdjust1();
111   void signalRender(int c);
112   void waitReadWrite();
113   void waitAnalyze(int i);
114   void waitExtract(int c);
115   void waitAssign(int c);
116   void waitTrial2(int c);
117   void waitAdjust2();
118   void waitTrial1(int c);
119   void waitAdjust1();
120   void waitRender(int c);
121   SubBand *top;
122   int channels;
123   pthread_mutex_t readWriteMutex;
124   pthread_cond_t readWriteCond;
125   pthread_t analyzeThread[3];
126   pthread_mutex_t analyzeMutex[3];
127   pthread_cond_t analyzeCond[3];
128   pthread_t extractThread[2];
129   pthread_mutex_t extractMutex[2];
130   pthread_cond_t extractCond[2];
131   pthread_t assignThread[2];
132   pthread_mutex_t assignMutex[2];
133   pthread_cond_t assignCond[2];
134   pthread_t trial2Thread[2];
135   pthread_mutex_t trial2Mutex[2];
136   pthread_cond_t trial2Cond[2];
137   pthread_t adjust2Thread;
138   pthread_mutex_t adjust2Mutex;
139   pthread_cond_t adjust2Cond;
140   pthread_t trial1Thread[2];
141   pthread_mutex_t trial1Mutex[2];
142   pthread_cond_t trial1Cond[2];
143   pthread_t adjust1Thread;
144   pthread_mutex_t adjust1Mutex;
145   pthread_cond_t adjust1Cond;
146   bool bRenderThread;
147   pthread_t renderThread[2];
148   pthread_mutex_t renderMutex[2];
149   pthread_cond_t renderCond[2];
150   channel_thread_data channelData[2];
151   analyze_thread_data analyzeData[3];
152   bool bActive;
153 };
154 
analyzeThreadCB(void * data)155 void *analyzeThreadCB(void *data) {
156   analyze_thread_data *analyzeData = (analyze_thread_data*)data;
157   ThreadInterface *threadInterface = analyzeData->threadInterface;
158   SubBand *top = threadInterface->top;
159   int i = analyzeData->i;
160   int channels = threadInterface->channels;
161   while(threadInterface->bActive) {
162     threadInterface->waitAnalyze(i);
163     if(top->analyzeInit(i,true)) {
164       top->analyze(i);
165       top->stepAnalyzeFrame(i);
166       threadInterface->signalReadWrite();
167       for(int c=0; c<channels; c++) {
168         threadInterface->signalExtract(c);
169       }
170     }
171   }
172   pthread_exit(NULL);
173   return NULL;
174 }
175 
extractThreadCB(void * data)176 void *extractThreadCB(void *data) {
177   channel_thread_data *channelData = (channel_thread_data*)data;
178   ThreadInterface *threadInterface = channelData->threadInterface;
179   SubBand *top = threadInterface->top;
180   int c = channelData->c;
181   while(threadInterface->bActive) {
182     threadInterface->waitExtract(c);
183     if(top->extractInit(c,true)) {
184       top->extract(c);
185       top->stepExtractFrame(c);
186       threadInterface->signalAnalyze();
187       threadInterface->signalMark(c);
188     }
189   }
190   pthread_exit(NULL);
191   return NULL;
192 }
193 
assignThreadCB(void * data)194 void *assignThreadCB(void *data) {
195   channel_thread_data *channelData = (channel_thread_data*)data;
196   ThreadInterface *threadInterface = channelData->threadInterface;
197   SubBand *top = threadInterface->top;
198   int c = channelData->c;
199   while(threadInterface->bActive) {
200     threadInterface->waitAssign(c);
201     if(top->markInit(c,true)) {
202       top->mark(c);
203       top->stepMarkFrame(c);
204       threadInterface->signalExtract(c);
205     }
206     if(top->assignInit(c,true)) {
207       top->assign(c);
208       top->advance(c);
209       top->stepAssignFrame(c);
210       threadInterface->signalTrial2(c);
211     }
212   }
213   pthread_exit(NULL);
214   return NULL;
215 }
216 
trial2ThreadCB(void * data)217 void *trial2ThreadCB(void *data) {
218   channel_thread_data *channelData = (channel_thread_data*)data;
219   ThreadInterface *threadInterface = channelData->threadInterface;
220   SubBand *top = threadInterface->top;
221   int c = channelData->c;
222   while(threadInterface->bActive) {
223     threadInterface->waitTrial2(c);
224     if(top->trial2Init(c,true)) {
225       top->trial2(c);
226       top->stepTrial2Frame(c);
227       threadInterface->signalAssign(c);
228       threadInterface->signalAdjust2();
229     }
230   }
231   pthread_exit(NULL);
232   return NULL;
233 }
234 
adjust2ThreadCB(void * data)235 void *adjust2ThreadCB(void *data) {
236   ThreadInterface *threadInterface = (ThreadInterface*)data;
237   int channels = threadInterface->channels;
238   SubBand *top = threadInterface->top;
239   while(threadInterface->bActive) {
240     threadInterface->waitAdjust2();
241     if(top->adjust2Init(true)) {
242       top->adjust2();
243       top->stepAdjust2Frame();
244       for(int c=0; c<channels; c++) {
245         threadInterface->signalTrial2(c);
246       }
247       for(int c=0; c<channels; c++) {
248         threadInterface->signalTrial1(c);
249       }
250     }
251   }
252   pthread_exit(NULL);
253   return NULL;
254 }
255 
trial1ThreadCB(void * data)256 void *trial1ThreadCB(void *data) {
257   channel_thread_data *channelData = (channel_thread_data*)data;
258   ThreadInterface *threadInterface = channelData->threadInterface;
259   SubBand *top = threadInterface->top;
260   int c = channelData->c;
261   while(threadInterface->bActive) {
262     threadInterface->waitTrial1(c);
263     if(top->trial1Init(c,true)) {
264       top->trial1(c);
265       top->stepTrial1Frame(c);
266       threadInterface->signalAdjust2();
267       threadInterface->signalAdjust1();
268     }
269   }
270   pthread_exit(NULL);
271   return NULL;
272 }
273 
adjust1ThreadCB(void * data)274 void *adjust1ThreadCB(void *data) {
275   ThreadInterface *threadInterface = (ThreadInterface*)data;
276   int channels = threadInterface->channels;
277   SubBand *top = threadInterface->top;
278   while(threadInterface->bActive) {
279     threadInterface->waitAdjust1();
280     if(top->adjust1Init(true)) {
281       top->adjust1();
282       top->stepAdjust1Frame();
283       for(int c=0; c<channels; c++) {
284         threadInterface->signalTrial1(c);
285       }
286       if(threadInterface->bRenderThread) {
287         for(int c=0; c<channels; c++) {
288           threadInterface->signalRender(c);
289         }
290       } else {
291         threadInterface->signalReadWrite();
292       }
293     }
294   }
295   pthread_exit(NULL);
296   return NULL;
297 }
298 
renderThreadCB(void * data)299 void *renderThreadCB(void *data) {
300   channel_thread_data *channelData = (channel_thread_data*)data;
301   ThreadInterface *threadInterface = channelData->threadInterface;
302   SubBand *top = threadInterface->top;
303   int c = channelData->c;
304   while(threadInterface->bActive) {
305     threadInterface->waitRender(c);
306     if(top->renderInit(c,true)) {
307       top->render(c);
308       top->stepRenderFrame(c);
309       threadInterface->signalAdjust1();
310       threadInterface->signalReadWrite();
311     }
312   }
313   pthread_exit(NULL);
314   return NULL;
315 }
316 
ThreadInterface(SBSMSImp * sbsms,bool bSynthesize)317 ThreadInterface :: ThreadInterface(SBSMSImp *sbsms, bool bSynthesize)
318 {
319   this->top = sbsms->top;
320   this->channels = sbsms->channels;
321   bActive = true;
322   pthread_cond_init(&readWriteCond, NULL);
323   pthread_mutex_init(&readWriteMutex, NULL);
324   if(bSynthesize) {
325     bRenderThread = true;
326   } else {
327     bRenderThread = false;
328   }
329   for(int i=0; i<3; i++) {
330     analyzeData[i].i = i;
331     analyzeData[i].threadInterface = this;
332     pthread_cond_init(&analyzeCond[i], NULL);
333     pthread_mutex_init(&analyzeMutex[i], NULL);
334   }
335   for(int c=0; c<channels; c++) {
336     channelData[c].c = c;
337     channelData[c].threadInterface = this;
338     pthread_cond_init(&extractCond[c], NULL);
339     pthread_mutex_init(&extractMutex[c], NULL);
340     pthread_cond_init(&assignCond[c], NULL);
341     pthread_mutex_init(&assignMutex[c], NULL);
342     pthread_cond_init(&trial2Cond[c], NULL);
343     pthread_mutex_init(&trial2Mutex[c], NULL);
344     pthread_cond_init(&trial1Cond[c], NULL);
345     pthread_mutex_init(&trial1Mutex[c], NULL);
346     if(bRenderThread) {
347       pthread_cond_init(&renderCond[c], NULL);
348       pthread_mutex_init(&renderMutex[c], NULL);
349     }
350   }
351   for(int i=0; i<3; i++) {
352     pthread_create(&analyzeThread[i], NULL, analyzeThreadCB, (void*)&analyzeData[i]);
353   }
354   for(int c=0; c<channels; c++) {
355     pthread_create(&extractThread[c], NULL, extractThreadCB, (void*)&channelData[c]);
356     pthread_create(&assignThread[c], NULL, assignThreadCB, (void*)&channelData[c]);
357     pthread_create(&trial2Thread[c], NULL, trial2ThreadCB, (void*)&channelData[c]);
358     pthread_create(&trial1Thread[c], NULL, trial1ThreadCB, (void*)&channelData[c]);
359     if(bRenderThread) {
360       pthread_create(&renderThread[c], NULL, renderThreadCB, (void*)&channelData[c]);
361     }
362   }
363   pthread_cond_init(&adjust2Cond, NULL);
364   pthread_mutex_init(&adjust2Mutex, NULL);
365   pthread_create(&adjust2Thread, NULL, adjust2ThreadCB, this);
366   pthread_cond_init(&adjust1Cond, NULL);
367   pthread_mutex_init(&adjust1Mutex, NULL);
368   pthread_create(&adjust1Thread, NULL, adjust1ThreadCB, this);
369 }
370 
~ThreadInterface()371 ThreadInterface :: ~ThreadInterface()
372 {
373   bActive = false;
374   for(int i=0; i<3; i++) {
375     pthread_mutex_lock(&analyzeMutex[i]);
376     pthread_cond_broadcast(&analyzeCond[i]);
377     pthread_mutex_unlock(&analyzeMutex[i]);
378     pthread_join(analyzeThread[i],NULL);
379   }
380   for(int c=0; c<channels; c++) {
381     pthread_mutex_lock(&extractMutex[c]);
382     pthread_cond_broadcast(&extractCond[c]);
383     pthread_mutex_unlock(&extractMutex[c]);
384     pthread_join(extractThread[c],NULL);
385     pthread_mutex_lock(&assignMutex[c]);
386     pthread_cond_broadcast(&assignCond[c]);
387     pthread_mutex_unlock(&assignMutex[c]);
388     pthread_join(assignThread[c],NULL);
389     pthread_mutex_lock(&trial2Mutex[c]);
390     pthread_cond_broadcast(&trial2Cond[c]);
391     pthread_mutex_unlock(&trial2Mutex[c]);
392     pthread_join(trial2Thread[c],NULL);
393     pthread_mutex_lock(&trial1Mutex[c]);
394     pthread_cond_broadcast(&trial1Cond[c]);
395     pthread_mutex_unlock(&trial1Mutex[c]);
396     pthread_join(trial1Thread[c],NULL);
397     if(bRenderThread) {
398       pthread_mutex_lock(&renderMutex[c]);
399       pthread_cond_broadcast(&renderCond[c]);
400       pthread_mutex_unlock(&renderMutex[c]);
401       pthread_join(renderThread[c],NULL);
402     }
403   }
404   pthread_mutex_lock(&adjust2Mutex);
405   pthread_cond_broadcast(&adjust2Cond);
406   pthread_mutex_unlock(&adjust2Mutex);
407   pthread_join(adjust2Thread,NULL);
408   pthread_mutex_lock(&adjust1Mutex);
409   pthread_cond_broadcast(&adjust1Cond);
410   pthread_mutex_unlock(&adjust1Mutex);
411   pthread_join(adjust1Thread,NULL);
412 }
413 
signalReadWrite()414 void ThreadInterface :: signalReadWrite()
415 {
416   pthread_mutex_lock(&readWriteMutex);
417   bool bReady;
418   if(bRenderThread) {
419     bReady = (top->writeInit() || top->readInit());
420   } else {
421     if(top->writeInit()) {
422       bReady = true;
423     } else {
424       bReady = true;
425       for(int c=0; c<channels; c++) {
426         if(!top->renderInit(c,false)) {
427           bReady = false;
428           break;
429         }
430       }
431     }
432   }
433   if(bReady) {
434     pthread_cond_broadcast(&readWriteCond);
435   }
436   pthread_mutex_unlock(&readWriteMutex);
437 }
438 
signalAnalyze()439 void ThreadInterface :: signalAnalyze()
440 {
441   for(int i=0; i<3; i++) {
442     pthread_mutex_lock(&analyzeMutex[i]);
443     if(top->analyzeInit(i,false)) {
444       pthread_cond_broadcast(&analyzeCond[i]);
445     }
446     pthread_mutex_unlock(&analyzeMutex[i]);
447   }
448 }
449 
signalExtract(int c)450 void ThreadInterface :: signalExtract(int c) {
451   pthread_mutex_lock(&extractMutex[c]);
452   if(top->extractInit(c,false)) {
453     pthread_cond_broadcast(&extractCond[c]);
454   }
455   pthread_mutex_unlock(&extractMutex[c]);
456 }
457 
signalMark(int c)458 void ThreadInterface :: signalMark(int c) {
459   pthread_mutex_lock(&assignMutex[c]);
460   if(top->markInit(c,false)) {
461     pthread_cond_broadcast(&assignCond[c]);
462   }
463   pthread_mutex_unlock(&assignMutex[c]);
464 }
465 
signalAssign(int c)466 void ThreadInterface :: signalAssign(int c) {
467   pthread_mutex_lock(&assignMutex[c]);
468   if(top->assignInit(c,false)) {
469     pthread_cond_broadcast(&assignCond[c]);
470   }
471   pthread_mutex_unlock(&assignMutex[c]);
472 }
473 
signalTrial2(int c)474 void ThreadInterface :: signalTrial2(int c) {
475   pthread_mutex_lock(&trial2Mutex[c]);
476   if(top->trial2Init(c,false)) {
477     pthread_cond_broadcast(&trial2Cond[c]);
478   }
479   pthread_mutex_unlock(&trial2Mutex[c]);
480 }
481 
signalAdjust2()482 void ThreadInterface :: signalAdjust2() {
483   pthread_mutex_lock(&adjust2Mutex);
484   if(top->adjust2Init(false)) {
485     pthread_cond_broadcast(&adjust2Cond);
486   }
487   pthread_mutex_unlock(&adjust2Mutex);
488 }
489 
signalTrial1(int c)490 void ThreadInterface :: signalTrial1(int c) {
491   pthread_mutex_lock(&trial1Mutex[c]);
492   if(top->trial1Init(c,false)) {
493     pthread_cond_broadcast(&trial1Cond[c]);
494   }
495   pthread_mutex_unlock(&trial1Mutex[c]);
496 }
497 
signalAdjust1()498 void ThreadInterface :: signalAdjust1() {
499   pthread_mutex_lock(&adjust1Mutex);
500   if(top->adjust1Init(false)) {
501     pthread_cond_broadcast(&adjust1Cond);
502   }
503   pthread_mutex_unlock(&adjust1Mutex);
504 }
505 
signalRender(int c)506 void ThreadInterface :: signalRender(int c) {
507   pthread_mutex_lock(&renderMutex[c]);
508   if(top->renderInit(c,false)) {
509     pthread_cond_broadcast(&renderCond[c]);
510   }
511   pthread_mutex_unlock(&renderMutex[c]);
512 }
513 
waitReadWrite()514 void ThreadInterface :: waitReadWrite() {
515   pthread_mutex_lock(&readWriteMutex);
516   bool bReady;
517   if(bRenderThread) {
518     bReady = (top->writeInit() || top->readInit());
519   } else {
520     if(top->writeInit()) {
521       bReady = true;
522     } else {
523       bReady = true;
524       for(int c=0; c<channels; c++) {
525         if(!top->renderInit(c,false)) {
526           bReady = false;
527           break;
528         }
529       }
530     }
531   }
532   if(!bReady) {
533     pthread_cond_wait(&readWriteCond,&readWriteMutex);
534   }
535   pthread_mutex_unlock(&readWriteMutex);
536 }
537 
waitAnalyze(int i)538 void ThreadInterface :: waitAnalyze(int i) {
539   pthread_mutex_lock(&analyzeMutex[i]);
540   if(!top->analyzeInit(i,false)) {
541     pthread_cond_wait(&analyzeCond[i],&analyzeMutex[i]);
542   }
543   pthread_mutex_unlock(&analyzeMutex[i]);
544 }
545 
waitExtract(int c)546 void ThreadInterface :: waitExtract(int c) {
547   pthread_mutex_lock(&extractMutex[c]);
548   if(!top->extractInit(c,false)) {
549     pthread_cond_wait(&extractCond[c],&extractMutex[c]);
550   }
551   pthread_mutex_unlock(&extractMutex[c]);
552 }
553 
waitAssign(int c)554 void ThreadInterface :: waitAssign(int c) {
555   pthread_mutex_lock(&assignMutex[c]);
556   if(!top->markInit(c,false) && !top->assignInit(c,false)) {
557     pthread_cond_wait(&assignCond[c],&assignMutex[c]);
558   }
559   pthread_mutex_unlock(&assignMutex[c]);
560 }
561 
waitTrial2(int c)562 void ThreadInterface :: waitTrial2(int c) {
563   pthread_mutex_lock(&trial2Mutex[c]);
564   if(!top->trial2Init(c,false)) {
565     pthread_cond_wait(&trial2Cond[c],&trial2Mutex[c]);
566   }
567   pthread_mutex_unlock(&trial2Mutex[c]);
568 }
569 
waitAdjust2()570 void ThreadInterface :: waitAdjust2() {
571   pthread_mutex_lock(&adjust2Mutex);
572   if(!top->adjust2Init(false)) {
573     pthread_cond_wait(&adjust2Cond,&adjust2Mutex);
574   }
575   pthread_mutex_unlock(&adjust2Mutex);
576 }
577 
waitTrial1(int c)578 void ThreadInterface :: waitTrial1(int c) {
579   pthread_mutex_lock(&trial1Mutex[c]);
580   if(!top->trial1Init(c,false)) {
581     pthread_cond_wait(&trial1Cond[c],&trial1Mutex[c]);
582   }
583   pthread_mutex_unlock(&trial1Mutex[c]);
584 }
585 
waitAdjust1()586 void ThreadInterface :: waitAdjust1() {
587   pthread_mutex_lock(&adjust1Mutex);
588   if(!top->adjust1Init(false)) {
589     pthread_cond_wait(&adjust1Cond,&adjust1Mutex);
590   }
591   pthread_mutex_unlock(&adjust1Mutex);
592 }
593 
waitRender(int c)594 void ThreadInterface :: waitRender(int c) {
595   pthread_mutex_lock(&renderMutex[c]);
596   if(!top->renderInit(c,false)) {
597     pthread_cond_wait(&renderCond[c],&renderMutex[c]);
598   }
599   pthread_mutex_unlock(&renderMutex[c]);
600 }
601 
602 #endif
603 
reset()604 void SBSMSImp :: reset()
605 {
606   nSamplesInputed = 0;
607   nSamplesOutputed = 0;
608   nPrepadDone = 0;
609   nPresamplesDone = 0;
610 }
611 
SBSMS(int channels,SBSMSQuality * quality,bool bSynthesize)612 SBSMS :: SBSMS(int channels, SBSMSQuality *quality, bool bSynthesize)
613 { imp = new SBSMSImp(channels,quality,bSynthesize); }
SBSMSImp(int channels,SBSMSQuality * quality,bool bSynthesize)614 SBSMSImp :: SBSMSImp(int channels, SBSMSQuality *quality, bool bSynthesize)
615 {
616   this->channels = channels;
617   this->quality = new SBSMSQuality(&quality->params);
618   error = SBSMSErrorNone;
619   top = new SubBand(NULL,0,channels,quality,bSynthesize);
620   ina = (audio*)malloc(quality->getFrameSize()*sizeof(audio));
621   nPrepad = quality->getMaxPresamples();
622   reset();
623 #ifdef MULTITHREADED
624   threadInterface = new ThreadInterface(this,bSynthesize);
625 #endif
626 }
627 
~SBSMS()628 SBSMS :: ~SBSMS() { delete imp; }
~SBSMSImp()629 SBSMSImp :: ~SBSMSImp()
630 {
631 #ifdef MULTITHREADED
632   if(threadInterface) delete threadInterface;
633 #endif
634   if(top) delete top;
635   if(ina) free(ina);
636   if(quality) delete quality;
637 }
638 
addRenderer(SBSMSRenderer * renderer)639 void SBSMS :: addRenderer(SBSMSRenderer *renderer) { imp->addRenderer(renderer); }
addRenderer(SBSMSRenderer * renderer)640 void SBSMSImp :: addRenderer(SBSMSRenderer *renderer)
641 {
642   top->addRenderer(renderer);
643 }
644 
removeRenderer(SBSMSRenderer * renderer)645 void SBSMS :: removeRenderer(SBSMSRenderer *renderer) { imp->removeRenderer(renderer); }
removeRenderer(SBSMSRenderer * renderer)646 void SBSMSImp :: removeRenderer(SBSMSRenderer *renderer)
647 {
648   top->removeRenderer(renderer);
649 }
650 
getError()651 SBSMSError SBSMS :: getError()
652 {
653   return imp->error;
654 }
655 
getInputTime(SBSMSInterface * iface)656 float SBSMSImp :: getInputTime(SBSMSInterface *iface)
657 {
658   return (float)nSamplesInputed / (float)iface->getSamplesToInput();
659 }
660 
write(SBSMSInterface * iface)661 long SBSMSImp :: write(SBSMSInterface *iface)
662 {
663   long nWrite = 0;
664 
665   float t = getInputTime(iface);
666   float t1 = (float)(nSamplesInputed + quality->getFrameSize()) / (float)iface->getSamplesToInput();
667   float stretch = iface->getMeanStretch(t,t1);
668   float pitch = iface->getPitch(t);
669 
670   long nPresamples = iface->getPresamples();
671   if(nPrepadDone < nPrepad - nPresamples) {
672     stretch = 1.0f;
673     nWrite = min(quality->getFrameSize(),nPrepad - nPresamples - nPrepadDone);
674     memset(ina,0,nWrite*sizeof(audio));
675     nPrepadDone += nWrite;
676   } else if(nPresamplesDone < nPresamples) {
677     stretch = 1.0f;
678     nWrite = min(quality->getFrameSize(),nPresamples - nPresamplesDone);
679     nWrite = iface->samples(ina,nWrite);
680     if(nWrite == 0) {
681       nWrite = quality->getFrameSize();
682       memset(ina,0,nWrite*sizeof(audio));
683     } else {
684       nPresamplesDone += nWrite;
685     }
686   } else {
687     nWrite = iface->samples(ina,quality->getFrameSize());
688     nSamplesInputed += nWrite;
689     if(nWrite == 0) {
690       nWrite = quality->getFrameSize();
691       memset(ina,0,nWrite*sizeof(audio));
692     }
693   }
694   nWrite = top->write(ina, nWrite, stretch, pitch);
695   return nWrite;
696 }
697 
read(SBSMSInterface * iface,audio * buf,long n)698 long SBSMS :: read(SBSMSInterface *iface, audio *buf, long n) { return imp->read(iface,buf,n); }
read(SBSMSInterface * iface,audio * buf,long n)699 long SBSMSImp :: read(SBSMSInterface *iface, audio *buf, long n)
700 {
701   long nReadTotal = 0;
702   while(nReadTotal < n) {
703     long nRead;
704     nRead = n - nReadTotal;
705     nRead = top->read(buf+nReadTotal,nRead);
706     nReadTotal += nRead;
707     if(nRead) {
708 #ifdef MULTITHREADED
709       if(threadInterface->bRenderThread) {
710         for(int c=0; c<channels; c++) {
711           threadInterface->signalRender(c);
712         }
713       }
714 #endif
715     } else {
716 #ifdef MULTITHREADED
717       threadInterface->waitReadWrite();
718 #endif
719       if(top->writeInit()) {
720         write(iface);
721 #ifdef MULTITHREADED
722         threadInterface->signalAnalyze();
723 #endif
724       }
725     }
726 #ifdef MULTITHREADED
727     if(!threadInterface->bRenderThread) {
728       for(int c=0; c<channels; c++) {
729         threadInterface->signalRender(c);
730       }
731     }
732 #else
733     top->process(true);
734 #endif
735     nSamplesOutputed += nRead;
736   }
737   return nReadTotal;
738 }
739 
renderFrame(SBSMSInterface * iface)740 long SBSMS :: renderFrame(SBSMSInterface *iface) { return imp->renderFrame(iface); }
renderFrame(SBSMSInterface * iface)741 long SBSMSImp :: renderFrame(SBSMSInterface *iface)
742 {
743   long nRendered = 0;
744   while(!nRendered) {
745     bool bReady = true;
746     for(int c=0; c<channels; c++) {
747       if(!top->renderInit(c,false)) {
748         bReady = false;
749         break;
750       }
751     }
752     if(bReady) {
753       nRendered = top->renderSynchronous();
754     }
755     if(nRendered) {
756 #ifdef MULTITHREADED
757       threadInterface->signalAdjust1();
758 #endif
759     } else {
760 #ifdef MULTITHREADED
761       threadInterface->waitReadWrite();
762 #endif
763       if(top->writeInit()) {
764         write(iface);
765       }
766 
767 #ifdef MULTITHREADED
768       threadInterface->signalAnalyze();
769 #endif
770     }
771 #ifdef MULTITHREADED
772 #else
773     top->process(false);
774 #endif
775     if(nSamplesOutputed >= iface->getSamplesToOutput()) {
776       top->renderComplete(iface->getSamplesToOutput());
777     }
778     nSamplesOutputed += nRendered;
779   }
780   return nRendered;
781 }
782 
getInputFrameSize()783 long SBSMS :: getInputFrameSize()
784 {
785   return imp->top->getInputFrameSize();
786 }
787 
788 }
789