/* * NAME: decode_header() * DESCRIPTION: read header data and following CRC word */ static int decode_header(struct mad_header *header, struct mad_stream *stream) { unsigned int index; header->flags = 0; header->private_bits = 0; /* header() */ /* syncword */ mad_bit_skip(&stream->ptr, 11); /* MPEG 2.5 indicator (really part of syncword) */ if (mad_bit_read(&stream->ptr, 1) == 0) header->flags |= MAD_FLAG_MPEG_2_5_EXT; /* ID */ if (mad_bit_read(&stream->ptr, 1) == 0) header->flags |= MAD_FLAG_LSF_EXT; else if (header->flags & MAD_FLAG_MPEG_2_5_EXT) { stream->error = MAD_ERROR_LOSTSYNC; return -1; } /* layer */ header->layer = 4 - mad_bit_read(&stream->ptr, 2); if (header->layer == 4) { stream->error = MAD_ERROR_BADLAYER; return -1; } /* protection_bit */ if (mad_bit_read(&stream->ptr, 1) == 0) { header->flags |= MAD_FLAG_PROTECTION; header->crc_check = mad_bit_crc(stream->ptr, 16, 0xffff); } /* bitrate_index */ index = mad_bit_read(&stream->ptr, 4); if (index == 15) { stream->error = MAD_ERROR_BADBITRATE; return -1; } if (header->flags & MAD_FLAG_LSF_EXT) header->bitrate = bitrate_table[3 + (header->layer >> 1)][index]; else
/* * NAME: bit->read() * DESCRIPTION: read an arbitrary number of bits and return their UIMSBF value */ unsigned long mad_bit_read(struct mad_bitptr *bitptr, unsigned int len) { register unsigned long value; if (len > sizeof(unsigned long) * CHAR_BIT) { mad_bit_skip(bitptr, len - sizeof(unsigned long) * CHAR_BIT); len = sizeof(unsigned long) * CHAR_BIT; } /* remaining bits in current byte */ value = *bitptr->byte & ((1 << mad_bit_bitsleft(bitptr)) - 1); if (len < mad_bit_bitsleft(bitptr)) { value >>= mad_bit_bitsleft(bitptr) - len; bitptr->bit += len; return value; }
static xmms_xing_lame_t * parse_lame (struct mad_bitptr *ptr) { struct mad_bitptr save = *ptr; unsigned long magic; unsigned char const *version; xmms_xing_lame_t *lame; lame = g_new0 (xmms_xing_lame_t, 1); /* if (*bitlen < 36 * 8) goto fail; */ /* bytes $9A-$A4: Encoder short VersionString */ magic = mad_bit_read (ptr, 4 * 8); if (magic != LAME_MAGIC) goto fail; XMMS_DBG ("LAME tag found!"); version = mad_bit_nextbyte (ptr); mad_bit_skip (ptr, 5 * 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" */ /* rgain_parse(&lame->replay_gain[0], ptr); */ /* bytes $AD-$AE: 16 bit "Audiophile Replay Gain" */ /* rgain_parse(&lame->replay_gain[1], ptr); */ mad_bit_skip (ptr, 32); /* * As of version 3.95.1, LAME writes Replay Gain values with a reference of * 89 dB SPL instead of the 83 dB specified in the Replay Gain proposed * standard. Here we compensate for the heresy. */ if (magic == LAME_MAGIC) { char str[6]; /* unsigned major = 0, minor = 0, patch = 0; int i; */ memcpy (str, version, 5); str[5] = 0; /* sscanf(str, "%u.%u.%u", &major, &minor, &patch); if (major > 3 || (major == 3 && (minor > 95 || (minor == 95 && str[4] == '.')))) { for (i = 0; i < 2; ++i) { if (RGAIN_SET(&lame->replay_gain[i])) lame->replay_gain[i].adjustment -= 60; } } */ } /* 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 |= XMMS_XING_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; */ return lame; fail: g_free (lame); *ptr = save; return NULL; }
/* * 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; }