/* MPEG/WAVE Sound library (C) 1997 by Woo-jae Jung */ // Mpegsound.h // This is typeset for functions in MPEG/WAVE Sound library. // Nasplayer class added by Willem (willem@stack.nl), thanks! /************************************/ /* Inlcude default library packages */ /************************************/ #include #include #include #ifdef HAVE_BOOL_H #include #endif #ifdef LIBPTH # include #elif defined(PTHREADEDMPEG) # include #endif #ifndef _L__SOUND__ #define _L__SOUND__ /* Not all OSS implementations define an endian-independant samplesize. * This code is taken from linux' // Playing raw audio over a Network Audio System // By Willem (willem@stack.nl) class NASplayer : public Soundplayer { public: ~NASplayer(); static NASplayer *opendevice(char *device); void abort(void); bool setsoundtype(int stereo, int samplesize, int speed); void set8bitmode() { want8bit = 1; } bool resetsoundtype(void); void releasedevice(void) {} bool attachdevice(void) { return true; } bool putblock(void *buffer, int size); int putblock_nt(void *buffer, int size); int getblocksize(void); int setvolume(int volume); AuBool event_handler(AuEvent *ev); private: NASplayer(AuServer *aud); AuServer *aud; AuFlowID flow; AuDeviceID dev; AuEventHandlerRec *evhnd; unsigned char format; int samplerate, channels; int want8bit; int buffer_ms; int req_size; }; #endif /*\ WANT_NAS \*/ /*********************************/ /* Data format converter classes */ /*********************************/ // Class for converting wave format to raw format class Wavetoraw { public: Wavetoraw(Soundinputstream *loader,Soundplayer *player); ~Wavetoraw(); bool initialize(void); void setforcetomono(short flag){forcetomonoflag=flag;}; bool run(void); int getfrequency(void) const {return speed;}; bool isstereo(void) const {return stereo;}; int getsamplesize(void) const {return samplesize;}; int geterrorcode(void) const {return __errorcode;}; int gettotallength(void) const {return size/pcmsize;}; int getcurrentpoint(void) const {return currentpoint/pcmsize;}; void setcurrentpoint(int p); private: int __errorcode; bool seterrorcode(int errorcode) {__errorcode=errorcode; return false; }; short forcetomonoflag; Soundinputstream *loader; Soundplayer *player; bool initialized; char *buffer; int buffersize; int samplesize,speed,stereo; int currentpoint,size; int pcmsize; bool testwave(char *buffer); }; // 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); int getbits9(int bits); int getbits(int bits); private: int point,bitindex; char buffer[2*WINDOWSIZE]; }; // Class for converting mpeg format to raw format class Mpegtoraw { /*****************************/ /* 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 layer,protection,bitrateindex,padding,extendedmode, is_vbr; int first_layer; enum _mpegversion {mpeg1,mpeg2} version; enum _mode {fullstereo,joint,dual,single} mode; enum _frequency {frequency44100,frequency48000,frequency32000} frequency; /*************************/ /* Initialization vars */ /*************************/ struct mpeg_header { int layer; int protection; int bitrateindex; int padding; int extendedmode; _mpegversion version; _mode mode; _frequency frequency; } header_one; /*******************************************/ /* Functions getting MPEG header variables */ /*******************************************/ public: // General int getversion(void) const {return version;}; int getlayer(void) const {return layer;}; bool getcrccheck(void) const {return (!protection);}; // Stereo or not int getmode(void) const {return mode;}; const char *getmodestring(void) const { return (mode == fullstereo ? "Stereo" : (mode == joint ? "JointStereo" : (mode == dual ? "DualChannel" : "Mono"))); }; bool isstereo(void) const {return (getmode()!=single);}; // Frequency and bitrate int getfrequency(void) const {return frequencies[version][frequency];}; int getbitrate(void) const {return bitrate[version][layer-1][bitrateindex];}; /***************************************/ /* Interface for setting music quality */ /***************************************/ private: short forcetomonoflag; int downfrequency; public: void setforcetomono(short flag); void set8bitmode() { if(player) player->set8bitmode(); } void setdownfrequency(int value); /******************************************/ /* Functions getting other MPEG variables */ /******************************************/ public: short getforcetomono(void); int getdownfrequency(void); int getpcmperframe(void); /******************************/ /* Frame management variables */ /******************************/ private: int currentframe,totalframe; int decodeframe; int *frameoffsets; /******************************/ /* Frame management functions */ /******************************/ public: int getcurrentframe(void) const {return currentframe;}; int gettotalframe(void) const {return totalframe;}; void setframe(int framenumber); #ifdef NEWTHREAD int skip; unsigned char *sound_buf; void continueplaying(void); void createplayer(void); void abortplayer(void); void pauseplaying(void); private: void setdecodeframe(int framenumber); /*******************************/ /* Buffer management functions */ /*******************************/ private: void settotalbuffers(short amount); short request_buffer(void); void release_buffer(short index); void queue_buf(short index); void dequeue_buf(short index); void dequeue_first(); struct mpeg_buffer *get_buffer(short index); void makeroom(int size); public: void real_alarm_handler(int bla); int getfreebuffers(void); /*******************************/ /* Buffer management variables */ /*******************************/ private: FILE *debugfile; short no_buffers; short free_buffers; mpeg_buffer *buffers; buffer_node *queue; buffer_node *spare; #endif /***************************************/ /* Variables made by MPEG-Audio header */ /***************************************/ private: int tableindex,channelbitrate; int stereobound,subbandnumber,inputstereo,outputstereo; REAL scalefactor; int framesize; /********************/ /* Song information */ /********************/ private: struct { char name [30+1]; char artist [30+1]; char album [30+1]; char year [ 4+1]; char comment[30+1]; unsigned char genre; }songinfo; int totaltime; /* Song information functions */ public: const char *getname (void) const { return (const char *)songinfo.name; }; const char *getartist (void) const { return (const char *)songinfo.artist; }; const char *getalbum (void) const { return (const char *)songinfo.album; }; const char *getyear (void) const { return (const char *)songinfo.year; }; const char *getcomment (void) const { return (const char *)songinfo.comment;}; unsigned char getgenre (void) { return songinfo.genre; }; int gettotaltime() { return totaltime; } /*******************/ /* Mpegtoraw class */ /*******************/ public: Mpegtoraw(Soundinputstream *loader,Soundplayer *player); ~Mpegtoraw(); bool initialize(char *filename); bool run(int frames); int geterrorcode(void) {return __errorcode;}; void clearbuffer(void); private: int __errorcode; bool seterrorcode(int errorno){__errorcode=errorno;return false;}; /*****************************/ /* Loading MPEG-Audio stream */ /*****************************/ public: void set_time_scan(short scan) { scan_mp3 = (scan ? 1 : 0); } private: Soundinputstream *loader; // Interface union { unsigned char store[4]; unsigned int current; }u; char buffer[4096]; int bitindex; short scan_mp3; //default = 1 => don't scan mp3 to calculate length in sec. bool fillbuffer(int size){bitindex=0;return loader->_readbuffer(buffer,size);}; void sync(void) {bitindex=(bitindex+7)&0xFFFFFFF8;}; bool issync(void){return (bitindex&7);}; int getbyte(void); int getbits(int bits); int getbits9(int bits); int getbits8(void); int getbit(void); /********************/ /* Global variables */ /********************/ private: int lastfrequency,laststereo; int suppress_sound; // for Layer3 int layer3slots,layer3framestart,layer3part2start; REAL prevblck[2][2][SBLIMIT][SSLIMIT]; int currentprevblock; layer3sideinfo sideinfo; layer3scalefactor scalefactors[2]; Mpegbitwindow bitwindow; int wgetbit(void); int wgetbits9(int bits); int wgetbits(int bits); /*************************************/ /* Decoding functions for each layer */ /*************************************/ private: bool loadheader(bool lookahead=true); // // 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: Soundplayer *player; // General playing interface int rawdataoffset; short int rawdata[RAWDATASIZE]; void clearrawdata(void) {rawdataoffset=0;}; void putraw(short int pcm) {rawdata[rawdataoffset++]=pcm;}; #ifdef NEWTHREAD void flushrawdata(short index=0); #else void flushrawdata(void); #endif /***************************/ /* Interface for threading */ /***************************/ #ifdef NEWTHREAD public: pth_t play_thread; bool player_run; void threadplay(void *bla); #elif defined(PTHREADEDMPEG) private: struct { short int *buffer; int framenumber,frametail; int head,tail; int *sizes; }threadqueue; struct { bool thread; bool quit,done; bool pause; bool criticallock,criticalflag; }threadflags; pthread_t thread; public: void threadedplayer(void); bool makethreadedplayer(int framenumbers); void freethreadedplayer(void); void stopthreadedplayer(void); void pausethreadedplayer(void); void unpausethreadedplayer(void); bool existthread(void); int getframesaved(void); #endif /* NEWTHREAD */ }; /***********************/ /* File player classes */ /***********************/ // Superclass for playing file class Fileplayer { public: enum audiodriver_t { AUDIODRV_OSS, AUDIODRV_ESD, AUDIODRV_SDL, AUDIODRV_NAS }; virtual ~Fileplayer(); //anyone may destruct a FilePlayer object directly int geterrorcode(void) {return __errorcode;}; struct song_info getsonginfo() { return info;}; virtual bool openfile(char *filename,char *device, soundtype write2file=NONE)=0; virtual void closefile(void) =0; virtual void setforcetomono(short flag) =0; virtual void setdownfrequency(int) =0; virtual void set8bitmode() =0; virtual bool playing() =0; virtual bool run(int) =0; virtual void skip(int) =0; virtual bool initialize(void *) =0; //if argument to forward < 0, will skip to end - virtual bool forward(int) =0; virtual bool rewind(int) =0; virtual bool pause() =0; virtual bool unpause() =0; virtual bool stop() =0; virtual bool ready() =0; virtual int elapsed_time() =0; virtual int remaining_time() =0; protected: Fileplayer(); //thou shallt not instantiate fileplayer itself. bool opendevice(char *device, soundtype write2file=NONE); void set_driver(audiodriver_t driver); bool seterrorcode(int errorno){__errorcode=errorno;return false;}; Soundplayer *player; struct song_info info; char *filename; private: int __errorcode; audiodriver_t audiodriver; }; struct init_opts { char option[30]; void *value; struct init_opts *next; }; // Class for playing wave file class Wavefileplayer : public Fileplayer { public: Wavefileplayer(audiodriver_t driver); ~Wavefileplayer(); bool openfile(char *filename,char *device, soundtype write2file=NONE); void closefile(void); void setforcetomono(short flag); void setdownfrequency(int value) { if (value); } void set8bitmode() { if(player) player->set8bitmode(); } bool playing(); bool run(int); bool initialize(void *); bool forward(int frames) { skip(frames); return true; } bool rewind(int frames) { skip(-frames); return true; } bool pause() { player->releasedevice(); return true; } bool ready() { return player->attachdevice(); } bool unpause() { return true; } bool stop() { return true; } int elapsed_time(); int remaining_time(); void skip(int); private: Soundinputstream *loader; protected: Wavetoraw *server; }; // Class for playing MPEG file class Mpegfileplayer : public Fileplayer { public: Mpegfileplayer(audiodriver_t driver); ~Mpegfileplayer(); bool openfile(char *filename,char *device, soundtype write2file=NONE); void closefile(void); void setforcetomono(short flag); void set8bitmode() { if (server) server->set8bitmode(); } void setdownfrequency(int value); bool playing(); bool run(int); void skip(int); bool initialize(void *); bool forward(int); bool rewind(int); #ifdef NEWTHREAD bool pause() { server->pauseplaying(); player->releasedevice(); return true; } bool unpause() { server->continueplaying(); return player->attachdevice(); } #elif defined(PTHREADEDMPEG) bool pause() { if (use_threads) server->pausethreadedplayer(); player->releasedevice(); return true;} bool unpause() { if (use_threads) server->unpausethreadedplayer(); return player->attachdevice();} #else bool pause() { player->releasedevice(); return true;} bool unpause() { return player->attachdevice(); } #endif bool stop(); bool ready(); int elapsed_time(); int remaining_time(); #ifndef NEWTHREAD #if PTHREADEDMPEG bool playingwiththread(int framenumbers); #endif #endif /* NEWTHREAD */ private: Soundinputstream *loader; short use_threads; protected: Mpegtoraw *server; }; #ifdef INCLUDE_OGG #include "vorbis/vorbisfile.h" class Oggplayer : public Fileplayer { public: Oggplayer(audiodriver_t driver); ~Oggplayer(); bool openfile(char *filename,char *device, soundtype write2file=NONE); void closefile(void); void setforcetomono(short flag); void set8bitmode(); void setdownfrequency(int value); bool playing(); bool run(int); void skip(int); bool initialize(void *); bool forward(int); bool rewind(int); bool pause(); bool unpause(); bool stop(); bool ready(); int elapsed_time(); int remaining_time(); private: short wordsize; short mono; short downfreq; short bigendian; short signeddata; int channels; long srate; short resetsound; protected: OggVorbis_File *of; char soundbuf[4096]; }; #endif /* INCLUDE_OGG */ #ifdef HAVE_SIDPLAYER //This is broken due to lack of functions #include #include #include class SIDfileplayer : public Fileplayer { public: SIDfileplayer(audiodriver_t driver); ~SIDfileplayer(); bool openfile(char *filename,char *device, soundtype write2file=NONE); bool initialize(void *data) { if(data); return true; } void closefile(void); void setforcetomono(short flag); void setdownfrequency(int value); void set8bitmode() {} bool run(int frames); bool playing(); bool ready() { return true; } void skip(int) {} //TODO: implement int elapsed_time() { return 0; } //TODO: implement int remaining_time() { return 0; } bool forward(int sec) { skip(sec); return true; } bool rewind(int sec) { skip(-sec); return true; } bool pause() { return true; } bool unpause() { return true; } bool stop() { return true; } protected: emuEngine emu; struct emuConfig emuConf; sidTune *tune; struct sidTuneInfo sidInfo; int song; private: char *buffer; int bufSize; }; #endif /*\ HAVE_SIDPLAYER \*/ #endif