player-mp3.c
branchtrunk
changeset 0 474a1293c3c0
child 6 111ef8181229
equal deleted inserted replaced
-1:000000000000 0:474a1293c3c0
       
     1 /*
       
     2  * MP3/MPlayer plugin to VDR (C++)
       
     3  *
       
     4  * (C) 2001-2007 Stefan Huelswitt <s.huelswitt@gmx.de>
       
     5  *
       
     6  * This code is free software; you can redistribute it and/or
       
     7  * modify it under the terms of the GNU General Public License
       
     8  * as published by the Free Software Foundation; either version 2
       
     9  * of the License, or (at your option) any later version.
       
    10  *
       
    11  * This code is distributed in the hope that it will be useful,
       
    12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
       
    14  * GNU General Public License for more details.
       
    15  *
       
    16  * You should have received a copy of the GNU General Public License
       
    17  * along with this program; if not, write to the Free Software
       
    18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
       
    19  * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
       
    20  */
       
    21 
       
    22 #include <stdlib.h>
       
    23 #include <stdio.h>
       
    24 #include <sys/ioctl.h>
       
    25 #include <math.h>
       
    26 #ifdef WITH_OSS
       
    27 #include <sys/soundcard.h>
       
    28 #endif
       
    29 
       
    30 #include <mad.h>
       
    31 #include <id3tag.h>
       
    32 
       
    33 #include <vdr/player.h>
       
    34 #include <vdr/ringbuffer.h>
       
    35 #include <vdr/thread.h>
       
    36 #include <vdr/tools.h>
       
    37 
       
    38 #include "common.h"
       
    39 #include "setup-mp3.h"
       
    40 #include "player-mp3.h"
       
    41 #include "data-mp3.h"
       
    42 #include "decoder.h"
       
    43 #include "decoder-core.h"
       
    44 
       
    45 #ifndef NO_DEBUG
       
    46 //#define DEBUG_MODE      // debug playmode changes
       
    47 #define DEBUG_BGR       // debug backround scan thread
       
    48 #define DEBUG_DELAY 300 // debug write/decode delays
       
    49 //#define ACC_DUMP        // dump limiter lookup table to /tmp/limiter
       
    50 #endif
       
    51 
       
    52 #if !defined(NO_DEBUG) && defined(DEBUG_MODE)
       
    53 #define dm(x) { (x); }
       
    54 #else
       
    55 #define dm(x) ; 
       
    56 #endif
       
    57 
       
    58 #if !defined(NO_DEBUG) && defined(DEBUG_BGR)
       
    59 #define db(x) { (x); }
       
    60 #else
       
    61 #define db(x) ; 
       
    62 #endif
       
    63 
       
    64 // ----------------------------------------------------------------
       
    65 
       
    66 #define MP3BUFSIZE (1024*1024)                               // output ringbuffer size
       
    67 #define OUT_BITS 16                                          // output 16 bit samples to DVB driver
       
    68 #define OUT_FACT (OUT_BITS/8*2)                              // output factor is 16 bit & 2 channels -> 4 bytes
       
    69 // cResample
       
    70 #define MAX_NSAMPLES (1152*7)                                // max. buffer for resampled frame
       
    71 // cNormalize
       
    72 #define MIN_GAIN   0.03                                      // min. gain required to launch the normalizer
       
    73 #define MAX_GAIN   3.0                                       // max. allowed gain
       
    74 #define USE_FAST_LIMITER
       
    75 #define LIM_ACC    12                                        // bit, accuracy for lookup table
       
    76 #define F_LIM_MAX  (mad_fixed_t)((1<<(MAD_F_FRACBITS+2))-1)  // max. value covered by lookup table
       
    77 #define LIM_SHIFT  (MAD_F_FRACBITS-LIM_ACC)                  // shift value for table lookup
       
    78 #define F_LIM_JMP  (mad_fixed_t)(1<<LIM_SHIFT)               // lookup table jump between values
       
    79 // cLevel
       
    80 #define POW_WIN 100                                          // window width for smoothing power values
       
    81 #define EPSILON 0.00000000001                                // anything less than EPSILON is considered zero
       
    82 
       
    83 // --- cResample ------------------------------------------------------------
       
    84 
       
    85 // The resample code has been adapted from the madplay project
       
    86 // (resample.c) found in the libmad distribution
       
    87    
       
    88 class cResample {
       
    89 private:
       
    90   mad_fixed_t ratio;
       
    91   mad_fixed_t step;
       
    92   mad_fixed_t last;
       
    93   mad_fixed_t resampled[MAX_NSAMPLES];
       
    94 public:
       
    95   bool SetInputRate(unsigned int oldrate, unsigned int newrate);
       
    96   unsigned int ResampleBlock(unsigned int nsamples, const mad_fixed_t *old);
       
    97   const mad_fixed_t *Resampled(void) { return resampled; }
       
    98   };
       
    99 
       
   100 bool cResample::SetInputRate(unsigned int oldrate, unsigned int newrate)
       
   101 {
       
   102   if(oldrate<8000 || oldrate>newrate*6) { // out of range
       
   103     esyslog("WARNING: samplerate %d out of range 8000-%d\n",oldrate,newrate*6);
       
   104     return 0;
       
   105     }
       
   106   ratio=mad_f_tofixed((double)oldrate/(double)newrate);
       
   107   step=0; last=0;
       
   108 #ifdef DEBUG
       
   109   static mad_fixed_t oldratio=0;
       
   110   if(oldratio!=ratio) {
       
   111     printf("mad: new resample ratio %f (from %d kHz to %d kHz)\n",mad_f_todouble(ratio),oldrate,newrate);
       
   112     oldratio=ratio;
       
   113     }
       
   114 #endif
       
   115   return ratio!=MAD_F_ONE;
       
   116 }
       
   117 
       
   118 unsigned int cResample::ResampleBlock(unsigned int nsamples, const mad_fixed_t *old)
       
   119 {
       
   120   // This resampling algorithm is based on a linear interpolation, which is
       
   121   // not at all the best sounding but is relatively fast and efficient.
       
   122   //
       
   123   // A better algorithm would be one that implements a bandlimited
       
   124   // interpolation.
       
   125 
       
   126   mad_fixed_t *nsam=resampled;
       
   127   const mad_fixed_t *end=old+nsamples;
       
   128   const mad_fixed_t *begin=nsam;
       
   129 
       
   130   if(step < 0) {
       
   131     step = mad_f_fracpart(-step);
       
   132 
       
   133     while (step < MAD_F_ONE) {
       
   134       *nsam++ = step ? last+mad_f_mul(*old-last,step) : last;
       
   135       step += ratio;
       
   136       if(((step + 0x00000080L) & 0x0fffff00L) == 0)
       
   137 	step = (step + 0x00000080L) & ~0x0fffffffL;
       
   138       }
       
   139     step -= MAD_F_ONE;
       
   140     }
       
   141 
       
   142   while (end - old > 1 + mad_f_intpart(step)) {
       
   143     old += mad_f_intpart(step);
       
   144     step = mad_f_fracpart(step);
       
   145     *nsam++ = step ? *old + mad_f_mul(old[1] - old[0], step) : *old;
       
   146     step += ratio;
       
   147     if (((step + 0x00000080L) & 0x0fffff00L) == 0)
       
   148       step = (step + 0x00000080L) & ~0x0fffffffL;
       
   149     }
       
   150 
       
   151   if (end - old == 1 + mad_f_intpart(step)) {
       
   152     last = end[-1];
       
   153     step = -step;
       
   154     }
       
   155   else step -= mad_f_fromint(end - old);
       
   156 
       
   157   return nsam-begin;
       
   158 }
       
   159 
       
   160 // --- cLevel ----------------------------------------------------------------
       
   161 
       
   162 // The normalize algorithm and parts of the code has been adapted from the
       
   163 // Normalize 0.7 project. (C) 1999-2002, Chris Vaill <cvaill@cs.columbia.edu>
       
   164 
       
   165 // A little background on how normalize computes the volume
       
   166 // of a wav file, in case you want to know just how your
       
   167 // files are being munged:
       
   168 //
       
   169 // The volumes calculated are RMS amplitudes, which corre­
       
   170 // spond (roughly) to perceived volume. Taking the RMS ampli­
       
   171 // tude of an entire file would not give us quite the measure
       
   172 // we want, though, because a quiet song punctuated by short
       
   173 // loud parts would average out to a quiet song, and the
       
   174 // adjustment we would compute would make the loud parts
       
   175 // excessively loud.
       
   176 //
       
   177 // What we want is to consider the maximum volume of the
       
   178 // file, and normalize according to that. We break up the
       
   179 // signal into 100 chunks per second, and get the signal
       
   180 // power of each chunk, in order to get an estimation of
       
   181 // "instantaneous power" over time. This "instantaneous
       
   182 // power" signal varies too much to get a good measure of the
       
   183 // original signal's maximum sustained power, so we run a
       
   184 // smoothing algorithm over the power signal (specifically, a
       
   185 // mean filter with a window width of 100 elements). The max­
       
   186 // imum point of the smoothed power signal turns out to be a
       
   187 // good measure of the maximum sustained power of the file.
       
   188 // We can then take the square root of the power to get maxi­
       
   189 // mum sustained RMS amplitude.
       
   190 
       
   191 class cLevel {
       
   192 private:
       
   193   double maxpow;
       
   194   mad_fixed_t peak;
       
   195   struct Power {
       
   196     // smooth
       
   197     int npow, wpow;
       
   198     double powsum, pows[POW_WIN];
       
   199     // sum
       
   200     unsigned int nsum;
       
   201     double sum;
       
   202     } power[2];
       
   203   //
       
   204   inline void AddPower(struct Power *p, double pow);
       
   205 public:
       
   206   void Init(void);
       
   207   void GetPower(struct mad_pcm *pcm);
       
   208   double GetLevel(void);
       
   209   double GetPeak(void);
       
   210   };
       
   211 
       
   212 void cLevel::Init(void)
       
   213 {
       
   214   for(int l=0 ; l<2 ; l++) {
       
   215     struct Power *p=&power[l];
       
   216     p->sum=p->powsum=0.0; p->wpow=p->npow=p->nsum=0;
       
   217     for(int i=POW_WIN-1 ; i>=0 ; i--) p->pows[i]=0.0;
       
   218     }
       
   219   maxpow=0.0; peak=0;
       
   220 }
       
   221 
       
   222 void cLevel::GetPower(struct mad_pcm *pcm)
       
   223 {
       
   224   for(int i=0 ; i<pcm->channels ; i++) {
       
   225     struct Power *p=&power[i];
       
   226     mad_fixed_t *data=pcm->samples[i];
       
   227     for(int n=pcm->length ; n>0 ; n--) {
       
   228       if(*data < -peak) peak = -*data;
       
   229       if(*data >  peak) peak =  *data;
       
   230       double s=mad_f_todouble(*data++);
       
   231       p->sum+=(s*s);
       
   232       if(++(p->nsum)>=pcm->samplerate/100) {
       
   233         AddPower(p,p->sum/(double)p->nsum);
       
   234         p->sum=0.0; p->nsum=0;
       
   235         }
       
   236       }
       
   237     }
       
   238 }
       
   239 
       
   240 void cLevel::AddPower(struct Power *p, double pow)
       
   241 {
       
   242   p->powsum+=pow;
       
   243   if(p->npow>=POW_WIN) {
       
   244     if(p->powsum>maxpow) maxpow=p->powsum;
       
   245     p->powsum-=p->pows[p->wpow];
       
   246     }
       
   247   else p->npow++;
       
   248   p->pows[p->wpow]=pow;
       
   249   p->wpow=(p->wpow+1) % POW_WIN;
       
   250 }
       
   251 
       
   252 double cLevel::GetLevel(void)
       
   253 {
       
   254   if(maxpow<EPSILON) {
       
   255     // Either this whole file has zero power, or was too short to ever
       
   256     // fill the smoothing buffer.  In the latter case, we need to just
       
   257     // get maxpow from whatever data we did collect.
       
   258 
       
   259     if(power[0].powsum>maxpow) maxpow=power[0].powsum;
       
   260     if(power[1].powsum>maxpow) maxpow=power[1].powsum;
       
   261     }
       
   262   double level=sqrt(maxpow/(double)POW_WIN);     // adjust for the smoothing window size and root
       
   263   d(printf("norm: new volumen level=%f peak=%f\n",level,mad_f_todouble(peak)))
       
   264   return level;
       
   265 }
       
   266 
       
   267 double cLevel::GetPeak(void)
       
   268 {
       
   269   return mad_f_todouble(peak);
       
   270 }
       
   271 
       
   272 // --- cNormalize ------------------------------------------------------------
       
   273 
       
   274 class cNormalize {
       
   275 private:
       
   276   mad_fixed_t gain;
       
   277   double d_limlvl, one_limlvl;
       
   278   mad_fixed_t limlvl;
       
   279   bool dogain, dolimit;
       
   280 #ifdef DEBUG
       
   281   // stats
       
   282   unsigned long limited, clipped, total;
       
   283   mad_fixed_t peak;
       
   284 #endif
       
   285   // limiter
       
   286 #ifdef USE_FAST_LIMITER
       
   287   mad_fixed_t *table, tablestart;
       
   288   int tablesize;
       
   289   inline mad_fixed_t FastLimiter(mad_fixed_t x);
       
   290 #endif
       
   291   inline mad_fixed_t Limiter(mad_fixed_t x);
       
   292 public:
       
   293   cNormalize(void);
       
   294   ~cNormalize();
       
   295   void Init(double Level, double Peak);
       
   296   void Stats(void);
       
   297   void AddGain(struct mad_pcm *pcm);
       
   298   };
       
   299 
       
   300 cNormalize::cNormalize(void)
       
   301 {
       
   302   d_limlvl=(double)MP3Setup.LimiterLevel/100.0;
       
   303   one_limlvl=1-d_limlvl;
       
   304   limlvl=mad_f_tofixed(d_limlvl);
       
   305   d(printf("norm: lim_lev=%f lim_acc=%d\n",d_limlvl,LIM_ACC))
       
   306 
       
   307 #ifdef USE_FAST_LIMITER
       
   308   mad_fixed_t start=limlvl & ~(F_LIM_JMP-1);
       
   309   tablestart=start;
       
   310   tablesize=(unsigned int)(F_LIM_MAX-start)/F_LIM_JMP + 2;
       
   311   table=new mad_fixed_t[tablesize];
       
   312   if(table) {
       
   313     d(printf("norm: table size=%d start=%08x jump=%08x\n",tablesize,start,F_LIM_JMP))
       
   314     for(int i=0 ; i<tablesize ; i++) {
       
   315       table[i]=Limiter(start);
       
   316       start+=F_LIM_JMP;
       
   317       }
       
   318     tablesize--; // avoid a -1 in FastLimiter()
       
   319 
       
   320     // do a quick accuracy check, just to be sure that FastLimiter() is working
       
   321     // as expected :-)
       
   322 #ifdef ACC_DUMP
       
   323     FILE *out=fopen("/tmp/limiter","w");
       
   324 #endif
       
   325     mad_fixed_t maxdiff=0;
       
   326     for(mad_fixed_t x=F_LIM_MAX ; x>=limlvl ; x-=mad_f_tofixed(1e-4)) {
       
   327       mad_fixed_t diff=mad_f_abs(Limiter(x)-FastLimiter(x));
       
   328       if(diff>maxdiff) maxdiff=diff;
       
   329 #ifdef ACC_DUMP
       
   330       fprintf(out,"%0.10f\t%0.10f\t%0.10f\t%0.10f\t%0.10f\n",
       
   331         mad_f_todouble(x),mad_f_todouble(Limiter(x)),mad_f_todouble(FastLimiter(x)),mad_f_todouble(diff),mad_f_todouble(maxdiff));
       
   332       if(ferror(out)) break;
       
   333 #endif
       
   334       }
       
   335 #ifdef ACC_DUMP
       
   336     fclose(out);
       
   337 #endif
       
   338     d(printf("norm: accuracy %.12f\n",mad_f_todouble(maxdiff)))
       
   339     if(mad_f_todouble(maxdiff)>1e-6) {
       
   340       esyslog("ERROR: accuracy check failed, normalizer disabled");
       
   341       delete table; table=0;
       
   342       }
       
   343     }
       
   344   else esyslog("ERROR: no memory for lookup table, normalizer disabled");
       
   345 #endif // USE_FAST_LIMITER
       
   346 }
       
   347 
       
   348 cNormalize::~cNormalize()
       
   349 {
       
   350 #ifdef USE_FAST_LIMITER
       
   351   delete[] table;
       
   352 #endif
       
   353 }
       
   354 
       
   355 void cNormalize::Init(double Level, double Peak)
       
   356 {
       
   357   double Target=(double)MP3Setup.TargetLevel/100.0;
       
   358   double dgain=Target/Level;
       
   359   if(dgain>MAX_GAIN) dgain=MAX_GAIN;
       
   360   gain=mad_f_tofixed(dgain);
       
   361   // Check if we actually need to apply a gain
       
   362   dogain=(Target>0.0 && fabs(1-dgain)>MIN_GAIN);
       
   363 #ifdef USE_FAST_LIMITER
       
   364   if(!table) dogain=false;
       
   365 #endif
       
   366   // Check if we actually need to do limiting:
       
   367   // we have to if limiter is enabled, if gain>1 and if the peaks will clip.
       
   368   dolimit=(d_limlvl<1.0 && dgain>1.0 && Peak*dgain>1.0);
       
   369 #ifdef DEBUG
       
   370   printf("norm: gain=%f dogain=%d dolimit=%d (target=%f level=%f peak=%f)\n",dgain,dogain,dolimit,Target,Level,Peak);
       
   371   limited=clipped=total=0; peak=0;
       
   372 #endif
       
   373 }
       
   374 
       
   375 void cNormalize::Stats(void)
       
   376 {
       
   377 #ifdef DEBUG
       
   378   if(total)
       
   379     printf("norm: stats tot=%ld lim=%ld/%.3f%% clip=%ld/%.3f%% peak=%.3f\n",
       
   380            total,limited,(double)limited/total*100.0,clipped,(double)clipped/total*100.0,mad_f_todouble(peak));
       
   381 #endif
       
   382 }
       
   383 
       
   384 mad_fixed_t cNormalize::Limiter(mad_fixed_t x)
       
   385 {
       
   386 // Limiter function:
       
   387 //
       
   388 //        / x                                                (for x <= lev)
       
   389 //   x' = |
       
   390 //        \ tanh((x - lev) / (1-lev)) * (1-lev) + lev        (for x > lev)
       
   391 //
       
   392 // call only with x>=0. For negative samples, preserve sign outside this function
       
   393 //
       
   394 // With limiter level = 0, this is equivalent to a tanh() function;
       
   395 // with limiter level = 1, this is equivalent to clipping.
       
   396 
       
   397   if(x>limlvl) {
       
   398 #ifdef DEBUG
       
   399     if(x>MAD_F_ONE) clipped++;
       
   400     limited++;
       
   401 #endif
       
   402     x=mad_f_tofixed(tanh((mad_f_todouble(x)-d_limlvl) / one_limlvl) * one_limlvl + d_limlvl);
       
   403     }
       
   404   return x;
       
   405 }
       
   406 
       
   407 #ifdef USE_FAST_LIMITER
       
   408 mad_fixed_t cNormalize::FastLimiter(mad_fixed_t x)
       
   409 {
       
   410 // The fast algorithm is based on a linear interpolation between the
       
   411 // the values in the lookup table. Relays heavly on libmads fixed point format.
       
   412 
       
   413   if(x>limlvl) {
       
   414     int i=(unsigned int)(x-tablestart)/F_LIM_JMP;
       
   415 #ifdef DEBUG
       
   416     if(x>MAD_F_ONE) clipped++;
       
   417     limited++;
       
   418     if(i>=tablesize) printf("norm: overflow x=%f x-ts=%f i=%d tsize=%d\n",
       
   419                             mad_f_todouble(x),mad_f_todouble(x-tablestart),i,tablesize);
       
   420 #endif
       
   421     mad_fixed_t r=x & (F_LIM_JMP-1);
       
   422     x=MAD_F_ONE;
       
   423     if(i<tablesize) {
       
   424       mad_fixed_t *ptr=&table[i];
       
   425       x=*ptr;
       
   426       mad_fixed_t d=*(ptr+1)-x;
       
   427       //x+=mad_f_mul(d,r)<<LIM_ACC;                // this is not accurate as mad_f_mul() does >>MAD_F_FRACBITS
       
   428                                                    // which is senseless in the case of following <<LIM_ACC.
       
   429       x+=((long long)d*(long long)r)>>LIM_SHIFT;   // better, don't know if works on all machines
       
   430       }
       
   431     }
       
   432   return x;
       
   433 }
       
   434 #endif
       
   435 
       
   436 #ifdef USE_FAST_LIMITER
       
   437 #define LIMITER_FUNC FastLimiter
       
   438 #else
       
   439 #define LIMITER_FUNC Limiter
       
   440 #endif
       
   441 
       
   442 void cNormalize::AddGain(struct mad_pcm *pcm)
       
   443 {
       
   444   if(dogain) {
       
   445     for(int i=0 ; i<pcm->channels ; i++) {
       
   446       mad_fixed_t *data=pcm->samples[i];
       
   447 #ifdef DEBUG
       
   448       total+=pcm->length;
       
   449 #endif
       
   450       if(dolimit) {
       
   451         for(int n=pcm->length ; n>0 ; n--) {
       
   452           mad_fixed_t s=mad_f_mul(*data,gain);
       
   453           if(s<0) {
       
   454             s=-s;
       
   455 #ifdef DEBUG
       
   456             if(s>peak) peak=s;
       
   457 #endif
       
   458             s=LIMITER_FUNC(s);
       
   459             s=-s;
       
   460             }
       
   461           else {
       
   462 #ifdef DEBUG
       
   463             if(s>peak) peak=s;
       
   464 #endif
       
   465             s=LIMITER_FUNC(s);
       
   466             }
       
   467           *data++=s;
       
   468           }
       
   469         }
       
   470       else {
       
   471         for(int n=pcm->length ; n>0 ; n--) {
       
   472           mad_fixed_t s=mad_f_mul(*data,gain);
       
   473 #ifdef DEBUG
       
   474           if(s>peak) peak=s;
       
   475           else if(-s>peak) peak=-s;
       
   476 #endif
       
   477           if(s>MAD_F_ONE) s=MAD_F_ONE;   // do clipping
       
   478           if(s<-MAD_F_ONE) s=-MAD_F_ONE;
       
   479           *data++=s;
       
   480           }
       
   481         }
       
   482       }
       
   483     }
       
   484 }
       
   485 
       
   486 // --- cScale ----------------------------------------------------------------
       
   487 
       
   488 // The dither code has been adapted from the madplay project
       
   489 // (audio.c) found in the libmad distribution
       
   490 
       
   491 enum eAudioMode { amRoundBE, amDitherBE, amRoundLE, amDitherLE };
       
   492 
       
   493 class cScale {
       
   494 private:
       
   495   enum { MIN=-MAD_F_ONE, MAX=MAD_F_ONE - 1 };
       
   496 #ifdef DEBUG
       
   497   // audio stats
       
   498   unsigned long clipped_samples;
       
   499   mad_fixed_t peak_clipping;
       
   500   mad_fixed_t peak_sample;
       
   501 #endif
       
   502   // dither
       
   503   struct dither {
       
   504     mad_fixed_t error[3];
       
   505     mad_fixed_t random;
       
   506     } leftD, rightD;
       
   507   //
       
   508   inline mad_fixed_t Clip(mad_fixed_t sample, bool stats=true);
       
   509   inline unsigned long Prng(unsigned long state);
       
   510   signed long LinearRound(mad_fixed_t sample);
       
   511   signed long LinearDither(mad_fixed_t sample, struct dither *dither);
       
   512 public:
       
   513   void Init(void);
       
   514   void Stats(void);
       
   515   unsigned int ScaleBlock(unsigned char *data, unsigned int size, unsigned int &nsamples, const mad_fixed_t * &left, const mad_fixed_t * &right, eAudioMode mode);
       
   516   };
       
   517 
       
   518 void cScale::Init(void)
       
   519 {
       
   520 #ifdef DEBUG
       
   521   clipped_samples=0; peak_clipping=peak_sample=0;
       
   522 #endif
       
   523   memset(&leftD,0,sizeof(leftD));
       
   524   memset(&rightD,0,sizeof(rightD));
       
   525 }
       
   526 
       
   527 void cScale::Stats(void)
       
   528 {
       
   529 #ifdef DEBUG
       
   530   printf("mp3: scale stats clipped=%ld peak_clip=%f peak=%f\n",
       
   531          clipped_samples,mad_f_todouble(peak_clipping),mad_f_todouble(peak_sample));
       
   532 #endif
       
   533 }
       
   534 
       
   535 // gather signal statistics while clipping
       
   536 mad_fixed_t cScale::Clip(mad_fixed_t sample, bool stats)
       
   537 {
       
   538 #ifndef DEBUG
       
   539   if (sample > MAX) sample = MAX;
       
   540   if (sample < MIN) sample = MIN;
       
   541 #else
       
   542   if(!stats) {
       
   543     if (sample > MAX) sample = MAX;
       
   544     if (sample < MIN) sample = MIN;
       
   545     }
       
   546   else {
       
   547     if (sample >= peak_sample) {
       
   548       if (sample > MAX) {
       
   549         ++clipped_samples;
       
   550         if (sample - MAX > peak_clipping)
       
   551 	  peak_clipping = sample - MAX;
       
   552         sample = MAX;
       
   553         }
       
   554       peak_sample = sample;
       
   555       }
       
   556     else if (sample < -peak_sample) {
       
   557       if (sample < MIN) {
       
   558         ++clipped_samples;
       
   559         if (MIN - sample > peak_clipping)
       
   560 	  peak_clipping = MIN - sample;
       
   561         sample = MIN;
       
   562         }
       
   563       peak_sample = -sample;
       
   564       }
       
   565     }
       
   566 #endif
       
   567   return sample;
       
   568 }
       
   569 
       
   570 // generic linear sample quantize routine
       
   571 signed long cScale::LinearRound(mad_fixed_t sample)
       
   572 {
       
   573   // round
       
   574   sample += (1L << (MAD_F_FRACBITS - OUT_BITS));
       
   575   // clip
       
   576   sample=Clip(sample);
       
   577   // quantize and scale
       
   578   return sample >> (MAD_F_FRACBITS + 1 - OUT_BITS);
       
   579 }
       
   580 
       
   581 // 32-bit pseudo-random number generator
       
   582 unsigned long cScale::Prng(unsigned long state)
       
   583 {
       
   584   return (state * 0x0019660dL + 0x3c6ef35fL) & 0xffffffffL;
       
   585 }
       
   586 
       
   587 // generic linear sample quantize and dither routine
       
   588 signed long cScale::LinearDither(mad_fixed_t sample, struct dither *dither)
       
   589 {
       
   590   // noise shape
       
   591   sample += dither->error[0] - dither->error[1] + dither->error[2];
       
   592   dither->error[2] = dither->error[1];
       
   593   dither->error[1] = dither->error[0] / 2;
       
   594   // bias
       
   595   mad_fixed_t output = sample + (1L << (MAD_F_FRACBITS + 1 - OUT_BITS - 1));
       
   596   const int scalebits = MAD_F_FRACBITS + 1 - OUT_BITS;
       
   597   const mad_fixed_t mask = (1L << scalebits) - 1;
       
   598   // dither
       
   599   const mad_fixed_t random = Prng(dither->random);
       
   600   output += (random & mask) - (dither->random & mask);
       
   601   dither->random = random;
       
   602   // clip
       
   603   output=Clip(output);
       
   604   sample=Clip(sample,false);
       
   605   // quantize
       
   606   output &= ~mask;
       
   607   // error feedback
       
   608   dither->error[0] = sample - output;
       
   609   // scale
       
   610   return output >> scalebits;
       
   611 }
       
   612 
       
   613 #define PUT_BE(data,sample) { *data++=(sample)>>8; *data++=(sample)>>0; }
       
   614 #define PUT_LE(data,sample) { *data++=(sample)>>0; *data++=(sample)>>8; }
       
   615 
       
   616 // write a block of signed 16-bit PCM samples
       
   617 unsigned int cScale::ScaleBlock(unsigned char *data, unsigned int size, unsigned int &nsamples, const mad_fixed_t * &left, const mad_fixed_t * &right, eAudioMode mode)
       
   618 {
       
   619   unsigned int len=size/OUT_FACT;
       
   620   if(len>nsamples) { len=nsamples; size=len*OUT_FACT; }
       
   621   nsamples-=len;
       
   622   switch(mode) {
       
   623     case amRoundBE:
       
   624       while(len--) {
       
   625         signed int sample=LinearRound(*left++);
       
   626         PUT_BE(data,sample);
       
   627         if(right) sample=LinearRound(*right++);
       
   628         PUT_BE(data,sample);
       
   629         }
       
   630       break;
       
   631     case amDitherBE:
       
   632       while(len--) {
       
   633 	signed int sample=LinearDither(*left++,&leftD);
       
   634         PUT_BE(data,sample);
       
   635 	if(right) sample=LinearDither(*right++,&rightD);
       
   636         PUT_BE(data,sample);
       
   637         }
       
   638       break;
       
   639     case amRoundLE:
       
   640       while(len--) {
       
   641         signed int sample=LinearRound(*left++);
       
   642         PUT_LE(data,sample);
       
   643         if(right) sample=LinearRound(*right++);
       
   644         PUT_LE(data,sample);
       
   645         }
       
   646       break;
       
   647     case amDitherLE:
       
   648       while(len--) {
       
   649 	signed int sample=LinearDither(*left++,&leftD);
       
   650         PUT_LE(data,sample);
       
   651 	if(right) sample=LinearDither(*right++,&rightD);
       
   652         PUT_LE(data,sample);
       
   653         }
       
   654       break;
       
   655     }
       
   656  return size;
       
   657 }
       
   658 
       
   659 // --- cShuffle ----------------------------------------------------------------
       
   660 
       
   661 class cShuffle {
       
   662 private:
       
   663   int *shuffle, max;
       
   664   unsigned int seed;
       
   665   //
       
   666   int Index(int pos);
       
   667 public:
       
   668   cShuffle(void);
       
   669   ~cShuffle();
       
   670   void Shuffle(int num, int curr);
       
   671   void Del(int pos);
       
   672   void Flush(void);
       
   673   int First(void);
       
   674   int Next(int curr);
       
   675   int Prev(int curr);
       
   676   int Goto(int pos, int curr);
       
   677   };
       
   678 
       
   679 cShuffle::cShuffle(void)
       
   680 {
       
   681   shuffle=0; max=0;
       
   682   seed=time(0);
       
   683 }
       
   684 
       
   685 cShuffle::~cShuffle(void)
       
   686 {
       
   687   Flush();
       
   688 }
       
   689 
       
   690 void cShuffle::Flush(void)
       
   691 {
       
   692   delete shuffle; shuffle=0;
       
   693   max=0;
       
   694 }
       
   695 
       
   696 int cShuffle::Index(int pos)
       
   697 {
       
   698   if(pos>=0)
       
   699     for(int i=0; i<max; i++) if(shuffle[i]==pos) return i;
       
   700   return -1;
       
   701 }
       
   702 
       
   703 void cShuffle::Shuffle(int num, int curr)
       
   704 {
       
   705   int oldmax=0;
       
   706   if(num!=max) {
       
   707     int *ns=new int[num];
       
   708     if(shuffle) {
       
   709       if(num>max) {
       
   710         memcpy(ns,shuffle,max*sizeof(int));
       
   711         oldmax=max;
       
   712         }
       
   713       delete shuffle;
       
   714       }
       
   715     shuffle=ns; max=num;
       
   716     }
       
   717   if(!oldmax) curr=-1;
       
   718   for(int i=oldmax ; i<max ; i++) shuffle[i]=i;
       
   719 
       
   720   int in=Index(curr)+1; if(in<0) in=0;
       
   721   if((max-in)>=2) {
       
   722     for(int i=in ; i<max ; i++) {
       
   723       int ran=(rand_r(&seed) % ((max-in)*4-4))/4; ran+=((ran+in) >= i);
       
   724       int t=shuffle[i];
       
   725       shuffle[i]=shuffle[ran+in];
       
   726       shuffle[ran+in]=t;
       
   727       }
       
   728     }
       
   729 #ifdef DEBUG
       
   730   printf("shuffle: order (%d , %d -> %d) ",num,curr,in);
       
   731   for(int i=0 ; i<max ; i++) printf("%d ",shuffle[i]);
       
   732   printf("\n");
       
   733 #endif
       
   734 }
       
   735 
       
   736 void cShuffle::Del(int pos)
       
   737 {
       
   738   int i=Index(pos);
       
   739   if(i>=0) {
       
   740     if(i+1<max) memmove(&shuffle[i],&shuffle[i+1],(max-i-1)*sizeof(int));
       
   741     max--;
       
   742     }
       
   743 }
       
   744 
       
   745 int cShuffle::First(void)
       
   746 {
       
   747   return shuffle[0];
       
   748 }
       
   749 
       
   750 int cShuffle::Next(int curr)
       
   751 {
       
   752   int i=Index(curr);
       
   753   return (i>=0 && i+1<max) ? shuffle[i+1] : -1;
       
   754 }
       
   755 
       
   756 int cShuffle::Prev(int curr)
       
   757 {
       
   758   int i=Index(curr);
       
   759   return (i>0) ? shuffle[i-1] : -1;
       
   760 }
       
   761 
       
   762 int cShuffle::Goto(int pos, int curr)
       
   763 {
       
   764   int i=Index(curr);
       
   765   int g=Index(pos);
       
   766   if(g>=0) {
       
   767     if(g<i) {
       
   768       for(int l=g; l<i; l++) shuffle[l]=shuffle[l+1];
       
   769       shuffle[i]=pos;
       
   770       }
       
   771     else if(g>i) {
       
   772       for(int l=g; l>i+1; l--) shuffle[l]=shuffle[l-1];
       
   773       shuffle[i+1]=pos;
       
   774       }
       
   775 #ifdef DEBUG
       
   776     printf("shuffle: goto order (%d -> %d , %d -> %d) ",pos,g,curr,i);
       
   777     for(int i=0 ; i<max ; i++) printf("%d ",shuffle[i]);
       
   778     printf("\n");
       
   779 #endif
       
   780     return pos;
       
   781     }
       
   782   return -1;
       
   783 }
       
   784 
       
   785 // --- cPlayManager ------------------------------------------------------------
       
   786 
       
   787 #define SCANNED_ID3 1
       
   788 #define SCANNED_LVL 2
       
   789 
       
   790 cPlayManager *mgr=0;
       
   791 
       
   792 cPlayManager::cPlayManager(void)
       
   793 {
       
   794   curr=0; currIndex=-1;
       
   795   scan=0; stopscan=throttle=pass2=release=false;
       
   796   play=0; playNew=eol=false;
       
   797   shuffle=new cShuffle;
       
   798   loopMode=(MP3Setup.InitLoopMode>0);
       
   799   shuffleMode=(MP3Setup.InitShuffleMode>0);
       
   800 }
       
   801 
       
   802 cPlayManager::~cPlayManager()
       
   803 {
       
   804   Flush();
       
   805   Release();
       
   806   listMutex.Lock();
       
   807   stopscan=true; bgCond.Broadcast();
       
   808   listMutex.Unlock();
       
   809   Cancel(2);
       
   810   delete shuffle;
       
   811 }
       
   812 
       
   813 void cPlayManager::ThrottleWait(void)
       
   814 {
       
   815   while(!stopscan && !release && throttle) {
       
   816     db(printf("mgr: background scan throttled\n"))
       
   817     bgCond.Wait(listMutex);
       
   818     db(printf("mgr: background scan throttle wakeup\n"))
       
   819     }
       
   820 }
       
   821 
       
   822 void cPlayManager::Action(void)
       
   823 {
       
   824   db(printf("mgr: background scan thread started (pid=%d)\n", getpid()))
       
   825   nice(5);
       
   826   listMutex.Lock();
       
   827   while(!stopscan) {
       
   828     for(scan=list.First(); !stopscan && !release && scan; scan=list.Next(scan)) {
       
   829       ThrottleWait();
       
   830       listMutex.Unlock();
       
   831       if(!(scan->user & SCANNED_ID3)) {
       
   832         db(printf("mgr: scanning (id3) %s\n",scan->Name()))
       
   833         cSongInfo *si=scan->Info(true);
       
   834         if(si && si->Level>0.0) scan->user|=SCANNED_LVL;
       
   835         scan->user|=SCANNED_ID3;
       
   836         }
       
   837       listMutex.Lock();
       
   838       }
       
   839     if(MP3Setup.BgrScan>1) {
       
   840       pass2=true;
       
   841       for(scan=list.First(); !stopscan && !release && scan; scan=list.Next(scan)) {
       
   842         if(scan==curr) continue;
       
   843         ThrottleWait();
       
   844         listMutex.Unlock();
       
   845         if(!(scan->user & SCANNED_LVL)) {
       
   846           cDecoder *dec=scan->Decoder();
       
   847           if(dec) {
       
   848             cSongInfo *si=scan->Info(false);
       
   849             if(!dec->IsStream() && (!si || si->Level<=0.0) && dec->Start()) {
       
   850               db(printf("mgr: scanning (lvl) %s\n",scan->Name()))
       
   851               cLevel level;
       
   852               level.Init();
       
   853               bool go=true;
       
   854               while(go && !release) {
       
   855                 if(throttle) {
       
   856                   listMutex.Lock(); ThrottleWait(); listMutex.Unlock();
       
   857                   continue;
       
   858                   }
       
   859                 struct Decode *ds=dec->Decode();
       
   860                 switch(ds->status) {
       
   861                   case dsPlay:
       
   862                     level.GetPower(ds->pcm);
       
   863                     break;
       
   864                   case dsSkip:
       
   865                   case dsSoftError:
       
   866                     break;
       
   867                   case dsEof:
       
   868                     {
       
   869                     double l=level.GetLevel();
       
   870                     if(l>0.0) {
       
   871                       cSongInfo *si=dec->SongInfo(false);
       
   872                       cFileInfo *fi=dec->FileInfo();
       
   873                       if(si && fi) {
       
   874                         si->Level=l;
       
   875                         si->Peak=level.GetPeak();
       
   876                         InfoCache.Cache(si,fi);
       
   877                         }
       
   878                       }
       
   879                     }
       
   880                     //fall through
       
   881                   case dsOK:
       
   882                   case dsError:
       
   883                     scan->user|=SCANNED_LVL;
       
   884                     go=false;
       
   885                     break;
       
   886                   }
       
   887                 }
       
   888               }
       
   889             else scan->user|=SCANNED_LVL;
       
   890             dec->Stop();
       
   891             }
       
   892           }
       
   893         listMutex.Lock();
       
   894         }
       
   895       pass2=false;
       
   896       }
       
   897     do {
       
   898       scan=0; release=false; fgCond.Broadcast();
       
   899       db(printf("mgr: background scan idle\n"))
       
   900       bgCond.Wait(listMutex);
       
   901       db(printf("mgr: background scan idle wakeup\n"))
       
   902       } while(!stopscan && (release || throttle));
       
   903     }
       
   904   listMutex.Unlock();
       
   905   db(printf("mgr: background scan thread ended (pid=%d)\n", getpid()))
       
   906 }
       
   907 
       
   908 void cPlayManager::Throttle(bool thr)
       
   909 {
       
   910   if(MP3Setup.BgrScan) {
       
   911     if(!thr && throttle) {
       
   912       db(printf("mgr: bgr-scan -> run (%d)\n",time_ms()))
       
   913       listMutex.Lock();
       
   914       throttle=false; bgCond.Broadcast();
       
   915       listMutex.Unlock();
       
   916       }
       
   917     if(thr && !throttle) {
       
   918       db(printf("mgr: bgr-scan -> throttle (%d)\n",time_ms()))
       
   919       throttle=true;
       
   920       }
       
   921     }
       
   922 }
       
   923 
       
   924 void cPlayManager::ToggleShuffle(void)
       
   925 {
       
   926   shuffleMode=!shuffleMode;
       
   927   d(printf("mgr: shuffle mode toggled : %d\n",shuffleMode))
       
   928   if(shuffleMode && !eol) {
       
   929     curr=0; currIndex=-1;
       
   930     shuffle->Shuffle(maxIndex+1,-1);
       
   931     Next();
       
   932     }
       
   933 }
       
   934 
       
   935 void cPlayManager::ToggleLoop(void)
       
   936 {
       
   937   loopMode=!loopMode;
       
   938   d(printf("mgr: loop mode toggled : %d\n",loopMode))
       
   939 }
       
   940 
       
   941 bool cPlayManager::Info(int num, cMP3PlayInfo *pi)
       
   942 {
       
   943   cSong *s;
       
   944   int idx=num-1;
       
   945   if(idx<0) { idx=currIndex; s=curr; }
       
   946   else      { s=list.Get(idx); }
       
   947   memset(pi,0,sizeof(*pi));
       
   948   pi->Num=idx+1;
       
   949   pi->MaxNum=maxIndex+1;
       
   950   pi->Loop=loopMode;
       
   951   pi->Shuffle=shuffleMode;
       
   952   bool res=false;
       
   953   if(s) {
       
   954     strn0cpy(pi->Title,s->Name(),sizeof(pi->Title));
       
   955     strn0cpy(pi->Filename,s->FullPath(),sizeof(pi->Filename));
       
   956     cSongInfo *si=s->Info(false);
       
   957     if(si && si->HasInfo()) {
       
   958       static char *modestr[] = { "Mono","Dual","Joint-Stereo","Stereo" };
       
   959 
       
   960       if(si->Title)  strn0cpy(pi->Title,si->Title,sizeof(pi->Title));
       
   961       if(si->Artist) strn0cpy(pi->Artist,si->Artist,sizeof(pi->Artist));
       
   962       if(si->Album)  strn0cpy(pi->Album,si->Album,sizeof(pi->Album));
       
   963       strn0cpy(pi->SMode,modestr[si->ChMode],sizeof(pi->SMode));
       
   964       pi->Year=si->Year;
       
   965       pi->SampleFreq=si->SampleFreq;
       
   966       pi->Bitrate=si->Bitrate;
       
   967       pi->MaxBitrate=si->MaxBitrate;
       
   968       res=true;
       
   969       }
       
   970     }
       
   971   pi->Hash=MakeHashBuff((char *)pi,(char *)&pi->Loop-(char *)pi);
       
   972   return res;
       
   973 }
       
   974 
       
   975 void cPlayManager::Add(cPlayList *pl)
       
   976 {
       
   977   cMutexLock lock(&listMutex);
       
   978   bool real=false;
       
   979   for(cSong *song=pl->First(); song; song=pl->cList<cSong>::Next(song)) {
       
   980     cSong *ns=new cSong(song);
       
   981     list.Add(ns);
       
   982     real=true;
       
   983     }
       
   984   if(real) {
       
   985     if(MP3Setup.BgrScan) { stopscan=false; if(!Active()) Start(); }
       
   986     else stopscan=true;
       
   987     bgCond.Broadcast();
       
   988     maxIndex=list.Count()-1;
       
   989     if(shuffleMode) shuffle->Shuffle(maxIndex+1,currIndex);
       
   990     if(!curr) Next();
       
   991     }
       
   992 }
       
   993 
       
   994 void cPlayManager::Flush(void)
       
   995 {
       
   996   cMutexLock lock(&listMutex);
       
   997   Halt();
       
   998   list.Clear();
       
   999   shuffle->Flush();
       
  1000 }
       
  1001 
       
  1002 void cPlayManager::Halt(void)
       
  1003 {
       
  1004   cMutexLock lock(&listMutex);
       
  1005   curr=0; currIndex=-1;
       
  1006   playNew=true;
       
  1007   stopscan=true; bgCond.Broadcast();
       
  1008   NoScan(0);
       
  1009   NoPlay(0);
       
  1010 }
       
  1011 
       
  1012 void cPlayManager::NoScan(cSong *nono)
       
  1013 {
       
  1014   // call with listMutex locked!!
       
  1015   while((nono && pass2 && scan==nono) || (!nono && scan)) {
       
  1016     release=true; bgCond.Broadcast();
       
  1017     d(printf("mgr: waiting for bgr release ... (pass2=%d nono=%p scan=%p)\n",pass2,nono,scan))
       
  1018     fgCond.Wait(listMutex);
       
  1019     }
       
  1020 }
       
  1021 
       
  1022 void cPlayManager::NoPlay(cSong *nono)
       
  1023 {
       
  1024   // call with listMutex locked!!
       
  1025   while((nono && play==nono) || (!nono && play)) {
       
  1026     playNew=true;
       
  1027     fgCond.Wait(listMutex);
       
  1028     }
       
  1029 }
       
  1030 
       
  1031 bool cPlayManager::Next(void)
       
  1032 {
       
  1033   cMutexLock lock(&listMutex);
       
  1034   int ni;
       
  1035   cSong *n;
       
  1036   if(shuffleMode) {
       
  1037     if(curr) {
       
  1038       ni=shuffle->Next(currIndex);
       
  1039       if(ni<0) {
       
  1040         if(loopMode || eol) {
       
  1041           shuffle->Shuffle(maxIndex+1,-1);
       
  1042           ni=shuffle->First();
       
  1043           }
       
  1044         else eol=true;
       
  1045         }
       
  1046       }
       
  1047     else
       
  1048       ni=shuffle->First();
       
  1049     n=(ni>=0) ? list.Get(ni) : 0;
       
  1050     }
       
  1051   else {
       
  1052     if(curr) {
       
  1053       n=list.cList<cSong>::Next(curr);
       
  1054       if(!n) {
       
  1055         if(loopMode || eol) n=list.First();
       
  1056         else eol=true;
       
  1057         }
       
  1058       }
       
  1059     else
       
  1060       n=list.First();
       
  1061     ni=n ? n->Index() : -1;
       
  1062     }
       
  1063   if(n) {
       
  1064     curr=n; currIndex=ni;
       
  1065     playNew=true; eol=false;
       
  1066     d(printf("mgr: next -> %d\n",currIndex))
       
  1067     return true;
       
  1068     }
       
  1069   return false;
       
  1070 }
       
  1071 
       
  1072 bool cPlayManager::Prev(void)
       
  1073 {
       
  1074   cMutexLock lock(&listMutex);
       
  1075   int ni;
       
  1076   cSong *n;
       
  1077   if(shuffleMode) {
       
  1078     ni=shuffle->Prev(currIndex);
       
  1079     n=(ni>=0) ? list.Get(ni) : 0;
       
  1080     }
       
  1081   else {
       
  1082     n=list.cList<cSong>::Prev(curr);
       
  1083     ni=n ? n->Index() : -1;
       
  1084     }
       
  1085   if(n) {
       
  1086     curr=n; currIndex=ni;
       
  1087     playNew=true; eol=false;
       
  1088     d(printf("mgr: prev -> %d\n",currIndex))
       
  1089     return true;
       
  1090     }
       
  1091   return false;
       
  1092 }
       
  1093 
       
  1094 void cPlayManager::Goto(int num)
       
  1095 {
       
  1096   cMutexLock lock(&listMutex);
       
  1097   if(num>0 && num<=maxIndex+1) {
       
  1098     int idx=num-1;
       
  1099     if(shuffleMode) {
       
  1100       if(eol) {
       
  1101         shuffle->Shuffle(maxIndex+1,-1);
       
  1102         currIndex=shuffle->Goto(idx,-1);
       
  1103         }
       
  1104       else
       
  1105         currIndex=shuffle->Goto(idx,currIndex);
       
  1106       }
       
  1107     else
       
  1108       currIndex=idx;
       
  1109     curr=(currIndex>=0) ? list.Get(currIndex) : 0;
       
  1110     playNew=true; eol=false;
       
  1111     d(printf("mgr: goto -> %d\n",currIndex))
       
  1112     }
       
  1113 }
       
  1114 
       
  1115 cSong *cPlayManager::Current(void)
       
  1116 {
       
  1117   cMutexLock lock(&listMutex);
       
  1118   if(!play) {
       
  1119     NoScan(curr);
       
  1120     play=curr;
       
  1121     playNew=false;
       
  1122     if(play) d(printf("mgr: playing %s\n",play->Name()))
       
  1123     else d(printf("mgr: nothing to play\n"))
       
  1124     fgCond.Broadcast();
       
  1125     }
       
  1126   return play;
       
  1127 }
       
  1128 
       
  1129 bool cPlayManager::NextCurrent(void)
       
  1130 {
       
  1131   cMutexLock lock(&listMutex);
       
  1132   return (!eol && (playNew || Next()));
       
  1133 }
       
  1134 
       
  1135 bool cPlayManager::NewCurrent(void)
       
  1136 {
       
  1137   return playNew;
       
  1138 }
       
  1139 
       
  1140 void cPlayManager::Release(void)
       
  1141 {
       
  1142   cMutexLock lock(&listMutex);
       
  1143   play=0;
       
  1144   fgCond.Broadcast();
       
  1145 }
       
  1146 
       
  1147 // --- cOutput -----------------------------------------------------------------
       
  1148 
       
  1149 struct FrameHeader {
       
  1150   unsigned int samplerate;
       
  1151   };
       
  1152 #define FHS sizeof(struct FrameHeader)
       
  1153 
       
  1154 class cOutput {
       
  1155 protected:
       
  1156   cMP3Player *player;
       
  1157   cScale scale;
       
  1158 public:
       
  1159   cOutput(cMP3Player *Player);
       
  1160   virtual ~cOutput() {}
       
  1161   virtual void Init(void);
       
  1162   virtual unsigned int SampleRate(unsigned int PcmSampleRate)=0;
       
  1163   virtual cFrame *MakeFrame(unsigned int & Samples, const mad_fixed_t **Data, int index, int sr)=0;
       
  1164   virtual int Output(const unsigned char *Data, int Len, bool SOF)=0;
       
  1165   virtual bool Poll(void)=0;
       
  1166   virtual void Play(void)=0;
       
  1167   virtual void Pause(void)=0;
       
  1168 #ifdef DEBUG
       
  1169   virtual void Stats(void);
       
  1170 #endif
       
  1171   };
       
  1172 
       
  1173 cOutput::cOutput(cMP3Player *Player)
       
  1174 {
       
  1175   player=Player;
       
  1176 }
       
  1177 
       
  1178 void cOutput::Init(void)
       
  1179 {
       
  1180   scale.Init();
       
  1181 }
       
  1182 
       
  1183 #ifdef DEBUG
       
  1184 void cOutput::Stats(void)
       
  1185 {
       
  1186   scale.Stats();
       
  1187 }
       
  1188 #endif
       
  1189 
       
  1190 // --- cOutputDvb --------------------------------------------------------------
       
  1191 
       
  1192 /*
       
  1193 struct LPCMHeader { int id:8;              // id
       
  1194                     int frame_count:8;     // number of frames
       
  1195                     int access_ptr:16;     // first acces unit pointer, i.e. start of audio frame
       
  1196                     bool emphasis:1;       // audio emphasis on-off
       
  1197                     bool mute:1;           // audio mute on-off
       
  1198                     bool reserved:1;       // reserved
       
  1199                     int frame_number:5;    // audio frame number
       
  1200                     int quant_wlen:2;      // quantization word length
       
  1201                     int sample_freq:2;     // audio sampling frequency (48khz=0, 96khz=1, 44,1khz=2, 32khz=3)
       
  1202                     bool reserved2:1;      // reserved
       
  1203                     int chan_count:3;      // number of audio channels - 1 (e.g. stereo = 1)
       
  1204                     int dyn_range_ctrl:8;  // dynamic range control (0x80 if off)
       
  1205                     };
       
  1206 */
       
  1207 
       
  1208 #define FRAMESIZE 2048 // max. frame size allowed for DVB driver
       
  1209 
       
  1210 class cOutputDvb : public cOutput {
       
  1211 private:
       
  1212   cPoller poll;
       
  1213   unsigned int outSr;
       
  1214   bool only48khz;
       
  1215 public:
       
  1216   cOutputDvb(cMP3Player *Player);
       
  1217   virtual unsigned int SampleRate(unsigned int PcmSampleRate);
       
  1218   virtual cFrame *MakeFrame(unsigned int & Samples, const mad_fixed_t **Data, int index, int sr);
       
  1219   virtual int Output(const unsigned char *Data, int Len, bool SOF);
       
  1220   virtual bool Poll(void);
       
  1221   virtual void Play(void);
       
  1222   virtual void Pause(void);
       
  1223   };
       
  1224 
       
  1225 cOutputDvb::cOutputDvb(cMP3Player *Player)
       
  1226 :cOutput(Player)
       
  1227 {
       
  1228   only48khz=MP3Setup.Only48kHz;
       
  1229   outSr=0;
       
  1230 #if APIVERSNUM == 10318
       
  1231   cDevice::PrimaryDevice()->SetCurrentAudioTrack(ttDolbyFirst);
       
  1232 #elif APIVERSNUM >= 10319
       
  1233   cDevice::PrimaryDevice()->SetCurrentAudioTrack(ttAudio);
       
  1234 #endif
       
  1235   d(printf("mp3-dvb: using DVB output\n"))
       
  1236 }
       
  1237 
       
  1238 unsigned int cOutputDvb::SampleRate(unsigned int PcmSampleRate)
       
  1239 {
       
  1240   unsigned int samplerate=48000;
       
  1241   if(!only48khz) {
       
  1242     switch(PcmSampleRate) { // If one of the supported frequencies, do it without resampling.
       
  1243       case 96000:           // Select a "even" upsampling frequency if possible, too.
       
  1244         samplerate=96000;
       
  1245         break;
       
  1246       //case 48000: // this is already the default ...
       
  1247       //  samplerate=48000;
       
  1248       //  break;
       
  1249       case 11025:
       
  1250       case 22050:
       
  1251       case 44100:
       
  1252         samplerate=44100;
       
  1253         break;
       
  1254       case 8000:
       
  1255       case 16000:
       
  1256       case 32000:
       
  1257         samplerate=32000;
       
  1258         break;
       
  1259       }
       
  1260     }
       
  1261   return samplerate;
       
  1262 }
       
  1263 
       
  1264 cFrame *cOutputDvb::MakeFrame(unsigned int & Samples, const mad_fixed_t **Data, int index, int sr)
       
  1265 {
       
  1266   static const unsigned char header[] = {
       
  1267     0x00, // PES header
       
  1268     0x00,
       
  1269     0x01,
       
  1270     0xBD, // private stream
       
  1271     0x00,
       
  1272     0x00,
       
  1273     0x87, // mpeg2, aligned, copyright, original
       
  1274     0x00, // no pts/dts
       
  1275     0x00, // PES header data len
       
  1276     0xA0, // aLPCM header
       
  1277     0xFF,
       
  1278     0x00,
       
  1279     0x04,
       
  1280     0x00,
       
  1281     0x01, // 2-channel stereo (n-1)
       
  1282     0x80  // neutral dynamic range
       
  1283     };
       
  1284   cFrame *f=0;
       
  1285   unsigned char *buff=MALLOC(uchar,FRAMESIZE);
       
  1286   if(buff) {
       
  1287     struct FrameHeader *fh=(struct FrameHeader *)buff;
       
  1288     fh->samplerate=sr;
       
  1289     memcpy(buff+FHS,header,sizeof(header));
       
  1290     int srMode;
       
  1291     switch(sr) {
       
  1292       default:
       
  1293       case 48000: srMode=0<<4; break;
       
  1294       case 96000: srMode=1<<4; break;
       
  1295       case 44100: srMode=2<<4; break;
       
  1296       case 32000: srMode=3<<4; break;
       
  1297       }
       
  1298     buff[14+FHS]|=srMode;
       
  1299     unsigned int outlen=scale.ScaleBlock(buff+sizeof(header)+FHS,FRAMESIZE-sizeof(header)-FHS,Samples,Data[0],Data[1],MP3Setup.AudioMode?amDitherBE:amRoundBE);
       
  1300     if(outlen) { 
       
  1301       // lPCM has 600 fps which is 80 samples at 48kHz per channel
       
  1302       // Frame size = (sample_rate * quantization * channels)/4800
       
  1303       buff[10+FHS]=outlen*(4800/16/2)/sr;
       
  1304       outlen+=(sizeof(header)-6);
       
  1305       buff[4+FHS]=outlen>>8;
       
  1306       buff[5+FHS]=outlen;
       
  1307       f=new cFrame(buff,-(outlen+6+FHS),ftUnknown,index);
       
  1308       }
       
  1309     if(!f) free(buff);
       
  1310     }
       
  1311   return f;
       
  1312 }
       
  1313 
       
  1314 #ifdef BROKEN_PCM
       
  1315 #include "player-mp3-sample.c"
       
  1316 #endif
       
  1317 
       
  1318 int cOutputDvb::Output(const unsigned char *Data, int Len, bool SOF)
       
  1319 {
       
  1320   int n=0;
       
  1321   if(SOF) {
       
  1322 #ifdef BROKEN_PCM
       
  1323     struct FrameHeader *fh=(struct FrameHeader *)Data;
       
  1324     if(fh->samplerate!=outSr) {
       
  1325       if(outSr) {
       
  1326         // at this point we would need access to AUDIO_STOP/AUDIO_PLAY
       
  1327         // ioctl, but unfortunaly VDR's API doesn't provides this.
       
  1328         // So we have to do magic to make the driver switch samplerate.
       
  1329         const unsigned char *p=testAudio;
       
  1330         int pc=sizeof(testAudio);
       
  1331         int r;
       
  1332         do {
       
  1333 #if APIVERSNUM < 10318
       
  1334           r=player->PlayVideo(p,pc);
       
  1335 #else
       
  1336           r=player->PlayPes(p,pc);
       
  1337 #endif
       
  1338           if(r>0) { p+=r; pc-=r; }
       
  1339           if(r==0) Poll();
       
  1340           } while(r>=0 && pc>0);
       
  1341         }
       
  1342       outSr=fh->samplerate;
       
  1343       d(printf("mp3-dvb: output samplerate now %d\n",outSr))
       
  1344       }
       
  1345 #endif
       
  1346     n=FHS;
       
  1347     Data+=n; Len-=n;
       
  1348     }
       
  1349 #if APIVERSNUM < 10318
       
  1350   int r=player->PlayVideo(Data,Len);
       
  1351 #else
       
  1352   int r=player->PlayPes(Data,Len);
       
  1353 #endif
       
  1354   return (r>=0 ? r+n : -1);
       
  1355 }
       
  1356 
       
  1357 bool cOutputDvb::Poll(void)
       
  1358 {
       
  1359   return player->DevicePoll(poll,500);
       
  1360 }
       
  1361 
       
  1362 void cOutputDvb::Play(void)
       
  1363 {
       
  1364 #ifndef BROKEN_PCM
       
  1365   player->DevicePlay();
       
  1366 #endif
       
  1367 }
       
  1368 
       
  1369 void cOutputDvb::Pause(void)
       
  1370 {
       
  1371 #ifndef BROKEN_PCM
       
  1372   player->DeviceFreeze();
       
  1373 #endif
       
  1374 }
       
  1375 
       
  1376 // --- cOutputOss --------------------------------------------------------------
       
  1377 
       
  1378 #ifdef WITH_OSS
       
  1379 
       
  1380 const char *dspdevice="/dev/dsp";
       
  1381 
       
  1382 class cOutputOss : public cOutput {
       
  1383 private:
       
  1384   int fd;
       
  1385   cPoller poll;
       
  1386   unsigned int outSr;
       
  1387   unsigned char buff[8192];
       
  1388   //
       
  1389   bool Reset(unsigned int sr);
       
  1390 public:
       
  1391   cOutputOss(cMP3Player *Player);
       
  1392   virtual ~cOutputOss();
       
  1393   virtual void Init(void);
       
  1394   virtual unsigned int SampleRate(unsigned int PcmSampleRate);
       
  1395   virtual cFrame *MakeFrame(unsigned int & Samples, const mad_fixed_t **Data, int index, int sr);
       
  1396   virtual int Output(const unsigned char *Data, int Len, bool SOF);
       
  1397   virtual bool Poll(void);
       
  1398   virtual void Play(void);
       
  1399   virtual void Pause(void);
       
  1400   };
       
  1401 
       
  1402 cOutputOss::cOutputOss(cMP3Player *Player)
       
  1403 :cOutput(Player)
       
  1404 {
       
  1405   fd=-1; outSr=0;
       
  1406   d(printf("mp3-oss: using OSS output\n"))
       
  1407 }
       
  1408 
       
  1409 cOutputOss::~cOutputOss()
       
  1410 {
       
  1411   close(fd);
       
  1412 }
       
  1413 
       
  1414 void cOutputOss::Init(void)
       
  1415 {
       
  1416   if(fd<0) {
       
  1417     fd=open(dspdevice,O_WRONLY|O_NONBLOCK);
       
  1418     if(fd>=0) poll.Add(fd,true);
       
  1419     else esyslog("ERROR: Cannot open dsp device '%s': %s!",dspdevice,strerror(errno));
       
  1420     }
       
  1421   cOutput::Init();
       
  1422 }
       
  1423 
       
  1424 bool cOutputOss::Reset(unsigned int sr)
       
  1425 {
       
  1426   if(fd>=0) {
       
  1427     CHECK(ioctl(fd,SNDCTL_DSP_SYNC,0));
       
  1428     int format=AFMT_S16_LE;
       
  1429     CHECK(ioctl(fd,SNDCTL_DSP_SETFMT,&format));
       
  1430     if(format==AFMT_S16_LE) {
       
  1431       int channels=2;
       
  1432       CHECK(ioctl(fd,SNDCTL_DSP_CHANNELS,&channels));
       
  1433       if(channels==2) {
       
  1434         int real=sr;
       
  1435         CHECK(ioctl(fd,SNDCTL_DSP_SPEED,&real));
       
  1436         d(printf("oss: DSP samplerate now %d\n",real))
       
  1437         if(abs(real-sr)<sr/50) {
       
  1438           outSr=sr;
       
  1439           d(printf("mp3-oss: DSP reset done\n"))
       
  1440           return true;
       
  1441           }
       
  1442         else {
       
  1443           d(printf("mp3-oss: driver can't handle samplerate %d, got %d\n",sr,real))
       
  1444           esyslog("ERROR: OSS driver can't handle samplerate %d, got %d\n",sr,real);
       
  1445           }
       
  1446         }
       
  1447       else {
       
  1448         d(printf("mp3-oss: 2-channel stereo not supported\n"))
       
  1449         esyslog("ERROR: OSS driver doesn't support 2-channel stereo.");
       
  1450         }
       
  1451       }
       
  1452     else {
       
  1453       d(printf("mp3-oss: little-endian samples not supported\n"))
       
  1454       esyslog("ERROR: OSS driver doesn't support 16-bit little-endian samples.");
       
  1455       }
       
  1456     close(fd); fd=-1;
       
  1457     }
       
  1458   return false;
       
  1459 }
       
  1460 
       
  1461 unsigned int cOutputOss::SampleRate(unsigned int PcmSampleRate)
       
  1462 {
       
  1463   return PcmSampleRate;
       
  1464 }
       
  1465 
       
  1466 cFrame *cOutputOss::MakeFrame(unsigned int & Samples, const mad_fixed_t **Data, int index, int sr)
       
  1467 {
       
  1468   struct FrameHeader *fh=(struct FrameHeader *)buff;
       
  1469   fh->samplerate=sr;
       
  1470   cFrame *f=0;
       
  1471   unsigned int outlen=scale.ScaleBlock(buff+FHS,sizeof(buff)-FHS,Samples,Data[0],Data[1],MP3Setup.AudioMode?amDitherLE:amRoundLE);
       
  1472   if(outlen) 
       
  1473     f=new cFrame(buff,outlen+FHS,ftUnknown,index);
       
  1474   return f;
       
  1475 }
       
  1476 
       
  1477 int cOutputOss::Output(const unsigned char *Data, int Len, bool SOF)
       
  1478 {
       
  1479   if(fd>=0) {
       
  1480     int n=0;
       
  1481     if(SOF) {
       
  1482       struct FrameHeader *fh=(struct FrameHeader *)Data;
       
  1483       if(fh->samplerate!=outSr) Reset(fh->samplerate);
       
  1484       n=FHS;
       
  1485       Data+=n; Len-=n;
       
  1486       }
       
  1487     int r=write(fd,Data,Len);
       
  1488     if(r<0 && !FATALERRNO) r=0;
       
  1489     if(r>=0) return n+r;
       
  1490     }
       
  1491   return -1;
       
  1492 }
       
  1493 
       
  1494 bool cOutputOss::Poll(void)
       
  1495 {
       
  1496   return fd>=0 ? poll.Poll(500) : false;
       
  1497 }
       
  1498 
       
  1499 void cOutputOss::Play(void)
       
  1500 {
       
  1501 }
       
  1502 
       
  1503 void cOutputOss::Pause(void)
       
  1504 {
       
  1505   CHECK(ioctl(fd,SNDCTL_DSP_POST,0));
       
  1506 }
       
  1507 
       
  1508 #endif
       
  1509 
       
  1510 // --- cMP3Player --------------------------------------------------------------
       
  1511 
       
  1512 cMP3Player::cMP3Player()
       
  1513 :cPlayer(MP3Setup.BackgrMode==1 ? pmAudioOnly : pmAudioOnlyBlack)
       
  1514 {
       
  1515   active=true; started=false; isStream=false;
       
  1516   ringBuffer=new cRingBufferFrame(MP3BUFSIZE);
       
  1517   rframe=0; pframe=0; decoder=0; output=0;
       
  1518   playMode=pmStartup; state=msStop;
       
  1519   playindex=total=0;
       
  1520 }
       
  1521 
       
  1522 cMP3Player::~cMP3Player()
       
  1523 {
       
  1524   Detach();
       
  1525   delete ringBuffer;
       
  1526 }
       
  1527 
       
  1528 void cMP3Player::Activate(bool On)
       
  1529 {
       
  1530   if(On) {
       
  1531     d(printf("mp3: player active true requested...\n"))
       
  1532     if(!started) {
       
  1533       playMode=pmStartup; Start(); started=true;
       
  1534       playModeMutex.Lock();
       
  1535       WaitPlayMode(pmStartup,true); // wait for the decoder to become ready
       
  1536       playModeMutex.Unlock();
       
  1537       Lock();
       
  1538       Play();
       
  1539       Unlock();
       
  1540       }
       
  1541     d(printf("mp3: player active true done\n"))
       
  1542     }
       
  1543   else if(started && active) {
       
  1544     d(printf("mp3: player active false requested...\n"))
       
  1545     Lock(); StopPlay(); Unlock();
       
  1546     active=false;
       
  1547     SetPlayMode(pmStartup);
       
  1548     Cancel(2);
       
  1549     d(printf("mp3: player active false done\n"))
       
  1550     }
       
  1551 }
       
  1552 
       
  1553 void cMP3Player::SetPlayMode(ePlayMode mode)
       
  1554 {
       
  1555   playModeMutex.Lock();
       
  1556   if(mode!=playMode) {
       
  1557     playMode=mode;
       
  1558     dm(printf("mp3: setting mode=%d (pid=%d)\n",mode,getpid()))
       
  1559     playModeCond.Broadcast();
       
  1560     }
       
  1561   playModeMutex.Unlock();
       
  1562 }
       
  1563 
       
  1564 void cMP3Player::WaitPlayMode(ePlayMode mode, bool inv)
       
  1565 {
       
  1566   // must be called with playModeMutex LOCKED !!!
       
  1567 
       
  1568   while(active && ((!inv && mode!=playMode) || (inv && mode==playMode))) {
       
  1569     dm(printf("mp3: entering wait for mode%s%d with mode=%d (pid=%d)\n",inv?"!=":"==",mode,playMode,getpid()))
       
  1570     playModeCond.Wait(playModeMutex);
       
  1571     dm(printf("mp3: returning from wait with mode=%d (pid=%d)\n",playMode,getpid()))
       
  1572     }
       
  1573 }
       
  1574 
       
  1575 void cMP3Player::Action(void)
       
  1576 {
       
  1577   cSong *playing=0;
       
  1578   struct mad_pcm *pcm=0;
       
  1579   cResample resample[2];
       
  1580   unsigned int nsamples[2];
       
  1581   const mad_fixed_t *data[2];
       
  1582   cLevel level;
       
  1583   cNormalize norm;
       
  1584   bool haslevel=false;
       
  1585   const unsigned char *p=0;
       
  1586   int pc=0, readindex=0;
       
  1587   bool imageValid=true;
       
  1588   int imageCheck=0;
       
  1589 #ifdef DEBUG
       
  1590   int beat=0;
       
  1591 #endif
       
  1592 #ifdef DEBUG_DELAY
       
  1593   int lastwrite=0;
       
  1594 #endif
       
  1595 
       
  1596   dsyslog("mp3: player thread started (pid=%d)", getpid());
       
  1597   state=msStop;
       
  1598   SetPlayMode(pmStopped);
       
  1599 
       
  1600   delete output; output=0;
       
  1601 #ifdef WITH_OSS
       
  1602   if(MP3Setup.AudioOutMode==AUDIOOUTMODE_OSS) output=new cOutputOss(this);
       
  1603 #endif
       
  1604   if(MP3Setup.AudioOutMode==AUDIOOUTMODE_DVB) output=new cOutputDvb(this);
       
  1605   if(!output) {
       
  1606     d(printf("mp3: audiooutmode mismatch or no output driver\n"))
       
  1607     esyslog("ERROR: no audio output driver. balling out");
       
  1608     goto abort;
       
  1609     }
       
  1610 
       
  1611   while(active) {
       
  1612 #ifdef DEBUG
       
  1613     {
       
  1614     int now=time(0);
       
  1615     if(now>=beat) {
       
  1616       int avail=ringBuffer->Available();
       
  1617       printf("mp3: heartbeat buffer=%d now=%d\n",avail,now&4095);
       
  1618       //output->Stats(); if(haslevel) norm.Stats();
       
  1619       beat=now+(avail>(MP3BUFSIZE*10/100) ? (avail<(MP3BUFSIZE*50/100) ? 2 : 20) : 1);
       
  1620       }
       
  1621     }
       
  1622 #endif
       
  1623 
       
  1624     Lock();
       
  1625 
       
  1626 next:
       
  1627     if(!pframe && playing && !imageValid && imageCheck<time_ms()) {
       
  1628       unsigned char *mem;
       
  1629       int len;
       
  1630       imageCheck=time_ms()+250;
       
  1631       imageValid=playing->Image(mem,len);
       
  1632       if(mem) {
       
  1633         if(playindex) SLEEP(80); // stillpicture ioctl freezes without this
       
  1634         DeviceStillPicture(mem,len);
       
  1635         free(mem);
       
  1636         }
       
  1637       }
       
  1638 
       
  1639     bool SOF=false;
       
  1640     if(!pframe && playMode==pmPlay) {
       
  1641       pframe=ringBuffer->Get();
       
  1642       if(pframe) {
       
  1643         playindex=pframe->Index();
       
  1644         p=pframe->Data();
       
  1645         pc=pframe->Count();
       
  1646         SOF=true;
       
  1647         }
       
  1648       }
       
  1649 
       
  1650     if(pframe) {
       
  1651 #ifdef DEBUG_DELAY
       
  1652       {
       
  1653       int now=time_ms();
       
  1654       if(lastwrite && lastwrite<now-(DEBUG_DELAY+50))
       
  1655         printf("mp3: write delayed %d ms\n",now-lastwrite);
       
  1656       lastwrite=now;
       
  1657       }
       
  1658 #endif
       
  1659       int w=output->Output(p,pc,SOF);
       
  1660       if(w>0) {
       
  1661         p+=w; pc-=w;
       
  1662         if(pc<=0) {
       
  1663           ringBuffer->Drop(pframe);
       
  1664           pframe=0;
       
  1665           goto next;
       
  1666           }
       
  1667         }
       
  1668       else if(w<0 && FATALERRNO) {
       
  1669         LOG_ERROR;
       
  1670         d(printf("mp3: output failed: %s\n",strerror(errno)))
       
  1671         Unlock();
       
  1672         goto abort;
       
  1673         }
       
  1674       }
       
  1675 
       
  1676     if(mgr->NewCurrent() && playMode==pmPlay && state!=msStart) {
       
  1677       Empty();
       
  1678       state=msRestart;
       
  1679       d(printf("mp3: stale song change, restart.\n"))
       
  1680       }
       
  1681 
       
  1682     if(!rframe && playMode==pmPlay) {
       
  1683       switch(state) {
       
  1684         case msStart:
       
  1685           d(printf("mp3: starting play\n"))
       
  1686           mgr->Throttle(true);
       
  1687           playindex=readindex=total=0;
       
  1688           playing=mgr->Current();
       
  1689           if(playing) {
       
  1690             if((decoder=playing->Decoder()) && decoder->Start()) {
       
  1691               isStream=decoder->IsStream(); levelgood=!isStream; haslevel=false;
       
  1692               cSongInfo *si=playing->Info(true);
       
  1693               if(si) {
       
  1694                 if(si->Level>0.0) {
       
  1695                   d(printf("mp3: found song level=%f peak=%f\n",si->Level,si->Peak))
       
  1696                   haslevel=true;
       
  1697                   norm.Init(si->Level,si->Peak);
       
  1698                   }
       
  1699                 if(si->HasInfo())
       
  1700                   total=SecondsToFrames(si->Total);
       
  1701                 }
       
  1702               d(printf("mp3: isStream=%d levelgood=%d haslevel=%d\n",isStream,levelgood,haslevel))
       
  1703               output->Init();
       
  1704               level.Init();
       
  1705               if(MP3Setup.BackgrMode==2) imageValid=false;
       
  1706               state=msDecode;
       
  1707               break;
       
  1708               }
       
  1709             else
       
  1710               esyslog("ERROR: playlist entry %s is not a valid file",playing->Name());
       
  1711             }
       
  1712           else
       
  1713             d(printf("mp3: no current on start play\n"))
       
  1714           state=msEof;
       
  1715           break;
       
  1716         case msDecode:
       
  1717           {
       
  1718 #ifdef DEBUG_DELAY
       
  1719           int now=time_ms();
       
  1720 #endif
       
  1721           struct Decode *ds=decoder->Decode();
       
  1722 #ifdef DEBUG_DELAY
       
  1723           now=time_ms()-now;
       
  1724           if(now>DEBUG_DELAY) printf("mp3: decode delayed %d ms\n",now);
       
  1725 #endif
       
  1726           switch(ds->status) {
       
  1727             case dsPlay:
       
  1728               pcm=ds->pcm;
       
  1729               readindex=ds->index;
       
  1730               state=msNormalize;
       
  1731               break;
       
  1732             case dsSkip:
       
  1733             case dsSoftError:
       
  1734               // skipping, state unchanged, next decode
       
  1735               break;
       
  1736             case dsEof:
       
  1737               if(!haslevel && levelgood) { // save level & peak to infocache on eof
       
  1738                 double l=level.GetLevel();
       
  1739                 if(l>0.0) {
       
  1740                   cSongInfo *si=decoder->SongInfo(false);
       
  1741                   cFileInfo *fi=decoder->FileInfo();
       
  1742                   if(si && fi) {
       
  1743                     si->Level=l;
       
  1744                     si->Peak=level.GetPeak();
       
  1745                     InfoCache.Cache(si,fi);
       
  1746                     }
       
  1747                   }
       
  1748                 }
       
  1749               state=msEof;
       
  1750               break;
       
  1751             case dsOK:
       
  1752             case dsError:
       
  1753               state=msError;
       
  1754               break;
       
  1755             }
       
  1756           break;
       
  1757           }
       
  1758         case msNormalize:
       
  1759           if(!haslevel) { if(levelgood) level.GetPower(pcm); }
       
  1760           else norm.AddGain(pcm);
       
  1761           state=msResample;
       
  1762           break;
       
  1763         case msResample:
       
  1764 #ifdef DEBUG
       
  1765           {
       
  1766           static unsigned int oldrate=0;
       
  1767           if(oldrate!=pcm->samplerate) {
       
  1768             printf("mp3: new input sample rate %d\n",pcm->samplerate);
       
  1769             oldrate=pcm->samplerate;
       
  1770             }
       
  1771           }
       
  1772 #endif
       
  1773           nsamples[0]=nsamples[1]=pcm->length;
       
  1774           data[0]=pcm->samples[0];
       
  1775           data[1]=pcm->channels>1 ? pcm->samples[1]:0;
       
  1776 
       
  1777           dvbSampleRate=output->SampleRate(pcm->samplerate);
       
  1778           if(dvbSampleRate!=pcm->samplerate) {
       
  1779             if(resample[0].SetInputRate(pcm->samplerate,dvbSampleRate)) {
       
  1780               nsamples[0]=resample[0].ResampleBlock(nsamples[0],data[0]);
       
  1781               data[0]    =resample[0].Resampled();
       
  1782               }
       
  1783             if(data[1] && resample[1].SetInputRate(pcm->samplerate,dvbSampleRate)) {
       
  1784               nsamples[1]=resample[1].ResampleBlock(nsamples[1],data[1]);
       
  1785               data[1]    =resample[1].Resampled();
       
  1786               }
       
  1787             }
       
  1788           state=msOutput;
       
  1789           break;
       
  1790         case msOutput:
       
  1791           if(nsamples[0]>0) rframe=output->MakeFrame(nsamples[0],data,readindex,dvbSampleRate);
       
  1792           else state=msDecode;
       
  1793           break;
       
  1794         case msError:
       
  1795         case msEof:
       
  1796           d(printf("mp3: eof or error\n"))
       
  1797           state=msWait;
       
  1798           // fall through
       
  1799         case msRestart:
       
  1800         case msStop:
       
  1801           d(printf("mp3: stopping play\n"))
       
  1802           if(decoder) { decoder->Stop(); decoder=0; }
       
  1803           mgr->Release(); playing=0; imageValid=true;
       
  1804           levelgood=false;
       
  1805 #ifdef DEBUG
       
  1806           output->Stats(); if(haslevel) norm.Stats();
       
  1807 #endif
       
  1808           if(state==msStop) SetPlayMode(pmStopped);
       
  1809           if(state==msRestart) state=msStart;
       
  1810           break;
       
  1811         case msWait:
       
  1812           if(ringBuffer->Available()==0) {
       
  1813             if(mgr->NextCurrent()) {
       
  1814               d(printf("mp3: playing next\n"))
       
  1815               state=msStart;
       
  1816               }
       
  1817             else {
       
  1818               d(printf("mp3: end of playlist\n"))
       
  1819               if(MP3Setup.AbortAtEOL) {
       
  1820                 active=false;
       
  1821                 d(printf("mp3: aborting player...\n"))
       
  1822                 }
       
  1823               else d(printf("mp3: player idle...\n"))
       
  1824               SetPlayMode(pmStopped);
       
  1825               }
       
  1826             }
       
  1827           break;
       
  1828         }
       
  1829       }
       
  1830 
       
  1831     if(rframe && ringBuffer->Put(rframe)) rframe=0;
       
  1832 
       
  1833     Unlock();
       
  1834 
       
  1835     if((rframe || state==msWait) && pframe) {
       
  1836       mgr->Throttle(false);
       
  1837       output->Poll();
       
  1838       }
       
  1839     else if(playMode!=pmPlay) {
       
  1840       mgr->Throttle(false);
       
  1841       if(!imageValid)
       
  1842         SLEEP(100);
       
  1843       else {
       
  1844         playModeMutex.Lock();
       
  1845         if(playMode!=pmPlay) WaitPlayMode(playMode,true);
       
  1846         playModeMutex.Unlock();
       
  1847         }
       
  1848 #ifdef DEBUG_DELAY
       
  1849       lastwrite=0;
       
  1850 #endif
       
  1851       }
       
  1852     else if(state!=msWait && ringBuffer->Available()<(MP3BUFSIZE*50/100)) {
       
  1853       mgr->Throttle(true);
       
  1854       }
       
  1855     }
       
  1856 
       
  1857 abort:
       
  1858   Lock();
       
  1859   delete rframe;
       
  1860   delete output; output=0;
       
  1861   if(decoder) { decoder->Stop(); decoder=0; }
       
  1862   mgr->Release(); playing=0;
       
  1863   SetPlayMode(pmStopped);
       
  1864   Unlock();
       
  1865   active=false;
       
  1866 
       
  1867   dsyslog("mp3: player thread ended (pid=%d)", getpid());
       
  1868 }
       
  1869 
       
  1870 void cMP3Player::Empty(void)
       
  1871 {
       
  1872   Lock();
       
  1873   delete rframe; rframe=0; pframe=0;
       
  1874   ringBuffer->Clear();
       
  1875   DeviceClear();
       
  1876   Unlock();
       
  1877 }
       
  1878 
       
  1879 void cMP3Player::StopPlay(void) // StopPlay() must be called in locked state!!!
       
  1880 {
       
  1881   if(playMode!=pmStopped) {
       
  1882     Empty();
       
  1883     state=msStop;
       
  1884     SetPlayMode(pmPlay);
       
  1885     Unlock();                 // let the decode thread process the stop signal
       
  1886     playModeMutex.Lock();
       
  1887     WaitPlayMode(pmStopped,false);
       
  1888     playModeMutex.Unlock();
       
  1889     Lock();
       
  1890     }
       
  1891 }
       
  1892 
       
  1893 void cMP3Player::Pause(void)
       
  1894 {
       
  1895   Lock();
       
  1896   if(playMode==pmPaused) Play();
       
  1897   else if(playMode==pmPlay && !isStream) {
       
  1898     d(printf("mp3: pause\n"))
       
  1899     if(output) output->Pause();
       
  1900     SetPlayMode(pmPaused);
       
  1901     }
       
  1902   Unlock();
       
  1903 }
       
  1904 
       
  1905 void cMP3Player::Play(void)
       
  1906 {
       
  1907   Lock();
       
  1908   if(playMode!=pmPlay) {
       
  1909     d(printf("mp3: play\n"))
       
  1910     if(playMode==pmStopped) state=msStart;
       
  1911     if(output) output->Play();
       
  1912     SetPlayMode(pmPlay);
       
  1913     }
       
  1914   Unlock();
       
  1915 }
       
  1916 
       
  1917 bool cMP3Player::PrevCheck(void)
       
  1918 {
       
  1919   bool res=false;
       
  1920   Lock();
       
  1921   if(playindex>=2000 && !isStream) {
       
  1922     state=msRestart; res=true;
       
  1923     Empty();
       
  1924     d(printf("mp3: skip to start of song\n"))
       
  1925     }
       
  1926   Unlock();
       
  1927   return res;
       
  1928 }
       
  1929 
       
  1930 void cMP3Player::SkipSeconds(int secs)
       
  1931 {
       
  1932   if(playMode!=pmStopped && !isStream) {
       
  1933     Lock();
       
  1934     d(printf("mp3: skip secs %d\n",secs))
       
  1935     if(playMode==pmPaused) SetPlayMode(pmPlay);
       
  1936     float bufsecs=(float)ringBuffer->Available() / (float)(dvbSampleRate*OUT_FACT);
       
  1937     d(printf("mp3: ringbuffer available %f secs\n",bufsecs))
       
  1938     if(secs>0 && bufsecs>=(float)secs) {
       
  1939       // clear intermediate queue
       
  1940       if(pframe) {
       
  1941         ringBuffer->Drop(pframe);
       
  1942         pframe=0;
       
  1943         }
       
  1944       DeviceClear();
       
  1945       // skip inside ringbuffer
       
  1946       int skipindex=playindex+secs*1000;
       
  1947       d(printf("mp3: skipping play=%d skip=%d ...",playindex,skipindex))
       
  1948       cFrame *f;
       
  1949       do {
       
  1950         f=ringBuffer->Get();
       
  1951         if(f) {
       
  1952           playindex=f->Index();
       
  1953           ringBuffer->Drop(f);
       
  1954           d(printf("*"))
       
  1955           }
       
  1956         } while(f && playindex<skipindex);
       
  1957       d(printf("\nmp3: skipped play=%d skip=%d\n",playindex,skipindex))
       
  1958       }
       
  1959     else {
       
  1960       if(decoder && decoder->Skip(secs,bufsecs)) levelgood=false;
       
  1961       Empty();
       
  1962       }
       
  1963     Unlock();
       
  1964     }
       
  1965 }
       
  1966 
       
  1967 bool cMP3Player::GetIndex(int &Current, int &Total, bool SnapToIFrame)
       
  1968 {
       
  1969   Current=SecondsToFrames(playindex/1000); Total=total;
       
  1970   return total>=0;
       
  1971 }
       
  1972 
       
  1973 bool cMP3Player::GetReplayMode(bool &Play, bool &Forward, int &Speed)
       
  1974 {
       
  1975   Play=(playMode==pmPlay);
       
  1976   Forward=true;
       
  1977   Speed=-1;
       
  1978   return true;
       
  1979 }