[Contents] [Index] [Help] [Retrace] [Browse <] [Browse >]

/*----------------------------------------------------------------------*
 * SMUS.H  Definitions for Simple MUSical score.   2/12/86
 *
 * By Jerry Morrison and Steve Hayes, Electronic Arts.
 * This software is in the public domain.
 *
 * Modified for use with iffparse.library 05/91 - CAS_CBM
 *
 * This version for the Amiga computer.
 *----------------------------------------------------------------------*/

#ifndef SMUS_H
#define SMUS_H

#ifndef COMPILER_H
#include "iffp/compiler.h"
#endif

#include "iffp/iff.h"

#define ID_SMUS      MAKE_ID('S', 'M', 'U', 'S')
#define ID_SHDR      MAKE_ID('S', 'H', 'D', 'R')

/* Now defined in iffp/iff.h as generic chunks
#define ID_NAME      MAKE_ID('N', 'A', 'M', 'E')
#define ID_Copyright MAKE_ID('(', 'c', ')', ' ')
#define ID_AUTH      MAKE_ID('A', 'U', 'T', 'H')
#define ID_ANNO      MAKE_ID('A', 'N', 'N', 'O')
*/

#define ID_INS1      MAKE_ID('I', 'N', 'S', '1')
#define ID_TRAK      MAKE_ID('T', 'R', 'A', 'K')


/* ---------- SScoreHeader ---------------------------------------------*/
typedef struct {
    UWORD tempo;        /* tempo, 128ths quarter note/minute */
    UBYTE volume;       /* playback volume 0 through 127 */
    UBYTE ctTrack;      /* count of tracks in the score */
    } SScoreHeader;

/* ---------- NAME -----------------------------------------------------*/
/* NAME chunk contains a CHAR[], the musical score's name. */

/* ---------- Copyright (c) --------------------------------------------*/
/* "(c) " chunk contains a CHAR[], the FORM's copyright notice. */

/* ---------- AUTH -----------------------------------------------------*/
/* AUTH chunk contains a CHAR[], the name of the score's author. */

/* ---------- ANNO -----------------------------------------------------*/
/* ANNO chunk contains a CHAR[], the author's text annotations. */

/* ---------- INS1 -----------------------------------------------------*/
/* Constants for the RefInstrument's "type" field. */
#define INS1_Name  0    /* just use the name; ignore data1, data2 */
#define INS1_MIDI  1    /* <data1, data2> = MIDI <channel, preset> */

typedef struct {
    UBYTE iRegister;    /* set this instrument register number */
    UBYTE type;         /* instrument reference type (see above) */
    UBYTE data1, data2; /* depends on the "type" field */
    char name[60];      /* instrument name */
    } RefInstrument;

/* ---------- TRAK -----------------------------------------------------*/
/* TRAK chunk contains an SEvent[]. */

/* SEvent: Simple musical event. */
typedef struct {
    UBYTE sID;          /* SEvent type code */
    UBYTE data;         /* sID-dependent data */
    } SEvent;

/* SEvent type codes "sID". */
#define SID_FirstNote     0
#define SID_LastNote    127     /* sIDs in the range SID_FirstNote through
                                 * SID_LastNote (sign bit = 0) are notes. The
                                 * sID is the MIDI tone number (pitch). */
#define SID_Rest        128     /* a rest; same data format as a note. */

#define SID_Instrument  129     /* set instrument number for this track. */
#define SID_TimeSig     130     /* set time signature for this track. */
#define SID_KeySig      131     /* set key signature for this track. */
#define SID_Dynamic     132     /* set volume for this track. */
#define SID_MIDI_Chnl   133     /* set MIDI channel number (sequencers) */
#define SID_MIDI_Preset 134     /* set MIDI preset number (sequencers) */
#define SID_Clef        135     /* inline clef change.
                                 * 0=Treble, 1=Bass, 2=Alto, 3=Tenor. */
#define SID_Tempo       136     /* Inline tempo change in beats per minute.*/

/* SID values 144 through 159: reserved for Instant Music SEvents. */

/* The remaining sID values up through 254: reserved for future
 * standardization. */
#define SID_Mark        255     /* SID reserved for an end-mark in RAM. */


/* ---------- SEvent FirstNote..LastNote or Rest -----------------------*/
typedef struct {
    unsigned tone     :8,       /* MIDI tone number 0 to 127; 128 = rest */
             chord    :1,       /* 1 = a chorded note */
             tieOut   :1,       /* 1 = tied to the next note or chord */
             nTuplet  :2,       /* 0 = none, 1 = triplet, 2 = quintuplet,
                                 * 3 = septuplet */
             dot      :1,       /* dotted note; multiply duration by 3/2 */
             division :3;       /* basic note duration is 2**-division:
                                 * 0 = whole note, 1 = half note, 2 = quarter
                                 * note, ... 7 = 128th note */
    } SNote;

/* Warning: An SNote is supposed to be a 16-bit entity.
 * Some C compilers will not pack bit fields into anything smaller
 * than an int. So avoid the actual use of this type unless you are certain
 * that the compiler packs it into a 16-bit word.
 */


/* You may get better object code by masking, ORing, and shifting using the
 * following definitions rather than the bit-packed fields, above. */
#define noteChord  (1<<7)     /* note is chorded to next note */

#define noteTieOut (1<<6)     /* note/chord is tied to next note/chord */

#define noteNShift 4                    /* shift count for nTuplet field */
#define noteN3     (1<<noteNShift)    /* note is a triplet */
#define noteN5     (2<<noteNShift)    /* note is a quintuplet */
#define noteN7     (3<<noteNShift)    /* note is a septuplet */
#define noteNMask  noteN7               /* bit mask for the nTuplet field */

#define noteDot    (1<<3)             /* note is dotted */

#define noteDShift 0                    /* shift count for division field */
#define noteD1     (0<<noteDShift)    /* whole note division */
#define noteD2     (1<<noteDShift)    /* half note division */
#define noteD4     (2<<noteDShift)    /* quarter note division */
#define noteD8     (3<<noteDShift)    /* eighth note division */
#define noteD16    (4<<noteDShift)    /* sixteenth note division */
#define noteD32    (5<<noteDShift)    /* thirty-secondth note division */
#define noteD64    (6<<noteDShift)    /* sixty-fourth note division */
#define noteD128   (7<<noteDShift)    /* 1/128 note division */
#define noteDMask  noteD128             /* bit mask for the division field */

#define noteDurMask 0x3F                /* bit mask for all duration fields
                                         * division, nTuplet, dot */

/* Field access: */
#define IsChord(snote)  (((UWORD)snote) & noteChord)
#define IsTied(snote)   (((UWORD)snote) & noteTieOut)
#define NTuplet(snote)  ((((UWORD)snote) & noteNMask) >> noteNShift)
#define IsDot(snote)    (((UWORD)snote) & noteDot)
#define Division(snote) ((((UWORD)snote) & noteDMask) >> noteDShift)

/* ---------- TimeSig SEvent -------------------------------------------*/
typedef struct {
    unsigned type     :8,       /* = SID_TimeSig */
             timeNSig :5,       /* time signature "numerator" timeNSig + 1 */
             timeDSig :3;       /* time signature "denominator" is
                                 * 2**timeDSig: 0 = whole note, 1 = half
                                 * note, 2 = quarter note, ...
                                 * 7 = 128th note */
    } STimeSig;

#define timeNMask  0xF8         /* bit mask for timeNSig field */
#define timeNShift 3            /* shift count for timeNSig field */

#define timeDMask  0x07         /*  bit mask for timeDSig field */

/* Field access: */
#define TimeNSig(sTime)  ((((UWORD)sTime) & timeNMask) >> timeNShift)
#define TimeDSig(sTime)   (((UWORD)sTime) & timeDMask)

/* ---------- KeySig SEvent --------------------------------------------*/
/* "data" value 0 = Cmaj; 1 through 7 = G,D,A,E,B,F#,C#;
 * 8 through 14 = F,Bb,Eb,Ab,Db,Gb,Cb.                                  */

/* ---------- Dynamic SEvent -------------------------------------------*/
/* "data" value is a MIDI key velocity 0..127. */


/* ---------- SMUS Writer Support Routines -----------------------------*/

/* Just call this to write a SHDR chunk. */
#define PutSHDR(iff, ssHdr)  \
    PutCk(iff, ID_SHDR, sizeof(SScoreHeader), (BYTE *)ssHdr)

#endif