Hi,
I'm writing a program to correct bad MP3 files (by dropping bad frames, dropping IDv2 tags on demand, etc.) by using libmad. One point is that I want to add an CRC-16 checksum to the header. Can I use the libmad low level interface for this (i.e. set protection bit, and call mad_frame_decode(), get crc-checksum from header->crc_target)?
Any ideas?
Dirk
On Tuesday, March 26, 2002, at 12:23 AM, Dirk Nehring wrote:
I'm writing a program to correct bad MP3 files (by dropping bad frames, dropping IDv2 tags on demand, etc.) by using libmad. One point is that I want to add an CRC-16 checksum to the header. Can I use the libmad low level interface for this (i.e. set protection bit, and call mad_frame_decode(), get crc-checksum from header->crc_target)?
You probably can't add a checksum easily if there isn't one already because it involves adding a 16-bit field to the audio data region, and you may not have enough room for it in every frame.
If you can overcome that problem, your strategy might work. If you mark the protection bit in the frame header, make sure you call mad_frame_decode() with the CRC field present or it will compute the wrong CRC.
The computed CRC is in header->crc_check.
-- Rob Leslie rob@mars.org
On Fri, Mar 29, 2002 at 01:04:58AM -0800, Rob Leslie wrote:
On Tuesday, March 26, 2002, at 12:23 AM, Dirk Nehring wrote:
I'm writing a program to correct bad MP3 files (by dropping bad frames, dropping IDv2 tags on demand, etc.) by using libmad. One point is that I want to add an CRC-16 checksum to the header. Can I use the libmad low level interface for this (i.e. set protection bit, and call mad_frame_decode(), get crc-checksum from header->crc_target)?
You probably can't add a checksum easily if there isn't one already because it involves adding a 16-bit field to the audio data region, and you may not have enough room for it in every frame.
I haven't understand it fully: if I use a CRC check field, I loose 2 bytes from the data field. If this is true, I think it is impossible to add a CRC field afterward.
If you can overcome that problem, your strategy might work. If you mark the protection bit in the frame header, make sure you call mad_frame_decode() with the CRC field present or it will compute the wrong CRC.
The computed CRC is in header->crc_check.
I developed the following lines:
---------------------------------------------------------- unsigned short crc_check; struct mad_bitptr crc_buffer; unsigned int nch, si_len;
ptr = (unsigned char *) Stream.this_frame; ptr2 = (unsigned char *) Stream.next_frame;
crc_check = 0xffff; mad_bit_init(&crc_buffer, ptr + 2); crc_check = mad_bit_crc(crc_buffer, 16, crc_check);
nch = MAD_NCHANNELS(&Frame.header); si_len = (Frame.header.flags & MAD_FLAG_LSF_EXT) ? (nch == 1 ? 9 : 17) : (nch == 1 ? 17 : 32);
if (Frame.header.flags & MAD_FLAG_PROTECTION) { mad_bit_init(&crc_buffer, ptr + 6); crc_check = mad_bit_crc(crc_buffer, si_len * 8, crc_check); if (crc_check != Frame.header.crc_target) { fprintf(stderr, "%s: Correct wrong crc16 checksum, expected 0x%x, got 0x%x.\n", ProgName, crc_check, Frame.header.crc_target); ptr[4] = crc_check >> 8; ptr[5] = crc_check & 255; } } else { unsigned char ch;
mad_bit_init(&crc_buffer, ptr + 4); crc_check = mad_bit_crc(crc_buffer, si_len * 8, crc_check); ptr[1] -= 1; /* set protection_bit */ } ----------------------------------------------------------
Is it theoretically possible to add an CRC checksum to a frame without reencoding?
Dirk
On Sunday, March 31, 2002, at 06:40 AM, Dirk Nehring wrote:
You probably can't add a checksum easily if there isn't one already because it involves adding a 16-bit field to the audio data region, and you may not have enough room for it in every frame.
I haven't understand it fully: if I use a CRC check field, I loose 2 bytes from the data field. If this is true, I think it is impossible to add a CRC field afterward.
That was my point.
I developed the following lines:
One thing I noticed is that you make the assumption all your frames are Layer III.
Is it theoretically possible to add an CRC checksum to a frame without reencoding?
Theoretically I think it is possible, yes, as long as there are at least 16 bits of unused ancillary data in each frame, or (for Layer III only) there are at least 16 additional bits available from the bit reservoir. If you take bits from the latter, you'll have to update the main_data_begin pointer as appropriate.
-- Rob Leslie rob@mars.org