

                    AudioMPEG V0.16, an audio MPEG decoder


Introduction


This module is supplied for free and without any warranty. No responsibility
will be taken for damages caused by it. You have been warned, if it scrambles
your harddisk or lets your monitor implode - it is all your own fault.

Big thanks go to Robin Watts from Warm Silence Software for helping with
his Callback support code for calling C functions back.

If you want to use this module in your own programs, you should ensure the
following:

1. You should install the module to System:Modules as your program will
   not be the only one to use this module
2. You should credit Peter in the info window of your program or in another
   way if it has nothing like that


Contacts


If you want to contact me:

email: Andre.Timmermans@sbs.be

snail mail: Andr Timmermans
            Rue du Vert Coron, 17
            7600 Pruwelz
            Belgium

If you want to contact Peter (who made the first versions):

email: teich-p@rcs.urz.tu-dresden.de

snail mail: Peter Teichmann
            R.-Haym-Str. 20
            06110 Halle
            Germany


Hardware requirements


The module is only suitable for Strongarm RiscPCs, not only because of the
speed but also because it uses long multiply instructions.

You should also look at the file c.Test. This is my test program for the
module. Don't look at style and so on...


Interface


The module is used in the following way:

1. Call AudioMPEG_Init. The module will allocate 2 dynamic areas for 2
   circular buffers (input and output) and return the pointers to the
   buffers.

2. Start feeding the data of your stream into the input buffer, until
   a call to AudioMPEG_Info does not return 0 anymore. Read the info
   about the stream returned by the AudioMPEG_Info call.
   
3. Continue feeding stream data into the input buffer and start reading the
   decoded sample data (signed 16bit) from the output buffer.

4. If the stream is finished, empty the output buffer before calling
   AudioMPEG_Quit
   
Decoding Speed


The module decodes as fast as it can provided there is enough space in the
output buffer, and input data is fed fast enough into the input buffer. On
200 MHz Strongarm systems it reaches nearly 3x realtime speed for a 128kbits/s
frame rate. If you want to use it for realtime playback and do not want it to
use all your CPU time, simply only read in playback speed from the output
buffer, and read only small amounts at once. The way you read from the output
buffer has a direct influence at the usability of the computer.                



                                 SWI Interface

   
Warning: on SWI exit flags are corrupted.


AudioMPEG_Init (0x52180)


  On entry

    R0 = code number which is needed to be allowed to call all other SWIs
         and which identifies your stream. Ensure it is unlikely for other
         tasks to use the same code, for example by using as code a pointer
         to one of your data structures.

  On exit

    If the module is already in use (no free buffers):
      R0 = -1
    Otherwise:
      R0 = pointer to input buffer (dynamic area)
      R1 = pointer to sound output buffer (dynamic area)

This SWI needs to be called to initialize the decoding procedure, it
allocates input and output buffer and returns their addresses.

The input buffer looks like this (C syntax):

typedef struct {
  int size;		//size of data in bytes (64*1024)
  int start;		//start position of data in the buffer
  int free;		//start position of free space in the buffer
  int finished;		//needs to be set to 1 if the input is finished
  int dummy[12];
  char data[];		//array of <size> bytes
} mp3buf;

and the output buffer like that:

typedef struct {
  int size;		//size of data in 16 bit words (512*1024)
  int start;		//start position of data in the buffer
  int free;		//start position of free space in the buffer
  int finished;		//will be set to 1 if the output is finished
  int dummy[12];
  short data[];		//array of <size> 16 bit words
} sndbuf;

Both buffers are circular buffers, and they are not allowed to be completely
filled. That means if start is equal to free, the buffer is empty.
As you see they are nearly identical, the only difference is that the input
buffer counts bytes (8bit), and the output buffer counts shorts (16bit).

The program using the AudioMPEG decoder module is only allowed to change
<free> in the input buffer if it puts new data into the input buffer. It must
ensure that the input buffer never is completely filled. If the input
stream is finished it should set <finished> in the input buffer to 1.
It is also allowed to change <start> in the output buffer if it reads audio
data from the output buffer. Under nocircumstances it should change <start>
in the input buffer or <free> in the output buffer.


AudioMPEG_Quit (0x52181)


  On entry

    R0 = the code number, this is to provide a bit safety

  On exit

    If all went ok:
      R0 = 0
    If the code was wrong or there is no stream to quit:
      R0 = -1

This SWI will remove input and output buffer and finish decoding.


AudioMPEG_Info (0x52182)


  On entry

    R0 = the code number

  On exit

    If all went ok:
      R0 = pointer to an info-structure about the stream
    If the module still does not know the information required, if that
    happens you should wait a bit or start feeding data into the module
    If you not already did it:
      R0 = 0
    If an error occured:
      R0 = 1
    If the code was wrong or there is no stream that gets decoded:
      R0 = -1

This SWI will return some information.

info-structure:

typedef struct {
  int version;		// 0 for MPEG-2 LSF, 1 for MPEG-1, 2 for MPEG-2.5 LSF
  int layer;		// Layer number
  int bitrate;		// kbits/sec
  int samplerate;	// samples/sec 
  int channels;		// 1=mono, 2=stereo
} mp3info;


AudiMPEG_Clear (0x52183)


  On entry

    R0 = the code number
    R1 = Bit 0 set -> input buffer cleared
         Bit 1 set -> output buffer cleared
         Bit 2 set -> mp3info is reset (otherwise the frame header seeking
                      routines continue to check that version, layer, sample
                      rate and channels remain identical while validating
                      the new headers).

  On exit

    -


AudiMPEG_Configure (0x52185)


  On entry

    R0 = the code number
    R1... = values

  On exit

    R1... = values

  Codes

    0, R1 = input buffer size in KBs, 0 to read
    1, R1 = output buffer size in KBs, 0 to read 


                                    History

Peter Teichmann
0.01	17.03.1999	first released version
0.02	18.03.1999	improved handling of errors in streams
0.03	22.03.1999	fixed "bug" with input buffer handling
0.04			reorganized memory handling
0.05	01.04.1999	fixed bug with layer 2 introduced in 0.04
0.06	08.04.1999	better balanced cpu usage
0.07	08.04.1999	fixed bug that could cause an output buffer overflow
			under some circumstances
0.08	12.04.1999	fixed bug with error handling if sync can not be
			found
0.09	04.05.1999	uses about 5% less CPU time, dct36 coded in
			assembler
0.10	05.05.1999	improvements in hufman_decode save another 3%
			of CPU time
0.11	22.07.1999	added SWI for clearing buffers

Andr Timmermans
0.12	01.05.2000	Made some routines faster:
			- III_hufman_decode
			- III_dequantize_sample
			- III_reorder
			- III_stereo
			Rewrote header seeking and some related routines, which
			makes the player more reliable.
			Fixed bug in bytes keeping from previous frame (layer3).
			Added some support for MPEG 2.5.
0.13	05.05.2000	Fixed overflow in dct64 part of subbandsynthesis.
			Reorganised the file structure.
			Modified bs_keepBytes to insert null bytes in main data
			buffer when number of bytes to keep from previous
			frame is negative (much better for file positionning).
	07.07.2000	Made out_fifo and III_huffman_decode faster.
			Modified III_hybrid for MPEG 2.5.
			Modified bg_task so that callbacks are still generated
			when output is finished (so that calling clearing SWI
			allows new input will be decode at the end of the old
			input).
0.14	09.09.2000	Error in original DCT64, there should be no >> 1
			in the final stage.
	11.05.2000	Forgot to read CRC in case of layer 3, implemented
			the check for layer 3.
0.15	22.05.2000	The tests files for layer 2 work without clipping
			if I add 1 to the scalefactor indexes (this scales
			the output by 2*exp(-1/3)). Having checked several
			sources I think it must be a bug in the encoder used
			for these files, anyway this allows me to remove the
			division by 2 present to avoid clipping.
	23.05.2000	I have disabled CRC check because of a stupid MP3
			encoder which leaves the CRC field to 0!!!!
0.16	29.09.2000	Skip RIFF-Wave and ID3v2 headers in first buffer.
			Return bitrate as the mean bitrate of 2 frames
			as some encoders alternate 2 bitrates (the bitrate
			is still incorrect for VBR files).
	30.09.2000	The module can decode several streams at once:
			two actually, because for more even the SA remains
			processing callbacks and never return in user mode.
	27.10.2000	Added configuration of buffer sizes.
	31.10.2000	dct12 routine could give different results for the same
			input, seems a bug in the Acorn C compiler. Moving the
			declaration of every variable to the beginning of the
			procedure solved the problem.