📄 common.c
字号:
int try = 0; /* TODO: make this more robust, I'd like to cat two mp3 fragments together (in a dirty way) and still have mpg123 beign able to decode all it somehow. */ if(give_note) fprintf(stderr, "Note: Trying to resync...\n"); /* 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 { if(!rd->head_shift(rd,&newhead)) return 0; debug2("resync try %i, got newhead 0x%08lx", try, newhead); if (!oldhead) { debug("going to init_resync..."); goto init_resync; /* "considered harmful", eh? */ } /* we should perhaps collect a list of valid headers that occured in file... there can be more */ /* Michael's new resync routine seems to work better with the one frame readahead (and some input buffering?) */ } while ( ++try < RESYNC_LIMIT && (newhead & HDRCMPMASK) != (oldhead & HDRCMPMASK) && (newhead & HDRCMPMASK) != (firsthead & HDRCMPMASK) ); /* too many false positives }while (!(head_check(newhead) && decode_header(fr, newhead))); */ if(try == RESYNC_LIMIT) { error("giving up resync - your stream is not nice... perhaps an improved routine could catch up"); return 0; } if (give_note) fprintf (stderr, "Note: Skipped %d bytes in input.\n", try); } else { error("not attempting to resync..."); return (0); } } if (!firsthead) { if(!decode_header(fr,newhead)) { error("decode header failed before first valid one, going to read again"); goto read_again; } } else if(!decode_header(fr,newhead)) { error("decode header failed - goto resync"); /* return 0; */ goto init_resync; } } else fr->header_change = 0; /* flip/init buffer for Layer 3 */ bsbufold = bsbuf; bsbuf = bsspace[bsnum]+512; bsnum = (bsnum + 1) & 1; /* if filepos is invalid, so is framepos */ framepos = rd->filepos - 4; /* read main data into memory */ /* 0 is error! */ if(!rd->read_frame_body(rd,bsbuf,fr->framesize)) return 0; if(!firsthead) { /* following stuff is actually layer3 specific (in practice, not in theory) */ if(fr->lay == 3) { /* going to look for Xing or Info at some position after the header MPEG 1 MPEG 2/2.5 (LSF) Stereo, Joint Stereo, Dual Channel 32 17 Mono 17 9 Also, how to avoid false positives? I guess I should interpret more of the header to rule that out(?). I hope that ensuring all zeros until tag start is enough. */ size_t lame_offset = (fr->stereo == 2) ? (fr->lsf ? 17 : 32 ) : (fr->lsf ? 9 : 17); if(fr->framesize >= 120+lame_offset) /* traditional Xing header is 120 bytes */ { size_t i; int lame_type = 0; /* only search for tag when all zero before it (apart from checksum) */ for(i=2; i < lame_offset; ++i) if(bsbuf[i] != 0) break; if(i == lame_offset) { if ( (bsbuf[lame_offset] == 'I') && (bsbuf[lame_offset+1] == 'n') && (bsbuf[lame_offset+2] == 'f') && (bsbuf[lame_offset+3] == 'o') ) { lame_type = 1; /* We still have to see what there is */ } else if ( (bsbuf[lame_offset] == 'X') && (bsbuf[lame_offset+1] == 'i') && (bsbuf[lame_offset+2] == 'n') && (bsbuf[lame_offset+3] == 'g') ) { lame_type = 2; vbr = VBR; /* Xing header means always VBR */ } if(lame_type) { unsigned long xing_flags; /* we have one of these headers... */ if(!param.quiet) fprintf(stderr, "Note: Xing/Lame/Info header detected\n"); /* now interpret the Xing part, I have 120 bytes total for sure */ /* there are 4 bytes for flags, but only the last byte contains known ones */ lame_offset += 4; /* now first byte after Xing/Name */ /* 4 bytes dword for flags */ #define make_long(a, o) ((((unsigned long) a[o]) << 24) | (((unsigned long) a[o+1]) << 16) | (((unsigned long) a[o+2]) << 8) | ((unsigned long) a[o+3])) /* 16 bit */ #define make_short(a,o) ((((unsigned short) a[o]) << 8) | ((unsigned short) a[o+1])) xing_flags = make_long(bsbuf, lame_offset); lame_offset += 4; debug1("Xing: flags 0x%08lx", xing_flags); if(xing_flags & 1) /* frames */ { /* In theory, one should use that value for skipping... When I know the exact number of samples I could simply count in audio_flush, but that's problematic with seeking and such. I still miss the real solution for detecting the end. */ track_frames = make_long(bsbuf, lame_offset); if(track_frames > TRACK_MAX_FRAMES) track_frames = 0; /* endless stream? */ #ifdef GAPLESS /* if no further info there, remove/add at least the decoder delay */ if(param.gapless) { unsigned long length = track_frames * spf(fr); if(length > 1) layer3_gapless_init(DECODER_DELAY+GAP_SHIFT, length+DECODER_DELAY+GAP_SHIFT); } #endif debug1("Xing: %lu frames", track_frames); lame_offset += 4; } if(xing_flags & 0x2) /* bytes */ { #ifdef DEBUG unsigned long xing_bytes = make_long(bsbuf, lame_offset); debug1("Xing: %lu bytes", xing_bytes); #endif lame_offset += 4; } if(xing_flags & 0x4) /* TOC */ { lame_offset += 100; /* just skip */ } if(xing_flags & 0x8) /* VBR quality */ { #ifdef DEBUG unsigned long xing_quality = make_long(bsbuf, lame_offset); debug1("Xing: quality = %lu", xing_quality); #endif lame_offset += 4; } /* I guess that either 0 or LAME extra data follows */ /* there may this crc16 be floating around... (?) */ if(bsbuf[lame_offset] != 0) { unsigned char lame_vbr; float replay_gain[2] = {0,0}; float peak = 0; float gain_offset = 0; /* going to be +6 for old lame that used 83dB */ char nb[10]; memcpy(nb, bsbuf+lame_offset, 9); nb[9] = 0; debug1("Info: Encoder: %s", nb); if(!strncmp("LAME", nb, 4)) { gain_offset = 6; debug("TODO: finish lame detetcion..."); } lame_offset += 9; /* the 4 big bits are tag revision, the small bits vbr method */ lame_vbr = bsbuf[lame_offset] & 15; debug1("Info: rev %u", bsbuf[lame_offset] >> 4); debug1("Info: vbr mode %u", lame_vbr); lame_offset += 1; switch(lame_vbr) { /* from rev1 proposal... not sure if all good in practice */ case 1: case 8: vbr = CBR; break; case 2: case 9: vbr = ABR; break; default: vbr = VBR; /* 00==unknown is taken as VBR */ } /* skipping: lowpass filter value */ lame_offset += 1; /* replaygain */ /* 32bit float: peak amplitude -- why did I parse it as int before??*/ /* Ah, yes, lame seems to store it as int since some day in 2003; I've only seen zeros anyway until now, bah! */ if ( (bsbuf[lame_offset] != 0) || (bsbuf[lame_offset+1] != 0) || (bsbuf[lame_offset+2] != 0) || (bsbuf[lame_offset+3] != 0) ) { debug("Wow! Is there _really_ a non-zero peak value? Now is it stored as float or int - how should I know?"); peak = *(float*) (bsbuf+lame_offset); } debug1("Info: peak = %f (I won't use this)", peak); peak = 0; /* until better times arrived */ lame_offset += 4; /* ReplayGain values - lame only writes radio mode gain... 16bit gain, 3 bits name, 3 bits originator, sign (1=-, 0=+), dB value*10 in 9 bits (fixed point) ignore the setting if name or originator == 000! radio 0 0 1 0 1 1 1 0 0 1 1 1 1 1 0 1 audiophile 0 1 0 0 1 0 0 0 0 0 0 1 0 1 0 0 */ for(i =0; i < 2; ++i) { unsigned char origin = (bsbuf[lame_offset] >> 2) & 0x7; /* the 3 bits after that... */ if(origin != 0) { unsigned char gt = bsbuf[lame_offset] >> 5; /* only first 3 bits */ if(gt == 1) gt = 0; /* radio */ else if(gt == 2) gt = 1; /* audiophile */ else continue; /* get the 9 bits into a number, divide by 10, multiply sign... happy bit banging */ replay_gain[0] = ((bsbuf[lame_offset] & 0x2) ? -0.1 : 0.1) * (make_short(bsbuf, lame_offset) & 0x1f); } lame_offset += 2; } debug1("Info: Radio Gain = %03.1fdB", replay_gain[0]); debug1("Info: Audiophile Gain = %03.1fdB", replay_gain[1]); for(i=0; i < 2; ++i) { if(rva_level[i] <= 0) { rva_peak[i] = 0; /* at some time the parsed peak should be used */ rva_gain[i] = replay_gain[i]; rva_level[i] = 0; } } lame_offset += 1; /* skipping encoding flags byte */ if(vbr == ABR) { abr_rate = bsbuf[lame_offset]; debug1("Info: ABR rate = %u", abr_rate); } lame_offset += 1; /* encoder delay and padding, two 12 bit values... lame does write them from int ...*/ #ifdef GAPLESS if(param.gapless) { /* Temporary hack that doesn't work with seeking and also is not waterproof but works most of the time; in future the lame delay/padding and frame number info should be passed to layer3.c and the junk samples avoided at the source. */ unsigned long length = track_frames * spf(fr); unsigned long skipbegin = DECODER_DELAY + ((((int) bsbuf[lame_offset]) << 4) | (((int) bsbuf[lame_offset+1]) >> 4)); unsigned long skipend = -DECODER_DELAY + (((((int) bsbuf[lame_offset+1]) << 8) | (((int) bsbuf[lame_offset+2]))) & 0xfff); debug3("preparing gapless mode for layer3: length %lu, skipbegin %lu, skipend %lu", length, skipbegin, skipend); if(length > 1) layer3_gapless_init(skipbegin+GAP_SHIFT, (skipend < length) ? length-skipend+GAP_SHIFT : length+GAP_SHIFT); } #endif } /* switch buffer back ... */ bsbuf = bsspace[bsnum]+512; bsnum = (bsnum + 1) & 1; goto read_again; } } } } /* end block for Xing/Lame/Info tag */ firsthead = newhead; /* _now_ it's time to store it... the first real header */ /* now adjust volume */ do_rva(); /* and print id3 info */ if(!param.quiet) print_id3_tag(rd->flags & READER_ID3TAG ? rd->id3buf : NULL); } bsi.bitindex = 0; bsi.wordpointer = (unsigned char *) bsbuf; if (param.halfspeed && fr->lay == 3) memcpy (ssave, bsbuf, ssize); if(++mean_frames != 0) { mean_framesize = ((mean_frames-1)*mean_framesize+compute_bpf(fr)) / mean_frames ; } /* index the position */ if(INDEX_SIZE > 0) /* any sane compiler should make a no-brainer out of this */ { if(fr->num == frame_index.fill*frame_index.step) { if(frame_index.fill == INDEX_SIZE) { size_t c; /* increase step, reduce fill */ frame_index.step *= 2; frame_index.fill /= 2; /* divisable by 2! */ for(c = 0; c < frame_index.fill; ++c) { frame_index.data[c] = frame_index.data[2*c]; } } if(fr->num == frame_index.fill*frame_index.step) { frame_index.data[frame_index.fill] = framepos; ++frame_index.fill; } } } ++fr->num; return 1;}void print_frame_index(FILE* out){ size_t c; for(c=0; c < frame_index.fill;++c) fprintf(out, "[%lu] %lu: %li (+%li)\n", (unsigned long) c, (unsigned long) c*frame_index.step, (long)frame_index.data[c], (long) (c ? frame_index.data[c]-frame_index.data[c-1] : 0));}/* find the best frame in index just before the wanted one, seek to there then step to just before wanted one with read_frame do not care tabout the stuff that was in buffer but not played back everything that left the decoder is counted as played Decide if you want low latency reaction and accurate timing info or stable long-time playback with buffer!*/off_t frame_index_find(unsigned long want_frame, unsigned long* get_frame){ /* default is file start if no index position */ off_t gopos = 0; *get_frame = 0; if(frame_index.fill) { /* find in index */ size_t fi; /* at index fi there is frame step*fi... */ fi = want_frame/frame_index.step; if(fi >= frame_index.fill) fi = frame_index.fill - 1; *get_frame = fi*frame_index.step; gopos = frame_index.data[fi]; } return gopos;}/* dead code? - see readers.c *//**************************************** * 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)) { error("tried to decode obviously invalid header"); return 0; } if( newhead & (1<<20) ) { fr->lsf = (newhead & (1<<19)) ? 0x0 : 0x1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -