dosgame1/audio/rad20player.h

174 lines
6.7 KiB
C++

#ifndef RAD20PLAYER_H
#define RAD20PLAYER_H
#include <stdint.h>
//==================================================================================================
// RAD player class.
//==================================================================================================
class RADPlayer {
// Various constants
enum {
kTracks = 100,
kChannels = 9,
kTrackLines = 64,
kRiffTracks = 10,
kInstruments = 127,
cmPortamentoUp = 0x1,
cmPortamentoDwn = 0x2,
cmToneSlide = 0x3,
cmToneVolSlide = 0x5,
cmVolSlide = 0xA,
cmSetVol = 0xC,
cmJumpToLine = 0xD,
cmSetSpeed = 0xF,
cmIgnore = ('I' - 55),
cmMultiplier = ('M' - 55),
cmRiff = ('R' - 55),
cmTranspose = ('T' - 55),
cmFeedback = ('U' - 55),
cmVolume = ('V' - 55),
};
enum e_Source {
SNone, SRiff, SIRiff,
};
enum {
fKeyOn = 1 << 0,
fKeyOff = 1 << 1,
fKeyedOn = 1 << 2,
};
struct CInstrument {
uint8_t Feedback[2];
uint8_t Panning[2];
uint8_t Algorithm;
uint8_t Detune;
uint8_t Volume;
uint8_t RiffSpeed;
uint8_t * Riff;
uint8_t Operators[4][5];
};
struct CEffects {
int8_t PortSlide;
int8_t VolSlide;
uint16_t ToneSlideFreq;
uint8_t ToneSlideOct;
uint8_t ToneSlideSpeed;
int8_t ToneSlideDir;
};
struct CChannel {
uint8_t LastInstrument;
CInstrument * Instrument;
uint8_t Volume;
uint8_t DetuneA;
uint8_t DetuneB;
uint8_t KeyFlags;
uint16_t CurrFreq;
int8_t CurrOctave;
CEffects FX;
struct CRiff {
CEffects FX;
uint8_t * Track;
uint8_t * TrackStart;
uint8_t Line;
uint8_t Speed;
uint8_t SpeedCnt;
int8_t TransposeOctave;
int8_t TransposeNote;
uint8_t LastInstrument;
} Riff, IRiff;
};
public:
RADPlayer() : Initialised(false) {}
void Init(const void *tune, void (*opl3)(void *, uint16_t, uint8_t), void *arg);
void Stop();
bool Update();
int GetHertz() const { return Hertz; }
int GetPlayTimeInSeconds() const { return PlayTime / Hertz; }
int GetTunePos() const { return Order; }
int GetTuneLength() const { return OrderListSize; }
int GetTuneLine() const { return Line; }
void SetMasterVolume(int vol) { MasterVol = vol; }
int GetMasterVolume() const { return MasterVol; }
int GetSpeed() const { return Speed; }
#if RAD_DETECT_REPEATS
uint32_t ComputeTotalTime();
#endif
private:
bool UnpackNote(uint8_t *&s, uint8_t &last_instrument);
uint8_t * GetTrack();
uint8_t * SkipToLine(uint8_t *trk, uint8_t linenum, bool chan_riff = false);
void PlayLine();
void PlayNote(int channum, int8_t notenum, int8_t octave, uint16_t instnum, uint8_t cmd = 0, uint8_t param = 0, e_Source src = SNone, int op = 0);
void LoadInstrumentOPL3(int channum);
void PlayNoteOPL3(int channum, int8_t octave, int8_t note);
void ResetFX(CEffects *fx);
void TickRiff(int channum, CChannel::CRiff &riff, bool chan_riff);
void ContinueFX(int channum, CEffects *fx);
void SetVolume(int channum, uint8_t vol);
void GetSlideDir(int channum, CEffects *fx);
void LoadInstMultiplierOPL3(int channum, int op, uint8_t mult);
void LoadInstVolumeOPL3(int channum, int op, uint8_t vol);
void LoadInstFeedbackOPL3(int channum, int which, uint8_t fb);
void Portamento(uint16_t channum, CEffects *fx, int8_t amount, bool toneslide);
void Transpose(int8_t note, int8_t octave);
void SetOPL3(uint16_t reg, uint8_t val) {
OPL3Regs[reg] = val;
OPL3(OPL3Arg, reg, val);
}
uint8_t GetOPL3(uint16_t reg) const {
return OPL3Regs[reg];
}
void (*OPL3)(void *, uint16_t, uint8_t);
void * OPL3Arg;
CInstrument Instruments[kInstruments];
CChannel Channels[kChannels];
uint32_t PlayTime;
#if RAD_DETECT_REPEATS
uint32_t OrderMap[4];
bool Repeating;
#endif
int16_t Hertz;
uint8_t * OrderList;
uint8_t * Tracks[kTracks];
uint8_t * Riffs[kRiffTracks][kChannels];
uint8_t * Track;
bool Initialised;
uint8_t Speed;
uint8_t OrderListSize;
uint8_t SpeedCnt;
uint8_t Order;
uint8_t Line;
int8_t Entrances;
uint8_t MasterVol;
int8_t LineJump;
uint8_t OPL3Regs[512];
// Values exported by UnpackNote()
int8_t NoteNum;
int8_t OctaveNum;
uint8_t InstNum;
uint8_t EffectNum;
uint8_t Param;
bool LastNote;
static const int8_t NoteSize[];
static const uint16_t ChanOffsets3[9], Chn2Offsets3[9];
static const uint16_t NoteFreq[];
static const uint16_t OpOffsets3[9][4];
static const bool AlgCarriers[7][4];
};
#endif