/* SMPEG - SDL MPEG Player Library Copyright (C) 1999 Loki Entertainment Software - Modified by Michel Darricau from eProcess for popcorn - This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* A class based on the MPEG stream class, used to parse and play audio */ #ifndef _MPEGAUDIO_H_ #define _MPEGAUDIO_H_ #include "SDL.h" #include "MPEGerror.h" #include "MPEGaction.h" #ifdef THREADED_AUDIO #include "MPEGring.h" #endif class MPEGstream; /* MPEG/WAVE Sound library (C) 1997 by Woo-jae Jung */ /**************************/ /* Define values for MPEG */ /**************************/ #define SCALEBLOCK 12 #define CALCBUFFERSIZE 512 #define MAXSUBBAND 32 #define MAXCHANNEL 2 #define MAXTABLE 2 #define SCALE 32768 #define MAXSCALE (SCALE-1) #define MINSCALE (-SCALE) #define RAWDATASIZE (2*2*32*SSLIMIT) #define LS 0 #define RS 1 #define SSLIMIT 18 #define SBLIMIT 32 #define WINDOWSIZE 4096 // Huffmancode #define HTN 34 /********************/ /* Type definitions */ /********************/ typedef float REAL; typedef struct { bool generalflag; unsigned int part2_3_length; unsigned int big_values; unsigned int global_gain; unsigned int scalefac_compress; unsigned int window_switching_flag; unsigned int block_type; unsigned int mixed_block_flag; unsigned int table_select[3]; unsigned int subblock_gain[3]; unsigned int region0_count; unsigned int region1_count; unsigned int preflag; unsigned int scalefac_scale; unsigned int count1table_select; }layer3grinfo; typedef struct { unsigned main_data_begin; unsigned private_bits; struct { unsigned scfsi[4]; layer3grinfo gr[2]; }ch[2]; }layer3sideinfo; typedef struct { int l[23]; /* [cb] */ int s[3][13]; /* [window][cb] */ }layer3scalefactor; /* [ch] */ typedef struct { int tablename; unsigned int xlen,ylen; unsigned int linbits; unsigned int treelen; const unsigned int (*val)[2]; }HUFFMANCODETABLE; // Class for Mpeg layer3 class Mpegbitwindow { public: Mpegbitwindow(){bitindex=point=0;}; void initialize(void) {bitindex=point=0;}; int gettotalbit(void) const {return bitindex;}; void putbyte(int c) {buffer[point&(WINDOWSIZE-1)]=c;point++;}; void wrap(void); void rewind(int bits) {bitindex-=bits;}; void forward(int bits) {bitindex+=bits;}; int getbit(void) { register int r=(buffer[bitindex>>3]>>(7-(bitindex&7)))&1; bitindex++; return r; } int getbits9(int bits) { register unsigned short a; { int offset=bitindex>>3; a=(((unsigned char)buffer[offset])<<8) | ((unsigned char)buffer[offset+1]); } a<<=(bitindex&7); bitindex+=bits; return (int)((unsigned int)(a>>(16-bits))); } int getbits(int bits); private: int point,bitindex; char buffer[2*WINDOWSIZE]; }; /* The actual MPEG audio class */ class MPEGaudio; void Play_MPEGaudioSDL(void *udata, Uint8 *stream, int len); int Play_MPEGaudio(MPEGaudio *audio, Uint8 *stream, int len); #ifdef THREADED_AUDIO int Decode_MPEGaudio(void *udata); #endif class MPEGaudio : public MPEGerror, public MPEGaudioaction { friend void Play_MPEGaudioSDL(void *udata, Uint8 *stream, int len); friend int Play_MPEGaudio(MPEGaudio *audio, Uint8 *stream, int len); #ifdef THREADED_AUDIO friend int Decode_MPEGaudio(void *udata); #endif public: MPEGaudio(MPEGstream *stream, bool initSDL = true); virtual ~MPEGaudio(); /* MPEG actions */ bool GetAudioInfo(MPEG_AudioInfo *info); double Time(void); void Play(void); void Stop(void); void Rewind(void); void ResetSynchro(double time); void Skip(float seconds); void Volume(int vol); /* Michel Darricau from eProcess conflict name in popcorn */ MPEGstatus GetStatus(void); /* Returns the desired SDL audio spec for this stream */ bool WantedSpec(SDL_AudioSpec *wanted); /* Inform SMPEG of the actual audio format if configuring SDL outside of this class */ void ActualSpec(const SDL_AudioSpec *actual); protected: bool sdl_audio; MPEGstream *mpeg; int valid_stream; bool stereo; double rate_in_s; Uint32 frags_playing; Uint32 frag_time; #ifdef THREADED_AUDIO bool decoding; SDL_Thread *decode_thread; void StartDecoding(void); void StopDecoding(void); #endif /* Code from splay 1.8.2 */ /*****************************/ /* Constant tables for layer */ /*****************************/ private: static const int bitrate[2][3][15],frequencies[2][3]; static const REAL scalefactorstable[64]; static const HUFFMANCODETABLE ht[HTN]; static const REAL filter[512]; static REAL hcos_64[16],hcos_32[8],hcos_16[4],hcos_8[2],hcos_4; /*************************/ /* MPEG header variables */ /*************************/ private: int last_speed; int layer,protection,bitrateindex,padding,extendedmode; enum _mpegversion {mpeg1,mpeg2} version; enum _mode {fullstereo,joint,dual,single} mode; enum _frequency {frequency44100,frequency48000,frequency32000} frequency; /***************************************/ /* Interface for setting music quality */ /***************************************/ private: bool forcetomonoflag; bool forcetostereoflag; int downfrequency; public: void setforcetomono(bool flag); void setdownfrequency(int value); /******************************/ /* Frame management variables */ /******************************/ private: int decodedframe,currentframe,totalframe; /***************************************/ /* Variables made by MPEG-Audio header */ /***************************************/ private: int tableindex,channelbitrate; int stereobound,subbandnumber,inputstereo,outputstereo; REAL scalefactor; int framesize; /*******************/ /* Mpegtoraw class */ /*******************/ public: void initialize(); bool run(int frames, double *timestamp = NULL); void clearbuffer(void); /*****************************/ /* Loading MPEG-Audio stream */ /*****************************/ private: Uint8 _buffer[4096]; Uint32 _buffer_pos; int bitindex; bool fillbuffer(int size); void sync(void); bool issync(void); int getbyte(void); int getbit(void); int getbits8(void); int getbits9(int bits); int getbits(int bits); /********************/ /* Global variables */ /********************/ private: int lastfrequency,laststereo; // for Layer3 int layer3slots,layer3framestart,layer3part2start; REAL prevblck[2][2][SBLIMIT][SSLIMIT]; int currentprevblock; layer3sideinfo sideinfo; layer3scalefactor scalefactors[2]; Mpegbitwindow bitwindow; int wgetbit (void) {return bitwindow.getbit (); } int wgetbits9(int bits){return bitwindow.getbits9(bits);} int wgetbits (int bits){return bitwindow.getbits (bits);} /*************************************/ /* Decoding functions for each layer */ /*************************************/ private: bool loadheader(void); // // Subbandsynthesis // REAL calcbufferL[2][CALCBUFFERSIZE],calcbufferR[2][CALCBUFFERSIZE]; int currentcalcbuffer,calcbufferoffset; void computebuffer(REAL *fraction,REAL buffer[2][CALCBUFFERSIZE]); void generatesingle(void); void generate(void); void subbandsynthesis(REAL *fractionL,REAL *fractionR); void computebuffer_2(REAL *fraction,REAL buffer[2][CALCBUFFERSIZE]); void generatesingle_2(void); void generate_2(void); void subbandsynthesis_2(REAL *fractionL,REAL *fractionR); // Extarctor void extractlayer1(void); // MPEG-1 void extractlayer2(void); void extractlayer3(void); void extractlayer3_2(void); // MPEG-2 // Functions for layer 3 void layer3initialize(void); bool layer3getsideinfo(void); bool layer3getsideinfo_2(void); void layer3getscalefactors(int ch,int gr); void layer3getscalefactors_2(int ch); void layer3huffmandecode(int ch,int gr,int out[SBLIMIT][SSLIMIT]); REAL layer3twopow2(int scale,int preflag,int pretab_offset,int l); REAL layer3twopow2_1(int a,int b,int c); void layer3dequantizesample(int ch,int gr,int in[SBLIMIT][SSLIMIT], REAL out[SBLIMIT][SSLIMIT]); void layer3fixtostereo(int gr,REAL in[2][SBLIMIT][SSLIMIT]); void layer3reorderandantialias(int ch,int gr,REAL in[SBLIMIT][SSLIMIT], REAL out[SBLIMIT][SSLIMIT]); void layer3hybrid(int ch,int gr,REAL in[SBLIMIT][SSLIMIT], REAL out[SSLIMIT][SBLIMIT]); void huffmandecoder_1(const HUFFMANCODETABLE *h,int *x,int *y); void huffmandecoder_2(const HUFFMANCODETABLE *h,int *x,int *y,int *v,int *w); /********************/ /* Playing raw data */ /********************/ private: int samplesperframe; int rawdatareadoffset, rawdatawriteoffset; Sint16 *rawdata; #ifdef THREADED_AUDIO MPEG_ring *ring; #else Sint16 spillover[ RAWDATASIZE ]; #endif int volume; void clearrawdata(void) { rawdatareadoffset=0; rawdatawriteoffset=0; rawdata=NULL; } void putraw(short int pcm) {rawdata[rawdatawriteoffset++]=pcm;} /********************/ /* Timestamp sync */ /********************/ public: #define N_TIMESTAMPS 5 double timestamp[N_TIMESTAMPS]; }; #endif /* _MPEGAUDIO_H_ */