mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-14 08:30:49 +00:00
f6866df0e6
timidity_voices cvar. - Added stats lines for the OPL and Timidity MIDI devices. - Completely changed the way TiMidity volume calculations are done. It should now be extremely close to the output a real GUS would produce with its official MIDI player (excepting where TiMidity normalizes sample volumes). The new equations more closely match what is specified by the DLS and SF2 specs (but not quite), so I presume it's also more musically correct than what TiMidity (and TiMidity++) do. SVN r925 (trunk)
287 lines
8.5 KiB
C
287 lines
8.5 KiB
C
/*
|
|
* Name: Main header include file
|
|
* Project: MUS File Player Library
|
|
* Version: 1.75
|
|
* Author: Vladimir Arnost (QA-Software)
|
|
* Last revision: Mar-9-1996
|
|
* Compiler: Borland C++ 3.1, Watcom C/C++ 10.0
|
|
*
|
|
*/
|
|
|
|
/* From muslib175.zip/README.1ST:
|
|
|
|
1.1 - Disclaimer of Warranties
|
|
------------------------------
|
|
|
|
#ifdef LAWYER
|
|
|
|
THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
|
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
SUCH DAMAGE.
|
|
|
|
#else
|
|
|
|
Use this software at your own risk.
|
|
|
|
#endif
|
|
|
|
|
|
1.2 - Terms of Use
|
|
------------------
|
|
|
|
This library may be used in any freeware or shareware product free of
|
|
charge. The product may not be sold for profit (except for shareware) and
|
|
should be freely available to the public. It would be nice of you if you
|
|
credited me in your product and notified me if you use this library.
|
|
|
|
If you want to use this library in a commercial product, contact me
|
|
and we will make an agreement. It is a violation of the law to make money
|
|
of this product without prior signing an agreement and paying a license fee.
|
|
This licence will allow its holder to sell any products based on MUSLib,
|
|
royalty-free. There is no need to buy separate licences for different
|
|
products once the licence fee is paid.
|
|
|
|
|
|
1.3 - Contacting the Author
|
|
---------------------------
|
|
|
|
Internet (address valid probably until the end of year 1998):
|
|
xarnos00@dcse.fee.vutbr.cz
|
|
|
|
FIDO:
|
|
2:423/36.2
|
|
|
|
Snail-mail:
|
|
|
|
Vladimir Arnost
|
|
Ceska 921
|
|
Chrudim 4
|
|
537 01
|
|
CZECH REPUBLIC
|
|
|
|
Voice-mail (Czech language only, not recommended; weekends only):
|
|
|
|
+42-455-2154
|
|
*/
|
|
|
|
#ifndef __MUSLIB_H_
|
|
#define __MUSLIB_H_
|
|
|
|
#ifndef __DEFTYPES_H_
|
|
#include "deftypes.h"
|
|
#endif
|
|
#include "files.h"
|
|
|
|
/* Global Definitions */
|
|
|
|
#define MLVERSION 0x0175
|
|
#define MLVERSIONSTR "1.75"
|
|
extern char MLversion[];
|
|
extern char MLcopyright[];
|
|
|
|
#define CHANNELS 16 // total channels 0..CHANNELS-1
|
|
#define PERCUSSION 15 // percussion channel
|
|
|
|
/* MUS file header structure */
|
|
struct MUSheader {
|
|
char ID[4]; // identifier "MUS" 0x1A
|
|
WORD scoreLen; // score length
|
|
WORD scoreStart; // score start
|
|
WORD channels; // primary channels
|
|
WORD sec_channels; // secondary channels (??)
|
|
WORD instrCnt; // used instrument count
|
|
WORD dummy;
|
|
// WORD instruments[...]; // table of used instruments
|
|
};
|
|
|
|
/* OPL2 instrument */
|
|
struct OPL2instrument {
|
|
/*00*/ BYTE trem_vibr_1; /* OP 1: tremolo/vibrato/sustain/KSR/multi */
|
|
/*01*/ BYTE att_dec_1; /* OP 1: attack rate/decay rate */
|
|
/*02*/ BYTE sust_rel_1; /* OP 1: sustain level/release rate */
|
|
/*03*/ BYTE wave_1; /* OP 1: waveform select */
|
|
/*04*/ BYTE scale_1; /* OP 1: key scale level */
|
|
/*05*/ BYTE level_1; /* OP 1: output level */
|
|
/*06*/ BYTE feedback; /* feedback/AM-FM (both operators) */
|
|
/*07*/ BYTE trem_vibr_2; /* OP 2: tremolo/vibrato/sustain/KSR/multi */
|
|
/*08*/ BYTE att_dec_2; /* OP 2: attack rate/decay rate */
|
|
/*09*/ BYTE sust_rel_2; /* OP 2: sustain level/release rate */
|
|
/*0A*/ BYTE wave_2; /* OP 2: waveform select */
|
|
/*0B*/ BYTE scale_2; /* OP 2: key scale level */
|
|
/*0C*/ BYTE level_2; /* OP 2: output level */
|
|
/*0D*/ BYTE unused;
|
|
/*0E*/ sshort basenote; /* base note offset */
|
|
};
|
|
|
|
/* OP2 instrument file entry */
|
|
struct OP2instrEntry {
|
|
/*00*/ WORD flags; // see FL_xxx below
|
|
/*02*/ BYTE finetune; // finetune value for 2-voice sounds
|
|
/*03*/ BYTE note; // note # for fixed instruments
|
|
/*04*/ struct OPL2instrument instr[2]; // instruments
|
|
};
|
|
|
|
#define FL_FIXED_PITCH 0x0001 // note has fixed pitch (see below)
|
|
#define FL_UNKNOWN 0x0002 // ??? (used in instrument #65 only)
|
|
#define FL_DOUBLE_VOICE 0x0004 // use two voices instead of one
|
|
|
|
|
|
#define OP2INSTRSIZE sizeof(struct OP2instrEntry) // instrument size (36 bytes)
|
|
#define OP2INSTRCOUNT (128 + 81-35+1) // instrument count
|
|
|
|
/* From MLOPL_IO.CPP */
|
|
#define OPL2CHANNELS 9
|
|
#define OPL3CHANNELS 18
|
|
#define MAXCHANNELS 18
|
|
|
|
|
|
/* Channel Flags: */
|
|
#define CH_SECONDARY 0x01
|
|
#define CH_SUSTAIN 0x02
|
|
#define CH_VIBRATO 0x04 /* set if modulation >= MOD_MIN */
|
|
#define CH_FREE 0x80
|
|
|
|
struct OPLdata {
|
|
uint channelInstr[CHANNELS]; // instrument #
|
|
uchar channelVolume[CHANNELS]; // volume
|
|
uchar channelLastVolume[CHANNELS]; // last volume
|
|
schar channelPan[CHANNELS]; // pan, 0=normal
|
|
schar channelPitch[CHANNELS]; // pitch wheel, 0=normal
|
|
uchar channelSustain[CHANNELS]; // sustain pedal value
|
|
uchar channelModulation[CHANNELS]; // modulation pot value
|
|
};
|
|
|
|
struct OPLio {
|
|
virtual ~OPLio();
|
|
|
|
void OPLwriteChannel(uint regbase, uint channel, uchar data1, uchar data2);
|
|
void OPLwriteValue(uint regbase, uint channel, uchar value);
|
|
void OPLwriteFreq(uint channel, uint freq, uint octave, uint keyon);
|
|
uint OPLconvertVolume(uint data, uint volume);
|
|
uint OPLpanVolume(uint volume, int pan);
|
|
void OPLwriteVolume(uint channel, struct OPL2instrument *instr, uint volume);
|
|
void OPLwritePan(uint channel, struct OPL2instrument *instr, int pan);
|
|
void OPLwriteInstrument(uint channel, struct OPL2instrument *instr);
|
|
void OPLshutup(void);
|
|
void OPLwriteInitState();
|
|
|
|
virtual int OPLinit(uint numchips);
|
|
virtual void OPLdeinit(void);
|
|
virtual void OPLwriteReg(int which, uint reg, uchar data);
|
|
virtual void SetClockRate(double samples_per_tick);
|
|
virtual void WriteDelay(int ticks);
|
|
|
|
uint OPLchannels;
|
|
};
|
|
|
|
struct DiskWriterIO : public OPLio
|
|
{
|
|
DiskWriterIO(const char *filename);
|
|
~DiskWriterIO();
|
|
|
|
int OPLinit(uint numchips);
|
|
void OPLdeinit();
|
|
void OPLwriteReg(int which, uint reg, uchar data);
|
|
void SetClockRate(double samples_per_tick);
|
|
void WriteDelay(int ticks);
|
|
|
|
void SetChip(int chipnum);
|
|
|
|
FILE *File;
|
|
FString Filename;
|
|
int Format;
|
|
bool NeedClockRate;
|
|
double TimePerTick; // In milliseconds
|
|
double CurTime;
|
|
int CurIntTime;
|
|
int TickMul;
|
|
int CurChip;
|
|
|
|
enum { FMT_RDOS, FMT_DOSBOX };
|
|
};
|
|
|
|
struct musicBlock {
|
|
musicBlock();
|
|
~musicBlock();
|
|
|
|
BYTE *score;
|
|
BYTE *scoredata;
|
|
int playingcount;
|
|
OPLdata driverdata;
|
|
OPLio *io;
|
|
|
|
struct OP2instrEntry *OPLinstruments;
|
|
|
|
ulong MLtime;
|
|
|
|
void OPLplayNote(uint channel, uchar note, int volume);
|
|
void OPLreleaseNote(uint channel, uchar note);
|
|
void OPLpitchWheel(uint channel, int pitch);
|
|
void OPLchangeControl(uint channel, uchar controller, int value);
|
|
void OPLprogramChange(uint channel, int value);
|
|
void OPLplayMusic(int vol);
|
|
void OPLstopMusic();
|
|
void OPLchangeVolume(uint volume);
|
|
|
|
int OPLloadBank (FileReader &data);
|
|
|
|
protected:
|
|
/* OPL channel (voice) data */
|
|
struct channelEntry {
|
|
uchar channel; /* MUS channel number */
|
|
uchar note; /* note number */
|
|
uchar flags; /* see CH_xxx below */
|
|
uchar realnote; /* adjusted note number */
|
|
schar finetune; /* frequency fine-tune */
|
|
sint pitch; /* pitch-wheel value */
|
|
uint volume; /* note volume */
|
|
uint realvolume; /* adjusted note volume */
|
|
struct OPL2instrument *instr; /* current instrument */
|
|
ulong time; /* note start time */
|
|
} channels[MAXCHANNELS];
|
|
|
|
void writeFrequency(uint slot, uint note, int pitch, uint keyOn);
|
|
void writeModulation(uint slot, struct OPL2instrument *instr, int state);
|
|
uint calcVolume(uint channelVolume, uint MUSvolume, uint noteVolume);
|
|
int occupyChannel(uint slot, uint channel,
|
|
int note, int volume, struct OP2instrEntry *instrument, uchar secondary);
|
|
int releaseChannel(uint slot, uint killed);
|
|
int releaseSustain(uint channel);
|
|
int findFreeChannel(uint flag, uint channel, uchar note);
|
|
struct OP2instrEntry *getInstrument(uint channel, uchar note);
|
|
|
|
friend class Stat_opl;
|
|
|
|
};
|
|
|
|
enum MUSctrl {
|
|
ctrlPatch = 0,
|
|
ctrlBank,
|
|
ctrlModulation,
|
|
ctrlVolume,
|
|
ctrlPan,
|
|
ctrlExpression,
|
|
ctrlReverb,
|
|
ctrlChorus,
|
|
ctrlSustainPedal,
|
|
ctrlSoftPedal,
|
|
_ctrlCount_,
|
|
ctrlSoundsOff = _ctrlCount_,
|
|
ctrlNotesOff,
|
|
ctrlMono,
|
|
ctrlPoly,
|
|
ctrlResetCtrls
|
|
};
|
|
|
|
#define OPL_SAMPLE_RATE 49716.0
|
|
#define ADLIB_CLOCK_MUL 24.0
|
|
|
|
#endif // __MUSLIB_H_
|