DOSBox-X
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator
src/hardware/dbopl.h
00001 /*
00002  *  Copyright (C) 2002-2015  The DOSBox Team
00003  *
00004  *  This program is free software; you can redistribute it and/or modify
00005  *  it under the terms of the GNU General Public License as published by
00006  *  the Free Software Foundation; either version 2 of the License, or
00007  *  (at your option) any later version.
00008  *
00009  *  This program is distributed in the hope that it will be useful,
00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *  GNU General Public License for more details.
00013  *
00014  *  You should have received a copy of the GNU General Public License
00015  *  along with this program; if not, write to the Free Software
00016  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00017  */
00018 
00019 #include "adlib.h"
00020 #include "dosbox.h"
00021 
00022 //Use 8 handlers based on a small logatirmic wavetabe and an exponential table for volume
00023 #define WAVE_HANDLER    10
00024 //Use a logarithmic wavetable with an exponential table for volume
00025 #define WAVE_TABLELOG   11
00026 //Use a linear wavetable with a multiply table for volume
00027 #define WAVE_TABLEMUL   12
00028 
00029 //Select the type of wave generator routine
00030 #define DBOPL_WAVE WAVE_TABLEMUL
00031 
00032 namespace DBOPL {
00033 
00034 struct Chip;
00035 struct Operator;
00036 struct Channel;
00037 
00038 #if (DBOPL_WAVE == WAVE_HANDLER)
00039 typedef Bits ( DB_FASTCALL *WaveHandler) ( Bitu i, Bitu volume );
00040 #endif
00041 
00042 typedef Bits ( DBOPL::Operator::*VolumeHandler) ( );
00043 typedef Channel* ( DBOPL::Channel::*SynthHandler) ( Chip* chip, Bit32u samples, Bit32s* output );
00044 
00045 //Different synth modes that can generate blocks of data
00046 typedef enum {
00047         sm2AM,
00048         sm2FM,
00049         sm3AM,
00050         sm3FM,
00051         sm4Start,
00052         sm3FMFM,
00053         sm3AMFM,
00054         sm3FMAM,
00055         sm3AMAM,
00056         sm6Start,
00057         sm2Percussion,
00058         sm3Percussion,
00059 } SynthMode;
00060 
00061 //Shifts for the values contained in chandata variable
00062 enum {
00063         SHIFT_KSLBASE = 16,
00064         SHIFT_KEYCODE = 24,
00065 };
00066 
00067 struct Operator {
00068 public:
00069         //Masks for operator 20 values
00070         enum {
00071                 MASK_KSR = 0x10,
00072                 MASK_SUSTAIN = 0x20,
00073                 MASK_VIBRATO = 0x40,
00074                 MASK_TREMOLO = 0x80,
00075         };
00076 
00077         typedef enum {
00078                 OFF,
00079                 RELEASE,
00080                 SUSTAIN,
00081                 DECAY,
00082                 ATTACK,
00083         } State;
00084 
00085         VolumeHandler volHandler;
00086 
00087 #if (DBOPL_WAVE == WAVE_HANDLER)
00088         WaveHandler waveHandler;        //Routine that generate a wave 
00089 #else
00090         Bit16s* waveBase;
00091         Bit32u waveMask;
00092         Bit32u waveStart;
00093 #endif
00094         Bit32u waveIndex;                       //WAVE_BITS shifted counter of the frequency index
00095         Bit32u waveAdd;                         //The base frequency without vibrato
00096         Bit32u waveCurrent;                     //waveAdd + vibratao
00097 
00098         Bit32u chanData;                        //Frequency/octave and derived data coming from whatever channel controls this
00099         Bit32u freqMul;                         //Scale channel frequency with this, TODO maybe remove?
00100         Bit32u vibrato;                         //Scaled up vibrato strength
00101         Bit32s sustainLevel;            //When stopping at sustain level stop here
00102         Bit32s totalLevel;                      //totalLevel is added to every generated volume
00103         Bit32u currentLevel;            //totalLevel + tremolo
00104         Bit32s volume;                          //The currently active volume
00105         
00106         Bit32u attackAdd;                       //Timers for the different states of the envelope
00107         Bit32u decayAdd;
00108         Bit32u releaseAdd;
00109         Bit32u rateIndex;                       //Current position of the evenlope
00110 
00111         Bit8u rateZero;                         //Bits for the different states of the envelope having no changes
00112         Bit8u keyOn;                            //Bitmask of different values that can generate keyon
00113         //Registers, also used to check for changes
00114         Bit8u reg20, reg40, reg60, reg80, regE0;
00115         //Active part of the envelope we're in
00116         Bit8u state;
00117         //0xff when tremolo is enabled
00118         Bit8u tremoloMask;
00119         //Strength of the vibrato
00120         Bit8u vibStrength;
00121         //Keep track of the calculated KSR so we can check for changes
00122         Bit8u ksr;
00123 private:
00124         void SetState( Bit8u s );
00125         void UpdateAttack( const Chip* chip );
00126         void UpdateRelease( const Chip* chip );
00127         void UpdateDecay( const Chip* chip );
00128 public:
00129         void UpdateAttenuation();
00130         void UpdateRates( const Chip* chip );
00131         void UpdateFrequency( );
00132 
00133         void Write20( const Chip* chip, Bit8u val );
00134         void Write40( const Chip* chip, Bit8u val );
00135         void Write60( const Chip* chip, Bit8u val );
00136         void Write80( const Chip* chip, Bit8u val );
00137         void WriteE0( const Chip* chip, Bit8u val );
00138 
00139         bool Silent() const;
00140         void Prepare( const Chip* chip );
00141 
00142         void KeyOn( Bit8u mask);
00143         void KeyOff( Bit8u mask);
00144 
00145         template< State state>
00146         Bits TemplateVolume( );
00147 
00148         Bit32s RateForward( Bit32u add );
00149         Bitu ForwardWave();
00150         Bitu ForwardVolume();
00151 
00152         Bits GetSample( Bits modulation );
00153         Bits GetWave( Bitu index, Bitu vol );
00154 public:
00155         Operator();
00156 };
00157 
00158 struct Channel {
00159         Operator op[2];
00160         inline Operator* Op( Bitu index ) {
00161                 return &( ( this + (index >> 1) )->op[ index & 1 ]);
00162         }
00163         SynthHandler synthHandler;
00164         Bit32u chanData;                //Frequency/octave and derived values
00165         Bit32s old[2];                  //Old data for feedback
00166 
00167         Bit8u feedback;                 //Feedback shift
00168         Bit8u regB0;                    //Register values to check for changes
00169         Bit8u regC0;
00170         //This should correspond with reg104, bit 6 indicates a Percussion channel, bit 7 indicates a silent channel
00171         Bit8u fourMask;
00172         Bit8s maskLeft;         //Sign extended values for both channel's panning
00173         Bit8s maskRight;
00174 
00175         //Forward the channel data to the operators of the channel
00176         void SetChanData( const Chip* chip, Bit32u data );
00177         //Change in the chandata, check for new values and if we have to forward to operators
00178         void UpdateFrequency( const Chip* chip, Bit8u fourOp );
00179         void WriteA0( const Chip* chip, Bit8u val );
00180         void WriteB0( const Chip* chip, Bit8u val );
00181         void WriteC0( const Chip* chip, Bit8u val );
00182         void ResetC0( const Chip* chip );
00183 
00184         //call this for the first channel
00185         template< bool opl3Mode >
00186         void GeneratePercussion( Chip* chip, Bit32s* output );
00187 
00188         //Generate blocks of data in specific modes
00189         template<SynthMode mode>
00190         Channel* BlockTemplate( Chip* chip, Bit32u samples, Bit32s* output );
00191         Channel();
00192 };
00193 
00194 struct Chip {
00195         //This is used as the base counter for vibrato and tremolo
00196         Bit32u lfoCounter;
00197         Bit32u lfoAdd;
00198         
00199 
00200         Bit32u noiseCounter;
00201         Bit32u noiseAdd;
00202         Bit32u noiseValue;
00203 
00204         //Frequency scales for the different multiplications
00205         Bit32u freqMul[16];
00206         //Rates for decay and release for rate of this chip
00207         Bit32u linearRates[76];
00208         //Best match attack rates for the rate of this chip
00209         Bit32u attackRates[76];
00210 
00211         //18 channels with 2 operators each
00212         Channel chan[18];
00213 
00214         Bit8u reg104;
00215         Bit8u reg08;
00216         Bit8u reg04;
00217         Bit8u regBD;
00218         Bit8u vibratoIndex;
00219         Bit8u tremoloIndex;
00220         Bit8s vibratoSign;
00221         Bit8u vibratoShift;
00222         Bit8u tremoloValue;
00223         Bit8u vibratoStrength;
00224         Bit8u tremoloStrength;
00225         //Mask for allowed wave forms
00226         Bit8u waveFormMask;
00227         //0 or -1 when enabled
00228         Bit8s opl3Active;
00229 
00230         //Return the maximum amount of samples before and LFO change
00231         Bit32u ForwardLFO( Bit32u samples );
00232         Bit32u ForwardNoise();
00233 
00234         void WriteBD( Bit8u val );
00235         void WriteReg(Bit32u reg, Bit8u val );
00236 
00237         Bit32u WriteAddr( Bit32u port, Bit8u val );
00238 
00239         void GenerateBlock2( Bitu samples, Bit32s* output );
00240         void GenerateBlock3( Bitu samples, Bit32s* output );
00241 
00242         void Generate( Bit32u samples );
00243         void Setup( Bit32u r );
00244 
00245         Chip();
00246 };
00247 
00248 struct Handler : public Adlib::Handler {
00249         DBOPL::Chip chip;
00250         virtual Bit32u WriteAddr( Bit32u port, Bit8u val );
00251         virtual void WriteReg( Bit32u addr, Bit8u val );
00252         virtual void Generate( MixerChannel* chan, Bitu samples );
00253         virtual void Init( Bitu rate );
00254 };
00255 
00256 
00257 }               //Namespace