aboutsummaryrefslogtreecommitdiff
path: root/src/dbopl.h
diff options
context:
space:
mode:
authorPhilippe Simons <simons.philippe@gmail.com>2017-02-16 17:48:52 +0100
committerGitHub <noreply@github.com>2017-02-16 17:48:52 +0100
commit687541e61b381b57d609d0c7da7882792bd02478 (patch)
treefba5c564256a68f0ebdb5e5834abdcff1a27e69c /src/dbopl.h
parent20aff6650e77940237f696e33728a85b1f566fa9 (diff)
parent04825f095d3c00d1e97924c38654a2c888e7ef9d (diff)
downloadlibADLMIDI-687541e61b381b57d609d0c7da7882792bd02478.tar.gz
libADLMIDI-687541e61b381b57d609d0c7da7882792bd02478.tar.bz2
libADLMIDI-687541e61b381b57d609d0c7da7882792bd02478.zip
Merge pull request #1 from Wohlstand/master
Better assembly for MIDI Player
Diffstat (limited to 'src/dbopl.h')
-rw-r--r--src/dbopl.h460
1 files changed, 237 insertions, 223 deletions
diff --git a/src/dbopl.h b/src/dbopl.h
index 794c645..bdd439d 100644
--- a/src/dbopl.h
+++ b/src/dbopl.h
@@ -19,6 +19,7 @@
/* BEGIN MIDIPLAY GLUE */
#include <stdint.h>
+#include <stdlib.h>
typedef unsigned long Bitu;
typedef signed long Bits;
typedef unsigned Bit32u;
@@ -33,241 +34,254 @@ typedef signed char Bit8s;
/* END MIDIPLAY GLUE */
//Use 8 handlers based on a small logatirmic wavetabe and an exponential table for volume
-#define WAVE_HANDLER 10
+#define WAVE_HANDLER 10
//Use a logarithmic wavetable with an exponential table for volume
-#define WAVE_TABLELOG 11
+#define WAVE_TABLELOG 11
//Use a linear wavetable with a multiply table for volume
-#define WAVE_TABLEMUL 12
+#define WAVE_TABLEMUL 12
//Select the type of wave generator routine
#define DBOPL_WAVE WAVE_TABLEMUL
-namespace DBOPL {
+namespace DBOPL
+{
-struct Chip;
-struct Operator;
-struct Channel;
+ struct Chip;
+ struct Operator;
+ struct Channel;
#if (DBOPL_WAVE == WAVE_HANDLER)
-typedef Bits ( DB_FASTCALL *WaveHandler) ( Bitu i, Bitu volume );
+ typedef Bits(DB_FASTCALL *WaveHandler)(Bitu i, Bitu volume);
#endif
-typedef Bits ( DBOPL::Operator::*VolumeHandler) ( );
-typedef Channel* ( DBOPL::Channel::*SynthHandler) ( Chip* chip, Bit32u samples, Bit32s* output );
-
-//Different synth modes that can generate blocks of data
-typedef enum {
- sm2AM,
- sm2FM,
- sm3AM,
- sm3FM,
- sm4Start,
- sm3FMFM,
- sm3AMFM,
- sm3FMAM,
- sm3AMAM,
- sm6Start,
- sm2Percussion,
- sm3Percussion,
-} SynthMode;
-
-//Shifts for the values contained in chandata variable
-enum {
- SHIFT_KSLBASE = 16,
- SHIFT_KEYCODE = 24,
-};
-
-struct Operator {
-public:
- //Masks for operator 20 values
- enum {
- MASK_KSR = 0x10,
- MASK_SUSTAIN = 0x20,
- MASK_VIBRATO = 0x40,
- MASK_TREMOLO = 0x80,
- };
-
- typedef enum {
- OFF,
- RELEASE,
- SUSTAIN,
- DECAY,
- ATTACK,
- } State;
-
- VolumeHandler volHandler;
+ typedef Bits(DBOPL::Operator::*VolumeHandler)();
+ typedef Channel *(DBOPL::Channel::*SynthHandler)(Chip *chip, Bit32u samples, Bit32s *output);
+
+ //Different synth modes that can generate blocks of data
+ typedef enum
+ {
+ sm2AM,
+ sm2FM,
+ sm3AM,
+ sm3FM,
+ sm4Start,
+ sm3FMFM,
+ sm3AMFM,
+ sm3FMAM,
+ sm3AMAM,
+ sm6Start,
+ sm2Percussion,
+ sm3Percussion,
+ } SynthMode;
+
+ //Shifts for the values contained in chandata variable
+ enum
+ {
+ SHIFT_KSLBASE = 16,
+ SHIFT_KEYCODE = 24,
+ };
+
+ struct Operator
+ {
+ public:
+ //Masks for operator 20 values
+ enum
+ {
+ MASK_KSR = 0x10,
+ MASK_SUSTAIN = 0x20,
+ MASK_VIBRATO = 0x40,
+ MASK_TREMOLO = 0x80,
+ };
+
+ typedef enum
+ {
+ OFF,
+ RELEASE,
+ SUSTAIN,
+ DECAY,
+ ATTACK,
+ } State;
+
+ VolumeHandler volHandler;
#if (DBOPL_WAVE == WAVE_HANDLER)
- WaveHandler waveHandler; //Routine that generate a wave
+ WaveHandler waveHandler; //Routine that generate a wave
#else
- Bit16s* waveBase;
- Bit32u waveMask;
- Bit32u waveStart;
+ Bit16s *waveBase;
+ Bit32u waveMask;
+ Bit32u waveStart;
#endif
- Bit32u waveIndex; //WAVE_BITS shifted counter of the frequency index
- Bit32u waveAdd; //The base frequency without vibrato
- Bit32u waveCurrent; //waveAdd + vibratao
-
- Bit32u chanData; //Frequency/octave and derived data coming from whatever channel controls this
- Bit32u freqMul; //Scale channel frequency with this, TODO maybe remove?
- Bit32u vibrato; //Scaled up vibrato strength
- Bit32s sustainLevel; //When stopping at sustain level stop here
- Bit32s totalLevel; //totalLevel is added to every generated volume
- Bit32u currentLevel; //totalLevel + tremolo
- Bit32s volume; //The currently active volume
-
- Bit32u attackAdd; //Timers for the different states of the envelope
- Bit32u decayAdd;
- Bit32u releaseAdd;
- Bit32u rateIndex; //Current position of the evenlope
-
- Bit8u rateZero; //Bits for the different states of the envelope having no changes
- Bit8u keyOn; //Bitmask of different values that can generate keyon
- //Registers, also used to check for changes
- Bit8u reg20, reg40, reg60, reg80, regE0;
- //Active part of the envelope we're in
- Bit8u state;
- //0xff when tremolo is enabled
- Bit8u tremoloMask;
- //Strength of the vibrato
- Bit8u vibStrength;
- //Keep track of the calculated KSR so we can check for changes
- Bit8u ksr;
-private:
- void SetState( Bit8u s );
- void UpdateAttack( const Chip* chip );
- void UpdateRelease( const Chip* chip );
- void UpdateDecay( const Chip* chip );
-public:
- void UpdateAttenuation();
- void UpdateRates( const Chip* chip );
- void UpdateFrequency( );
-
- void Write20( const Chip* chip, Bit8u val );
- void Write40( const Chip* chip, Bit8u val );
- void Write60( const Chip* chip, Bit8u val );
- void Write80( const Chip* chip, Bit8u val );
- void WriteE0( const Chip* chip, Bit8u val );
-
- bool Silent() const;
- void Prepare( const Chip* chip );
-
- void KeyOn( Bit8u mask);
- void KeyOff( Bit8u mask);
-
- template< State state>
- Bits TemplateVolume( );
-
- Bit32s RateForward( Bit32u add );
- Bitu ForwardWave();
- Bitu ForwardVolume();
-
- Bits GetSample( Bits modulation );
- Bits GetWave( Bitu index, Bitu vol );
-public:
- Operator();
-};
-
-struct Channel {
- Operator op[2];
- inline Operator* Op( Bitu index ) {
- return &( ( this + (index >> 1) )->op[ index & 1 ]);
- }
- SynthHandler synthHandler;
- Bit32u chanData; //Frequency/octave and derived values
- Bit32s old[2]; //Old data for feedback
-
- Bit8u feedback; //Feedback shift
- Bit8u regB0; //Register values to check for changes
- Bit8u regC0;
- //This should correspond with reg104, bit 6 indicates a Percussion channel, bit 7 indicates a silent channel
- Bit8u fourMask;
- Bit8s maskLeft; //Sign extended values for both channel's panning
- Bit8s maskRight;
-
- //Forward the channel data to the operators of the channel
- void SetChanData( const Chip* chip, Bit32u data );
- //Change in the chandata, check for new values and if we have to forward to operators
- void UpdateFrequency( const Chip* chip, Bit8u fourOp );
- void WriteA0( const Chip* chip, Bit8u val );
- void WriteB0( const Chip* chip, Bit8u val );
- void WriteC0( const Chip* chip, Bit8u val );
- void ResetC0( const Chip* chip );
-
- //call this for the first channel
- template< bool opl3Mode >
- void GeneratePercussion( Chip* chip, Bit32s* output );
-
- //Generate blocks of data in specific modes
- template<SynthMode mode>
- Channel* BlockTemplate( Chip* chip, Bit32u samples, Bit32s* output );
- Channel();
-};
-
-struct Chip {
- //This is used as the base counter for vibrato and tremolo
- Bit32u lfoCounter;
- Bit32u lfoAdd;
-
-
- Bit32u noiseCounter;
- Bit32u noiseAdd;
- Bit32u noiseValue;
-
- //Frequency scales for the different multiplications
- Bit32u freqMul[16];
- //Rates for decay and release for rate of this chip
- Bit32u linearRates[76];
- //Best match attack rates for the rate of this chip
- Bit32u attackRates[76];
-
- //18 channels with 2 operators each
- Channel chan[18];
-
- Bit8u reg104;
- Bit8u reg08;
- Bit8u reg04;
- Bit8u regBD;
- Bit8u vibratoIndex;
- Bit8u tremoloIndex;
- Bit8s vibratoSign;
- Bit8u vibratoShift;
- Bit8u tremoloValue;
- Bit8u vibratoStrength;
- Bit8u tremoloStrength;
- //Mask for allowed wave forms
- Bit8u waveFormMask;
- //0 or -1 when enabled
- Bit8s opl3Active;
-
- //Return the maximum amount of samples before and LFO change
- Bit32u ForwardLFO( Bit32u samples );
- Bit32u ForwardNoise();
-
- void WriteBD( Bit8u val );
- void WriteReg(Bit32u reg, Bit8u val );
-
- Bit32u WriteAddr( Bit32u port, Bit8u val );
-
- void GenerateBlock2( Bitu samples, Bit32s* output );
- void GenerateBlock3( Bitu samples, Bit32s* output );
-
- void Generate( Bit32u samples );
- void Setup( Bit32u r );
-
- Chip();
-};
-
-struct Handler {
- DBOPL::Chip chip;
- Bit32u WriteAddr( Bit32u port, Bit8u val );
- void WriteReg( Bit32u addr, Bit8u val );
- void Generate( void(*AddSamples_m32)(Bitu,Bit32s*),
- void(*AddSamples_s32)(Bitu,Bit32s*),
- Bitu samples );
- void GenerateArr(Bit32s* out, Bitu *samples );
- void Init( Bitu rate );
-};
-
-
-} //Namespace
+ Bit32u waveIndex; //WAVE_BITS shifted counter of the frequency index
+ Bit32u waveAdd; //The base frequency without vibrato
+ Bit32u waveCurrent; //waveAdd + vibratao
+
+ Bit32u chanData; //Frequency/octave and derived data coming from whatever channel controls this
+ Bit32u freqMul; //Scale channel frequency with this, TODO maybe remove?
+ Bit32u vibrato; //Scaled up vibrato strength
+ Bit32s sustainLevel; //When stopping at sustain level stop here
+ Bit32s totalLevel; //totalLevel is added to every generated volume
+ Bit32u currentLevel; //totalLevel + tremolo
+ Bit32s volume; //The currently active volume
+
+ Bit32u attackAdd; //Timers for the different states of the envelope
+ Bit32u decayAdd;
+ Bit32u releaseAdd;
+ Bit32u rateIndex; //Current position of the evenlope
+
+ Bit8u rateZero; //Bits for the different states of the envelope having no changes
+ Bit8u keyOn; //Bitmask of different values that can generate keyon
+ //Registers, also used to check for changes
+ Bit8u reg20, reg40, reg60, reg80, regE0;
+ //Active part of the envelope we're in
+ Bit8u state;
+ //0xff when tremolo is enabled
+ Bit8u tremoloMask;
+ //Strength of the vibrato
+ Bit8u vibStrength;
+ //Keep track of the calculated KSR so we can check for changes
+ Bit8u ksr;
+ private:
+ void SetState(Bit8u s);
+ void UpdateAttack(const Chip *chip);
+ void UpdateRelease(const Chip *chip);
+ void UpdateDecay(const Chip *chip);
+ public:
+ void UpdateAttenuation();
+ void UpdateRates(const Chip *chip);
+ void UpdateFrequency();
+
+ void Write20(const Chip *chip, Bit8u val);
+ void Write40(const Chip *chip, Bit8u val);
+ void Write60(const Chip *chip, Bit8u val);
+ void Write80(const Chip *chip, Bit8u val);
+ void WriteE0(const Chip *chip, Bit8u val);
+
+ bool Silent() const;
+ void Prepare(const Chip *chip);
+
+ void KeyOn(Bit8u mask);
+ void KeyOff(Bit8u mask);
+
+ template< State state>
+ Bits TemplateVolume();
+
+ Bit32s RateForward(Bit32u add);
+ Bitu ForwardWave();
+ Bitu ForwardVolume();
+
+ Bits GetSample(Bits modulation);
+ Bits GetWave(Bitu index, Bitu vol);
+ public:
+ Operator();
+ char ____padding[5];
+ };
+
+ struct Channel
+ {
+ Operator op[2];
+ inline Operator *Op(Bitu index)
+ {
+ return &((this + (index >> 1))->op[ index & 1 ]);
+ }
+ SynthHandler synthHandler;
+ Bit32u chanData; //Frequency/octave and derived values
+ Bit32s old[2]; //Old data for feedback
+
+ Bit8u feedback; //Feedback shift
+ Bit8u regB0; //Register values to check for changes
+ Bit8u regC0;
+ //This should correspond with reg104, bit 6 indicates a Percussion channel, bit 7 indicates a silent channel
+ Bit8u fourMask;
+ Bit8s maskLeft; //Sign extended values for both channel's panning
+ Bit8s maskRight;
+
+ //Forward the channel data to the operators of the channel
+ void SetChanData(const Chip *chip, Bit32u data);
+ //Change in the chandata, check for new values and if we have to forward to operators
+ void UpdateFrequency(const Chip *chip, Bit8u fourOp);
+ void WriteA0(const Chip *chip, Bit8u val);
+ void WriteB0(const Chip *chip, Bit8u val);
+ void WriteC0(const Chip *chip, Bit8u val);
+ void ResetC0(const Chip *chip);
+
+ //call this for the first channel
+ template< bool opl3Mode >
+ void GeneratePercussion(Chip *chip, Bit32s *output);
+
+ //Generate blocks of data in specific modes
+ template<SynthMode mode>
+ Channel *BlockTemplate(Chip *chip, Bit32u samples, Bit32s *output);
+ Channel();
+ char ____padding[6];
+ };
+
+ struct Chip
+ {
+ //This is used as the base counter for vibrato and tremolo
+ Bit32u lfoCounter;
+ Bit32u lfoAdd;
+
+
+ Bit32u noiseCounter;
+ Bit32u noiseAdd;
+ Bit32u noiseValue;
+
+ //Frequency scales for the different multiplications
+ Bit32u freqMul[16];
+ //Rates for decay and release for rate of this chip
+ Bit32u linearRates[76];
+ //Best match attack rates for the rate of this chip
+ Bit32u attackRates[76];
+
+ //18 channels with 2 operators each
+ Channel chan[18];
+
+ Bit8u reg104;
+ Bit8u reg08;
+ Bit8u reg04;
+ Bit8u regBD;
+ Bit8u vibratoIndex;
+ Bit8u tremoloIndex;
+ Bit8s vibratoSign;
+ Bit8u vibratoShift;
+ Bit8u tremoloValue;
+ Bit8u vibratoStrength;
+ Bit8u tremoloStrength;
+ //Mask for allowed wave forms
+ Bit8u waveFormMask;
+ //0 or -1 when enabled
+ Bit8s opl3Active;
+
+ //Return the maximum amount of samples before and LFO change
+ Bit32u ForwardLFO(Bit32u samples);
+ Bit32u ForwardNoise();
+
+ void WriteBD(Bit8u val);
+ void WriteReg(Bit32u reg, Bit8u val);
+
+ Bit32u WriteAddr(Bit32u port, Bit8u val);
+
+ void GenerateBlock2(Bitu samples, Bit32s *output);
+ void GenerateBlock3(Bitu samples, Bit32s *output);
+
+ void Generate(Bit32u samples);
+ void Setup(Bit32u r);
+
+ Chip();
+ };
+
+ struct Handler
+ {
+ DBOPL::Chip chip;
+ Bit32u WriteAddr(Bit32u port, Bit8u val);
+ void WriteReg(Bit32u addr, Bit8u val);
+ void Generate(void(*AddSamples_m32)(Bitu, Bit32s *),
+ void(*AddSamples_s32)(Bitu, Bit32s *),
+ Bitu samples);
+ void GenerateArr(Bit32s *out, Bitu *samples);
+ void GenerateArr(Bit32s *out, ssize_t *samples);
+ void Init(Bitu rate);
+ };
+
+
+} //Namespace