📄 tag.c
字号:
/* * madplay - MPEG audio decoder and player * Copyright (C) 2000-2004 Robert Leslie * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * $Id: tag.c,v 1.1 2004/02/17 02:26:43 rob Exp $ */# ifdef HAVE_CONFIG_H# include "config.h"# endif# include "global.h"# include <mad.h># include "crc.h"# include "tag.h"# define XING_MAGIC (('X' << 24) | ('i' << 16) | ('n' << 8) | 'g')# define INFO_MAGIC (('I' << 24) | ('n' << 16) | ('f' << 8) | 'o')# define LAME_MAGIC (('L' << 24) | ('A' << 16) | ('M' << 8) | 'E')/* * NAME: tag->init() * DESCRIPTION: initialize tag structure */void tag_init(struct tag *tag){ tag->flags = 0; tag->encoder[0] = 0;}/* * NAME: parse_xing() * DESCRIPTION: parse a Xing VBR tag */staticint parse_xing(struct tag_xing *xing, struct mad_bitptr *ptr, unsigned int *bitlen){ if (*bitlen < 32) goto fail; xing->flags = mad_bit_read(ptr, 32); *bitlen -= 32; if (xing->flags & TAG_XING_FRAMES) { if (*bitlen < 32) goto fail; xing->frames = mad_bit_read(ptr, 32); *bitlen -= 32; } if (xing->flags & TAG_XING_BYTES) { if (*bitlen < 32) goto fail; xing->bytes = mad_bit_read(ptr, 32); *bitlen -= 32; } if (xing->flags & TAG_XING_TOC) { int i; if (*bitlen < 800) goto fail; for (i = 0; i < 100; ++i) xing->toc[i] = mad_bit_read(ptr, 8); *bitlen -= 800; } if (xing->flags & TAG_XING_SCALE) { if (*bitlen < 32) goto fail; xing->scale = mad_bit_read(ptr, 32); *bitlen -= 32; } return 0; fail: xing->flags = 0; return -1;}/* * NAME: tag->parse_rgain() * DESCRIPTION: parse a 16-bit Replay Gain field */void tag_parse_rgain(struct tag_rgain *rgain, struct mad_bitptr *ptr){ int negative; rgain->name = mad_bit_read(ptr, 3); rgain->originator = mad_bit_read(ptr, 3); negative = mad_bit_read(ptr, 1); rgain->adjustment = mad_bit_read(ptr, 9); if (negative) rgain->adjustment = -rgain->adjustment;}/* * NAME: parse_lame() * DESCRIPTION: parse a LAME tag */staticint parse_lame(struct tag_lame *lame, struct mad_bitptr *ptr, unsigned int *bitlen, unsigned short crc){ struct mad_bitptr save = *ptr; if (*bitlen < 36 * 8) goto fail; /* bytes $9A-$A4: Encoder short VersionString */ mad_bit_skip(ptr, 9 * 8); /* byte $A5: Info Tag revision + VBR method */ lame->revision = mad_bit_read(ptr, 4); if (lame->revision == 15) goto fail; lame->vbr_method = mad_bit_read(ptr, 4); /* byte $A6: Lowpass filter value (Hz) */ lame->lowpass_filter = mad_bit_read(ptr, 8) * 100; /* bytes $A7-$AA: 32 bit "Peak signal amplitude" */ lame->peak = mad_bit_read(ptr, 32) << 5; /* bytes $AB-$AC: 16 bit "Radio Replay Gain" */ tag_parse_rgain(&lame->replay_gain[0], ptr); /* bytes $AD-$AE: 16 bit "Audiophile Replay Gain" */ tag_parse_rgain(&lame->replay_gain[1], ptr); /* byte $AF: Encoding flags + ATH Type */ lame->flags = mad_bit_read(ptr, 4); lame->ath_type = mad_bit_read(ptr, 4); /* byte $B0: if ABR {specified bitrate} else {minimal bitrate} */ lame->bitrate = mad_bit_read(ptr, 8); /* bytes $B1-$B3: Encoder delays */ lame->start_delay = mad_bit_read(ptr, 12); lame->end_padding = mad_bit_read(ptr, 12); /* byte $B4: Misc */ lame->source_samplerate = mad_bit_read(ptr, 2); if (mad_bit_read(ptr, 1)) lame->flags |= TAG_LAME_UNWISE; lame->stereo_mode = mad_bit_read(ptr, 3); lame->noise_shaping = mad_bit_read(ptr, 2); /* byte $B5: MP3 Gain */ lame->gain = mad_bit_read(ptr, 8); /* bytes $B6-B7: Preset and surround info */ mad_bit_skip(ptr, 2); lame->surround = mad_bit_read(ptr, 3); lame->preset = mad_bit_read(ptr, 11); /* bytes $B8-$BB: MusicLength */ lame->music_length = mad_bit_read(ptr, 32); /* bytes $BC-$BD: MusicCRC */ lame->music_crc = mad_bit_read(ptr, 16); /* bytes $BE-$BF: CRC-16 of Info Tag */ if (mad_bit_read(ptr, 16) != crc) goto fail; *bitlen -= 36 * 8; return 0; fail: *ptr = save; return -1;}/* * NAME: tag->parse() * DESCRIPTION: parse Xing/LAME tag(s) */int tag_parse(struct tag *tag, struct mad_stream const *stream){ struct mad_bitptr ptr = stream->anc_ptr; struct mad_bitptr start = ptr; unsigned int bitlen = stream->anc_bitlen; unsigned long magic; int i; if (bitlen < 32) return -1; magic = mad_bit_read(&ptr, 32); bitlen -= 32; if (magic != XING_MAGIC && magic != INFO_MAGIC && magic != LAME_MAGIC) { /* * Due to an unfortunate historical accident, a Xing VBR tag may be * misplaced in a stream with CRC protection. We check for this by * assuming the tag began two octets prior and the high bits of the * following flags field are always zero. */ if (magic != ((XING_MAGIC << 16) & 0xffffffffL) && magic != ((INFO_MAGIC << 16) & 0xffffffffL)) return -1; magic >>= 16; /* backtrack the bit pointer */ ptr = start; mad_bit_skip(&ptr, 16); bitlen += 16; } if ((magic & 0x0000ffffL) == (XING_MAGIC & 0x0000ffffL)) tag->flags |= TAG_VBR; /* Xing tag */ if (magic == LAME_MAGIC) { ptr = start; bitlen += 32; } else if (parse_xing(&tag->xing, &ptr, &bitlen) == 0) tag->flags |= TAG_XING; /* encoder string */ if (bitlen >= 20 * 8) { start = ptr; for (i = 0; i < 20; ++i) { tag->encoder[i] = mad_bit_read(&ptr, 8); if (tag->encoder[i] == 0) break; /* keep only printable ASCII chars */ if (tag->encoder[i] < 0x20 || tag->encoder[i] >= 0x7f) { tag->encoder[i] = 0; break; } } tag->encoder[20] = 0; ptr = start; } /* LAME tag */ if (stream->next_frame - stream->this_frame >= 192 && parse_lame(&tag->lame, &ptr, &bitlen, crc_compute(stream->this_frame, 190, 0x0000)) == 0) { tag->flags |= TAG_LAME; tag->encoder[9] = 0; } else { for (i = 0; i < 20; ++i) { if (tag->encoder[i] == 0) break; /* stop at padding chars */ if (tag->encoder[i] == 0x55) { tag->encoder[i] = 0; break; } } } return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -