1 /* 2 SMPEG - SDL MPEG Player Library 3 Copyright (C) 1999 Loki Entertainment Software 4 5 - Modified by Michel Darricau from eProcess <mdarricau@eprocess.fr> for popcorn - 6 7 This library is free software; you can redistribute it and/or 8 modify it under the terms of the GNU Library General Public 9 License as published by the Free Software Foundation; either 10 version 2 of the License, or (at your option) any later version. 11 12 This library is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 Library General Public License for more details. 16 17 You should have received a copy of the GNU Library General Public 18 License along with this library; if not, write to the Free 19 Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 */ 21 22 /* A class based on the MPEG stream class, used to parse and play audio */ 23 24 #ifndef _MPEGAUDIO_H_ 25 #define _MPEGAUDIO_H_ 26 27 #include "SDL.h" 28 #include "MPEGerror.h" 29 #include "MPEGaction.h" 30 31 #ifdef THREADED_AUDIO 32 #include "MPEGring.h" 33 #endif 34 35 class MPEGstream; 36 37 /* MPEG/WAVE Sound library 38 39 (C) 1997 by Woo-jae Jung */ 40 41 /**************************/ 42 /* Define values for MPEG */ 43 /**************************/ 44 #define SCALEBLOCK 12 45 #define CALCBUFFERSIZE 512 46 #define MAXSUBBAND 32 47 #define MAXCHANNEL 2 48 #define MAXTABLE 2 49 #define SCALE 32768 50 #define MAXSCALE (SCALE-1) 51 #define MINSCALE (-SCALE) 52 #define RAWDATASIZE (2*2*32*SSLIMIT) 53 54 #define LS 0 55 #define RS 1 56 57 #define SSLIMIT 18 58 #define SBLIMIT 32 59 60 #define WINDOWSIZE 4096 61 62 // Huffmancode 63 #define HTN 34 64 65 /********************/ 66 /* Type definitions */ 67 /********************/ 68 typedef float REAL; 69 70 typedef struct 71 { 72 bool generalflag; 73 unsigned int part2_3_length; 74 unsigned int big_values; 75 unsigned int global_gain; 76 unsigned int scalefac_compress; 77 unsigned int window_switching_flag; 78 unsigned int block_type; 79 unsigned int mixed_block_flag; 80 unsigned int table_select[3]; 81 unsigned int subblock_gain[3]; 82 unsigned int region0_count; 83 unsigned int region1_count; 84 unsigned int preflag; 85 unsigned int scalefac_scale; 86 unsigned int count1table_select; 87 }layer3grinfo; 88 89 typedef struct 90 { 91 unsigned main_data_begin; 92 unsigned private_bits; 93 struct 94 { 95 unsigned scfsi[4]; 96 layer3grinfo gr[2]; 97 }ch[2]; 98 }layer3sideinfo; 99 100 typedef struct 101 { 102 int l[23]; /* [cb] */ 103 int s[3][13]; /* [window][cb] */ 104 }layer3scalefactor; /* [ch] */ 105 106 typedef struct 107 { 108 int tablename; 109 unsigned int xlen,ylen; 110 unsigned int linbits; 111 unsigned int treelen; 112 const unsigned int (*val)[2]; 113 }HUFFMANCODETABLE; 114 115 116 // Class for Mpeg layer3 117 class Mpegbitwindow 118 { 119 public: Mpegbitwindow()120 Mpegbitwindow(){bitindex=point=0;}; 121 initialize(void)122 void initialize(void) {bitindex=point=0;}; gettotalbit(void)123 int gettotalbit(void) const {return bitindex;}; putbyte(int c)124 void putbyte(int c) {buffer[point&(WINDOWSIZE-1)]=c;point++;}; 125 void wrap(void); rewind(int bits)126 void rewind(int bits) {bitindex-=bits;}; forward(int bits)127 void forward(int bits) {bitindex+=bits;}; getbit(void)128 int getbit(void) { 129 register int r=(buffer[bitindex>>3]>>(7-(bitindex&7)))&1; 130 bitindex++; 131 return r; 132 } getbits9(int bits)133 int getbits9(int bits) 134 { 135 register unsigned short a; 136 { int offset=bitindex>>3; 137 138 a=(((unsigned char)buffer[offset])<<8) | ((unsigned char)buffer[offset+1]); 139 } 140 a<<=(bitindex&7); 141 bitindex+=bits; 142 return (int)((unsigned int)(a>>(16-bits))); 143 } 144 int getbits(int bits); 145 146 private: 147 int point,bitindex; 148 char buffer[2*WINDOWSIZE]; 149 }; 150 151 class MPEGaudio; 152 void Play_MPEGaudioSDL(void *udata, Uint8 *stream, int len); 153 int Play_MPEGaudio(MPEGaudio *audio, Uint8 *stream, int len); 154 #ifdef THREADED_AUDIO 155 int Decode_MPEGaudio(void *udata); 156 #endif 157 158 /* The actual MPEG audio class */ 159 class MPEGaudio : public MPEGerror, public MPEGaudioaction { 160 161 friend void Play_MPEGaudioSDL(void *udata, Uint8 *stream, int len); 162 friend int Play_MPEGaudio(MPEGaudio *audio, Uint8 *stream, int len); 163 #ifdef THREADED_AUDIO 164 friend int Decode_MPEGaudio(void *udata); 165 #endif 166 167 public: 168 MPEGaudio(MPEGstream *stream, bool initSDL = true); 169 virtual ~MPEGaudio(); 170 171 /* MPEG actions */ 172 bool GetAudioInfo(MPEG_AudioInfo *info); 173 double Time(void); 174 void Play(void); 175 void Stop(void); 176 void Rewind(void); 177 void ResetSynchro(double time); 178 void Skip(float seconds); 179 void Volume(int vol); 180 /* Michel Darricau from eProcess <mdarricau@eprocess.fr> conflict name in popcorn */ 181 MPEGstatus GetStatus(void); 182 183 /* Returns the desired SDL audio spec for this stream */ 184 bool WantedSpec(SDL_AudioSpec *wanted); 185 186 /* Inform SMPEG of the actual audio format if configuring SDL 187 outside of this class */ 188 void ActualSpec(const SDL_AudioSpec *actual); 189 190 protected: 191 bool sdl_audio; 192 MPEGstream *mpeg; 193 int valid_stream; 194 bool stereo; 195 double rate_in_s; 196 Uint32 frags_playing; 197 Uint32 frag_time; 198 #ifdef THREADED_AUDIO 199 bool decoding; 200 SDL_Thread *decode_thread; 201 202 void StartDecoding(void); 203 void StopDecoding(void); 204 #endif 205 206 /* Code from splay 1.8.2 */ 207 208 /*****************************/ 209 /* Constant tables for layer */ 210 /*****************************/ 211 private: 212 static const int bitrate[2][3][15],frequencies[2][3]; 213 static const REAL scalefactorstable[64]; 214 static const HUFFMANCODETABLE ht[HTN]; 215 static const REAL filter[512]; 216 static REAL hcos_64[16],hcos_32[8],hcos_16[4],hcos_8[2],hcos_4; 217 218 /*************************/ 219 /* MPEG header variables */ 220 /*************************/ 221 private: 222 int layer,protection,bitrateindex,padding,extendedmode; 223 enum _mpegversion {mpeg1,mpeg2} version; 224 enum _mode {fullstereo,joint,dual,single} mode; 225 enum _frequency {frequency44100,frequency48000,frequency32000} frequency; 226 227 /***************************************/ 228 /* Interface for setting music quality */ 229 /***************************************/ 230 private: 231 bool forcetomonoflag; 232 bool forcetostereoflag; 233 int downfrequency; 234 235 public: 236 void setforcetomono(bool flag); 237 void setdownfrequency(int value); 238 239 /******************************/ 240 /* Frame management variables */ 241 /******************************/ 242 private: 243 int decodedframe,currentframe,totalframe; 244 245 /***************************************/ 246 /* Variables made by MPEG-Audio header */ 247 /***************************************/ 248 private: 249 int tableindex,channelbitrate; 250 int stereobound,subbandnumber,inputstereo,outputstereo; 251 REAL scalefactor; 252 int framesize; 253 254 /*******************/ 255 /* Mpegtoraw class */ 256 /*******************/ 257 public: 258 void initialize(); 259 bool run(int frames, double *timestamp = NULL); 260 void clearbuffer(void); 261 262 /*****************************/ 263 /* Loading MPEG-Audio stream */ 264 /*****************************/ 265 private: 266 Uint8 _buffer[4096]; 267 Uint32 _buffer_pos; 268 int bitindex; 269 bool fillbuffer(int size); 270 void sync(void); 271 bool issync(void); 272 int getbyte(void); 273 int getbit(void); 274 int getbits8(void); 275 int getbits9(int bits); 276 int getbits(int bits); 277 278 279 /********************/ 280 /* Global variables */ 281 /********************/ 282 private: 283 int lastfrequency,laststereo; 284 285 // for Layer3 286 int layer3slots,layer3framestart,layer3part2start; 287 REAL prevblck[2][2][SBLIMIT][SSLIMIT]; 288 int currentprevblock; 289 layer3sideinfo sideinfo; 290 layer3scalefactor scalefactors[2]; 291 292 Mpegbitwindow bitwindow; wgetbit(void)293 int wgetbit (void) {return bitwindow.getbit (); } wgetbits9(int bits)294 int wgetbits9(int bits){return bitwindow.getbits9(bits);} wgetbits(int bits)295 int wgetbits (int bits){return bitwindow.getbits (bits);} 296 297 298 /*************************************/ 299 /* Decoding functions for each layer */ 300 /*************************************/ 301 private: 302 bool loadheader(void); 303 304 // 305 // Subbandsynthesis 306 // 307 REAL calcbufferL[2][CALCBUFFERSIZE],calcbufferR[2][CALCBUFFERSIZE]; 308 int currentcalcbuffer,calcbufferoffset; 309 310 void computebuffer(REAL *fraction,REAL buffer[2][CALCBUFFERSIZE]); 311 void generatesingle(void); 312 void generate(void); 313 void subbandsynthesis(REAL *fractionL,REAL *fractionR); 314 315 void computebuffer_2(REAL *fraction,REAL buffer[2][CALCBUFFERSIZE]); 316 void generatesingle_2(void); 317 void generate_2(void); 318 void subbandsynthesis_2(REAL *fractionL,REAL *fractionR); 319 320 // Extarctor 321 void extractlayer1(void); // MPEG-1 322 void extractlayer2(void); 323 void extractlayer3(void); 324 void extractlayer3_2(void); // MPEG-2 325 326 327 // Functions for layer 3 328 void layer3initialize(void); 329 bool layer3getsideinfo(void); 330 bool layer3getsideinfo_2(void); 331 void layer3getscalefactors(int ch,int gr); 332 void layer3getscalefactors_2(int ch); 333 void layer3huffmandecode(int ch,int gr,int out[SBLIMIT][SSLIMIT]); 334 REAL layer3twopow2(int scale,int preflag,int pretab_offset,int l); 335 REAL layer3twopow2_1(int a,int b,int c); 336 void layer3dequantizesample(int ch,int gr,int in[SBLIMIT][SSLIMIT], 337 REAL out[SBLIMIT][SSLIMIT]); 338 void layer3fixtostereo(int gr,REAL in[2][SBLIMIT][SSLIMIT]); 339 void layer3reorderandantialias(int ch,int gr,REAL in[SBLIMIT][SSLIMIT], 340 REAL out[SBLIMIT][SSLIMIT]); 341 342 void layer3hybrid(int ch,int gr,REAL in[SBLIMIT][SSLIMIT], 343 REAL out[SSLIMIT][SBLIMIT]); 344 345 void huffmandecoder_1(const HUFFMANCODETABLE *h,int *x,int *y); 346 void huffmandecoder_2(const HUFFMANCODETABLE *h,int *x,int *y,int *v,int *w); 347 348 /********************/ 349 /* Playing raw data */ 350 /********************/ 351 private: 352 int samplesperframe; 353 int rawdatareadoffset, rawdatawriteoffset; 354 Sint16 *rawdata; 355 #ifdef THREADED_AUDIO 356 MPEG_ring *ring; 357 #else 358 Sint16 spillover[ RAWDATASIZE ]; 359 #endif 360 int volume; 361 clearrawdata(void)362 void clearrawdata(void) { 363 rawdatareadoffset=0; 364 rawdatawriteoffset=0; 365 rawdata=NULL; 366 } putraw(short int pcm)367 void putraw(short int pcm) {rawdata[rawdatawriteoffset++]=pcm;} 368 369 /********************/ 370 /* Timestamp sync */ 371 /********************/ 372 public: 373 #define N_TIMESTAMPS 5 374 375 double timestamp[N_TIMESTAMPS]; 376 }; 377 378 #endif /* _MPEGAUDIO_H_ */ 379