SourceForge Logo

[ index | download | howto | todo | developers | sf project | author ]



  • Technical description of some thing which might be useful when coding Ample
  • Explaination why some parts work in the way they do
  • To avoid having to explain the same stuff over and over
  • To simplify the task of understanding Ample



ShoutCast metadata protocol

Client side
When listening to a ShoutCast (or compatible) server, a client can request to have metadata (information about the music) included in the stream. Since ShoutCast is a popular format, support for this kind of metadata has been built into many different clients.
Even though it's not a ShoutCast server, Ample can still use this feature to send metadata to its clients about the songs currently playing.
A client informs the server that it's willing to accept ShoutCast type metadata by including the following header in its HTTP request:

Icy-MetaData: 1

Server side
Since Ample is such a well-behaved server ;-), it does a case-unsensitive match for "icy-metadata:" and then makes sure that the integer that follows is positive.
The server then indicates that it has understood the clients request for metadata and that it's going to send metadata by doing two things: first it changes the first reply header ("HTTP/1.1 200 OK" or similar) to "ICY 200 OK", second, it must include an "icy-metaint" header in its HTTP reply:

ICY 200 OK

Some notes
The number "16000" is just an example and I will soon explain how it is used. This line is the only one that is mandatory as far as I know, but other ones (that I know of) will be explained later.
The integer is an interval (in bytes) that specifies how often metadata updates will be sent to the client. In this example, 16000 bytes of music data would be sent first, then metadata (format will follow soon), then another 16000 bytes of music data etc. etc.
It may seem like there will be a lot of overhead if a line like "ZZ Top-Rough boy" (16 bytes) would be sent every 16000 bytes but that's 1/1000 of the total traffic. Also, (almost) no data is sent when the song title hasn't changed from the last time metadata was sent which makes the ratio in our example even lower.

Metadata message format
A metadata message starts with one byte that specifies the length, then the message itself and last one or more NULL bytes that pad the rest of the message and indicate the end of it.
An illustration is always nice:

ShoutCast Metadata format

  • Length - One byte, the value of this byte * 16 is the length of the rest of the message. If the title hasn't changed since the last metadata message, this should be zero and the only byte in the message.
  • Message - Usually the title of the song currently playing, encoded in ASCII.
  • Padding - At least one zero byte must end the message and there must be enough zeros to make the part after the length byte a multiple of 16. Thus a message of 15 bytes would have 1 zero byte following it and a message of 16 bytes would have 16 zero bytes following it.

Let's add an example, if we wanted to send the song title "U2 - One" to the client we would add the following data to the stream:

Hex:   0x01 0x55 0x32 0x20 0x2D 0x20 0x4F 0x6E 0x65 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
ASCII: N/A  U    2    SPC  -    SPC  O    n    e    NUL  NUL  NUL  NUL  NUL  NUL  NUL  NUL

Other HTTP reply headers
These are other headers that can (optionally) be included with the HTTP reply

  • icy-notice1 - An informational message.
  • icy-notice2 - Another informational message, probably "icy-notice3", "icy-notice4" etc. can also be used.
  • icy-name - The name of the stream that the server is sending, this is usually displayed along with the current song title in clients.
  • icy-genre - The genre of the music served.
  • icy-url - An URL associated with the stream, usually the homepage of the "webradio" or similar.
  • icy-pub - Not sure, believe it indicates if the stream is public or private
  • icy-br - BitRate, seems mostly informational as most clients encountered seem to support VBR (Variable BitRate).

Let's finish of with a complete example of a server reply:

ICY 200 OK
icy-notice1:This stream is served using Ample/0.5.4
icy-notice2:AMPLE - An MP3 LEnder -

ID3v2 tag format

An ID3v2 tag starts with a tag header followed by one or more frames. Each frame in turn consists of a header and (usually) some kind of content.
Let's start with an illustration:

ID3v2 Diagram - small

Header fields

  • Header ID - The text "ID3" identifies the start of a ID3 tag
  • Version - This is a BCD coded value (byte1 = minor version and byte2 = micro version)
    example: a value of $04 00 would mean version 2.4.0
  • Flags - 8 bits representing flags, for exact meaning - see ID3v2 spec*
    in normal operation the value should be $00
  • Size - a 32 bit syncsafe* integer representing the total ID3v2 tag size - header length (10)

Frame header fields

  • Frame Header ID - 4 byte frame identifier*
  • Frame Size - a 32 bit syncsafe* integer representing the frame size - frame header length (10)
  • Frame Flags - 16 bits representing flags, for exact meaning - see ID3v2 spec*
    in normal operation the value should be $00 00

Frame content
In frames where the content is a string, the first byte represents it's encoding as follows:

  • $00 - ISO-8859-1 terminated with $00.
  • $01 - UTF-16 encoded Unicode with BOM. All strings in the same frame SHALL have the same byteorder, terminated with $00 00.
  • $02 - UTF-16BE encoded Unicode without BOM, terminated with $00 00.
  • $03 - UTF-8 encoded Unicode, terminated with $00.


  • * A syncsafe integer is one where the highest bit of each byte is unused and always zero.
    example: 255 (%11111111) encoded as a 16 bit synchsafe integer is 383 (%00000001 01111111)
  • * The ones we commonly deal with in Ample is TPE1 (artist) and TIT2 (title).
  • * All info thanks to the ID3v2 spec

Version differences
The first publically released version was 2.2.0, it is now considered obsolote (but obviously still in use) and has some differences to later versions:

  • The frame identifiers are 3 bytes long (TPE1 is TP1 and TIT2 is TT2 for instance)
  • The frame size is 3 bytes long and not syncsafe (which means 24 significant bits)
  • There is no frame flags field
  • All this means that a frame header is 6 bytes in version 2.2.0

ID3v1 tag format

An ID3v1 tag is always found 128 bytes from the end of a file. It is statically divided into smaller pieces that are used to represent different info about the file.
Let's have another illustration:

ID3v1 Diagram - small

Header fields

  • Header ID - The text "TAG" identifies the start of a ID3 tag
  • Title - 30 characters, the title of the song
  • Artist - 30 characters, the artist performing the song
  • Album - 30 characters, which album the song came from
  • Year - 4 integers, which year the song was recorded
  • Comment - 30 characters, just about any info about the song
  • Genre - 1 integer, which genre the song belongs to

Text fields
The format of the text fields is rather fuzzy. The text should be in ASCII but how to indicate end of string differs between clients. Some client applications pad the end of the string with ASCII character <space>, some mark the end of string with <newline> and some do it with NULL.

The genre is encoded as an integer, check URL for the mapping between integer values and genres. This field didn't exist in early versions of ID3v1 (instead the comment field was 31 bytes long).


Valid XHTML 1.0!
Valid CSS
Valid CSS!
Hosting by
SourceForge Logo
GPL:ed program
This program is GPLed