📄 common.c
字号:
/* common: anything can happen here... frame reading, output, messages copyright ?-2006 by the mpg123 project - free software under the terms of the LGPL 2.1 see COPYING and AUTHORS files in distribution or http://mpg123.de initially written by Michael Hipp*/#include <ctype.h>#include <stdlib.h>#include <signal.h>#include <sys/types.h>#include <sys/stat.h>#include <sys/time.h>#include <math.h>#ifdef HAVE_INTTYPES_H#include <inttypes.h>#endif#include <fcntl.h>#include "config.h"#include "mpg123.h"#include "id3.h"#include "icy.h"#include "common.h"#include "debug.h"/* bitrates for [mpeg1/2][layer] */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;#define CBR 0#define VBR 1#define ABR 2int vbr = CBR; /* variable bitrate flag */int abr_rate = 0;#ifdef GAPLESS#include "layer3.h"#endifunsigned long track_frames = 0;/* a limit for number of frames in a track; beyond that unsigned long may not be enough to hold byte addresses */#ifdef HAVE_LIMITS_H#include <limits.h>#endif#ifndef ULONG_MAX/* hm, is this portable across preprocessors? */#define ULONG_MAX ((unsigned long)-1)#endif#define TRACK_MAX_FRAMES ULONG_MAX/4/1152/* this could become a struct... */long lastscale = -1; /* last used scale */int rva_level[2] = {-1,-1}; /* significance level of stored rva */float rva_gain[2] = {0,0}; /* mix, album */float rva_peak[2] = {0,0};static double mean_framesize;static unsigned long mean_frames;static int do_recover = 0;struct { off_t data[INDEX_SIZE]; size_t fill; unsigned long step;} frame_index;unsigned char *pcm_sample;int pcm_point = 0;int audiobufsize = AUDIOBUFSIZE;#define RESYNC_LIMIT 1024#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;#endifstatic int decode_header(struct frame *fr,unsigned long newhead);#ifdef GAPLESS/* take into account: channels, bytes per sample, resampling (integer samples!) */unsigned long samples_to_bytes(unsigned long s, struct frame *fr , struct audio_info_struct* ai){ /* rounding positive number... */ double sammy, samf; sammy = (1.0*s) * (1.0*ai->rate)/freqs[fr->sampling_frequency]; debug4("%lu samples to bytes with freq %li (ai.rate %li); sammy %f", s, freqs[fr->sampling_frequency], ai->rate, sammy); samf = floor(sammy); return (unsigned long) (((ai->format & AUDIO_FORMAT_MASK) == AUDIO_FORMAT_16) ? 2 : 1) * ai->channels * (int) (((sammy - samf) < 0.5) ? samf : ( sammy-samf > 0.5 ? samf+1 : ((unsigned long) samf % 2 == 0 ? samf : samf + 1)));}#endifvoid audio_flush(int outmode, struct audio_info_struct *ai){ #ifdef GAPLESS if(param.gapless) layer3_gapless_buffercheck(); #endif 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 fprintf (stderr, "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);}#endifvoid read_frame_init (struct frame* fr){ fr->num = 0; oldhead = 0; firsthead = 0; vbr = CBR; abr_rate = 0; track_frames = 0; mean_frames = 0; mean_framesize = 0; rva_level[0] = -1; rva_level[1] = -1; #ifdef GAPLESS /* one can at least skip the delay at beginning - though not add it at end since end is unknown */ if(param.gapless) layer3_gapless_init(DECODER_DELAY+GAP_SHIFT, 0); #endif frame_index.fill = 0; frame_index.step = 1; reset_id3();}#define free_format_header(head) ( ((head & 0xffe00000) == 0xffe00000) && ((head>>17)&3) && (((head>>12)&0xf) == 0x0) && (((head>>10)&0x3) != 0x3 ))/* compiler is smart enought to inline this one or should I really do it as macro...? */int head_check(unsigned long head){ if ( /* first 11 bits are set to 1 for frame sync */ ((head & 0xffe00000) != 0xffe00000) || /* layer: 01,10,11 is 1,2,3; 00 is reserved */ (!((head>>17)&3)) || /* 1111 means bad bitrate */ (((head>>12)&0xf) == 0xf) || /* 0000 means free format... */ (((head>>12)&0xf) == 0x0) || /* sampling freq: 11 is reserved */ (((head>>10)&0x3) == 0x3 ) /* here used to be a mpeg 2.5 check... re-enabled 2.5 decoding due to lack of evidence that it is really not good */ ) { return FALSE; } /* if no check failed, the header is valid (hopefully)*/ else { return TRUE; }}/* adjust the volume, taking both outscale and rva values into account */void do_rva(){ float rvafact = 1; float peak = 0; long newscale; if(param.rva) { int rt = 0; /* Should one assume a zero RVA as no RVA? */ if(param.rva == 2 && rva_level[1] != -1) rt = 1; if(rva_level[rt] != -1) { rvafact = pow(10,rva_gain[rt]/20); peak = rva_peak[rt]; if(param.verbose > 1) fprintf(stderr, "Note: doing RVA with gain %f\n", rva_gain[rt]); } else { warning("no RVA value found"); } } newscale = outscale*rvafact; /* if peak is unknown (== 0) this check won't hurt */ if((peak*newscale) > MAXOUTBURST) { newscale = (long) ((float) MAXOUTBURST/peak); warning2("limiting scale value to %li to prevent clipping with indicated peak factor of %f", newscale, peak); } /* first rva setting is forced with lastscale < 0 */ if(newscale != lastscale) { debug3("changing scale value from %li to %li (peak estimated to %li)", lastscale != -1 ? lastscale : outscale, newscale, (long) (newscale*peak)); make_decode_tables(newscale); /* the actual work */ lastscale = newscale; }}int read_frame_recover(struct frame* fr){ int ret; do_recover = 1; ret = read_frame(fr); do_recover = 0; return ret;}/***************************************************************** * read next frame */int read_frame(struct frame *fr){ /* TODO: rework this thing */ unsigned long newhead; static unsigned char ssave[34]; off_t framepos; int give_note = param.verbose > 1 ? 1 : (do_recover ? 0 : 1 ); 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; } /* this if wrap looks like dead code... */ 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 /* watch out for junk/tags on beginning of stream by invalid header */ if(!firsthead && !head_check(newhead) && !free_format_header(newhead)) { int i; /* check for id3v2; first three bytes (of 4) are "ID3" */ if((newhead & (unsigned long) 0xffffff00) == (unsigned long) 0x49443300) { int id3length = 0; id3length = parse_new_id3(newhead, rd); goto read_again; } else if(param.verbose > 1) fprintf(stderr,"Note: Junk at the beginning (0x%08lx)\n",newhead); /* I even saw RIFF headers at the beginning of MPEG streams ;( */ if(newhead == ('R'<<24)+('I'<<16)+('F'<<8)+'F') { if(param.verbose > 1) fprintf(stderr, "Note: Looks like a RIFF header.\n"); 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; if(param.verbose > 1) fprintf(stderr,"Note: Skipped RIFF header!\n"); goto read_again; } /* unhandled junk... just continue search for a header */ /* 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)) */ if(head_check(newhead) && decode_header(fr, newhead)) break; } if(i == 65536) { if(!param.quiet) error("Giving up searching valid MPEG header after 64K of junk."); 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 /* first attempt of read ahead check to find the real first header; cannot believe what junk is out there! */ /* for now, a spurious first free format header screws up here; need free format support for detecting false free format headers... */ if(!firsthead && rd->flags & READER_SEEKABLE && head_check(newhead) && decode_header(fr, newhead)) { unsigned long nexthead = 0; int hd = 0; off_t start = rd->tell(rd); debug1("doing ahead check with BPF %d", fr->framesize+4); /* step framesize bytes forward and read next possible header*/ if(rd->back_bytes(rd, -fr->framesize)) { error("cannot seek!"); return 0; } hd = rd->head_read(rd,&nexthead); if(rd->back_bytes(rd, rd->tell(rd)-start)) { error("cannot seek!"); return 0; } if(!hd) { warning("cannot read next header, a one-frame stream? Duh..."); } else { debug2("does next header 0x%08lx match first 0x%08lx?", nexthead, newhead); /* not allowing free format yet */ if(!head_check(nexthead) || (nexthead & HDRCMPMASK) != (newhead & HDRCMPMASK)) { debug("No, the header was not valid, start from beginning..."); /* try next byte for valid header */ if(rd->back_bytes(rd, 3)) { error("cannot seek!"); return 0; } goto read_again; } } } /* why has this head check been avoided here before? */ if(!head_check(newhead)) { if(!firsthead && free_format_header(newhead)) { error1("Header 0x%08lx seems to indicate a free format stream; I do not handle that yet", newhead); goto read_again; return 0; } /* and those ugly ID3 tags */ if((newhead & 0xffffff00) == ('T'<<24)+('A'<<16)+('G'<<8)) { rd->skip_bytes(rd,124); if (param.verbose > 1) fprintf(stderr,"Note: Skipped ID3 Tag!\n"); goto read_again;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -