\input texinfo   @c -*-texinfo-*-
@c %**start of header
@setfilename libadplug.info
@include version.texi
@settitle AdPlug Core Library @value{VERSION} Manual
@c %**end of header

@macro class{name}
@tindex \name\
@code{\name\}
@end macro

@copying
This manual documents the AdPlug core library, version
@value{VERSION}.

Copyright @copyright{} 2002 - 2017 Simon Peter <dn.tlp@@gmx.net>

@quotation
Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.1 or
any later version published by the Free Software Foundation; with no
Invariant Sections, with the Front-Cover texts being ``A GNU Manual,''
and with the Back-Cover Texts as in (a) below.  A copy of the license is
included in the section entitled ``GNU Free Documentation License.''

(a) The FSF's Back-Cover Text is: ``You have freedom to copy and modify
this GNU Manual, like GNU software.  Copies published by the Free
Software Foundation raise funds for GNU development.''
@end quotation
@end copying

@dircategory Software Libraries
@direntry
* AdPlug Core Library: (libadplug).     AdPlug Core Library @value{VERSION}
@end direntry

@titlepage
@title AdPlug Core Library Manual
@subtitle Version @value{VERSION}
@subtitle Last updated on @value{UPDATED}
@author Simon Peter

@page
@vskip 0pt plus 1filll
@insertcopying
@end titlepage

@contents

@ifnottex
@node Top
@top AdPlug core library

@insertcopying
@end ifnottex

@menu
* Introduction::                What is AdPlug?
* Basic Usage::                 Using AdPlug in your programs the easy way.
* Advanced Usage::              Using AdPlug in your programs the hard way.
* Hacking::                     How to hack around in AdPlug.
* Player development::          How to write new replayers for AdPlug.
* Protracker based players::    How to write Protracker based players.
* Copying This Manual::         Your rights and freedoms.
* Method Index::
* Variable Index::
* Class Index::
@end menu

@node Introduction
@chapter Introduction

AdPlug is a free, multi-platform, hardware independent AdLib sound
player library, mainly written in C++. AdPlug plays sound data,
originally created for the AdLib and Sound Blaster (OPL2/OPL3) audio
boards, on top of an OPL emulator or by using the real hardware. No
OPL chip is required for playback.

@menu
* Supported Formats::
* Concepts::
@end menu

@node Supported Formats
@section Supported Formats

AdPlug implements unique file replayers for each supported format in
order to achieve the best possible replay quality. Below is a list of
all currently supported file formats along with information about
possible replay issues. Players marked as "preliminary" aren't
considered final by the author(s) and may contain many replay issues,
but are included for testing purposes anyway.

@itemize @bullet
@item @file{A2M}: AdLib Tracker 2 by subz3ro
@itemize @bullet
@item File format versions 1, 4, 5 and 8 are supported
@item Unimplemented commands (versions 1-4): @code{FF1 - FF9, FAx - FEx}
@item Unimplemented commands (versions 5-8): @code{Gxy, Hxy, Kxy - &xy}
@item In version 5-8 files, some parts of the flags byte are ignored
@item Only SixPack compressed and uncompressed files are supported
@end itemize
@item @file{ADL}: Westwood ADL File Format
@item @file{AGD}: Herbulot AdLib System AGD @strong{(preliminary)}
@item @file{AMD}: AMUSIC Adlib Tracker by Elyssis
@item @file{BAM}: Bob's Adlib Music Format by Bob
@item @file{BMF}: Easy AdLib 1.0 by The Brain
@item @file{CFF}: BoomTracker 4.0 by CUD
@item @file{CMF}: Creative Music File Format by Creative Technology
@item @file{CMF}: SoundFX Macs Opera tracker by Linel
@item @file{D00}: EdLib by Vibrants
@itemize @bullet
@item Bugs: Hard restart SR sometimes sounds wrong
@end itemize
@item @file{DFM}: Digital-FM by R.Verhaag
@item @file{DMO}: Twin TrackPlayer by TwinTeam
@item @file{DRO}: DOSBox Raw OPL Format
@item @file{DTM}: DeFy Adlib Tracker by DeFy
@item @file{GOT}: God of Thunder Music by Roy Davis of Adept Software
@item @file{HA2}: Herbulot AdLib System (version 2) @strong{(preliminary)}
@item @file{HSC}: HSC Adlib Composer by Hannes Seifert, HSC-Tracker by Electronic Rats
@item @file{HSP}: HSC Packed by Number Six / Aegis Corp.
@item @file{HSQ}: Herbulot AdLib System SDB/AGD (HSQ packed)
@item @file{IMF}: Apogee IMF File Format by Apogee
@item @file{IMS}: IMPlay Song Format
@itemize @bullet
@item Needs file @file{implay.bnk} or @file{standard.bnk} or @file{@var{filename}.bnk}
in the same directory as loaded file, where @var{filename} is the name
of music file without extension
@end itemize
@item @file{KSM}: Ken Silverman's Adlib Music Format by Ken Silverman
@itemize @bullet
@item Needs file @file{insts.dat} in the same directory as loaded file
@end itemize
@item @file{LAA}: LucasArts AdLib Audio File Format by LucasArts
@itemize @bullet
@item Bugs: Some volumes are a bit off
@end itemize
@item @file{LDS}: LOUDNESS Music Format by Andras Molnar
@item @file{M}: Ultima 6 Music Format by Origin
@item @file{MAD}: Mlat Adlib Tracker
@item @file{MDI}: AdLib MIDIPlay File Format
@item @file{MID}: MIDI Audio File Format
@item @file{MKJ}: MKJamz by M \ K Productions @strong{(preliminary)}
@item @file{MSC}: AdLib MSCplay
@item @file{MTK}: MPU-401 Trakker by SuBZeR0
@item @file{MUS}: AdLib MIDI Music Format
@itemize @bullet
@item Needs file @file{@var{filename}.snd} or @file{@var{filename}.tim} or
@file{timbres.snd} in the same directory as loaded file, where @var{filename}
is the name of music file without extension
@end itemize
@item @file{RAD}: Reality ADlib Tracker by Reality
@item @file{RAW}: RdosPlay RAW file format by RDOS
@item @file{RIX}: Softstar RIX OPL Music Format
@item @file{ROL}: AdLib Visual Composer by AdLib Inc.
@itemize @bullet
@item Needs file @file{standard.bnk} in the same directory as loaded file
@end itemize
@item @file{S3M}: Scream Tracker 3 by Future Crew
@itemize @bullet
@item Bugs: Extra Fine Slides (@code{EEx, FEx}) & Fine Vibrato
(@code{Uxy}) are inaccurate
@end itemize
@item @file{SA2}: Surprise! Adlib Tracker 2 by Surprise! Productions
@item @file{SAT}: Surprise! Adlib Tracker by Surprise! Productions
@item @file{SCI}: Sierra's AdLib Audio File Format by Sierra On-Line Inc.
@itemize @bullet
@item Needs file @file{@var{???}patch.003} in the same directory as
loaded file, where @var{???} are the first 3 characters of the loaded
file's filename
@item Bugs: Some instruments are messed up
@end itemize
@item @file{SDB}: Herbulot AdLib System SDB @strong{(preliminary)}
@item @file{SNG}: SNGPlay by BUGSY of OBSESSION
@item @file{SNG}: Faust Music Creator by FAUST
@item @file{SNG}: Adlib Tracker 1.0 by TJ
@itemize @bullet
@item Needs file @file{@var{songname}.ins} in the same directory as
loaded file, where @var{songname} is the song's filename without
@file{.sng} extension.
@end itemize
@item @file{SOP}: Note Sequencer by Lee Ho Bum (sopepos)
@item @file{SQX}: Herbulot AdLib System SDB (SQX packed)
@item @file{VGM}: Video Game Music 1.51 by Valley Bell
@itemize @bullet
@item Supports OPL2, Dual OPL2 and OPL3 playback.
@end itemize
@item @file{XAD}: eXotic ADlib Format by Riven the Mage
@item @file{XMS}: XMS-Tracker by MaDoKaN/E.S.G
@item @file{XSM}: eXtra Simple Music by Davey W Taylor
@end itemize

Whenever a player requires more files to be present in a given
directory, be especially careful under UNIX systems, because all file
names are case-sensitive.

@node Concepts
@section Concepts

All of AdPlug's header files are installed under the directory
@file{adplug} inside your specified include path. Whenever a specific
header file in this manual is referred to, the filename with the path
@file{adplug/} prepended is meant.

AdPlug can be divided into 2 sections and 3 layers of
functionality. These are the @dfn{Playback} and @dfn{Sound
generation} sections and the @dfn{Frontend}, @dfn{Mid-End} and
@dfn{Backend} layers.

The Frontend layer is simply your application itself, using AdPlug. It
is above of it all and does not belong to any particular
section. Anything that provides the user-interface to AdPlug or an
interface to another application is in the Frontend layer.

@menu
* Playback section::
* Sound generation section::
@end menu

@node Playback section
@subsection Playback section

The Playback section is divided into the Mid-End and the Backend
layers. As a whole, it is responsible for making the sound files play
back.

The Mid-End layer provides the glue between the Frontend and the
Backend layers. It provides methods and classes for these layers to
communicate. The headers @file{adplug.h}, @file{fprovide.h},
@file{players.h} and @file{database.h} belong to the Mid-End
layer. From your application's point of view, you only have to include
the file @file{adplug.h} in your source files, which automatically
includes all the other Mid-End headers.

The Backend layer is responsible for reading and decoding the sound
files into OPL command data. It then passes this data to the sound
generation section, which generates the final audio data. The header
@file{player.h} and all player header files belong to the Backend
layer.

@node Sound generation section
@subsection Sound generation section

The Sound generation section is responsible for generating the OPL's
sound, according to the input of the Playback section. This sound is
either routed back to the application for it to do something with it
or routed directly to a specific audio hardware.

The following headers provide the interface to the sound generation
section: @file{emuopl.h}, @file{temuopl.h}, @file{kemuopl.h},
@file{realopl.h}, @file{silentopl.h}, @file{analopl.h} and
@file{diskopl.h}. All classes inside these headers are derived from
the abstract base class @class{Copl}, declared inside the file
@file{opl.h}, which provides the common interface for the Backend
layer of the Playback section. This interface is not meant for the
Frontend layer (i.e. your application). Your application, however, has
to call special methods of these classes in order to route the data
back, if there is any.

@file{emuopl.h} provides the class @class{CEmuopl}, which implements a
virtual OPL emulator, which automatically selects the best available
OPL chip emulation and type for each replayer.

@file{temuopl.h} provides the class @class{CTEmuopl}, which is a
wrapper class around Tatsuyuki Satoh's fmopl OPL2 emulator, which
generates wave audio data to be routed back to the application.

@file{kemuopl.h} provides the class @class{CKemuopl}, which is a
wrapper class around Ken Silverman's adlibemu OPL2 emulator, which
generates wave audio data to be routed back to the application.

@file{realopl.h} provides the class @class{CRealopl}, which outputs to
a real hardware OPL2 or OPL3 chip. No data is routed back to the
application. This class is currently only working on x86 hardware.

@file{silentopl.h} provides the class @class{CSilentopl}, which is a
dummy OPL2/3, which generates nothing. All data sent to it is
forgotten immediately. No data is routed back to the application.

@file{analopl.h} provides the class @class{CAnalopl}, which is the same
as @class{CRealopl}, but also provides a 9-channel loudness
pseudo-analyzer interface for the application. The loudness data is
the only data routed back to the application.

@file{diskopl.h} provides the class @class{CDiskopl}, which is an OPL3
emulator that does not output any sound to the soundcard, but instead
writes all received OPL commands to a file in the RdosPlay RAW
format.

@node Basic Usage
@chapter Basic Usage

AdPlug provides convenience methods and classes inside its Mid-End
layer that make generic usage in your applications pretty easy. This
is most probably all that you need. For very advanced usage of
particular features of AdPlug, please refer to @ref{Advanced Usage}.

For basic usage, you need to include the header @file{adplug.h} inside
your application's source code. In addition, you need one of the
headers from the sound generation section, if you want sound output.

@file{adplug.h} provides the class @class{CAdPlug}, which in turn
provides the load and playback facilities for the song
files. @code{CAdPlug} is a static class, you do not need to
instantiate an object of it.

@menu
* Loading::
* Playback::
* Audio output::
* Chip support selection::
* Getting Playback Information::
* Example::
@end menu

@node Loading
@section Loading

To load a supported file for playback, you use the method
@code{CAdPlug::factory(const std::string &@var{filename}, Copl *@var{opl},
...)}. The method takes more arguments, but we don't need them for
basic usage. They are explained in @ref{Advanced Usage}.

The first argument, @var{filename}, is a string object, containing the
filename of the sound file to be loaded with AdPlug. The second
argument, @var{opl}, is a pointer to an already initialized object
from the sound generation section of the library.

The method returns a pointer to an initialized player object from the
Backend layer, or the NULL pointer if the file couldn't be loaded for
any reason.

I guess @var{filename} does not need any more explanation, so i will
just explain how to get an instance of a @code{Copl} derived class:

If you want to use the OPL emulator class @code{CEmuopl}, you have to
include the header @file{emuopl.h} inside your application's source
code. @code{CEmuopl}'s constructor looks like this:
@code{CEmuopl::CEmuopl(int @var{rate}, bool @var{bit16}, bool
@var{usestereo})}. The @var{rate} argument specifies the playback
frequency rate in Hz. The @var{bit16} argument specifies whether to
create 8 bit or 16 bit wave audio data. If it is set, 16 bit data is
created. The @var{usestereo} argument specifies whether to create
stereo or mono audio data. If it is set, stereo data is created.

If you want to use real hardware OPL2 output, you have to include the
header @file{realopl.h} inside your application and use the class
@code{CRealopl}. Its constructor just takes one optional argument,
specifying the hardware OPL2's base port, which is @samp{0x388} by
default. As an option, you can include @file{analopl.h} instead, using
the class @code{CAnalopl}, and also use the analyzer interface
instead. This is explained in @ref{Audio output}.

For no audio generation at all, include the header @file{silentopl.h}
inside your application and use the class @code{CSilentopl}. Its
constructor does not take any arguments.

@node Playback
@section Playback

On successful operation, @code{CAdPlug}'s @code{factory()} method
returns a pointer to an initialized player object from the Backend
layer. You use this object to do the main song playback. The important
methods for song playback are:

@ftable @code
@item void seek(unsigned long ms)
Use this to seek inside the song. The only argument specifies the
number of milliseconds to seek from the beginning of the song.

@item bool update()
The most important method of them all. You have to call this method in
a loop. As long as it returns @samp{true}, the song has not ended
yet. At some point, it will start to always return @samp{false}. When
it does this, the song has ended. The song will play on (and is maybe
already automatically rewound by the player itself), but you should
use the @code{rewind()} method to rewind it or stop playing.

@item void rewind(int subsong = -1)
This method rewinds the song to the beginning of the subsong,
specified by the only argument. If no argument or @samp{-1} is given,
the currently selected subsong will be rewound. If the player does not
support subsongs, just don't provide an argument.

@item float getrefresh()
Returns a float containing the player object's idea of with what
frequency its @code{update()} method should be called, in Hz. This can
change at any time, so you have to poll it before every call to
@code{update()}.

@item unsigned int getsubsongs()
Returns the number of subsongs of the currently loaded song. If the
player doesn't support subsongs, @samp{1} is returned, representing
the only ``subsong''.
@end ftable

@node Audio output
@section Audio output

To actually generate some sound, you probably additionally have to
make some calls to the OPL object. While the two hardware OPL2 output
and the silent OPL2 classes do not need any additional calls, the
@code{CEmuopl} class provides methods for your application's readback
of the generated wave audio data.

To get a buffer of wave audio data from the emulator, you have to call
the @code{void CEmuopl::update(short *@var{buf}, int @var{samples})}
method. The @var{buf} argument is a pointer to a previously allocated
memory block of the size specified by the @var{samples} argument, in
samples. The method will fill the specified amount of samples into the
buffer. Multibyte samples have the machine's byte ordering.

For easier and more uniform handling of the different OPL classes, the
@code{Copl} base class also provides the @code{update()} method. For
subclasses that do not support read back of the audio data (and for
which this is not necessary), the method is empty and does nothing.

The volume analyzing hardware OPL class @code{CAnalopl} also has some
data readback methods:

@ftable @code
@item int getcarriervol(unsigned int v)
Returns the carrier's current volume of the OPL2 channel given as the
only argument.
@item int getmodulatorvol(unsigned int v)
Returns the modulator's current volume of the OPL2 channel given as
the only argument.
@item bool getkeyon(unsigned int v)
Returns whether a key-on event just happened on the OPL2 channel given
as the only argument.
@end ftable

@node Chip support selection
@section Chip support selection

With some OPL classes, like @code{CEmuopl} and @code{CRealopl}, it is
also possible to select the chip type to support. The hardware OPL
class will of course only be able to support those chip types that are
available in the system. The emulated OPL class will be able to
support all chip types that it can emulate, provided the corresponding
emulators are compiled in.

Three different OPL chip configurations can be identified, which can
all be support by AdPlug.

@itemize
@item Single OPL2: This is the classic configuration found on the
standard AdLib boards. One OPL2 chip is supported.
@item Dual OPL2: This configuration was first implemented on the Sound
Blaster Pro II boards. Two independent OPL2 chips are on this card.
@item OPL3: This is the configuration found on all newer sound
cards. An OPL3 chip is supported, which is capable of emulating the
other two configurations.
@end itemize

In accordance to this, AdPlug's @code{Copl} base class defines the
enumeration type @code{ChipType}, containing the items
@code{TYPE_OPL2}, @code{TYPE_OPL3} and @code{TYPE_DUAL_OPL2}.

OPL classes supporting multiple OPL interfaces have the
@code{settype(@var{type})} method, which can be used to set the chip
interface to support, using the @code{ChipType} enumeration type.

The chip type needs not to be set, as all supporting classes
automatically set the best available chip type, they can support, but
you may like to provide your user with this selection to suite his
listenting preferences.

You may retrieve the currently supported chip type of a class by using
the method @code{Copl::gettype()}, which returns a variable of type
@code{ChipType}. This method is defined in the @code{Copl} base class
and thus supported by all of the OPL classes.

@node Getting Playback Information
@section Getting Playback Information

During playback, it is possible to gain some replay statistics with
some players. The following methods are for getting playback
information:

@ftable @code
@item std::string gettype()
Returns a descriptive string containing the current file's format
type. This is for user information only and cannot be interpreted by
software.

@item std::string gettitle()
Returns a string holding the current song's title. An empty string is
returned if the song's format does not support title information.

@item std::string getauthor()
Returns a string containing the current song's author name. An empty
string is returned if the song's format doesn't support author
information.

@item std::string getdesc()
Returns a string with the current song's description. An empty string
is returned if the song's format doesn't support a description.

@item unsigned int getpatterns()
Returns the number of patterns in the current song. @samp{0} is
returned if the format isn't pattern-based.

@item unsigned int getpattern()
Returns the number of the currently playing pattern. @samp{0} is
returned if the format isn't pattern-based.

@item unsigned int getorders()
Returns the length of the order list of the current song. @samp{0} is
returned if the format doesn't have an order list.

@item unsigned int getorder()
Returns the number of the currently playing order list entry. @samp{0}
is returned if the format doesn't have an order list.

@item unsigned int getrow()
Returns the number of the currently playing row inside the current
pattern. @samp{0} is returned if the format isn't pattern-based.

@item unsigned int getspeed()
Returns the current speed setting of the song. @samp{0} is returned if
the format doesn't support Protracker-based speed settings.

@item unsigned int getinstruments()
Returns the number of defined instruments in the song. This does not
necessarily mean that any of the defined instruments has an instrument
name attached to it. @samp{0} is returned if the format doesn't define
any instruments.

@item std::string getinstrument(unsigned int n)
Returns a string with the name of the instrument, specified by the
only argument. If the specified instrument doesn't have a name, an
empty string is returned instead.
@end ftable

These methods may be called at any time on an initialized player
object (i.e. a file has already been loaded). If a player or song does
not support any of the above methods, or their values are not
meaningful for a format, reasonable bogus values are returned
instead.

Some informational methods may not be called while the song itself is
playing because they change the internal replay state and will
destroy the running playback. These are:

@ftable @code
@item unsigned long songlength(int subsong = -1)
This method returns the total length in milliseconds of the subsong
given as the only argument. If it is omitted or @samp{-1}, the
currently selected subsong's length will be returned.
@end ftable

@node Example
@section Example

This is an example of a minimal playback utility that reads the
filename to be played from the commandline, uses the emulator to
generate the sound and writes the raw wave audio data back to disk:

@verbatim
#include <stdlib.h>
#include <stdio.h>
#include <adplug/adplug.h>
#include <adplug/emuopl.h>

#define RATE	44100   // Output frequency in Hz
#define BIT16	true    // true when 16bit samples should be used
#define STEREO	false   // true when stereo samples should be used
#define BUFSIZE	512     // Sound buffer size in samples

bool play(const char *filename, const char *output)
/*
 * Main playback function. Returns true on successful playback.
 * false is returned otherwise.
 */
{
  CEmuopl	opl(RATE, BIT16, STEREO);
  CPlayer	*p = CAdPlug::factory(filename, &opl);
  FILE		*f;
  short		buf[BUFSIZE];
  unsigned long	towrite, write;

  if(!p) return false;		// File couldn't be loaded

  f = fopen(output, "wb");
  while(p->update())
    for(towrite = RATE / p->getrefresh(); towrite; towrite -= write) {
      write = (towrite > BUFSIZE ? BUFSIZE : towrite);
      opl.update(buf, write);
      fwrite(buf, write, 2, f);
    }

  fclose(f);
  return true;
}

int main(int argc, char **argv)
{
  if(argc < 3) {
    cout << "usage: " << argv[0] << " <filename> <output>" << endl;
    exit(EXIT_FAILURE);
  }

  if(play(argv[1], argv[2]))
    exit(EXIT_SUCCESS);
  else
    exit(EXIT_FAILURE);
}
@end verbatim

@node Advanced Usage
@chapter Advanced Usage

This chapter explains very advanced usage of AdPlug. You do not
normally need to read this if you just want to write a usual frontend
application for AdPlug.

@menu
* Player Lists::
* File Providers::
* Using the Database::
* Without CAdPlug::
@end menu

@node Player Lists
@section Player Lists

There is another argument to the @code{CAdPlug::factory(const
std::string &fn, Copl *opl, const CPlayers &@var{pl} = players, ...)}
method. The argument @var{pl} is a reference to an object holding a
@dfn{Player List}.

A player list object is an instance of the @class{CPlayers} class (not
to be confused with the @class{CPlayer} class). The object can be
constant and even static (so it is possible to pass a temporary
object, created on the fly).

The @code{CPlayers} class itself is not much more than a specialized
@code{std::list} from the @acronym{STL}, holding pointers to objects
of type @class{CPlayerDesc}, which are explained below. Look into the
@acronym{STL} documentation for more information on @code{std::list}
functionality.

The @class{CPlayerDesc} class is essentially an information-holder,
describing all needed characteristics of a player class, to create an
instance and load a supported file with it. It has two public
attributes:

@vtable @code
@item Factory factory
The @code{Factory} type defines a pointer to a static method inside a
class, inherited from @code{CPlayer}, taking a pointer to a
@code{Copl}-derived object as the sole argument. The meaning of this
attribute is to provide a pointer to the factory method of the player
class, which takes a pointer to an initialized @code{Copl}-derived
object and returns a pointer to an initialized instance of the same
player class, this @code{CPlayerDesc} object describes.

@item std::string filetype
This is a string containing the unique file type identifier of the
player class, this @code{CPlayerDesc} object describes. The string
normally contains the name of the file format, which the belonging
player class handles. This string should be unique.
@end vtable

In addition, @code{CPlayerDesc} has the following methods:

@ftable @code
@item CPlayerDesc(Factory f, const std::string &type, const char *ext)
A specialized constructor, which initializes the whole object at
once. The first argument is the pointer to the factory method of the
accompanying player class. The second argument is a string with the
unique file type description, this player class handles. The last
argument is a pseudo @acronym{ASCIIZ} string, holding many
@acronym{ASCIIZ} strings with all file extensions to be associated
with the accompanying player class. To create such a string, include
the leading @samp{.} with all file extensions and terminate any file
extension entry with a @samp{\0} character. Concatenate all entries
one after the other, forming a string of strings. Terminate the last
entry with another @samp{\0} character, so the final string is doubly
terminated.

@item void add_extension(const std::string &ext)
Adds the single file extension, passed as the only argument, to the
list of file extensions, the accompanying player class handles.

@item const char *get_extension(unsigned int n)
Returns a pointer to the @var{n}-th file extension string in the file
extension list. If @var{n} is out of range, a @samp{NULL}-pointer is
returned instead.
@end ftable

The @code{CPlayers} class itself adds two more methods to the
inherited @code{std::list} interface:

@ftable @code
@item const CPlayerDesc *lookup_filetype(const std::string &ftype)
Returns a pointer to the first occurrence of a @code{CPlayerDesc}
object with a file type of @var{ftype}, passed as the only
argument. This should also be the only object with that file type in
the list. If an object with the given file type is not found, a
@samp{NULL}-pointer if returned instead.

@item const CPlayerDesc *lookup_extension(const std::string &extension)
Returns a pointer to the first occurrence of a @code{CPlayerDesc}
object, defining a file extension of @var{extension}, passed as the
only argument. Since file extensions are not necessarily unique in a
@code{CPlayers} list, it is often much more efficient to use the
search facilities provided by the @acronym{STL}. If no object,
specifying the given file extension, could be found, a
@samp{NULL}-pointer is returned instead.
@end ftable

Thus, the @code{CPlayers} class holds a list of player
descriptions. This list is used by the @code{CAdPlug::factory()}
method for the list of players to try out on a given filename. If no
list is passed to the method, it is @code{CAdPlug::players} by
default. This list always holds all players compiled into the AdPlug
library and is also your starting point for generating lists of your
own.

@node File Providers
@section File Providers

@dfn{File Providers} are special classes that provide abstracted
access to files. AdPlug's player classes request files using a file
provider, in their @code{load()} methods. This system is necessary
because some players require multiple files in their load stage and
these files cannot all be passed to their @code{load()} method
because the application's programmer would have to be aware of each of
the player's characteristics to know which files to pass.

A file provider class is derived from the abstract base class
@class{CFileProvider}, which is declared in the header
@file{fprovide.h}. This class defines the following methods:

@ftable @code
@item binistream *open(std::string) const
An abstract virtual method that takes a string containing a filename
as the only argument and returns an initialized input-only binary
stream to that file. The stream is always created with x86
capabilities (i.e. Little-Endian, @acronym{IEEE-754} floating-point
numbers). If the file could not be opened, the @samp{NULL}-pointer is
returned instead.

@item void close(binistream *) const
An abstract virtual method that takes an input-only binary stream,
which was formerly created with the @code{open()} method, and closes
this stream.

@item bool extension(const std::string &filename, const std::string &extension)
This static method takes a string holding a filename as its first and
another string holding a file extension as its last argument. It does
a caseless compare of the given file extension to the extension of the
given filename and returns @samp{true} if they match. @samp{false} is
returned otherwise.

@item unsigned long filesize(binistream *f)
This static method takes an input-only binary stream, previously
returned by the @code{open()} method, and returns the total size, in
bytes, of the associated file. The stream's state is not altered.
@end ftable

If you like to create your own file provider, you have to inherit from
this class and implement the methods @code{open()} and
@code{close()}. Remember to open the stream with x86 capabilities! One
situation in which you would have to create your own file provider is
when your application doesn't load the files from the machine's local
filesystem. For example, when it supports reading from archives, you
would use your file provider to fetch and depack the file from the
archive first, before passing it to AdPlug.

One derived file provider class is already defined in
@file{fprovide.h}: @class{CProvider_Filesystem}. This file provider
supports loading from the machine's local filesystem. File names are
normal paths in the operating system's common notation.

A file provider object can also be passed to the
@code{CAdPlug::factory()} method as last argument. If it is not
provided, it is a temporary instance of @code{CProvider_Filesystem} by
default. The method passes this object on to all player objects'
@code{load()} methods, it tries to open the file with. The player
objects' @code{load()} methods also take the file provider object as
their last argument and default to @code{CProvider_Filesystem} if none
is given.

@node Using the Database
@section Using the Database

AdPlug recently features a full-blown database, specialized for
storing information relevant to the replay of AdLib-specific music
data.

The database can be maintained by using the @command{adplugdb}
command. Usage of this command is explained in its own manual page.

The application's interface to the database is defined through the
@class{CAdPlugDatabase} class, residing in the header file
@file{database.h}.

If you just want to pass a database for AdPlug to make use of it,
reading @ref{Usage with CAdPlug} is sufficient. If you want to write a
complete database manipulation application, you have to read the other
subsections as well.

@menu
* Usage with CAdPlug::
* Records::
* Keys::
* Players using the Database::
* Direct Usage::
@end menu

@node Usage with CAdPlug
@subsection Usage with CAdPlug

You can pass AdPlug a database for it to get specific information
about a file. Some file formats store insufficient information within
themselves and AdPlug uses the database to get the missing data. You
do not need to include any more header files other than
@file{adplug.h} within your application to do this.

To hand a database to AdPlug, you have to initialize an instance of
@code{CAdPlugDatabase} first. To do this, you just have to declare an
object of this class. This creates an empty database for
you.

Additionally, for the database to be of any use to AdPlug, you have to
fill it with some records (see @ref{Records}). This is most preferably
done by loading an already existing database from a file. To do this,
you use the @code{load(std::string  @var{db_name})} method of the
class. This will merge any records in the database file @var{db_name}
into your database object. You can merge any more database files, if
you wish. Only new records will be merged. Duplicate records will be
ignored.

To hand your database to AdPlug, you simply call
@code{CAdPlug::set_database(CAdPlugDatabase *db)} and pass a pointer
to your database object as the only argument. From now on, AdPlug will
use your database to do lookups for special information about some
file types. You have to keep your instance of the database until you
close AdPlug and free it by yourself after that.

@node Records
@subsection Records

@dfn{Records} are the primary data containers in the database. A
record is a very flexible object. It can store virtually any number of
different data types, you can think of.

All record classes are derived from the common abstract base class
@code{CAdPlugDatabase::CRecord}. All records have at least three
common attributes:

@vtable @code
@item RecordType type
Specifies what type of data this record holds. @code{RecordType} is an
enumeration variable with the following values:

@vtable @code
@item Plain
This record doesn't store any more information than the three standard
attributes.
@item SongInfo
This record additionally stores song name and author information.
@item ClockSpeed
This record additionally stores timer clock speed information.
@end vtable

@item CKey key
This is the unique key, allocated for any record in the
database. @xref{Keys}.

@item std::string filetype
Holds the unique file type of the file associated with the
record. This value is taken from the player list (see
@ref{Player Lists}).
@end vtable

The common base class @code{CAdPlugDatabase::CRecord} defines a
static method @code{factory(RecordType type)} for application usage
that returns a pointer to a newly allocated @class{CRecord} object, or
the @samp{NULL}-pointer if an error occurred. You pass the type of the
record to be created as the only argument.

All other public methods are meant for internal use of the database
only and should not be called from an application. They are explained
here anyway, for informational purposes:

@ftable @code
@item CRecord *factory(binistream &in)
Another factory method that takes a reference to an input-only binary
stream as the only argument. It tries to extract a record from the
stream's current position, initializes a new record object with the
data and returns a pointer to that record object. The
@samp{NULL}-pointer is returned if the record type couldn't be
determined from the stream's data.

@item void write(binostream &out)
Writes the record's contents to the output-only binary stream,
referenced by the only argument.

@item bool user_read(std::istream &in, std::ostream &out)
Attaches to the input and output streams, referenced by the first and
second arguments and tries to prompt an apparent user for the relevant
data input.

@item bool user_write(std::ostream &out)
Attaches to the output stream, referenced by the only argument and
writes the record's contents in human-readable form to it.

@item void read_own(binistream &in)
@itemx void write_own(binostream &out)
@itemx bool user_read_own(std::istream &in, std::ostream &out)
@itemx bool user_write_own(std::ostream &out)
Abstract virtual base methods to be inherited by the real record
classes to read and write their own data, in both binary and
human-readable ways.

@item unsigned long get_size()
Abstract virtual base method to be inherited by the real record
classes to report the size of the extra data defined by them.
@end ftable

@node Keys
@subsection Keys

@dfn{Keys} are @acronym{CRC32}:@acronym{CRC16} pairs that uniquely
identify a file's contents and are used to associate a record with a
file. Only if the file's key match with the record key, that record is
actually used for that file.

Keys are stored in key objects, which are instances of the
@code{CAdPlugDatabase::CKey} class. The class has two attributes,
@code{crc16} and @code{crc32} which store the two @acronym{CRC}
values, respectively. It also has the following methods:

@ftable @code
@item CKey()
A constructor that creates an empty key object.
@item CKey(binistream &in)
A constructor that creates a key from the contents of the input-only
binary stream, referenced by the only argument.

@item bool operator==(const CKey &key)
Operator that compares two key objects and returns @samp{true} when
they are equal. @samp{false} is returned otherwise.
@end ftable

@node Players using the Database
@subsection Players using the Database

The following players make active use of the database:

@table @asis
@item Apogee IMF
The IMF player uses the database to find out about the timer clock
speed of a file, since this data is not stored in the file itself.
@end table

@node Direct Usage
@subsection Direct Usage

The following methods are for application usage of the database:

@ftable @code
@item bool load(std::string db_name)
@itemx bool load(binistream &f)
Two versions to load a database. The first method takes a string
containing a file name of a file from which the database is
loaded. The second method takes a reference to an input-only binary
stream to load the database from.

@item bool save(std::string db_name)
@itemx bool save(binostream &f)
Two versions to save the database. These work analogous to the
@code{load()} methods, above.

@item bool insert(CRecord *record)
Inserts the record object, pointed to by the only argument, into the
database and returns @samp{true} on successful operation. @samp{false}
is returned otherwise. Duplicate record entries (i.e. records that
have the same key) cannot be inserted into the database and old ones
will not automatically be overwritten by the new ones with this
method. @samp{false} is returned in this case.

@item void wipe(CRecord *record)
@itemx void wipe()
Two versions of a method to remove (wipe) a record from the
database. The first version takes a pointer to a record object as the
only argument and removes exactly this record from the database. The
record object itself is deallocated, too. Do not reference it again!
If the record object is not in the database, nothing is done. The
second version removes the record at the current position in the
database.

@item CRecord *search(CKey const &key)
Takes a reference to a key object, searches for a record with the same
key value in the database and returns a pointer to this record. The
@samp{NULL}-pointer is returned if the record could not be found.

@item bool lookup(CKey const &key)
The same as @code{search()}, but instead of returning a pointer to the
record, it just positions the internal database pointer to the
corresponding record. Returns @samp{true} if the record could be found
and @samp{false} otherwise.

@item CRecord *get_record()
Returns a pointer to the record at the current position in the
database. The @samp{NULL}-pointer is returned if an error occurred.

@item bool go_forward()
Advances the internal position in the database by one record. Returns
@samp{true} on success, @samp{false} otherwise.
@item bool go_backward()
The same as @code{go_forward()}, but goes backward by one record.
@item void goto_begin()
Goes to the beginning (i.e. the first record) of the database.
@item void goto_end()
Goes to the end (i.e. the last record) of the database.
@end ftable

@node Without CAdPlug
@section Without CAdPlug

It is also possible to only use specific players from the AdPlug
library, without using the @code{CAdPlug} class to cycle through them
all.

If you just want to use a single player class from the library, you
only include that player's header file in your application's source
code.

You can construct an instance of that player by either using its
constructor or by using the @code{factory()} method of that
class. Both have the same syntax and take a pointer to an initialized
@code{Copl}-derived object.

Use the player's @code{load()} method to load a file. It takes a
filename as the first argument and, optionally, a file provider class
as its last argument.

All other methods have already been explained in the text above.

@node Hacking
@chapter Hacking

This chapter gives some coding guidelines for people wishing to hack
around in AdPlug. Be sure to also read the overall and system-specific
@file{INSTALL} files in the distribution's base directory to learn
more about the build systems.

@menu
* Coding Style::
* Debug Logging::
@end menu

@node Coding Style
@section Coding Style
I do not really enforce any coding style guidelines (i don't adhere to any
style guidelines myself, so... ;) ), but it would be nice if you follow the
overall coding style, used throughout most of AdPlug's source files. If you
don't, that's perfectly okay, too.

Most of today's "super-intelligent" editors, like MSVC's one or GNU Emacs'
cc-mode, have their own idea of what the code has to look like, anyway. And
since most people tend to use these, there's no point in torturing them to
always having to change anything their editor thinks it knows better. ;)

@node Debug Logging
@section Debug Logging

AdPlug recently offers centralized debug log management. If you like to
implement debug logging inside your code, please follow these guidelines:

To implement debug logging, @code{#include "debug.h"} in your code
(this header is @emph{not} being installed with the rest of the
AdPlug header files into your standard include directory! It is only
available in AdPlug's @file{src/} subdirectory!).

@file{debug.h} is C code, so it is useable from both C and C++
sources. The only function you have to use is the
@code{LogWrite(fmt, ...)} function. @code{LogFile()} is used by AdPlug
internally. @code{LogWrite()} works exactly like @code{printf()},
instead that it writes to a logfile, rather than on the console.

Please format your log messages like this:

@itemize @bullet
@item
If your method/function is going to output a lot of debug info
(i.e. more than one line), please put a @code{LogWrite()} directly at
the beginning of your function, which looks like this:

@example
LogWrite("*** yourclass::yourmethod(@var{param1}, @var{param2}, @var{...}) ***\n");
@end example

And put the following line before every return from your function:

@example
LogWrite("--- yourclass::yourmethod ---\n");
@end example

This way, one can easily inspect the logfile and know to which
function every logfile-line belongs. The @code{***} lines mark the
start of a function, and the @code{---} lines mark the end.

Please substitute @var{param*} with the corresponding parameter values
of your function, if that is reasonable. For example, it won't help
much to log a pointer value --- just put something bogus or helpful
there, or noting (i.e. just a comma, so the logfile reader knows, to
which parameters the other values correspond). But logging the values
of passed ints or strings could be very helpful.

@item
If your method/function is going to output just one line, format the
line something like this:

@example
LogWrite("yourclass::yourmethod(@var{param1}, @var{param2}): your message\n");
@end example

You don't need the @code{***} and @code{---} beginning and end markers
then.

@item
For threads, there is no way but to prefix any line with the function
name, because these messages will be sprayed throughout the logfile.
@end itemize

@node Player development
@chapter Player development

Before you try to write a new player for AdPlug, be sure to also read
through @ref{Hacking}.

@menu
* Before the work::
* Main work::
* Loading and File Providers::
* Sound generation::
@end menu

@node Before the work
@section Before the work

Your player normally consists of two files (the @file{.h} &
@file{.cpp} files) and you normally name them by the file extensions,
your player handles. For example, the HSC player consists of the files
@file{hsc.cpp} & @file{hsc.h}, because it handles @file{.hsc}
files. This is the same with your player class name. Thus, the HSC
player's class is called @class{ChscPlayer}. If any of these names
happens to be already taken for other purposes, just name your player
something else, appropriately.

@file{player.h} contains the abstract player interface. You have to
include it in your player to communicate with AdPlug. It also contains
some very helpful structures for use in your player. You don't need to
use the structs, but you have to use the methods provided by the
@code{opl} object (declared in @file{opl.h}, but automatically
included from @file{player.h}) inside the player class to do the OPL
I/O and initialization work.

@node Main work
@section Main work

All you have to do now is to inherit the @class{CPlayer} class into
your own player class and fill the abstract methods with code. You at
least have to fill in the following methods:

@example
bool load(const std::string &filename, const CFileProvider &fp);
bool update();
void rewind(int subsong);
float getrefresh();
std::string gettype();
@end example

The other methods from @code{CPlayer} just serve informational
purposes (as does @code{gettype()}, but it's required anyway) for
AdPlug's info box and needn't to be filled. It would be nice if you
fill them anyway, if that's reasonable for your player.

There's one more public method you have to define in your player
class:

@example
static CPlayer *factory(Copl *newopl);
@end example

Since it is static, it isn't already virtually defined in the
@code{CPlayer} class and you have to add it manually. This method
should return a pointer to a freshly initialized object of your player
class. If any errors occurred (e.g. not enough memory), return @samp{0}
instead.

Return true from your @code{load()} method, if the file was loaded
successfully, or false if it couldn't be loaded for any reason (e.g.
because AdPlug passed a wrong file to your player). Your
@code{update()} method will be called with the frequency, you return
from your @code{getrefresh()} method, in Hz. Return true from
@code{update()} if your module hasn't ended yet. If it looped or
ended, return false from that point, but play further for any
subsequent calls to @code{update()}. AdPlug will rewind or stop your
player by itself, using the @code{rewind()} method, when necessary.

AdPlug passes the number of the subsong, it wants to play next, to the
@code{rewind()} method of your player. This can be any value from
@samp{0} to the value returned by @code{getsubsongs()}. If you haven't
provided your own @code{getsubsongs()}, AdPlug will presume your
player doesn't have support for subsongs. In that case, AdPlug will
always @code{rewind(0)}. Please ignore any value passed to
@code{rewind()} that is out of spec for your player. This should
virtually never happen, but who knows. If a value of @samp{-1} is
given as an argument, you should rewind the currently playing
subsong.

After initializing your player (either by a call to @code{factory()}
or by creating an instance by itself), AdPlug normally first calls
@code{load()} and then @code{getrefresh()} and @code{update()} in a
loop until something happens (i.e. the user stops playback or the song
ends). @code{rewind()} and all the informational methods can be called
anytime in between the other calls, but of course only after
@code{load()} has been called.

You can add your own constructors, destructors and methods to your
player object, as you like. AdPlug won't care in any way.

@node Loading and File Providers
@section Loading and File Providers

The @code{load(const std::string &filename, const CFileProvider &fp)}
method needs some special explanation. This method takes two
arguments. The first is a reference to a string containing the
filename of the main file for your player to load. This is the
filename the user selected in the frontend (maybe altered by the
frontend, but not by AdPlug) and does not need to have any meaning to
your player.

To finally load your files to get to their data, you have to request
them. This is done through a @dfn{File Provider}. A reference to a
file provider is always passed as the second argument to your
@code{load()} method. You will most likely want to load the file,
using the filename passed as the first argument. To do this, you
simply call @code{binistream *f = fp.open(filename)}. This method
returns a pointer to an open, input-only binary stream of the
requested file. You can now operate on this stream, using its standard
interface (refer to the manual of the binary I/O stream class library
for further information). When you're done loading your file, don't
forget to call @code{fp.close(f)} to close it again. It is very
important to do this anytime you leave your @code{load()} method! Any
streams not closed will be left open for the whole lifetime of the
controlling process!

Don't worry about the passed filename. It normally doesn't need to
have any meaning to your player. The file provider will know how and
from where to open the file.

@code{fp.open()} returns a null-pointer if something went wrong
(e.g. file not found or access denied, etc.). If this happens, return
@samp{false} from your @code{load()} method immediately. You do not
have to call @code{fp.close()} in this case.

The @class{CFileProvider} class offers two convenience methods. These
are @code{unsigned long filesize(binistream *f)} and @code{bool
extension(const std::string &filename, const std::string
&extension)}.

@code{filesize()} returns the size in bytes of the stream, pointed to
by @code{f}, without altering it otherwise. @code{extension()} does a
filename extension check as follows: The first argument is a reference
to a string containing a filename. The second argument is a reference
to a string containing a file extension to check for. If the passed
filename has got exactly this extension (caselessly), the method
returns @samp{true}. @code{false} is returned otherwise.

@node Sound generation
@section Sound generation

You generate sound by using the @code{Copl::write(@var{reg},
@var{val})} method of the @code{Copl} class, which has been passed to
your constructor.

@var{reg} is the number of the register of the OPL chip, you want to
write data into. @var{val} is the value to write into it. There is no
method to read back written data from an OPL chip, as this also was
not possible with the original hardware. Log all data into an array if
you have to remember written values.

If your player supports the dual-OPL2 or OPL3 configurations, you can
use the method @code{Copl::setchip(@var{n})} to set the output chip
number, all subsequent @code{write()} methods will write to. As two
chips can be supported at maximum, the value of @var{n} may only be 0
or 1 for the first or the second chip, respectively.

Before switching to another chip, your player always has to make sure
that the configuration, you are going to address, is supported by the
current OPL class. This can be done by calling the
@code{Copl::gettype()} method, which will return the currently
supported OPL chip type as an enumeration of type
@code{Copl::ChipType}.

If the desired configuration is not supported, your player should
support playback on any of the other configurations. Your player
should never switch to another OPL chip when this is not actually
supported by the OPL class! The sound will be totally messed up.

@node Protracker based players
@chapter Protracker based players

If you want to create a player for a Protracker-derivative format, the
generic Protracker player @class{CmodPlayer} that comes with AdPlug can
be of great help. It supports all standard Protracker features, plus a
good set of extensions to cope with most derivative formats.

When writing a player for a Protracker-derivative format, it is almost
always better to use and extend the @code{CmodPlayer} class, instead
of writing a whole new player.

@menu
* Features::
* Defaults::
* Protracker Loaders::
* Designing your Loader::
* Loading Patterns::
* Loading Instruments::
* Special Flags::
* Special Arpeggio::
@end menu

@node Features
@section Features

In addition to handling your data just like the original Protracker
would, AdPlug's generic Protracker player has the following extra
features:

@itemize @bullet
@item Special Arpeggio lists, compatible with the SA2 format.
@item Extendable set of up to 256 note commands.
@item Simulates many different tracker flavors.
@item Arbitrary numbers of rows, patterns, tracks, instruments and
orderlist entries.
@end itemize

The only current limitation is that it has a maximum 9 voice
polyphony, which isn't really a limitation, since the OPL2 is just 9
voices, anyway.

@node Defaults
@section Defaults

For historical reasons, @code{CmodPlayer} sets defaults to some
values, so they need not be initialized. These are:

@itemize @bullet
@item The orderlist is preallocated to 128 entries.
@item The patterndata is preinitialized to 64 patterns with 9 channels
and 64 rows each.
@item The instruments array is preallocated to 250 instruments.
@item All flags are cleared (simulates Protracker flavor).
@end itemize

These are mostly standard Protracker limits. They stem from the
original SA2 defaults, for which this was once the player. Look at the
@code{CmodPlayer} constructor for info on which variables are
involved.

@node Protracker Loaders
@section Protracker Loaders

When you decided to extend the @code{CmodPlayer} class, instead of
writing a whole new player, you do this by writing a loader for
it. This is done very similarly to writing a unique player for
AdPlug. Thus, reading the @ref{Player development} chapter is
recommended for this task, too.

Instead of naming your player class @code{CxxxPlayer}, you should name
it @code{CxxxLoader} or something appropriate if the name is already
taken. You then publicly inherit the @code{CmodPlayer} class and fill
the missing methods with code. These are now:

@example
static CPlayer *factory(Copl *newopl);
bool load(const std::string &filename, const CFileProvider &fp);
float getrefresh();
std::string gettype();
@end example

Plus maybe some (or all) of the other informational methods, listed in
the @ref{Player development} chapter. Refer also to that chapter to
see what the above methods are about.

@node Designing your Loader
@section Designing your Loader

File validation and initial loading is the same as it would be with
any other player. One speciality is that you have to call
@code{rewind(0)} whenever you completely loaded a valid file. Don't
call it when you just exit your loader because the file was invalid!

The Protracker player needs at least an orderlist, the patterns and
the instruments to function. Most of the time, you have to convert
these between your file's ordering and @code{CmodPlayer}'s internal
ordering. Look in the file @file{protrack.cpp}, @code{CmodPlayer}'s
actual sources, for a list on how these constructs are ordered
internally.

Also, please look up the @ref{Defaults} section to see if you need to
reallocate any of the defaults.

There are some variables that you have automatically inherited with
your new loader and that you have to set in order to tell the
Protracker player something about your loaded module. These are the
following:

@vtable @code
@item length
The orderlist length. When @code{CmodPlayer}'s orderlist pointer
equals or is bigger than this length, it is automatically wrapped
around to @code{restartpos}. This variable has no default.

@item trackord
Refer to @ref{Loading Patterns} below on this one. This variable
defaults to @samp{0}.

@item restartpos
The restarting position in the orderlist, when @code{length} is
exceeded. This variable has no default.

@item activechan
A flag array, telling the player which channels in every pattern are
actually active and to be played. The ordering of this variable is a
bit awkward, so be careful! It is a 32-bit @code{unsigned long},
holding the activeness of a channel in each of its bits,
@emph{starting at the highest order bit}. It can hold values for up to
32 channels. So, to set channel 0 active, you have to set bit 31
(counting from bit 0) to @samp{1} and so on. Setting any bits for
channels that are not defined has no effect. This variable defaults to
all bits set to 1, meaning all channels are enabled.

@item initspeed
Initial protracker-compatible speed setting. This variable defaults to
@samp{6}, the standard Protracker speed setting.

@item bpm
Initial protracker-compatible bpm (sometimes called tempo)
setting. This variable has no default.

@item flags
Refer to @ref{Special Flags} below. This variable defaults to
@samp{Standard}, which sets standard Protracker defaults and imposes
no specialities.

@item nop
The number of patterns in your module. You don't need to set this
value. If you leave it at @samp{0}, @code{CmodPlayer} will
automatically determine the number of @emph{accessed} patterns (which
need not be the same as the actual number of patterns in your module)
from the orderlist, in the @code{rewind()} method. The value serves
only informational purposes, anyway. It is not needed for the actual
playback. If you think you know better than @code{CmodPlayer}, feel
free to set it to something else and @code{CmodPlayer} won't touch it
anymore and display your value instead. This variable defaults to
@samp{0}.
@end vtable

@node Loading Patterns
@section Loading Patterns

AdPlug's Protracker player stores the tracks (or channels, as some may
call them), that make up a pattern, in a way that makes it possible
for you to reorder and reuse them in an easy way. This also makes
storing patterns in the classic way a bit awkward.

If you just want to store your tracks the classic Protracker way
(usually the case), first use the @code{CmodPlayer::init_trackord()}
method to do an initial setup. Then store your tracks in a sequential
manner, counting from 0, in the @code{tracks} array. That is, for the
first 9 channels of your first pattern, use @code{tracks[0..9]}. The
second dimension of this array holds the rows of each channel. For the
next 9 channels, you use @code{tracks[10..19]}, and so on.

If you want to make use of the reorder/reuse feature of the
@code{trackord} array, please refer to the @file{sa2.cpp} source
file. This player utilizes this method.  Basically, the
@code{trackord} array tells the player which track out of the
@code{tracks} array it has to insert for each of the 9 tracks of a
pattern. Thus, the first dimension of this array stands for the
corresponding pattern and the next dimension holds the entries for all
the 9 tracks.

@code{CmodPlayer} orders its note data, in the @code{Tracks} struct,
the following way:

@code{note} holds the note value. A value of @samp{0} means @samp{no
note}. A value of @samp{127} means @samp{key off}. Values from
@samp{1} to @samp{96} are actual notes to be played. Everything else
is ignored. The octaves are encoded with the actual note values. Thus,
notes from @samp{1} to @samp{12} are the 12 halftone-steps of the
first, lowest octave, @samp{13} to @samp{24} are those of the next
lowest octave, and so on. Refer to the source code to see which
frequencies are actually associated with the note values.

@code{inst} holds the instrument to be played with this note. Again, a
@samp{0} value means no instrument is associated with this note and
the last active instrument is taken instead. Otherwise, the instrument
with the number @code{inst} minus 1 is fetched from the @code{inst}
array (it's 0 based).

@code{command} holds the command to be issued with this note. All
available commands are listed in the following table:

@multitable {@code{255--}} {Command descriptionwifuehwuifhw} {Parametersewufwuhwjjhhui} {@code{[0-3,F]iufhu}}
@headitem Value @tab Command description @tab Parameters @tab Range
@item @code{@ @ 0xy} @tab Arpeggio @tab @code{xy}=1st note,2nd note @tab @code{[0-F]}
@item @code{@ @ 1xx} @tab Frequency slide up @tab @code{xx}=sliding speed @tab @code{[0-FF]}
@item @code{@ @ 2xx} @tab Frequency slide down @tab @code{xx}=sliding speed @tab @code{[0-FF]}
@item @code{@ @ 3xx} @tab Tone portamento @tab @code{xx}=sliding speed @tab @code{[0-FF]}
@item @code{@ @ 4xy} @tab Vibrato @tab @code{xx}=speed,depth @tab @code{[0-F]}
@item @code{@ @ 5xy} @tab Tone portamento & volume slide @tab @code{xy}=vol up|vol down @tab @code{[0-FF]}
@item @code{@ @ 6xy} @tab Vibrato & volume slide @tab @code{xy}=vol up|vol down @tab @code{[0-FF]}
@item @code{@ @ 7xx} @tab Set tempo @tab @code{xx}=new tempo @tab @code{[0-FF]}
@item @code{@ @ 8--} @tab Release sustaining note
@item @code{@ @ 9xy} @tab Set carrier/modulator volume @tab @code{xy}=car vol|mod vol @tab @code{[0-F]}
@item @code{@ 10xy} @tab SA2 volume slide @tab @code{xy}=vol up|vol down @tab @code{[0-F]}
@item @code{@ 11xx} @tab Position jump @tab @code{xx}=new position @tab @code{[0-FF]}
@item @code{@ 12xx} @tab Set carr. & mod. volume @tab @code{xx}=new volume @tab @code{[0-3F]}
@item @code{@ 13xx} @tab Pattern break @tab @code{xx}=new row @tab @code{[0-FF]}
@item @code{@ 14??} @tab Extended command:
@item @code{@ @ @ 0y} @tab Set chip tremolo @tab @code{y}=new depth @tab @code{[0-1]}
@item @code{@ @ @ 1y} @tab Set chip vibrato @tab @code{y}=new depth @tab @code{[0-1]}
@item @code{@ @ @ 3y} @tab Retrig note @tab @code{y}=retrig speed @tab @code{[0-F]}
@item @code{@ @ @ 4y} @tab Fine volume slide up @tab @code{y}=vol up @tab @code{[0-F]}
@item @code{@ @ @ 5y} @tab Fine volume slide down @tab @code{y}=vol down @tab @code{[0-F]}
@item @code{@ @ @ 6y} @tab Fine frequency slide up @tab @code{y}=freq up @tab @code{[0-F]}
@item @code{@ @ @ 7y} @tab Fine frequency slide down @tab @code{y}=freq down @tab @code{[0-F]}
@item @code{@ @ @ 8y} @tab Pattern delay (rows) @tab @code{y}=rows to delay @tab @code{[0-F]}
@item @code{@ 15xx} @tab SA2 set speed @tab @code{xx}=new speed @tab @code{[0-FF]}
@item @code{@ 16xy} @tab AMD volume slide @tab @code{xy}=vol up|vol down @tab @code{[0-F]}
@item @code{@ 17xx} @tab Set instrument volume @tab @code{xx}=new volume @tab @code{[0-3F]}
@item @code{@ 18xx} @tab AMD set speed @tab @code{xx}=new speed @tab @code{[0-FF]}
@item @code{@ 19xx} @tab RAD set speed @tab @code{xx}=new speed @tab @code{[0-FF]}
@item @code{@ 20xx} @tab RAD volume slide @tab @code{xx}=vol up/down @tab @code{[0-FF]}
@item @code{@ 21xx} @tab Set modulator volume @tab @code{xx}=new volume @tab @code{[0-3F]}
@item @code{@ 22xx} @tab Set carrier volume @tab @code{xx}=new volume @tab @code{[0-3F]}
@item @code{@ 23xx} @tab Fine frequency slide up @tab @code{xx}=freq up @tab @code{[0-FF]}
@item @code{@ 24xx} @tab Fine frequency slide down @tab @code{xx}=freq down @tab @code{[0-FF]}
@item @code{@ 25xy} @tab Set carrier/modulator waveform @tab @code{xy}=carr wav|mod wav @tab @code{[0-3,F]}
@item @code{@ 26xy} @tab Volume slide @tab @code{xy}=vol up|vol down @tab @code{[0-F]}
@item @code{@ 27xy} @tab Set chip tremolo/vibrato @tab @code{xy}=tr depth|vb depth @tab @code{[0-1]}
@item @code{@ 28xy} @tab DTM frequency slide @tab @code{xy}=frames up|down @tab @code{[0-F]}
@item @code{@ 29xx} @tab Pattern delay (frames) @tab @code{xx}=frames to delay @tab @code{[0-FF]}
@item @code{255--} @tab No operation (NOP)
@end multitable

The @code{param1} and @code{param2} variables hold the command's
parameters. These are command-dependent. Refer to the table above to
see what they do with each of the commands and their value ranges. An
@samp{xx} in the @emph{Parameters} column means that @code{param1} and
@code{param2} form one 2-digit parameter, with @code{param1} being the
leftmost decimal. Otherwise, @samp{x} refers to @code{param1} and
@samp{y} to @code{param2}.

@node Loading Instruments
@section Loading Instruments

For the instrument data, @code{CmodPlayer} stores it in the
@code{inst[].data[]} array, in the following way:

@multitable {Index} {Modulator} {Amp Mod / Vib / EG type / Key Scaling / Multiple} {@samp{0x00}}
@headitem Index @tab Operator @tab Description @tab Register
@item 0 @tab Channel @tab (Panning) / Feedback strength / Connection type @tab @samp{0xc0}
@item 1 @tab Modulator @tab Tremolo / Vibrato / Sustain / KSR / Multiple @tab @samp{0x20}
@item 2	@tab Carrier @tab Tremolo / Vibrato / Sustain / KSR / Multiple @tab @samp{0x23}
@item 3 @tab Modulator @tab Attack Rate / Decay Rate @tab @samp{0x60}
@item 4 @tab Carrier @tab Attack Rate / Decay Rate @tab @samp{0x63}
@item 5 @tab Modulator @tab Sustain Level / Release Rate @tab @samp{0x80}
@item 6 @tab Carrier @tab Sustain Level / Release Rate @tab @samp{0x83}
@item 7 @tab Modulator @tab Wave Select @tab @samp{0xe0}
@item 8 @tab Carrier @tab Wave Select @tab @samp{0xe3}
@item 9 @tab Modulator @tab Key scaling level / Operator output level @tab @samp{0x40}
@item 10 @tab Carrier @tab Key scaling level / Operator output level @tab @samp{0x43}
@end multitable

There are three extensions to the standard instrument data. These are
also stored within the @code{inst[]} array.

@enumerate
@item The @emph{Special Arpeggio}. This is explained in the
@ref{Special Arpeggio} section, below.

@item The @code{slide} variable. This is a pre-slide value that is
always added to the frequency of the note, whenever this instrument is
to be played.

@item The @code{misc} variable. This is just the holder for the value
of the 0xbd register (i.e. the "drums'n'misc" register) of the OPL.
@end enumerate

@node Special Flags
@section Special Flags

The @code{flags} variable holds special flags to change the behaviour
of the player. These are:

@table @samp
@item Standard
Act like standard Protracker would. This is the default.

@item Decimal
Command parameters are decimal values, not hexadecimal. For split
parameter commands (i.e. commands with two parameters, like
@samp{0xy}), this has no effect, since decimal values would be from
@samp{0} to @samp{9}, anyway. But commands that take both parameters
as one value (i.e. like @samp{1xx}) now take values from @samp{0} to
@samp{99} and handle them properly (i.e. decimal wrap-around is now at
@samp{9} to @samp{10} and not at @samp{F} to @samp{10}).

@item Faust
Treat the files like @emph{Faust Music Creator} does. This tracker
uses a different volume handling scheme. In standard Protracker, the
volume is computed as follows:

@example
final volume = channel volume = instrument volume
@end example

In @emph{Faust Music Creator}, it is done like this:

@example
final volume = (channel volume + instrument volume) / 2
@end example

@item NoKeyOn
This prevents the OPL key off/on toggle on every newly played
note. Some trackers require it that way...

@item Opl3
Sets the player into OPL3 mode. Extended register settings of the OPL3
become effective and the player initializes the OPL chip to OPL3
mode. This has no effect if the hardware does not support OPL3
features. Be careful to set panning information in register
@code{0xc0} or else no sound will appear.

@item Tremolo
Sets tremolo depth to 4.8dB upon each @code{rewind()}.

@item Vibrato
Sets Vibrato depth to 14 cents upon each @code{rewind()}.

@item Percussion
Enables the OPL percussion mode.
@end table

These flags can be set and unset at any time. To set a flag, just
binary @emph{OR} it with the @code{flags} variable. Use the
@code{enum Flags} data type, defined in the @code{CmodPlayer} class
for this purpose.

@node Special Arpeggio
@section Special Arpeggio

To use the @emph{Special Arpeggio} facility, you have to initialize it
first. Use the @code{init_specialarp()} method for this
purpose. @code{CmodPlayer}'s deconstructor automatically handles the
deinit for you.

The special arpeggio uses the 4 variables @code{arpstart},
@code{arpspeed}, @code{arppos} and @code{arpspdcnt} of the
@code{Instrument} struct.

[TODO: actually explain. Refer to sa2.[cpp,h] and the original SA2 docs in
the meantime. The following table summarizes the special commands.]

@multitable {Value} {Set carr. & mod. volume}
@headitem Value @tab Command description
@item @samp{252} @tab Set carr. & mod. volume
@item @samp{253} @tab Release sustaining note
@item @samp{254} @tab Arpeggio loop
@item @samp{255} @tab End of special arpeggio
@end multitable

@node Copying This Manual
@appendix Copying This Manual

@menu
* GNU Free Documentation License::  License for copying this manual.
@end menu

@include fdl.texi

@node Method Index
@unnumbered Method Index

@printindex fn

@node Variable Index
@unnumbered Variable Index

@printindex vr

@node Class Index
@unnumbered Class Index

@printindex tp

@shortcontents

@bye
