On Tuesday, May 28, 2002, at 10:37 AM, Robin O'Leary wrote:
On Mon, May 27, 2002 at 12:04:21AM -0700, Rob Leslie wrote:
... I think the problem is that you are refilling your stream buffer without copying the unconsumed data from the end of the previous buffer. ...
Is there a good reason for this requirement?
One of the goals of the stream API was to avoid "owning" the data passed to it. The stream just maintains a set of pointers within a buffer or memory mapping which you provide. This minimizes data copying (or rather, places it under the control of your application) and avoids other overhead, and is consistent with the minimalist nature of the library.
How many places go fishing around in the stream struct directly? It seems mad_bit_read() and friends are almost exclusively responsible for furnishing input data to the rest of the library; mad_header_decode() does some direct manipulation too. If these functions were taught how to get bytes from the previous stream buffer until it was fully `used up', before starting on the current one, could we then have a new function, say mad_stream_buffer_append(), which would leave the bitptr struct intact counting down bits from the last buffer, and hence avoid the need for the caller to do memmove()? Would the overhead of checking the number of bits left in those low-level access routines be prohibitive?
I'm reluctant to add overhead to the bit reading routine that would make it any slower than it is already. It's for this reason that libmad requires the stream to contain complete, contiguous frames.
I think the best approach, if you really want the kind of API you describe, is to write an abstraction layer on top of libmad that implements it. Such a library could also include other useful utilities such as PCM formatting, resampling, dithering, etc. Arguably the high-level API provided by libmad should have been a part of this hypothetical library also since it is effectively layered on top of the low-level API.
-- Rob Leslie rob@mars.org