Hi!
I have the following question - is it possible to decode a stream using MAD? For example: I have shoutcast stream and I read it in small portions (say, 40960 bytes), decode it and encode back to mp3 using LAME (chaning bitrate, samplerate, etc...).
The problem is that I have to call mad_stream_buffer with each piece of stream data, decode/encode it and then if I listen the resulting mp3 file - I notice "noise" between theese small decoded pieces. Seems like it happen not only with VBR files.
Pseudo-code:
while ( bytes = read(file_id, buff, SHOUT_BUFFER_LENGTH ) ) {
mad_stream_buffer(&stream, buff, bytes );
while(1){ mad_frame_decode(&frame,&stream) .... int ret = lame_encode_buffer( lameGlobalFlags, left, right, nsamples, mp3Buf, mp3Size ); // Play resulting mp3 data
}
}
Is it possible to decode a stream without theese "edge effects" ? May be I should not re-initialize MAD buffer after each read in some way? Please help.
Alexey V Paramonov wrote:
Hi!
I have the following question - is it possible to decode a stream using MAD?
Yes, of course.
For example: I have shoutcast stream and I read it in small portions (say, 40960 bytes), decode it and encode back to mp3 using LAME (chaning bitrate, samplerate, etc...).
The problem is that I have to call mad_stream_buffer with each piece of stream data, decode/encode it and then if I listen the resulting mp3 file - I notice "noise" between theese small decoded pieces. Seems like it happen not only with VBR files.
Haven't looked at madplay (etc..) in years but originally it was mmap()'ing an mp3 file into memory which works fine assuming the mmap() region could grow for as long as you need to decode the respective file.
If rather you are trying to decode into a fixed buffer you'll need to do some adjustment when your decode nears the end of the static buffer. This means detecting when you don't have enough data left at the buffer tail to do a valid frame decode (ie: mad_frame_decode() returns MAD_ERROR_BUFLEN). In that case you need to copy the partial frame at the buffer's tail, back at/near the head of the buffer (depending on your stream management logic) and readjust libmad's notion of where it is via a mad_stream_buffer() call.
Pseudo-code:
while ( bytes = read(file_id, buff, SHOUT_BUFFER_LENGTH ) ) {
mad_stream_buffer(&stream, buff, bytes );
while(1){ mad_frame_decode(&frame,&stream) .... int ret = lame_encode_buffer( lameGlobalFlags, left, right, nsamples, mp3Buf, mp3Size ); // Play resulting mp3 data
}
}
I really don't understand what you are trying to accomplish via the back-to-back decode/encode but I suppose that is unrelated to your question.
Is it possible to decode a stream without theese "edge effects" ?
Yes but it can be a little tricky to get right in the case you allow a user to manipulate the stream pointer and perform arbitrary seeks within the stream.
May be I should not re-initialize MAD buffer after each read in some way?
If you are altering the [memory address] seek point within the current buffer you'll need to reset the decoder's notion of decode location via a mad_stream_buffer() call.
-john