AMPlayer

Introduction and Overview

AMPlayer is a module for playing Audio MPEG data through the computers sound output, or to a streaming destination. Where sound is to be output, it will select the 8 or 16 bit output depending on the normal configuration (and availability).

The module has been designed so it is easy to make other frontends, or add support for the module to existing player-frontends.

The AMPlayer module supports MPEG version 1, 2 and 2.5, for layers I, II and III. Mixed data may be safely used with the module. The AMPlayer is resilient when faced with corrupt data, and will skip unknown data in a safe manner. Streams of data may contain ID3v2 tags, and may be terminated by ID3v1.1 tags. ID3v2 footers are skipped and not parsed.

Terminology

MPEG audio data is used as a generic term, covering MPEG 1/2/2.5 audio data, using layers I, II, or III.

The term VBR is used to mean 'Variable Bit-Rate'. VBR data is data which contains non-constant bitrate through the track. It is still assumed that the MPEG version and layer remain constant.

Technical Details

In order to play MPEG audio data, AMPlayer processes data in the background using callbacks. This allows the module to continue in, and out of the desktop with no supervision from any other component.

MPEG data input methods

MPEG audio data can come from either a file, or from a data stream. When operating in both of these modes, the functionality of AMPlayer is similar.

File playback

During file playback, the AMPlayer module continually takes data from the file as it needs it. File data is buffered by the module.

File playback will initially read the ID3v1.1 tags from the file if present, and store these for later retrieval by front ends. During playback, ID3v2 tags will be processed (if enabled) and services issued announcing their arrival.

Streaming playback

When streaming, an application must feed data to AMPlayer in a timely fashion. Data is supplied to a ring of buffers which are drained individually by the AMPlayer module. As each buffer is emptied it is the job of the streaming application to provide further data or to close the stream.

The player will take data from buffers supplied by the streaming application in the order given. When the end of a buffer is reached, the player will continue seamlessly to the next buffer. There is no necessity to provide frame-aligned data to the buffers. Where frames straddle the buffer end, it may be necessary for the player to retain the buffer until the frame can be processed. Because of this streaming application must supply at least two buffers and at least 2000 bytes in total for streaming playback. When a buffer is no longer required, a service will be issued to inform the streaming application.

Metadata can be supplied to the AMPlayer module during streaming. This data will be inserted in-line with the stream and made available at the point at which it is played. This data is incompatible with ID3v1.1 data, and with ID3v2 data. During playback, ID3v1.1 and ID3v2 tags are skipped. ID3v2 tags larger than the total size of the ring of buffers will cause the player to stall.

File output methods

AMPlayer is able to output to a number of different destinations. Where the destination is the physical sound system (8bit, 16bit or SharedSound), the interface to the module is unchanged.

8 bit sound output

All sound output is generated as 16bit-stereo data. When only the 8bit sound system is available, a lookup table will be used by the output code to generate the correct logarithmic output. This will result in a slight degradation in quality, but only to the level of the system accuracy. The overall frequency of the sound system will track that of the sound being generated to the limits of the sound system itself. This may result in further inaccuracies.

Because AMPlayer takes over the entire sound system to handle its output, no other sounds (for example, the system beep) will be heard in this mode.

16 bit sound output

Where 16 bit sound is available, but SharedSound support is not, the standard 16 bit sound drivers will be used. The overall frequency of the sound system will track the sound being output to the limits that it is capable.

In this mode, AMPlayer uses the entire 16 bit sound system. As a consequence, no other sound will be generated whilst AMPlayer is playing.

SharedSound output

Where the SharedSound module is available, it will be used by the AMPlayer module. When playing through the SharedSound module, the frequency of the sound system is unaffected by playback. In this mode, the sound most closely matches that which would be generated within the limits of the sound system and its configuration. Importantly, if the overall sound system frequency is configured lower than any of the clients of SharedSound, the output quality will suffer.

Sound from other sources is unaffected by AMPlayer playback, allowing other clients to share the sound system.

Streaming output

AMPlayer can be used to stream generated sound data to any other destination through the use of the streaming output interface. In this mode, the sound system is totally unaffected by processing performed by the module. The streaming interface can obtain the frequency at which the data being read should be played through this interface.

Multiple instantiation

AMPlayer is able to function as a decoder for multiple clients. It achieves this by multiple instantiation of the AMPlayer module. The SWI SWI AMPlayer_Instance manages the instances for clients such that it is not necessary for every client to duplicate the same code.

In addition to this, all AMPlayer SWIs may have bit 31 of their flags set to indicate that the operation should be directed to the instance of the AMPlayer module held in R8. This allows background processes to communicate with just the instance to which they are interested. When services are issued to notify clients of events from the decoder, R8 will be set to the instance handle that generated the service.

If a SWI is not directed at a particular instance, then the currently preferred instance will deal with the request.

User front ends

Front end applications which are controlled by the user, queue tracks, or just monitor the state of the player should only communicate with the base instance of AMPlayer. This allows them to function with any number of other concurrent utilities.

Under most circumstances it is advisable that front ends not worry about the existance of multiple instances and merely communicate with the currently preferred instance. This allows for the greatest flexibility with clients selecting alternative instances as the private for control if necessary

Plugins

Plugins should be aware of the existance of plugins, and only register themselves with the base instance unless explicitly requested otherwise. Because of their nature, plugins are only really suitable for the base instance, or a secondary instance which is being mixed with the base.

* Commands

*Commands will always be issued to the currently 'preferred' instance. In general this will be the base, but under specialised circumstances another instance may be preferred. The AMPlayer module itself will retain the current preferred instance through all operations, and therefore the only mechanism by which another AMPlayer instance may be the preferred is by explicitly issuing the relevant OS_Module, or by issuing a * Command directly to an instance.

Data structures

In order to communicate with AMPlayer, a number of data structures are required. These provide information about the streams being processed.

File Information Block

The File Information Block provides information about the file currently being played.

OffsetRequired flagsContents
0noneflags :
Bit(s)Meaning
0Total time valid
1Elapsed time valid
2ID3 tag info pointers valid
3VU values valid
4Error message pointer valid
5Next filename pointer valid
6File uses variable bit rate, high and low rates valid
7ID3v1.1 track valid
8Data comes from stream
9-31Reserved, must be zero
4nonebuffer usage ratio in % (*)
8bit 0projected total time in cs
12bit 1time elapsed in cs
16bit 2pointer to ID3 song title
20bit 2pointer to ID3 artist
24bit 2pointer to ID3 album name
28bit 2pointer to ID3 year string
32bit 2pointer to ID3 comment
36bit 3left channel VU
40bit 3right channel VU
44nonemain volume (0..127) (*)
48bit 4pointer to most recent error/warning message, or 0 if no message is pending
52bit 5pointer to filename of the "next" file, or 0 if no file currently queued
56bit 2ID3v1 genre (a number)
60bit 2+7ID3v1.1 track (a number), or 0 if not specified
64bit 6lowest bitrate used
68bit 6highest bitrate used

Fields marked with (*) are not valid when returned from an AMPlayer_FileInfo call.

Projected total time

The projected total time for the track is based on the bitrate used by the file so far (unless supplied in another manner). It is assumed that the bitrate remains constant for this calculation. The total time given will be wrong if :

  • the file size is unknown, e.g. if playing a stream
  • the frame type will later change in a way that alters the number of bytes per frame (eg change in bit rate)
  • the data is partially corrupt or contains skippable data (ID3v2 tags, rogue unsynchronised data, etc)

None of the above exceptions are true in the vast majority of MPEG files. The first case is determined by the module, and bit 0 of the flags will be clear. The second case cannot be known in advance, and it will also affect the elapsed time. No matter what happens, the time will always move forward, it just might not be counting centiseconds in these cases.

Within VBR files generated by the Xing encoder (or applying a Xing compatible header) the total time will be calculated from the header. If the file has been truncated, this time will be estimated based on the information in the header.

ID3v1 genre values

ID3v1 genre values are defined elsewhere. See http://www.id3.org for more details.

ID3v1.1 track numbers

ID3v1.1 is an extension to ID3 which, if present, declares the track number within an album.

VU-var values

When the VU level is available, it is a number between 0 and 255. The value is from -42 to 0 dB, in 1/6th dB steps. The level is the peak of the average level since last calling this SWI.

Bitrate values

Where VBR Audio MPEG data is being processed, the high and low bitrate values are used to indicate the current known limits of the data.

Frame Information Block

The Frame Information Block provides information about the most recent frame processed.

OffsetContents
0MPEG version as 3 ASCII chars and a 0 terminator, e.g. "2.0"
4layer type (1..3). 0 is unknown layer
8sampling frequency in Hz
12bitrate in kbit/sec
16mode :
ModeMeaning
0Stereo
1Joint-stereo
2Dual channel
3Single channel
20number of channels
24frame flags :
Bit(s)Meaning
0Copyright
1Original
2CRC
28pointer to left channel DCT array (*)
32pointer to right channel DCT array (*)

Fields marked with (*) are not valid when returned from an AMPlayer_FileInfo call.

Plugin Information Block

The Plugin Information Block is used when registering and enumerating plugins present.

OffsetContents
0Filter name, padded with 0's (16 chars)
16Filter author, padded with 0's (32 chars)
48Filter version, padded with 0's (8 chars)

IDTag Information block

The IDTag Information Block is passed to the service handlers for ID3v2 processing. It provides information on the overall structure of the ID3v2 tag.

OffsetContents
0Version of original tag data (major * 256 + minor)
4Header flags :
Bit(s)NameMeaning
7HEADERF_UNSYNCHRONISEDData was unsynchronised
6HEADERF_EXTENDEDHEADERExtended header was present (ignored at present)
5HEADERF_EXPERIMENTALTag is experimental (should never be seen by decoder)
4HEADERF_FOOTERFooter was included (has been ignored)
otherreserved, must be 0

IDFrame Information block

The IDFrame Information Block is passed to the service handlers for ID3v2 processing. It provides information on the specific ID3v2 frame being processed.

OffsetContents
0frame number (within this tag)
4frame name (0 terminated)
12flags for this frame :
Bit(s)NameMeaning
0FRAMEF_HASLENGTHLength field was given
1FRAMEF_UNSYNCHRONISEDFrame was unsynchronised
2FRAMEF_ENCRYPTEDFrame was encrypted (N/I)
3FRAMEF_COMPRESSEDFrame was compressed
6FRAMEF_GROUPFrame is one of a group
12FRAMEF_READONLYFrame should not be edited
13FRAMEF_FILEDISCARDDiscard frame if file changed
14FRAMEF_TAGDISCARDDiscard frame if tag changed
otherreserved, must be 0
16Pointer to frame data (decompressed, de-unsynchronised)
20Frame data length
24Encryption type, or -1 if not given
28Compressed length, or -1 if not compressed
32Frame group, or -1 if not given

Flags will be promoted to those used by ID3v2.4, if they are of a lower version than that.

Frame data will be terminated by a 0 (not included in the length) for ease of decoding text fields.

System variables

AMPlayer$Buffer$*
Default AMPlayer output buffer sizes

When starting playback, AMPlayer checks the file being played against the variable AMPlayer$Buffer$part path, where part path is the longest component of the path name which is set as a system variable. For example, if you were to play ADFS::Music.$.Lennon.Imagine and had the system variables AMPlayer$Buffer$ and AMPlayer$Buffer$ADFS set, the latter would be used in preference to the former.

The value given is used to determine the number of 'blocks' of output data that will be buffered in the 'Antishock buffer'. The larger this buffer is, the longer the system can be busy before playback ceases. Larger buffers have a greater initial load on the machine as more data is decoded to fill the buffer when the first file is played.

A 'block' is an arbitrary size, currently around 4.5K. The reason for supplying a buffering value in blocks is to provide a more robust means of storing the buffering size. If in future the block size changes, the amount of time that that buffer corresponds to will remain constant (for a given frequency of data).

In the case of streams, the variable AMPlayer$Buffer$Stream will be used to determine the initial output buffer size.

AMPlayer$FileBuffer
Input file buffer size

When starting playback, AMPlayer allocates a buffer for data from the file. Whereas AMPlayer$Buffer$* determines the output buffer size, AMPlayer$FileBuffer determines the input buffer size. If you are accessing files on a filing system which has a slow start up time, (for example networks or CDs) you may wish to set this higher value than the default.

The value this variable is set to is in Kilobytes. Unlike the output buffer, the input cannot be measured in blocks because that would require knowing in advance the data contained in the blocks.

For Streams AMPlayer$FileBuffer has no meaning and is not used.

AMPlayer$Volume
Volume level to use when AMPlayer starts

When AMPlayer initialises, it reads AMPlayer$Volume to determine the initial volume. This is a linear volume level, with a maximum at 127, a minimum at 0, and a default level of 112.

Whenever the volume level is changed in the base instance, this system variable is updated to reflect this. When an instance starts (in the same manner as the base AMPlayer instantiation intialising), it reads the state of AMPlayer$Volume and sets its volume to that specified. The result of this is that at any time that an instance is created it starts with the same volume level as the base instance. Should an instance wish to control the volume level of its instance, it should do so with care and pay attention to the initial volume level where appropriate. For example, if the user is playing their base instance at a volume level of 12, they will not wish to have a new instance playing at 112 unless they specifically requested it.

AMPlayer$DecimationThreshold
Select decimation threshold to use when AMPlayer starts

When AMPlayer initialises, it reads AMPlayer$DecimationThreshold to determine the initial decimation threshold. This threshold is used to determine during playback whether decimation of input data is used to provide output data.

Whenever the decimation threshold is changed in the base instance, this system variable is updated to reflect this. When an instance starts (in the same manner as the base AMPlayer instantiation intialising), it reads the state of AMPlayer$DecimationThreshold and sets its threshold to that specified. The result of this is that at any time that an instance is created it starts with the same threshold as the base instance.

When decimating input data, the upper half of the frequency data is discarded, resulting in a frequency of half that normally required for the input data. This reduces the processing required by the data, and therefore reduces the load that AMPlayer places on the system. This speed increase is to the detriment of the quality of the output data.

Service calls

Service_AMPlayerService Call &52E00
Events issued by AMPlayer
R0=reason code :
ReasonMeaning
0 AMPlayer module is initialising
0 AMPlayer module is initialising
1 AMPlayer module is dying
2 Playback is about to start
3 Playback has stopped
4 Playback has moved on to another track
5 ID3v2 tag has been found
6 One or more buffers previously passed to an AMPlayer have been marked as free
R1=service call number
R2 - RR7=dependant on reason code
R8=instance handle of issuing instance, or 0 for the base
R1preserved

Service_AMPlayer is issued by the AMPlayer module to inform clients of a change in state, or other information about playback. Consult the individual reason codes for more details.

Service_AMPlayer 0InitialisingService Call &52E00
AMPlayer module is initialising
R0=reason code
R1=service call number
R8=instance handle of issuing instance, or 0 for the base
R1preserved

Service_AMPlayer 0 is issued by the AMPlayer module when it initialises. Clients wishing to add plugins to the output of the module should register themselves.

Service_AMPlayer 1DyingService Call &52E00
AMPlayer module is dying
R0=reason code
R1=service call number
R8=instance handle of issuing instance, or 0 for the base
R1preserved

Service_AMPlayer 1 is issued by the AMPlayer module (or an instance of AMPlayer) when it is killed. Clients wishing to only run during the lifetime of AMPlayer should either become dormant or terminate.

Service_AMPlayer 2StartService Call &52E00
Playback is about to start
R0=reason code
R1=service call number
R8=instance handle of issuing instance, or 0 for the base
R1preserved

Service_AMPlayer 2 is issued by the AMPlayer module when it is about to stat playing a track. Clients wishing to monitor the progress of the track in the background, or to schedule new tracks may wish to watch for this service.

Service_AMPlayer 3StopService Call &52E00
Playback has stopped
R0=reason code
R1=service call number
R8=instance handle of issuing instance, or 0 for the base
R1preserved

Service_AMPlayer 3 is issued by the AMPlayer module when it has stopped playing and moved to state 'Dormant'.

Service_AMPlayer 4ChangeService Call &52E00
Playback has moved on to another track
R0=reason code
R1=service call number
R8=instance handle of issuing instance, or 0 for the base
R1preserved

Service_AMPlayer 4 is issued by the AMPlayer module when it has changed to playing the next track queued. Clients wishing to track the file being played should watch for this service.

Service_AMPlayer 5ID3v2Service Call &52E00
ID3v2 tag has been found
R0=reason code
R1=service call number
R2=pointer to IDTag Information Block
R3=pointer to IDFrame Information Block
R8=instance handle of issuing instance, or 0 for the base
R1preserved

Service_AMPlayer 5 is issued by the AMPlayer module during playback, when an ID3v2 tag has been encountered. Clients wishing to process ID3v2 as they arrive should watch for this service.

Service_AMPlayer 6StreamBuffersAvailableService Call &52E00
One or more buffers previously passed to an AMPlayer have been marked as free
R0=reason code
R1=service call number
R2=stream handle
R3=flag word (currently 0)
R8=instance handle of issuing instance, or 0 for the base
R1preserved

Service_AMPlayer 6 is issued by the AMPlayer module during playback from an AMPlayer stream for which service call reporting was requested at creation time when one or more blocks previously passed to that stream have been marked as being freed. Clients wishing to be informed when their blocks are no longer being held by the module should watch for this service.

SWI calls

AMPlayer_PlaySWI &52E00
Plays or queues a file
R0=flags :
Bit(s)NameMeaning
0QueuePlaces the named file in the queue of tracks to play. If there is no file currently playing, the behaviour is exactly as if bit 0 were clear.
1CueStarts the named file immediately, but paused at the first frame. Use SWI AMPlayer_Pause to start playback.
2Transient Creates a new instance, sets the volume level, marks the instance as transient, and starts the named file within that instance.
3-30Reserved, must be 0.
31R8 contains the instance handle to which this call should be directed.
R1=pointer to filename
R2=if bit 2 of R0 set:
volume level to set, or -1 for default
R3=if bit 2 of R0 set:
pointer to instance name, or 0 to name automatically
R8=if bit 31 of R0 set:
instance handle to direct at, or 0 for the base
R0=if bit 2 of R0 set:
handle of created instance
Interrupts are undefined
Fast interrupts are enabled
Processor is in SVC mode
SWI is not re-entrant

This SWI is used to play or queue a file for playback. When starting play transiently, the current play is unchaged and only the new instance is affected.

AMPlayer_StopSWI &52E01
Stops playback
R0=flags :
Bit(s)NameMeaning
0Cut Playback continues with the queued file if any. If no file is queued, playback will stop.
1-30Reserved, must be 0.
31R8 contains the instance handle to which this call should be directed.
R8=if bit 31 of R0 set:
instance handle to direct at, or 0 for the base
None
Interrupts are undefined
Fast interrupts are enabled
Processor is in SVC mode
SWI is not re-entrant

This SWI is used to stop playback, or start the skip to the queued file.

AMPlayer_PauseSWI &52E02
Pauses playback
R0=flags :
Bit(s)NameMeaning
0Resume Resumes playback.
1-30Reserved, must be 0.
31R8 contains the instance handle to which this call should be directed.
R8=if bit 31 of R0 set:
instance handle to direct at, or 0 for the base
None
Interrupts are undefined
Fast interrupts are enabled
Processor is in SVC mode
SWI is not re-entrant

This SWI is used to pause or resume playback. When paused, decoding to the output buffer continues, but at a much reduced rate. There is no sound output.

Pause mode may also be cancelled by stopping. If SWI AMPlayer_Stop is used to cut to the next file, or if a different file is started, pause mode will continue to be in effect, freezing the new file at the start of the file. This can be used to ensure that playback starts at the instant of calling AMPlayer_Pause (as opposed to calling SWI AMPlayer_Play, which can have a delay while opening the file etc).

AMPlayer_LocateSWI &52E03
Locates a position in the playback
R0=flags :
Bit(s)Meaning
0-30Reserved, must be 0.
31R8 contains the instance handle to which this call should be directed.
R1=target time in centi-seconds
R8=if bit 31 of R0 set:
instance handle to direct at, or 0 for the base
None
Interrupts are undefined
Fast interrupts are enabled
Processor is in SVC mode
SWI is not re-entrant

This SWI locates the position of the target time, and continues playback (or pausing) from there. This has no effect unless the status is either Playing, Locating or Paused. This may take some time, and the playback buffer may empty (which will mute the sound).

The time given here corresponds to the elapsed time returned from SWI AMPlayer_Info. This is true even when the elapsed time is wrong. So when, at time X, the Info call returns the wrong time Y, giving time Y to this call will still start playing at the right time X.

Playback can only start on a frame boundary, so the resolution of the start point is around 2 cs (for 128kbit/sec, 44.1kHz frames).

AMPlayer_InfoSWI &52E04
Return information on the state of playback
R0=flags :
Bit(s)Meaning
0-30Reserved, must be 0.
31R8 contains the instance handle to which this call should be directed.
R8=if bit 31 of R0 set:
instance handle to direct at, or 0 for the base
R0=Player status :
StateMeaning and registers
0Dormant
R1 - R4 preserved
1Starting
R1 = pointer to filename
R2 - R4 preserved
2Locating
R1 = pointer to filename
R2 = pointer to File Information Block, or 0 if not set up yet
R3 = pointer to Frame Information Block, or 0 if not set up yet
R4 = target time
3Playing
R1 = pointer to filename
R2 = pointer to File Information Block, or 0 if not set up yet
R3 = pointer to Frame Information Block, or 0 if not set up yet
R4 preserved
4Pausing
R1 = pointer to filename
R2 = pointer to File Information Block, or 0 if not set up yet
R3 = pointer to Frame Information Block, or 0 if not set up yet
R4 preserved
5Stopping
R1 = pointer to filename
R2 - R4 preserved
6Changing
R1 = pointer to filename
R2 - R4 preserved
7Cueing
R1 = pointer to filename
R2 - R4 preserved
Interrupts are undefined
Fast interrupts are enabled
Processor is in SVC mode
SWI is not re-entrant

This call will return information about the current state of the player.

When locating, the current time can be read from the file info block, as it moves toward the target time returned in R4.

This call might be made from BASIC with :

SYS "AMPlayer_Info",,"" TO ,Filename$,FIB%

This will set Filename$ to either "" or the filename. Similarily, FIB% will be 0 if there is no info at this stage, or a pointer to it if there is.

There is a brief period when the status might be returned as Locating (2) or Playing (3), but where there is no valid FIB or FRIB, because the first frame has yet to be read.

AMPlayer_ControlSWI &52E05
Configure the operation of the player
R0=flags :
Bit(s)Meaning
0-7reason code :
ReasonConfiguration
0 Read or write the volume level
1 Read or write the output buffer size
2 Set SVC stack check level
3 Control the ID3v2 tag processing facilities
4 Read or write the 'transience' flag
5 Read or write the decimation threshold
8-30Reserved, must be 0.
31R8 contains the instance handle to which this call should be directed.
R8=if bit 31 of R0 set:
instance handle to direct at, or 0 for the base
None
Interrupts are undefined
Fast interrupts are enabled
Processor is in SVC mode
SWI is not re-entrant

This SWI is used to configure various aspects of the AMPlayer module's operation.

AMPlayer_Control 0VolumeSWI &52E05
Read or write the volume level
R0=flags :
Bit(s)Meaning
0-70 (reason code)
8-30Reserved, must be 0.
31R8 contains the instance handle to which this call should be directed.
R1=new volume level (0-127), or -1 to read current level
R8=if bit 31 of R0 set:
instance handle to direct at, or 0 for the base
R1=old volume level
Interrupts are undefined
Fast interrupts are enabled
Processor is in SVC mode
SWI is not re-entrant

This SWI is used to read or write the main volume level of the player.

AMPlayer_Control 1BufferSizeSWI &52E05
Read or write the output buffer size
R0=flags :
Bit(s)Meaning
0-71 (reason code)
8Use blocks, rather than bytes
9-30Reserved, must be 0.
31R8 contains the instance handle to which this call should be directed.
R1=new buffer size in bytes or blocks, or -1 to read current size
R8=if bit 31 of R0 set:
instance handle to direct at, or 0 for the base
R1=old size in bytes or blocks
Interrupts are undefined
Fast interrupts are enabled
Processor is in SVC mode
SWI is not re-entrant

This control call is used to read or write the size of the audio buffer used by AMPlayer to store decoded data. The size can be specified in bytes or in blocks. It is recommended that you use the blocks size to be compatible with the system variable usage, and to ensure that similar amounts of data are buffered in future.

If the buffer isn't currently created, this controls how large it will be when it eventually is. If it exists, OS_ChangeDynamicArea is used to change the size. This may fail with an error, even if some of the job was done (this can happen when reducing the size, as the amount that can be released depends on what is currently being played). This effect is greatly reduced in AMPlayer 1.29 and later.

If it succeeds, the sound may be broken up slightly. On versions of AMPlayer prior to 1.29, this will always cause at least one 'jump' in the playback.

AMPlayer_Control 2StackSizeSWI &52E05
Set SVC stack check level
R0=flags :
Bit(s)Meaning
0-72 (reason code)
8-30Reserved, must be 0.
31R8 contains the instance handle to which this call should be directed.
R1=new level (in words), or 0 for default
R8=if bit 31 of R0 set:
instance handle to direct at, or 0 for the base
R1=old level
Interrupts are undefined
Fast interrupts are enabled
Processor is in SVC mode
SWI is not re-entrant

This SWI call is used to set the stack check level used when a callback occurs

When receiving a callback, the SVC stack depth is checked to see if the kernel is reasonably unthreaded. By using this call, you can control what is considered "reasonable". The default value is currently 64, i.e. if there are more than 64 words on the stack by the time of the callback, a new callback will be registered later instead. Setting this too low will cause the player to stall, and you can only stop it by killing the module (or putting the level back up).

It is not expected that users of the AMPlayer API will need to use this SWI.

AMPlayer_Control 3ID3v2ControlSWI &52E05
Control the ID3v2 tag processing facilities
R0=flags :
Bit(s)Meaning
0-73 (reason code)
8-30Reserved, must be 0.
31R8 contains the instance handle to which this call should be directed.
R1=sub-reason code :
Sub-reasonMeaning
0 Enable or disable ID3v2 processing
1 Select ID3v2 frame filtering
R8=if bit 31 of R0 set:
instance handle to direct at, or 0 for the base
R1=old level
Interrupts are undefined
Fast interrupts are enabled
Processor is in SVC mode
SWI is not re-entrant

This control call is used to control ID3v2 processing within the player.

ID3v2 processing is quite intensive and can have a performance hit, especially when compressed frames are used.

AMPlayer_Control 3, 0ID3v2StateSWI &52E05
Enable or disable ID3v2 processing
R0=flags :
Bit(s)Meaning
0-73 (reason code)
8-30Reserved, must be 0.
31R8 contains the instance handle to which this call should be directed.
R1=0 (sub-reason code)
R2=type of change :
TypeMeaning
0disable
1enable
-1read current state
R8=if bit 31 of R0 set:
instance handle to direct at, or 0 for the base
R2=enable count, or 0 if disabled
Interrupts are undefined
Fast interrupts are enabled
Processor is in SVC mode
SWI is not re-entrant

This SWI is used to enable or disable the processing of ID3v2 tags by the AMPlayer module.

When disabled, no ID3v2 processing at all is performed - the tags are merely skipped. This will improve performance when such tags are encountered.

AMPlayer_Control 3, 1ID3v2FilteringSWI &52E05
Select ID3v2 frame filtering
R0=flags :
Bit(s)Meaning
0-73 (reason code)
8-30Reserved, must be 0.
31R8 contains the instance handle to which this call should be directed.
R1=1 (sub-reason code)
R2=pointer to frame name, or 0 for 'all frames'
R3=filtering operation :
TypeMeaning
0disable frame processing
1enable frame processing
-1read current state of processing
-2read frame state as matched by processing engine
R8=if bit 31 of R0 set:
instance handle to direct at, or 0 for the base
R2=enable count, or 0 if disabled
Interrupts are undefined
Fast interrupts are enabled
Processor is in SVC mode
SWI is not re-entrant

This SWI is used to enable or disable specific frames or groups of frames for processing through the service interface.

A single character frame name will select all frames starting with that character. Three character frame names select the ID3v2.2 and earlier frames that match. Four character frame names select the ID3v2.3 and ID3v2.4 frame explicitly.

Claimants of the ID3v2 service should enable the frames they wish to see, and disable them when they no longer require them.

AMPlayer_Control 4TransienceSWI &52E05
Read or write the 'transience' flag
R0=flags :
Bit(s)Meaning
0-74 (reason code)
8-30Reserved, must be 0.
31R8 contains the instance handle to which this call should be directed.
R1=Operation to apply:
ValueMeaning
0Mark as intransient
1Mark as transient
-1Read current flag
R8=if bit 31 of R0 set:
instance handle to direct at, or 0 for the base
R1=old transience flag
Interrupts are undefined
Fast interrupts are enabled
Processor is in SVC mode
SWI is not re-entrant

This SWI is used to read or write the transiency flag for an instance. Transiency has no meaning for the base instance, but for created instances, it means that when playback completes, the instance will be destroyed automatically.

AMPlayer_Control 5DecimationControlSWI &52E05
Read or write the decimation threshold
R0=flags :
Bit(s)Meaning
0-75 (reason code)
8-30Reserved, must be 0.
31R8 contains the instance handle to which this call should be directed.
R1=Operation to apply:
ValueMeaning
0Read decimation threshold
1Set decimation threshold
R2=new decimation threshold
R8=if bit 31 of R0 set:
instance handle to direct at, or 0 for the base
R1=current decimation threshold
Interrupts are undefined
Fast interrupts are enabled
Processor is in SVC mode
SWI is not re-entrant

This SWI is used to read or write the 'decimation threshold'. AMPlayer will normally decode data at full accuracy. If the 'decimation threshold' frequency is met or exceeded, the module will apply automatic decimation to the output.

The initial decimation value is based on the version of the module in use (for AMPlayer, this is 1000000, for AMPlayerFP, it is 22050, and for AMPlayer6 it is 0). This can be overridden by setting the AMPlayer$DecimationThreshold variable to a number before starting the module. Setting the decimation threshold of the base instance will set the variable to the same value.

On builds that do not support decimation, the calls are ignored, and reading the decimation always returns 1000000.

AMPlayer_PluginSWI &52E06
Plugin operations
R0=flags :
Bit(s)Meaning
0-30Reserved, must be 0.
31R8 contains the instance handle to which this call should be directed.
R1=reason code :
ValueMeaning
0Register plugin
1Deregister plugin
R2=private word to pass in R0
R3=pointer to pre-processor (pre-DCT), or 0 for none
R4=pointer to post-processor (post-DCT), or 0 for none
R5=pointer to static Plugin Information Block
R8=if bit 31 of R0 set:
instance handle to direct at, or 0 for the base
None
Interrupts are undefined
Fast interrupts are enabled
Processor is in SVC mode
SWI is not re-entrant

This SWI is used to register or deregister plugins.

AMPlayer_FileInfoSWI &52E07
Return information on the a file
R0=flags for requested information, or 0 to return size of buffers :
Bit(s)Meaning
0Return total time, and Frame Information Block for the first frame
1Reserved, must be 0
2Return ID3 tag information
3-30Reserved, must be 0.
31R8 contains the instance handle to which this call should be directed.
R1=pointer to filename
R2=pointer to buffer for File Information Block
R3=pointer to buffer for Frame Information Block
R8=if bit 31 of R0 set:
instance handle to direct at, or 0 for the base
R2=required size of the File Information Buffer, if reading size of buffer
R3=required size of the Frame Information Buffer, if reading size of buffer
Interrupts are undefined
Fast interrupts are enabled
Processor is in SVC mode
SWI is not re-entrant

This SWI attempts to return useful information about the file given. The more bits you set in R0, the slower it gets, as it requires more of the file to be read. In particular, requesting the ID3 tag information means seeking to the end of the file, which may be very slow on some filing systems (like DATFS).

Therefore, it sometimes makes sense to make 3 calls:

  1. With R0=&000, to get the size of the buffers.
  2. With R0=&001, to read the quick things and determine whether the file is interesting at all.
  3. With R0=&004, to read only the ID3 tag fields.

Remember to read the buffer sizes first. These information blocks will no doubt be extended, and if you assume the old size, your program will stop working when a new AMPlayer module comes out. Just read the size, and your program will continue to work for eternity. You don't need to supply a frame info pointer in R3 unless bit 0 is set.

AMPlayer_StreamOpenSWI &52E08
Starts a stream playing
R0=flags :
Bit(s)NameMeaning
0QueuePlaces the named file in the queue of tracks to play. If there is no file currently playing, the behaviour is exactly as if bit 0 were clear.
1CueStarts the named file immediately, but paused at the first frame. Use SWI AMPlayer_Pause to start playback.
2GenerateServiceIndicates that Service_AMPlayer 6 should be generated every time one or more blocks passed into the stream become free.
3-30Reserved, must be 0.
31R8 contains the instance handle to which this call should be directed.
R1=pointer to stream name (for information)
R8=if bit 31 of R0 set:
instance handle to direct at, or 0 for the base
R0=stream handle, or 0 if failed to start
Interrupts are undefined
Fast interrupts are enabled
Processor is in SVC mode
SWI is not re-entrant

This SWI is used to start streamed input, ready for playback.

Called by a streaming application to get a Stream Handle. Most streamers will start the stream paused and feed data in until the buffer full flag (see SWI AMPlayer_StreamInfo) is set.

Note: The combination of Queue and Start Paused may not work.

AMPlayer_StreamCloseSWI &52E09
Informs AMPlayer that a stream has ended
R0=flags :
Bit(s)Meaning
0-30Reserved, must be 0.
31R8 contains the instance handle to which this call should be directed.
R1=stream handle
R8=if bit 31 of R0 set:
instance handle to direct at, or 0 for the base
None
Interrupts are undefined
Fast interrupts are enabled
Processor is in SVC mode
SWI is not re-entrant

This SWI is used to inform the AMPlayer module that no more data will be supplied to the stream. This does NOT release outstanding buffers that have been passed to AMPlayer. If you need to get these back, call AMPlayer_StreamClose, then SWI AMPlayer_Stop.

AMPlayer_StreamGiveDataSWI &52E0A
Inform AMPlayer of the location of input data
R0=flags :
Bit(s)Meaning
0-30Reserved, must be 0.
31R8 contains the instance handle to which this call should be directed.
R1=stream handle
R2=pointer to streaming data block :
OffsetContents
0Usage word
4Meta data list associated with this buffer, or 0 for no data
8Length of data following
R8=if bit 31 of R0 set:
instance handle to direct at, or 0 for the base
None
Interrupts are undefined
Fast interrupts are enabled
Processor is in SVC mode
SWI is not re-entrant

Called by a streamer application to pass a block of data to AMPlayer. All but the first word may be considered read-only and must be in interrupt sharable space (i.e. in a dynamic area, module area, sprite pool etc, NOT in the application). By calling this SWI, the application must guarantee that it will keep the buffer around (and unchanged) at least until AMPlayer sets the usage word to zero.

The streamer application should monitor the first word of the buffers it has previously passed in to see when it gets set to 0 to allow reuse. Buffers will be released strictly in the same order they were passed in.

The metadata list blocks must be kept intact for the same length of time as the data blocks, and can be considered 'released' by AMPlayer when their corresponding data blocks are.

Metadata blocks are in the following format:

OffsetContents
0Pointer to next metadata block, or 0 for the last entry
4Pointer to a 0-terminated 'Key name' field
8Pointer to a value field (often a 0-terminated string, but may be binary data)
12Length of value buffer in bytes

It is envisaged that there will be a SWI added later to allow metadata to be supplied for non-streaming sources.

AMPlayer_StreamInfoSWI &52E0B
Read information about the streaming data
R0=flags :
Bit(s)Meaning
0-30Reserved, must be 0.
31R8 contains the instance handle to which this call should be directed.
R1=stream handle
R8=if bit 31 of R0 set:
instance handle to direct at, or 0 for the base
R0=flags word :
Bit(s)Meaning
0Stream is active (actively being processed)
1Output buffer has been full
2Stream is paused
Interrupts are undefined
Fast interrupts are enabled
Processor is in SVC mode
SWI is not re-entrant

This SWI is called by a streaming application to monitor the state of the decoder. Typically a streamer will start a stream up paused and feed it data. The streamer application will then wait until the stream becomes active, and until either the output buffer becomes full, or until it runs out of buffer space itself. Then it can unpause the stream knowing that the maximum amount of buffering is in use.

AMPlayer_MetaDataPollChangeSWI &52E0C
Read meta-data state value
None
R0=flags :
Bit(s)Meaning
0-30Reserved, must be 0.
31R8 contains the instance handle to which this call should be directed.
R1=opaque unique value, guaranteed to change to a new unique value when any metadata items change.
R8=if bit 31 of R0 set:
instance handle to direct at, or 0 for the base
Interrupts are undefined
Fast interrupts are enabled
Processor is in SVC mode
SWI is not re-entrant

This SWI is called by streaming applications to discover when meta-data provided by the application has been 'passed' by the decoder and is now active.

AMPlayer_MetaDataLookupSWI &52E0C
Read meta-data token value
R0=flags :
Bit(s)Meaning
0-30Reserved, must be 0.
31R8 contains the instance handle to which this call should be directed.
R1=pointer to key field to match
R2=pointer to buffer for result (or NULL to read length)
R3=length of buffer, or 0 to read required length
R8=if bit 31 of R0 set:
instance handle to direct at, or 0 for the base
R0preserved
R1=buffer, filled with data to length given
R2=length of buffer required, including terminator
Interrupts are undefined
Fast interrupts are enabled
Processor is in SVC mode
SWI is not re-entrant

This SWI is called by applications to read meta-data passed to the AMPlayer module. Every element of meta-data is tagged with a 'key' which is used to return its value.

AMPlayer_SoundSystemSWI &52E0E
Read sound systems available, or set output sound system
R0=flags :
Bit(s)Meaning
0-30Reserved, must be 0.
31R8 contains the instance handle to which this call should be directed.
R1=Operation type :
TypeMeaning
-1Read available sound systems
0Select any available system (best possible)
1Select 8 bit sound system
2Select 16 bit sound system
3Select SharedSound
4Select 'User' sound system (data read via SWI AMPlayer_StreamReadData)
R8=if bit 31 of R0 set:
instance handle to direct at, or 0 for the base
R0=Bit mask of avialable sound systems :
Bit(s)Meaning
08 bit output available
116 bit output available
2SharedSound output available
3User output available
R1=Last sound system in use (as on input)
Interrupts are undefined
Fast interrupts are enabled
Processor is in SVC mode
SWI is not re-entrant

This SWI is used to determine what sound systems are available on the current machine, and to select a different sound system. Its most common use is to select the User sound system for streaming output data.

AMPlayer_StreamReadDataSWI &52E0F
Read data from streaming sound system
R0=flags :
Bit(s)Meaning
0-30Reserved, must be 0.
31R8 contains the instance handle to which this call should be directed.
R1=Unused
R2=pointer to next byte of data to read, or 0 for first call
R8=if bit 31 of R0 set:
instance handle to direct at, or 0 for the base
R2=pointer to first byte of data to read, or 0 if none available
R3=number of bytes of data available
R4=frequency of data
Interrupts are undefined
Fast interrupts are enabled
Processor is in SVC mode
SWI is not re-entrant

This SWI is used to take data from the 'user' sound system. Initially, users would call with R2 = 0, to determine where to read data from. They then take use from this address up to the limit supplied. Subsequently, the call this SWI again to inform AMPlayer how much data has been read. AMPlayer will only remove data after it has been informed that it has been read.

Decoding will continue in the background. It may be necessary to delay processing if no data is ready. Data can only be generated on callbacks. It may, therefore, be necessary to wait for a moment or so for the decode to function.

VU-bars are inactive when use user sound state is in use.

Callers should note that only complete frames fed in will produce any output - not all the input stream may be used.

AMPlayer_InstanceSWI &52E10
Manipulate AMPlayer instances
R0=flags :
Bit(s)Meaning
0-30Reserved, must be 0.
31R8 contains the instance handle to which this call should be directed.
R1=Reason code :
ReasonMeaning
0 Read current instance handle
1 Create a new instance of the module
2 Destroy an instance of the module
3 Read handle of base instance
4 Enumerate handles of known instances
R8=if bit 31 of R0 set:
instance handle to direct at, or 0 for the base
R0 - R7=dependant on reason code
Interrupts are undefined
Fast interrupts are enabled
Processor is in SVC mode
SWI is not re-entrant

This SWI is used control instances of AMPlayer. You should use it in preference to directly creating instances of the AMPlayer module yourself. Consult the reason code descriptions for more details.

AMPlayer_Instance 0CurrentSWI &52E10
Read current instance handle
R0=flags :
Bit(s)Meaning
0-30Reserved, must be 0.
31R8 contains the instance handle to which this call should be directed.
R1=0 (reason code)
R8=if bit 31 of R0 set:
instance handle to direct at, or 0 for the base
R0=instance handle
Interrupts are undefined
Fast interrupts are enabled
Processor is in SVC mode
SWI is not re-entrant

This SWI is used return the instance handle of the current instance of AMPlayer. This may be used to discover the handle of the preferred instance such that the preferred instance may be changed to allow fading from one track to another. It is not expected that this call be used often.

AMPlayer_Instance 1CreateSWI &52E10
Create a new instance of the module
R0=flags :
Bit(s)Meaning
0-30Reserved, must be 0.
31R8 contains the instance handle to which this call should be directed.
R1=1 (reason code)
R2=pointer to zero terminated suffix for the instance name. Ideally you should keep this to < 16 characters.
R8=if bit 31 of R0 set:
instance handle to direct at, or 0 for the base
R0=instance handle of new instance
Interrupts are undefined
Fast interrupts are enabled
Processor is in SVC mode
SWI is not re-entrant

This SWI is used create a new instance of the AMPlayer module. This instance may be used in exactly the same manner as any other, if SWIs are directed at it. Set bit 31 of any SWIs flags to direct the call to the instance whose handle is in R8.

AMPlayer_Instance 2DestroySWI &52E10
Destroy an instance of the module
R0=flags :
Bit(s)Meaning
0-30Reserved, must be 0.
31R8 contains the instance handle to which this call should be directed.
R1=2 (reason code)
R2=instance handle to destroy
R8=if bit 31 of R0 set:
instance handle to direct at, or 0 for the base
None
Interrupts are undefined
Fast interrupts are enabled
Processor is in SVC mode
SWI is not re-entrant

This SWI is used destroy an instance of the AMPlayer module. You should destroy instances when you have no further use for them, to free up resources and processing time.

AMPlayer_Instance 3ReadBaseSWI &52E10

This SWI call is for internal use only. You must not use it in your own code.

AMPlayer_Instance 4EnumerateSWI &52E10
Enumerate handles of known instances
R0=flags :
Bit(s)Meaning
0-30Reserved, must be 0.
31R8 contains the instance handle to which this call should be directed.
R1=4 (reason code)
R2=last instance handle, or -1 to start enumerating
R3=pointer to buffer to write name into
R4=length of buffer
R8=if bit 31 of R0 set:
instance handle to direct at, or 0 for the base
R2=instance handle, or -1 if no more
R4=length written to buffer, or -ve length if failed to write
Interrupts are undefined
Fast interrupts are enabled
Processor is in SVC mode
SWI is not re-entrant

This SWI is used to enumerate the instances currently in use by AMPlayer. A 'visualisation' application might use this call to select what source to provide a representation of.

Entry points

Plugin_PreProcess
Pre-process DCT blocks
R0=private word
R1=pointer to 'out 1' buffer
R2=pointer to 'out 2' buffer
R3=pointer to 32 frequencies (16.16 format)
R0=0 if frequencies processed
1 if DCTs done (not recommended)
Interrupts are disabled
Fast interrupts are enabled
Processor is in SVC mode
Entry point is not re-entrant

This entry is called prior to 'dct64' which decodes the frequencies into the buffer. Note that there is no way in which to identify whether the buffer is for the left or right channel.

Plugin_PostProcess
Post-process DCT output buffers
R0=private word
R1=pointer to 'out 1' buffer
R2=pointer to 'out 2' buffer
R3=pointer to samples buffer
R0=0 if buffer processed
Interrupts are disabled
Fast interrupts are enabled
Processor is in SVC mode
Entry point is not re-entrant

This entry is called after the 'dct64' which decodes the frequencies into the buffer. Note that there is no way in which to identify whether the buffer is for the left or right channel.

*Commands

*AMInfo
Read information on playback, plugins or file
*AMInfo -plugins -file filename
-plugins - Display information about the plugins currently active.
-file <filename>- Display information about a file, rather than about the current playback state.

This command is used to display information about the current playback state, or the state of the plugins.

*AMInfo -file Corrs,The.01ForgivenNotForgotten.01ErinShore(TraditionalIntro)
*AMLocate
Skip to a position in the current file
*AMLocate + | - hours:minutes:seconds
*AMLocate minutes:seconds
<hours>-Number of hours to search for
<minutes>-Number of minutes to search for
<seconds>-Number of seconds to search for

This command is used to jump to a point in the playback of the file. Use + and - to indicate a location relative to the current playback position.

*AMLocate 7:23
*AMPause
Pause, or resume, playback
*AMPause -off
-off -resume playback, instead of pausing

This command is used to pause, or resume playback.

*AMPause
*AMPlay
Play a new file
*AMPlay -next -queue -cue -transient filename
-next -Start playback of queued file immediately
-queue -Queue this file, rather than playing it immediately
-cue -Start decoding this track, but leave the player paused
-transient -Start decoding this track in a new instance which will terminate when playback completes.

This command is used to play a new file.

*AMPlay -queue ADFS::4.$.Music.Artists.Dido.NoAngel.06Thankyou
*AMStop
Stops playback
*AMStop
None

This command is used to stop playback.

*AMStop
*AMVolume
AMVolume
*AMVolume + | - volume
<volume>-volume level (0-127)

This command is set the playback volume. Initially, 113 is selected.

*AMVolume 113