123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732 |
- #include <ctype.h>
- #include <stdlib.h>
- #include <signal.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <sys/time.h>
- #include <fcntl.h>
- #ifdef READ_MMAP
- #include <sys/mman.h>
- #ifndef MAP_FAILED
- #define MAP_FAILED ( (void *) -1 )
- #endif
- #endif
- #include "mpg123.h"
- #include "genre.h"
- #include "common.h"
- int tabsel_123[2][3][16] = {
- { {0,32,64,96,128,160,192,224,256,288,320,352,384,416,448,},
- {0,32,48,56, 64, 80, 96,112,128,160,192,224,256,320,384,},
- {0,32,40,48, 56, 64, 80, 96,112,128,160,192,224,256,320,} },
- { {0,32,48,56,64,80,96,112,128,144,160,176,192,224,256,},
- {0,8,16,24,32,40,48,56,64,80,96,112,128,144,160,},
- {0,8,16,24,32,40,48,56,64,80,96,112,128,144,160,} }
- };
- long freqs[9] = { 44100, 48000, 32000, 22050, 24000, 16000 , 11025 , 12000 , 8000 };
- struct bitstream_info bsi;
- static int fsizeold=0,ssize;
- static unsigned char bsspace[2][MAXFRAMESIZE+512]; /* MAXFRAMESIZE */
- static unsigned char *bsbuf=bsspace[1],*bsbufold;
- static int bsnum=0;
- static unsigned long oldhead = 0;
- unsigned long firsthead=0;
- unsigned char *pcm_sample;
- int pcm_point = 0;
- int audiobufsize = AUDIOBUFSIZE;
- #ifdef VARMODESUPPORT
- /*
- * This is a dirty hack! It might burn your PC and kill your cat!
- * When in "varmode", specially formatted layer-3 mpeg files are
- * expected as input -- it will NOT work with standard mpeg files.
- * The reason for this:
- * Varmode mpeg files enable my own GUI player to perform fast
- * forward and backward functions, and to jump to an arbitrary
- * timestamp position within the file. This would be possible
- * with standard mpeg files, too, but it would be a lot harder to
- * implement.
- * A filter for converting standard mpeg to varmode mpeg is
- * available on request, but it's really not useful on its own.
- *
- * Oliver Fromme <oliver.fromme@heim3.tu-clausthal.de>
- * Mon Mar 24 00:04:24 MET 1997
- */
- int varmode = FALSE;
- int playlimit;
- #endif
- static int decode_header(struct frame *fr,unsigned long newhead);
- void audio_flush(int outmode, struct audio_info_struct *ai)
- {
- if (pcm_point) {
- switch (outmode) {
- case DECODE_FILE:
- write (OutputDescriptor, pcm_sample, pcm_point);
- break;
- case DECODE_AUDIO:
- audio_play_samples (ai, pcm_sample, pcm_point);
- break;
- case DECODE_BUFFER:
- write (buffer_fd[1], pcm_sample, pcm_point);
- break;
- case DECODE_WAV:
- case DECODE_CDR:
- case DECODE_AU:
- wav_write(pcm_sample, pcm_point);
- break;
- }
- pcm_point = 0;
- }
- }
- #if !defined(WIN32) && !defined(GENERIC)
- void (*catchsignal(int signum, void(*handler)()))()
- {
- struct sigaction new_sa;
- struct sigaction old_sa;
- #ifdef DONT_CATCH_SIGNALS
- printf ("Not catching any signals.\n");
- return ((void (*)()) -1);
- #endif
- new_sa.sa_handler = handler;
- sigemptyset(&new_sa.sa_mask);
- new_sa.sa_flags = 0;
- if (sigaction(signum, &new_sa, &old_sa) == -1)
- return ((void (*)()) -1);
- return (old_sa.sa_handler);
- }
- #endif
- void read_frame_init (void)
- {
- oldhead = 0;
- firsthead = 0;
- }
- int head_check(unsigned long head)
- {
- if( (head & 0xffe00000) != 0xffe00000)
- return FALSE;
- if(!((head>>17)&3))
- return FALSE;
- if( ((head>>12)&0xf) == 0xf)
- return FALSE;
- if( ((head>>10)&0x3) == 0x3 )
- return FALSE;
- if ((head & 0xffff0000) == 0xfffe0000)
- return FALSE;
- return TRUE;
- }
- /*****************************************************************
- * read next frame
- */
- int read_frame(struct frame *fr)
- {
- unsigned long newhead;
- static unsigned char ssave[34];
- fsizeold=fr->framesize; /* for Layer3 */
- if (param.halfspeed) {
- static int halfphase = 0;
- if (halfphase--) {
- bsi.bitindex = 0;
- bsi.wordpointer = (unsigned char *) bsbuf;
- if (fr->lay == 3)
- memcpy (bsbuf, ssave, ssize);
- return 1;
- }
- else
- halfphase = param.halfspeed - 1;
- }
- read_again:
- if(!rd->head_read(rd,&newhead))
- return FALSE;
- if(1 || oldhead != newhead || !oldhead)
- {
- init_resync:
- fr->header_change = 2;
- if(oldhead) {
- if((oldhead & 0xc00) == (newhead & 0xc00)) {
- if( (oldhead & 0xc0) == 0 && (newhead & 0xc0) == 0)
- fr->header_change = 1;
- else if( (oldhead & 0xc0) > 0 && (newhead & 0xc0) > 0)
- fr->header_change = 1;
- }
- }
- #ifdef SKIP_JUNK
- if(!firsthead && !head_check(newhead) ) {
- int i;
- fprintf(stderr,"Junk at the beginning %08lx\n",newhead);
- /* I even saw RIFF headers at the beginning of MPEG streams ;( */
- if(newhead == ('R'<<24)+('I'<<16)+('F'<<8)+'F') {
- if(!rd->head_read(rd,&newhead))
- return 0;
- while(newhead != ('d'<<24)+('a'<<16)+('t'<<8)+'a') {
- if(!rd->head_shift(rd,&newhead))
- return 0;
- }
- if(!rd->head_read(rd,&newhead))
- return 0;
- fprintf(stderr,"Skipped RIFF header!\n");
- goto read_again;
- }
- {
- /* step in byte steps through next 64K */
- for(i=0;i<65536;i++) {
- if(!rd->head_shift(rd,&newhead))
- return 0;
- if(head_check(newhead))
- break;
- #if 0
- fprintf(stderr,"%08lx ",newhead);
- #endif
- }
- if(i == 65536) {
- fprintf(stderr,"Giving up searching valid MPEG header\n");
- return 0;
- }
- }
- /*
- * should we additionaly check, whether a new frame starts at
- * the next expected position? (some kind of read ahead)
- * We could implement this easily, at least for files.
- */
- }
- #endif
- if( (newhead & 0xffe00000) != 0xffe00000) {
- if (!param.quiet)
- fprintf(stderr,"Illegal Audio-MPEG-Header 0x%08lx at offset 0x%lx.\n",
- newhead,rd->tell(rd)-4);
- /* and those ugly ID3 tags */
- if((newhead & 0xffffff00) == ('T'<<24)+('A'<<16)+('G'<<8)) {
- rd->skip_bytes(rd,124);
- fprintf(stderr,"Skipped ID3 Tag!\n");
- goto read_again;
- }
- if (param.tryresync) {
- int try = 0;
- /* Read more bytes until we find something that looks
- reasonably like a valid header. This is not a
- perfect strategy, but it should get us back on the
- track within a short time (and hopefully without
- too much distortion in the audio output). */
- do {
- try++;
- if(!rd->head_shift(rd,&newhead))
- return 0;
- if (!oldhead)
- goto init_resync; /* "considered harmful", eh? */
- } while ((newhead & HDRCMPMASK) != (oldhead & HDRCMPMASK)
- && (newhead & HDRCMPMASK) != (firsthead & HDRCMPMASK));
- if (!param.quiet)
- fprintf (stderr, "Skipped %d bytes in input.\n", try);
- }
- else
- return (0);
- }
- if (!firsthead) {
- if(!decode_header(fr,newhead))
- goto read_again;
- firsthead = newhead;
- }
- else
- if(!decode_header(fr,newhead))
- return 0;
- }
- else
- fr->header_change = 0;
- /* flip/init buffer for Layer 3 */
- bsbufold = bsbuf;
- bsbuf = bsspace[bsnum]+512;
- bsnum = (bsnum + 1) & 1;
- /* read main data into memory */
- if(!rd->read_frame_body(rd,bsbuf,fr->framesize))
- return 0;
- bsi.bitindex = 0;
- bsi.wordpointer = (unsigned char *) bsbuf;
- if (param.halfspeed && fr->lay == 3)
- memcpy (ssave, bsbuf, ssize);
- return 1;
- }
- /****************************************
- * HACK,HACK,HACK: step back <num> frames
- * can only work if the 'stream' isn't a real stream but a file
- */
- int back_frame(struct reader *rds,struct frame *fr,int num)
- {
- long bytes;
- unsigned long newhead;
-
- if(!firsthead)
- return 0;
-
- bytes = (fr->framesize+8)*(num+2);
-
- if(rds->back_bytes(rds,bytes) < 0)
- return -1;
- if(!rds->head_read(rds,&newhead))
- return -1;
-
- while( (newhead & HDRCMPMASK) != (firsthead & HDRCMPMASK) ) {
- if(!rds->head_shift(rds,&newhead))
- return -1;
- }
-
- if(rds->back_bytes(rds,4) <0)
- return -1;
- read_frame(fr);
- read_frame(fr);
-
- if(fr->lay == 3) {
- set_pointer(512);
- }
-
- return 0;
- }
- /*
- * decode a header and write the information
- * into the frame structure
- */
- static int decode_header(struct frame *fr,unsigned long newhead)
- {
- if(!head_check(newhead))
- return 0;
- if( newhead & (1<<20) ) {
- fr->lsf = (newhead & (1<<19)) ? 0x0 : 0x1;
- fr->mpeg25 = 0;
- }
- else {
- fr->lsf = 1;
- fr->mpeg25 = 1;
- }
-
- if (!param.tryresync || !oldhead) {
- /* If "tryresync" is true, assume that certain
- parameters do not change within the stream! */
- fr->lay = 4-((newhead>>17)&3);
- if( ((newhead>>10)&0x3) == 0x3) {
- fprintf(stderr,"Stream error\n");
- exit(1);
- }
- if(fr->mpeg25) {
- fr->sampling_frequency = 6 + ((newhead>>10)&0x3);
- }
- else
- fr->sampling_frequency = ((newhead>>10)&0x3) + (fr->lsf*3);
- fr->error_protection = ((newhead>>16)&0x1)^0x1;
- }
- fr->bitrate_index = ((newhead>>12)&0xf);
- fr->padding = ((newhead>>9)&0x1);
- fr->extension = ((newhead>>8)&0x1);
- fr->mode = ((newhead>>6)&0x3);
- fr->mode_ext = ((newhead>>4)&0x3);
- fr->copyright = ((newhead>>3)&0x1);
- fr->original = ((newhead>>2)&0x1);
- fr->emphasis = newhead & 0x3;
- fr->stereo = (fr->mode == MPG_MD_MONO) ? 1 : 2;
- oldhead = newhead;
- if(!fr->bitrate_index) {
- fprintf(stderr,"Free format not supported: (head %08lx)\n",newhead);
- return (0);
- }
- switch(fr->lay) {
- case 1:
- fr->do_layer = do_layer1;
- #ifdef VARMODESUPPORT
- if (varmode) {
- fprintf(stderr,"Sorry, layer-1 not supported in varmode.\n");
- return (0);
- }
- #endif
- fr->framesize = (long) tabsel_123[fr->lsf][0][fr->bitrate_index] * 12000;
- fr->framesize /= freqs[fr->sampling_frequency];
- fr->framesize = ((fr->framesize+fr->padding)<<2)-4;
- break;
- case 2:
- fr->do_layer = do_layer2;
- #ifdef VARMODESUPPORT
- if (varmode) {
- fprintf(stderr,"Sorry, layer-2 not supported in varmode.\n");
- return (0);
- }
- #endif
- fr->framesize = (long) tabsel_123[fr->lsf][1][fr->bitrate_index] * 144000;
- fr->framesize /= freqs[fr->sampling_frequency];
- fr->framesize += fr->padding - 4;
- break;
- case 3:
- fr->do_layer = do_layer3;
- if(fr->lsf)
- ssize = (fr->stereo == 1) ? 9 : 17;
- else
- ssize = (fr->stereo == 1) ? 17 : 32;
- if(fr->error_protection)
- ssize += 2;
- fr->framesize = (long) tabsel_123[fr->lsf][2][fr->bitrate_index] * 144000;
- fr->framesize /= freqs[fr->sampling_frequency]<<(fr->lsf);
- fr->framesize = fr->framesize + fr->padding - 4;
- break;
- default:
- fprintf(stderr,"Sorry, unknown layer type.\n");
- return (0);
- }
- return 1;
- }
- #ifdef MPG123_REMOTE
- void print_rheader(struct frame *fr)
- {
- static char *modes[4] = { "Stereo", "Joint-Stereo", "Dual-Channel", "Single-Channel" };
- static char *layers[4] = { "Unknown" , "I", "II", "III" };
- static char *mpeg_type[2] = { "1.0" , "2.0" };
- /* version, layer, freq, mode, channels, bitrate, BPF */
- fprintf(stderr,"@I %s %s %ld %s %d %d %d\n",
- mpeg_type[fr->lsf],layers[fr->lay],freqs[fr->sampling_frequency],
- modes[fr->mode],fr->stereo,
- tabsel_123[fr->lsf][fr->lay-1][fr->bitrate_index],
- fr->framesize+4);
- }
- #endif
- void print_header(struct frame *fr)
- {
- static char *modes[4] = { "Stereo", "Joint-Stereo", "Dual-Channel", "Single-Channel" };
- static char *layers[4] = { "Unknown" , "I", "II", "III" };
- fprintf(stderr,"MPEG %s, Layer: %s, Freq: %ld, mode: %s, modext: %d, BPF : %d\n",
- fr->mpeg25 ? "2.5" : (fr->lsf ? "2.0" : "1.0"),
- layers[fr->lay],freqs[fr->sampling_frequency],
- modes[fr->mode],fr->mode_ext,fr->framesize+4);
- fprintf(stderr,"Channels: %d, copyright: %s, original: %s, CRC: %s, emphasis: %d.\n",
- fr->stereo,fr->copyright?"Yes":"No",
- fr->original?"Yes":"No",fr->error_protection?"Yes":"No",
- fr->emphasis);
- fprintf(stderr,"Bitrate: %d Kbits/s, Extension value: %d\n",
- tabsel_123[fr->lsf][fr->lay-1][fr->bitrate_index],fr->extension);
- }
- void print_header_compact(struct frame *fr)
- {
- static char *modes[4] = { "stereo", "joint-stereo", "dual-channel", "mono" };
- static char *layers[4] = { "Unknown" , "I", "II", "III" };
-
- fprintf(stderr,"MPEG %s layer %s, %d kbit/s, %ld Hz %s\n",
- fr->mpeg25 ? "2.5" : (fr->lsf ? "2.0" : "1.0"),
- layers[fr->lay],
- tabsel_123[fr->lsf][fr->lay-1][fr->bitrate_index],
- freqs[fr->sampling_frequency], modes[fr->mode]);
- }
- void print_id3_tag(unsigned char *buf)
- {
- struct id3tag {
- char tag[3];
- char title[30];
- char artist[30];
- char album[30];
- char year[4];
- char comment[30];
- unsigned char genre;
- };
- struct id3tag *tag = (struct id3tag *) buf;
- char title[31]={0,};
- char artist[31]={0,};
- char album[31]={0,};
- char year[5]={0,};
- char comment[31]={0,};
- char genre[31]={0,};
- if(param.quiet)
- return;
- strncpy(title,tag->title,30);
- strncpy(artist,tag->artist,30);
- strncpy(album,tag->album,30);
- strncpy(year,tag->year,4);
- strncpy(comment,tag->comment,30);
- if ( tag->genre <= sizeof(genre_table)/sizeof(*genre_table) ) {
- strncpy(genre, genre_table[tag->genre], 30);
- } else {
- strncpy(genre,"Unknown",30);
- }
-
- fprintf(stderr,"Title : %-30s Artist: %s\n",title,artist);
- fprintf(stderr,"Album : %-30s Year : %4s\n",album,year);
- fprintf(stderr,"Comment: %-30s Genre : %s\n",comment,genre);
- }
- #if 0
- /* removed the strndup for better portability */
- /*
- * Allocate space for a new string containing the first
- * "num" characters of "src". The resulting string is
- * always zero-terminated. Returns NULL if malloc fails.
- */
- char *strndup (const char *src, int num)
- {
- char *dst;
- if (!(dst = (char *) malloc(num+1)))
- return (NULL);
- dst[num] = '\0';
- return (strncpy(dst, src, num));
- }
- #endif
- /*
- * Split "path" into directory and filename components.
- *
- * Return value is 0 if no directory was specified (i.e.
- * "path" does not contain a '/'), OR if the directory
- * is the same as on the previous call to this function.
- *
- * Return value is 1 if a directory was specified AND it
- * is different from the previous one (if any).
- */
- int split_dir_file (const char *path, char **dname, char **fname)
- {
- static char *lastdir = NULL;
- char *slashpos;
- if ((slashpos = strrchr(path, '/'))) {
- *fname = slashpos + 1;
- *dname = strdup(path); /* , 1 + slashpos - path); */
- if(!(*dname)) {
- perror("memory");
- exit(1);
- }
- (*dname)[1 + slashpos - path] = 0;
- if (lastdir && !strcmp(lastdir, *dname)) {
- /*** same as previous directory ***/
- free (*dname);
- *dname = lastdir;
- return 0;
- }
- else {
- /*** different directory ***/
- if (lastdir)
- free (lastdir);
- lastdir = *dname;
- return 1;
- }
- }
- else {
- /*** no directory specified ***/
- if (lastdir) {
- free (lastdir);
- lastdir = NULL;
- };
- *dname = NULL;
- *fname = (char *)path;
- return 0;
- }
- }
- void set_pointer(long backstep)
- {
- bsi.wordpointer = bsbuf + ssize - backstep;
- if (backstep)
- memcpy(bsi.wordpointer,bsbufold+fsizeold-backstep,backstep);
- bsi.bitindex = 0;
- }
- /********************************/
- double compute_bpf(struct frame *fr)
- {
- double bpf;
- switch(fr->lay) {
- case 1:
- bpf = tabsel_123[fr->lsf][0][fr->bitrate_index];
- bpf *= 12000.0 * 4.0;
- bpf /= freqs[fr->sampling_frequency] <<(fr->lsf);
- break;
- case 2:
- case 3:
- bpf = tabsel_123[fr->lsf][fr->lay-1][fr->bitrate_index]; bpf *= 144000;
- bpf /= freqs[fr->sampling_frequency] << (fr->lsf);
- break;
- default:
- bpf = 1.0;
- }
- return bpf;
- }
- double compute_tpf(struct frame *fr)
- {
- static int bs[4] = { 0,384,1152,1152 };
- double tpf;
- tpf = (double) bs[fr->lay];
- tpf /= freqs[fr->sampling_frequency] << (fr->lsf);
- return tpf;
- }
- /*
- * Returns number of frames queued up in output buffer, i.e.
- * offset between currently played and currently decoded frame.
- */
- long compute_buffer_offset(struct frame *fr)
- {
- long bufsize;
-
- /*
- * buffermem->buf[0] holds output sampling rate,
- * buffermem->buf[1] holds number of channels,
- * buffermem->buf[2] holds audio format of output.
- */
-
- if(!param.usebuffer || !(bufsize=xfermem_get_usedspace(buffermem))
- || !buffermem->buf[0] || !buffermem->buf[1])
- return 0;
- bufsize = (long)((double) bufsize / buffermem->buf[0] /
- buffermem->buf[1] / compute_tpf(fr));
-
- if((buffermem->buf[2] & AUDIO_FORMAT_MASK) == AUDIO_FORMAT_16)
- return bufsize/2;
- else
- return bufsize;
- }
- void print_stat(struct frame *fr,int no,long buffsize,struct audio_info_struct *ai)
- {
- double bpf,tpf,tim1,tim2;
- double dt = 0.0;
- int sno,rno;
- char outbuf[256];
- if(!rd || !fr)
- return;
- outbuf[0] = 0;
- #ifndef GENERIC
- {
- struct timeval t;
- fd_set serr;
- int n,errfd = fileno(stderr);
- t.tv_sec=t.tv_usec=0;
- FD_ZERO(&serr);
- FD_SET(errfd,&serr);
- n = select(errfd+1,NULL,&serr,NULL,&t);
- if(n <= 0)
- return;
- }
- #endif
- bpf = compute_bpf(fr);
- tpf = compute_tpf(fr);
- if(buffsize > 0 && ai && ai->rate > 0 && ai->channels > 0) {
- dt = (double) buffsize / ai->rate / ai->channels;
- if( (ai->format & AUDIO_FORMAT_MASK) == AUDIO_FORMAT_16)
- dt *= 0.5;
- }
- rno = 0;
- sno = no;
- if(rd->filelen >= 0) {
- long t = rd->tell(rd);
- rno = (int)((double)(rd->filelen-t)/bpf);
- sno = (int)((double)t/bpf);
- }
- sprintf(outbuf+strlen(outbuf),"\rFrame# %5d [%5d], ",sno,rno);
- tim1 = sno*tpf-dt;
- tim2 = rno*tpf+dt;
- #if 0
- tim1 = tim1 < 0 ? 0.0 : tim1;
- #endif
- tim2 = tim2 < 0 ? 0.0 : tim2;
- sprintf(outbuf+strlen(outbuf),"Time: %02u:%02u.%02u [%02u:%02u.%02u], ",
- (unsigned int)tim1/60,
- (unsigned int)tim1%60,
- (unsigned int)(tim1*100)%100,
- (unsigned int)tim2/60,
- (unsigned int)tim2%60,
- (unsigned int)(tim2*100)%100);
- if(param.usebuffer)
- sprintf(outbuf+strlen(outbuf),"[%8ld] ",(long)buffsize);
- write(fileno(stderr),outbuf,strlen(outbuf));
- #if 0
- fflush(out); /* hmm not really nec. */
- #endif
- }
- int get_songlen(struct frame *fr,int no)
- {
- double tpf;
-
- if(!fr)
- return 0;
-
- if(no < 0) {
- if(!rd || rd->filelen < 0)
- return 0;
- no = (double) rd->filelen / compute_bpf(fr);
- }
- tpf = compute_tpf(fr);
- return no*tpf;
- }
|