(* STMB.PAS -- Pascal Programming interface for FMSYNTH.DRV
 *             Copyright (c) 1993 by Jamie O'Connell
 *
 * Currently four functions are defined: GetTimbre, SetTimbre, GetPercMap,
 * ans SetPercMap.
 * 
 * Get Timbre retrieves the Timbre parameters from the specified location.
 *
 * SetTimbre will change the sound of an instrument in either working 
 * storage or the sound of an instrument stored within a RAM Timbre Bank.
 * 
 * GetPercMap and SetPercMap perform equivalent functions on the internal
 * percussion map: which note plays which percussion timbre at what pitch.
 *
 * Working storage is the current version of a Timbre stored on a 
 * per-channel basis.  It is the version of the timbre which is used to
 * sound a voice for the channel when a note is to be played. The working 
 * storage is overwritten by Bank storage whenever a program change is 
 * received for the channel.
 *
 * The RAM Timbre bank is either the internal Timbre Bank, or one which 
 * has been loaded from a file.  In either case it is volatile storage
 * which is overwritten when the bank is reloaded.
 *)

unit STmb;

interface

uses WinTypes, WinProcs;

const
  TMB_WORKING_STORAGE  =  0;
  TMB_BANK_STORAGE     =  1;
  TMB_BANK_PERCUSSION  =  2;

  FIRSTDRUMNOTE = 35;
  LASTDRUMNOTE  = 81;
  NUMDRUMNOTES  = (LASTDRUMNOTE - FIRSTDRUMNOTE + 1);

Type

(* The timbre definition (IBK - SBI Format) *)

  PTmbRec = ^TmbRec;
  TmbRec  = Record
    MSndChr : Byte;
    CSndChr : Byte;
    MKSLOut : Byte;
    CKSLOut : Byte;
    MAtkDcy : Byte;
    CAtkDcy : Byte;
    MSusRel : Byte;
    CSusRel : Byte;
    MWavSel : Byte;
    CWavSel : Byte;
    FDBkCon : Byte;
    PercVoc : Byte;
    Transps : ShortInt;
    Future1 : Byte;
    Future2 : Word;
  end;

PercElem = Record
    patch : Byte;
    note  : Byte;
  end;


PPercMap = ^PercMap;
PercMap  = Array [1..NUMDRUMNOTES] of PercElem;

(* The percussion map provides info for each pecussion MIDI key
 * To access (retrieve or send) the Percussion map you create an
 * array of these things: PERCMAP percMap[NUMDRUMNOTES];
 * and pass it to GetPercMap or SetPercMap.  The buffer must be at least
 * sizeof(PERCMAP) * NUMDRUMNOTES = 94 bytes large.
 *)

Procedure GetPercMap(lpPM: PPercMap); Far;
Procedure SetPercMap(lpPM: PPercMap); Far;

Function GetTimbre(wLoc: Word; lpTmb: PTmbRec; wSrc: Word): Word;  Far;
Function SetTimbre(wLoc: Word; lpTmb: PTmbRec; wDest: Word): Word; Far;

(*
 *  DESCRIPTION
 *
 *  wLoc - If the Destination (wDest) or Source (wSrc) is TMB_WORKING_STORAGE,
 *         then wLoc is the channel number (0 based) for storing the Timbre.
 *         If the Destination is TMB_BANK_STORAGE, then the most
 *         significant byte of wLoc (HIBYTE(wLoc)) is the Bank number
 *         (valid values: 0 - 4), and the least significant byte is the
 *         timbre number (0-127).
 *         If the destination is TMB_PERC_BANK, the Bank number is ignored
 *         (there is only one percussion bank), and the LSB is the timbre
 *         number (0-46).
 *
 *  lpTmb  A far pointer to a TIMBRE structure, defining the new timbre to
 *         store.  The structure should be the full 16 bytes in length.
 *
 *  wSrc   This value determines how wLoc is interpreted when retrieving
 *         the timbre.  If wSrc is TMB_WORKING_STORAGE the timbre is retrieved
 *         from working storage (wLoc is a channel number). If wSrc is
 *         TMB_BANK_STORAGE, the timbre is retrieved from the specified
 *         bank and timbre slot (wLoc is the combination of Bank & Timbre#).
 *
 *  wDest  This value determines how wLoc is interpreted and the final
 *         destination for the timbre.  If wDest is ST_WORKING_STORAGE the
 *         channel timbre info is updated, and future voices on channel will
 *         sound this timbre. If wDest is ST_BANK_STORAGE, both the Bank
 *         Timbre, and any channels set to this Bank and Timbre are updated.
 *         Any future notes playing this bank and timbre will sound the
 *         timbre.
 *
 *  Return Value
 *         If all goes well, 0 is returned, otherwise a non-zero value is
 *         returned indicating, an incorrect or out-of-range parameter.
 *         The values within the TIMBRE structure itself are not checked
 *         for validity, but stored as supplied.
 *)

implementation

Procedure GetPercMap;  external 'FMSYNTH' index  9;
Procedure SetPercMap;  external 'FMSYNTH' index 10;

Function GetTimbre;    external 'FMSYNTH' index  7;
Function SetTimbre;    external 'FMSYNTH' index  8;

end.

