I was looking through the MAD examples (minimad and madplay) in order for me to integrate MAD into Apollo. It became apparent pretty quickly that this is no easy task, with just one of the files for the madplay example touching 2000 lines of compact, fairly complex code. That combined with no documentation easily destroyed most of my motivation.
I wondered if anybody has written a fairly decoupled C++ wrapper class. It doesn't have to be quite:
MP3File m("my_song.mp3"); m.play();
but at least closer to that than to the 2000+ line example included.
- Marius Sundbakken Apollo Developer: http://www.apolloplayer.org
Marius Sundbakken wrote:
I was looking through the MAD examples (minimad and madplay) in order for me to integrate MAD into Apollo. It became apparent pretty quickly that this is no easy task, with just one of the files for the madplay example touching 2000 lines of compact, fairly complex code. That combined with no documentation easily destroyed most of my motivation.
I don't consider madplay really to be an example, at least not a simple one, precisely because it is so complex. It's a full-featured command-line decoder and player. However, I think minimad ought to be quite a bit easier to wrap your head around, and it uses exactly the same high-level MAD API that madplay does.
I wondered if anybody has written a fairly decoupled C++ wrapper class. It doesn't have to be quite:
MP3File m("my_song.mp3"); m.play();
but at least closer to that than to the 2000+ line example included.
I don't think I've seen anything like this yet, but it sounds like it might be useful.
I don't consider madplay really to be an example, at least not a simple one, precisely because it is so complex. It's a full-featured command-line decoder and player. However, I think minimad ought to be quite a bit easier to wrap your head around, and it uses exactly the same high-level MAD API that madplay does.
I did wrap the minimad example easily into a class, but I then got stuck. Firstly, it outputs to stdio. Can MAD actually output to the audio device or is that beyond the scope of the library (i.e. it's only a decoder). I figured I could replace stdio with /dev/pcm (or audio?), but this, I'm afraid, is not very portable, is it?
Writing these questions down, I realize how "trivial" they are. I think it shows clearly that documentation is needed, though I understand MAD still has some way left to go for a 1.0 release (true?) and things will change. Have you considered to use a documentation tool (e.g. Doxygen) for the code?
I wondered if anybody has written a fairly decoupled C++ wrapper class. It doesn't have to be quite:
MP3File m("my_song.mp3"); m.play();
but at least closer to that than to the 2000+ line example included.
I don't think I've seen anything like this yet, but it sounds like it might be useful.
Absolutely. It's great that MAD provides a fine level of control, but a class like the above, with additional stop(), pause(), jump(int) functions is probably enough for many.
- Marius
Ive been having a bit of trouble trying to use mad in the normal manner I usually decode mpeg, because mad has introduced this stream api which I am finding getting in the way somewhat as it seems to dig into the lower levels of logic such as frame.c I usually do decoding 1 frame at a time in this manner:
Read 4 byte header Decode header Read single mpeg frame - size based on previous header. Decode single frame (then synth etc) to 1152 samples. Repeat
My own (fpu) decoder and intel's IPP for arm decoder allows this, but mad seems to want the 'next' frame with the stream stuff, which can mess up my logic a bit when I don't want to or cant give it another frame. Is it simple enough to do the above method with mad?
Thanks, Brett
Brett Paterson wrote:
Ive been having a bit of trouble trying to use mad in the normal manner I usually decode mpeg, because mad has introduced this stream api which I am finding getting in the way somewhat as it seems to dig into the lower levels of logic such as frame.c I usually do decoding 1 frame at a time in this manner:
Read 4 byte header Decode header Read single mpeg frame - size based on previous header. Decode single frame (then synth etc) to 1152 samples. Repeat
My own (fpu) decoder and intel's IPP for arm decoder allows this, but mad seems to want the 'next' frame with the stream stuff, which can mess up my logic a bit when I don't want to or cant give it another frame. Is it simple enough to do the above method with mad?
MAD uses a stream API because frames don't always begin and end at frame boundaries. Reading the main_data for Layer III is quite messy: in order to determine where the next frame's main_data begins (and thus, where the current frame's main_data must end), it's necessary to read the next frame's main_data_begin pointer, which lies after the next frame header. So, MAD requires the beginning of the next frame to be present in the stream.
And anyway, you don't really want to be grubbing around in the MPEG frame headers, do you? That's what the decoder library is *for*. A call to mad_header_decode() will neatly fill a data structure with all the info from the next frame header, and also set stream->this_frame and stream->next_frame with pointers to the frame's boundaries (ignoring main_data).
There's actually a second reason MAD needs the next frame present in the stream buffer, having to do with a technicality of Huffman decoding. If the Huffman data is corrupt, it's possible MAD may inadvertently read a few bytes past the end of the frame before discovering the error. To prevent this from crashing your application, MAD requires the stream buffer to extend a few bytes past the end of the current frame.
-rob
Marius Sundbakken wrote:
I did wrap the minimad example easily into a class, but I then got stuck. Firstly, it outputs to stdio. Can MAD actually output to the audio device or is that beyond the scope of the library (i.e. it's only a decoder). I figured I could replace stdio with /dev/pcm (or audio?), but this, I'm afraid, is not very portable, is it?
MAD itself is just a decoder. What you do with the decoded PCM is up to you.
If you want to play the PCM on an audio device, you'll need to use the audio API for your particular system. Some systems use OSS (Open Sound System) which is accessed via /dev/dsp or /dev/audio, with a set of ioctl()s to select the output format and sampling frequency. Other systems use the Sun audio interface which is similar but different. On Windows boxes, there is the waveOut API. Other systems now support ALSA, the Advanced Linux Sound Architecture. And so on. So no, sound output methods are not very portable.
`madplay' supports multiple audio APIs as well as a number of audio file formats through an audio output abstraction, implemented by the audio_*.c files.
Writing these questions down, I realize how "trivial" they are. I think it shows clearly that documentation is needed, though I understand MAD still has some way left to go for a 1.0 release (true?) and things will change. Have you considered to use a documentation tool (e.g. Doxygen) for the code?
I'm not a fan of automatic documentation systems, but yes, documentation is definitely something on the list to do.
MP3File m("my_song.mp3"); m.play();
I don't think I've seen anything like this yet, but it sounds like it might be useful.
Absolutely. It's great that MAD provides a fine level of control, but a class like the above, with additional stop(), pause(), jump(int) functions is probably enough for many.
While I think this might be useful, let me clarify by saying I probably won't be the one to write such a thing. Perhaps, however, you will. :-)
Cheers, -rob
Writing these questions down, I realize how "trivial" they are. I think it shows clearly that documentation is needed, though I understand MAD still has some way left to go for a 1.0 release (true?) and things will change. Have you considered to use a documentation tool (e.g. Doxygen) for the
code?
I'm not a fan of automatic documentation systems, but yes, documentation is definitely something on the list to do.
Why are you not a fan of automatic documentation systems? Would you rather make something like this by hand:
http://doc.trolltech.com/3.0/classes.html
Absolutely. It's great that MAD provides a fine level of control, but a class like the above, with additional stop(), pause(), jump(int) functions is probably enough for many.
While I think this might be useful, let me clarify by saying I probably won't be the one to write such a thing. Perhaps, however, you will. :-)
OK. Well, it's good to have that cleared up so I'm not waiting for anything. And yes, I'll probably make a class like that :-)
- Marius