Hi!
I have been struggling with MAD's code for quite some time now, and have managed to understand almost all of it - except I haven't been able to figure out the way it manages a buffer of main_data for mp3 files. (I am working solely on the MP3 part of the decoder) The problem is, the function mad_frame_decode(which decodes ONE entire frame, excluding the polyphase filterbank) works as follows:
1) Read the sideinfo(the header's already been decoded)
[ I don't know why, but apparently Rob had named all main_data_end pointers as main_data_begin. Of course, main_data_end for one frame is the beginning of main data for the other frame.... but they're slightly misleading ]
2) Depending on the value of main_data_end of the current frame, it collects together the main_data which has been buffered till now in an array, stream->(*main_data). I couldn't figure out how Rob does this. He actually looks at the NEXT frame, reads its main_data_end pointer, calculates a variable named frame_space according to: frame_space = stream->next_frame - mad_bit_nextbyte(&stream->ptr); This is the no. of bytes of main_data(which may belong to ANY of the subsequent frames) present in the current frame. So far, so good. Next up is the statement: md_len = si.main_data_begin + frame_space - next_md_begin;
This has me absolutely stumped.
____________________________________________________________________________ ||| header +sideinfo | main_data ||| head + si | main_data |||
----------------------------------------------------------------------------- ^ ^
si.main_data_begin next_md_begin
If frame_space was the length of main data in the second frame above, md_len would be "the no. of main_data bytes in the next frame". But frame_space is the length of the first frame (above), so I don't really know what md_len stands for. Can someone please help me out here???
From this point onward, I absolutely cannot understand the way Rob is bufferring up main_data. I see a couple of memcpy's(), and I can guess what's happenning, but I'm not really sure. Also Rob, how did you manage keeping a main_data buffer without using a circular queue??
3) After all this is done , III_decode is called, which is passed a pointer named ptr, which happens to point to the beginning of main_data for the current frame. III_decode actually decodes the Huffman bits ....and does the actual decoding.
Can somebody please help me out with how the main_data buffer is built up (I know the basics, i.e, main_data of the current frame may be present in any of the previous frames, mani_data_end is a negative offset from the end of the frame...etc...etc)
Thanks a lot!!
Kshitiz
__________________________________________________ Do You Yahoo!? Sign up for SBC Yahoo! Dial - First Month Free http://sbc.yahoo.com
On Friday, July 12, 2002, at 01:09 AM, Kshitiz Malik wrote:
I have been struggling with MAD's code for quite some time now, and have managed to understand almost all of it - except I haven't been able to figure out the way it manages a buffer of main_data for mp3 files. (I am working solely on the MP3 part of the decoder) The problem is, the function mad_frame_decode(which decodes ONE entire frame, excluding the polyphase filterbank) works as follows:
Read the sideinfo(the header's already been decoded)
[ I don't know why, but apparently Rob had named all main_data_end
pointers as main_data_begin. Of course, main_data_end for one frame is the beginning of main data for the other frame.... but they're slightly misleading ]
main_data_begin is the name used by ISO/IEC 11172-3 to describe the offset of the beginning of a frame's main_data relative to the frame's header. It also happens to be the end of the previous frame's main_data, but in the context of decoding the current frame, "main_data_begin" should not at all be misleading.
Note that although it is a positive number, it denotes the number of bytes *before* the current frame that the main_data actually begins, not counting bytes used by previous frame headers or side information.
- Depending on the value of main_data_end of the current frame, it collects together the main_data which has been buffered till now in an array, stream->(*main_data). I couldn't figure out how Rob does
this. He actually looks at the NEXT frame, reads its main_data_end pointer, calculates a variable named frame_space according to: frame_space = stream->next_frame - mad_bit_nextbyte(&stream->ptr); This is the no. of bytes of main_data(which may belong to ANY of the subsequent frames) present in the current frame. So far, so good. Next up is the statement: md_len = si.main_data_begin + frame_space - next_md_begin;
This has me absolutely stumped.
This calculates the effective length of the current frame's main_data: the number of bytes between the current frame's main_data_begin and the next frame's main_data_begin. frame_space is the number of bytes between the end of the current frame's side info and the next frame header, i.e. as you said, bytes of main_data which may belong to *any* of the current or subsequent frames. We add to this the number of bytes of main_data preceding the current frame (i.e. main_data_begin) and then subtract the number of bytes belonging to the next or subsequent frames (i.e. next_md_begin).
To make things clearer, imagine the case when main_data_begin is always 0. In this case, every frame's main_data is contained entirely between frame headers, and the length is exactly frame_space. Now consider one frame whose main_data_begin is 1, but the rest are still 0. The main_data length of this frame is one byte larger because it begins one byte earlier. The main_data length of the *previous* frame is one byte smaller.
From this point onward, I absolutely cannot understand the way Rob is bufferring up main_data. I see a couple of memcpy's(), and I can guess what's happenning, but I'm not really sure. Also Rob, how did you manage keeping a main_data buffer without using a circular queue??
The general assumption is that once a frame has been decoded, its frame data area will no longer be accessible, so any data that might belong to future frames is copied to the main_data buffer. When the next frame is processed, the rest of the frame's main_data is appended to the buffer in a contiguous fashion and the audio data is decoded. Then the buffer is re-initialized with the remaining data that might belong to future frames, and the process repeats.
- After all this is done , III_decode is called, which is passed a
pointer named ptr, which happens to point to the beginning of main_data for the current frame. III_decode actually decodes the Huffman bits ....and does the actual decoding.
Can somebody please help me out with how the main_data buffer is built up (I know the basics, i.e, main_data of the current frame may be present in any of the previous frames, mani_data_end is a negative offset from the end of the frame...etc...etc)
I think this might be the source of your misunderstanding: there is nothing called main_data_end, and main_data_begin is a negative offset from the *beginning* of the frame, not the end.
Cheers,
-- Rob Leslie rob@mars.org