Hi folks,
I've just started writing an audio processing utility, using libmad to read from MP3 files.
I've modelled my code on minimad.c and it works fine, but as I'm decoding each file all at once, I want to provide a progress meter. In minimad.c the whole file is mmapped, so the read function only gets called once. I figured I would change my read function to make available a small fraction of the data, update the progress bar, then make the next block available, etc.
Unfortunately this doesn't work, I get "lost synchronisation" , "reserved sample frequency value", "bad main_data_begin pointer", "forbidden bitrate value" and "Huffman data overrun" errors each time I return a new block of data. As far as I can tell, my code is doing the right thing (I've included it below). In madllc.c, there is provision for when a frame is not wholly included by a buffer, but I would expect in the case of the high-level functions that this would be detected by mad_decoder_run and the input function would be polled for more data automatically.
Am I missing something obvious? Also, is there a better way to implement a progress bar?
Thanks in advance, Hamish
P.S. this code is in Objective-C: "[inputData length]" does what the C++ "inputdata.length()" would do, and "id" is like "NSObject *" (NSObject is the root object).
struct dataDescriptor { NSData *inputData; NSMutableData *outputData; unsigned int bytesRead; unsigned int byteChunk; // number of bytes to read at a time id progressObject; };
static enum mad_flow madInput(void *data, struct mad_stream *stream) { struct dataDescriptor *descriptor = data; NSData *inputData = descriptor->inputData; unsigned int bytesTotal = [inputData length]; unsigned int bytesLeft = bytesTotal - descriptor->bytesRead; double progress = (double)(descriptor->bytesRead) / (double)bytesTotal;
[descriptor->progressObject showProgress:progress]
if (bytesLeft == 0) return MAD_FLOW_STOP;
fprintf(stderr, "Bytes read=%d, left=%d\n", descriptor->bytesRead, bytesLeft);
if (bytesLeft > descriptor->byteChunk) bytesLeft = descriptor->byteChunk; mad_stream_buffer(stream, [inputData bytes] + (descriptor->bytesRead), bytesLeft); descriptor->bytesRead += bytesLeft;
return MAD_FLOW_CONTINUE; }