From - Mon Nov  5 09:19:09 2001
Return-Path: <mad-dev-admin@lists.mars.org>
Received: from smtp01.wxs.nl ([195.121.5.15]) by po05.wxs.nl
          (Netscape Messaging Server 4.15) with ESMTP id GLLMFJ00.3DF for
          <jpsaman@wxs.nl>; Mon, 22 Oct 2001 10:33:19 +0200 
Received: from surveyor.mars.org ([216.98.134.66]) by
          smtp01.wxs.nl (Netscape Messaging Server 4.15) with ESMTP id
          GLLMFZ00.C2Z for <jpsaman@wxs.nl>; Mon, 22 Oct 2001 10:33:35 +0200 
Received: from surveyor.mars.org (localhost [127.0.0.1])
	by surveyor.mars.org (8.9.3/8.9.3/Debian 8.9.3-21) with ESMTP id BAA07654;
	Mon, 22 Oct 2001 01:32:07 -0700
Received: from mars.org (localhost [127.0.0.1])
	by surveyor.mars.org (8.9.3/8.9.3/Debian 8.9.3-21) with ESMTP id BAA07629
	for <mad-dev@lists.mars.org>; Mon, 22 Oct 2001 01:31:30 -0700
Message-Id: <200110220831.BAA07629@surveyor.mars.org>
X-Authentication-Warning: surveyor.mars.org: Host localhost [127.0.0.1] claimed to be mars.org
From: Rob Leslie <rob@mars.org>
To: mad-dev@lists.mars.org
Subject: Re: [mad-dev] Some information about programming with MAD (in synchronous mode)
In-reply-to: Your message of "21 Oct 2001 16:13:19 EDT."
	<1003695199.24019.56.camel@pisces>
Mime-Version: 1.0 (generated by tm-edit 7.106)
Content-Type: text/plain; charset=US-ASCII
Sender: mad-dev-admin@lists.mars.org
Errors-To: mad-dev-admin@lists.mars.org
X-BeenThere: mad-dev@lists.mars.org
X-Mailman-Version: 2.0.1
Precedence: bulk
List-Help: <mailto:mad-dev-request@lists.mars.org?subject=help>
List-Post: <mailto:mad-dev@lists.mars.org>
List-Subscribe: <http://www.mars.org/bin/mailman/listinfo/mad-dev>,
	<mailto:mad-dev-request@lists.mars.org?subject=subscribe>
List-Id: MAD developer's mailing list <mad-dev.lists.mars.org>
List-Unsubscribe: <http://www.mars.org/bin/mailman/listinfo/mad-dev>,
	<mailto:mad-dev-request@lists.mars.org?subject=unsubscribe>
List-Archive: <http://www.mars.org/mailman/public/mad-dev/>
Date: Mon, 22 Oct 2001 01:31:30 -0700
X-Mozilla-Status: 8011
X-Mozilla-Status2: 00000000
X-UIDL: 1879-1001307689

Joe Drew wrote some good info on the MAD high-level API that I hope will be
helpful to others.

By way of clarification, MAD also has a low-level API which does not use
callbacks. You can control the entire decoding process yourself more or less
as follows:

  /* load buffer with your MPEG audio data */

  mad_stream_buffer(&stream, buffer, buflen);

  while (1) {
    mad_frame_decode(&frame, &stream);
    mad_synth_frame(&synth, &frame);

    /* output PCM samples in synth.pcm */
  }

This is vastly simplified, but it shows the general idea. mad_frame_decode()
decodes the next frame's header and subband samples. mad_synth_frame() takes
those subband samples and synthesizes PCM samples.

It is also possible to call mad_header_decode() before mad_frame_decode().
This just gives you the frame's header info, in case that's all you want, or
perhaps to help you decide whether you want to decode the rest of the frame.

As Joe mentions, each of the stream, frame, and synth structs needs to be
initialized and "finished" before and after use:

  struct mad_stream stream;
  struct mad_frame frame;
  struct mad_synth synth;

  mad_stream_init(&stream);
  mad_frame_init(&frame);
  mad_synth_init(&synth);

  /* ... */

  mad_synth_finish(&synth);
  mad_frame_finish(&frame);
  mad_stream_finish(&stream);

You can work with just a struct mad_header instead of a struct mad_frame if
you only want to decode frame headers.

Joe writes:
> MAD always outputs 32-bit (well, mad_fixed_t) little-endian data. Take
> this into account when outputting samples to the sound card.

This isn't quite right: the mad_fixed_t type is not necessarily little-endian.
It's the same endianness as the native integer types. Also, it's only
guaranteed to be *at least* 32 bits wide.

The fixed-point sample format is important to understand, and I recommend
reading the comments in libmad/fixed.h. The thing to remember when converting
MAD's fixed-point integer samples to 16-bit PCM (or whatever) is that MAD
encodes samples as numbers in the full-scale range [-1.0, +1.0) where the
binary point is placed 28 (MAD_F_FRACBITS) bits to the left of the integer.
However, you need to be prepared to handle clipping as some numbers may be
less than -1.0 (-MAD_F_ONE) or greater than or equal to +1.0 (MAD_F_ONE, aka
1 << MAD_F_FRACBITS).

> Information on the other (error, filter, message) functions would be
> appreciated, though I think in knowing this information anyone should be
> able to puzzle it out.

In the high-level API, the error callback function is called whenever a
decoding error occurs. The error number is in stream->error.

The filter callback function is called after decoding a frame, but before
synthesis. Here it is possible to modify the frame's subband samples, for
example to perform a uniform attenuation/amplification, or to do other special
processing in the frequency domain.

The message callback function is only used with MAD_DECODER_MODE_ASYNC, and is
called whenever the parent process sends a message via mad_decoder_message().
This callback can generate a reply by overwriting the message buffer that is
passed to it. (The size of the reply must be the same or smaller than the
message.)

Cheers,
  -rob
