Updated ft2play and fixed up dbopl

CQTexperiment
Chris Moeller 2014-03-30 17:19:18 -07:00
parent 0839cbbd9d
commit 55eec18bfe
3 changed files with 189 additions and 166 deletions

View File

@ -38,9 +38,159 @@
#include <math.h>
#include <stdlib.h>
#include <string.h>
//#include "dosbox.h"
#include "dbopl.h"
//Use 8 handlers based on a small logatirmic wavetabe and an exponential table for volume
#define WAVE_HANDLER 10
//Use a logarithmic wavetable with an exponential table for volume
#define WAVE_TABLELOG 11
//Use a linear wavetable with a multiply table for volume
#define WAVE_TABLEMUL 12
//Select the type of wave generator routine
#define DBOPL_WAVE WAVE_TABLEMUL
#if (DBOPL_WAVE == WAVE_HANDLER)
typedef Bits ( DB_FASTCALL *WaveHandler) ( Bitu i, Bitu volume );
#endif
typedef struct Operator Operator;
typedef struct Channel Channel;
typedef struct Chip Chip;
typedef Bits ( *Operator_VolumeHandler) ( struct Operator * );
typedef struct Channel* ( *Channel_SynthHandler) ( struct Channel *, struct 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
};
enum {
MASK_KSR = 0x10,
MASK_SUSTAIN = 0x20,
MASK_VIBRATO = 0x40,
MASK_TREMOLO = 0x80
};
typedef enum {
OFF,
RELEASE,
SUSTAIN,
DECAY,
ATTACK
} Operator_State;
struct Operator {
//Masks for operator 20 values
Operator_VolumeHandler volHandler;
#if (DBOPL_WAVE == WAVE_HANDLER)
WaveHandler waveHandler; //Routine that generate a wave
#else
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;
};
struct Channel {
struct Operator op[2];
Channel_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;
};
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
struct 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;
};
#ifndef PI
#define PI 3.14159265358979323846
@ -905,8 +1055,8 @@ static Bit32s Channel_GeneratePercussion( struct Channel *chan, struct Chip* chi
//Precalculate stuff used by other outputs
noiseBit = Chip_ForwardNoise( chip ) & 0x1;
c2 = Operator_ForwardWave( Channel_Operator( chan, 2 ) );
c5 = Operator_ForwardWave( Channel_Operator( chan, 5 ) );
c2 = Operator_ForwardWave( Channel_Op( chan, 2 ) );
c5 = Operator_ForwardWave( Channel_Op( chan, 5 ) );
phaseBit = (((c2 & 0x88) ^ ((c2<<5) & 0x80)) | ((c5 ^ (c5<<2)) & 0x20)) ? 0x02 : 0x00;
//Hi-Hat
@ -1136,10 +1286,16 @@ static void Channel_ResetC0( struct Channel *c, const struct Chip* chip ) {
Chip
*/
Bitu Chip_GetSize()
{
return sizeof(struct Chip);
}
static void InitTables( void );
void Chip_Init(struct Chip *chip) {
void Chip_Init(void *_chip) {
Bit32u i;
struct Chip *chip = (struct Chip *)_chip;
InitTables();
chip->reg08 = 0;
chip->reg04 = 0;
@ -1267,8 +1423,9 @@ static void Chip_WriteBD( struct Chip *chip, Bit8u val ) {
Channel_##_FUNC_( regChan, chip, val ); \
}
void Chip_WriteReg( struct Chip *chip, Bit32u reg, Bit8u val ) {
void Chip_WriteReg( void *_chip, Bit32u reg, Bit8u val ) {
Bitu index;
struct Chip *chip = (struct Chip *)_chip;
switch ( (reg & 0xf0) >> 4 ) {
case 0x00 >> 4:
if ( reg == 0x01 ) {
@ -1330,7 +1487,8 @@ void Chip_WriteReg( struct Chip *chip, Bit32u reg, Bit8u val ) {
}
}
Bit32u Chip_WriteAddr( struct Chip *chip, Bit32u port, Bit8u val ) {
Bit32u Chip_WriteAddr( void *_chip, Bit32u port, Bit8u val ) {
struct Chip *chip = (struct Chip *)_chip;
switch ( port & 3 ) {
case 0:
return val;
@ -1343,7 +1501,8 @@ Bit32u Chip_WriteAddr( struct Chip *chip, Bit32u port, Bit8u val ) {
return 0;
}
void Chip_GenerateBlock2( struct Chip *chip, Bitu total, Bit32s* output ) {
void Chip_GenerateBlock2( void *_chip, Bitu total, Bit32s* output ) {
struct Chip *chip = (struct Chip *)_chip;
while ( total > 0 ) {
struct Channel* ch;
int count;
@ -1361,11 +1520,12 @@ void Chip_GenerateBlock2( struct Chip *chip, Bitu total, Bit32s* output ) {
}
}
void Chip_GenerateBlock3( struct Chip *chip, Bitu total, Bit32s* output ) {
void Chip_GenerateBlock3( void *_chip, Bitu total, Bit32s* output ) {
struct Chip *chip = (struct Chip *)_chip;
while ( total > 0 ) {
struct Channel* ch;
int count;
Bit32u samples = ForwardLFO( total );
Bit32u samples = Chip_ForwardLFO( chip, total );
for ( Bitu i = 0; i < samples; i++ ) {
output[i * 2 + 0 ] = 0;
output[i * 2 + 1 ] = 0;
@ -1380,7 +1540,8 @@ void Chip_GenerateBlock3( struct Chip *chip, Bitu total, Bit32s* output ) {
}
}
void Chip_Setup( struct Chip *chip, Bit32u clock, Bit32u rate ) {
void Chip_Setup( void *_chip, Bit32u clock, Bit32u rate ) {
struct Chip *chip = (struct Chip *)_chip;
double original = (double)clock / 288.0;
double scale = original / (double)rate;
if (fabs(scale - 1.0) < 0.00001)

View File

@ -57,161 +57,13 @@ typedef signed long long Bit64s;
typedef unsigned int Bitu;
typedef signed int Bits;
//#include "dosbox.h"
Bitu Chip_GetSize();
//Use 8 handlers based on a small logatirmic wavetabe and an exponential table for volume
#define WAVE_HANDLER 10
//Use a logarithmic wavetable with an exponential table for volume
#define WAVE_TABLELOG 11
//Use a linear wavetable with a multiply table for volume
#define WAVE_TABLEMUL 12
void Chip_Init( void *chip );
void Chip_Setup( void *chip, Bit32u clock, Bit32u rate );
//Select the type of wave generator routine
#define DBOPL_WAVE WAVE_TABLEMUL
void Chip_WriteReg( void *chip, Bit32u reg, Bit8u val );
Bit32u Chip_WriteAddr( void *chip, Bit32u port, Bit8u val );
#if (DBOPL_WAVE == WAVE_HANDLER)
typedef Bits ( DB_FASTCALL *WaveHandler) ( Bitu i, Bitu volume );
#endif
typedef Bits ( *Operator_VolumeHandler) ( struct Operator * );
typedef struct Channel* ( *Channel_SynthHandler) ( struct Channel *, struct 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
};
enum {
MASK_KSR = 0x10,
MASK_SUSTAIN = 0x20,
MASK_VIBRATO = 0x40,
MASK_TREMOLO = 0x80
};
typedef enum {
OFF,
RELEASE,
SUSTAIN,
DECAY,
ATTACK
} Operator_State;
struct Operator {
//Masks for operator 20 values
Operator_VolumeHandler volHandler;
#if (DBOPL_WAVE == WAVE_HANDLER)
WaveHandler waveHandler; //Routine that generate a wave
#else
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;
};
struct Channel {
struct Operator op[2];
Channel_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;
};
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
struct 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;
};
void Chip_Init(struct Chip *chip);
void Chip_Setup( struct Chip *chip, Bit32u clock, Bit32u rate );
void Chip_WriteReg( struct Chip *chip, Bit32u reg, Bit8u val );
Bit32u Chip_WriteAddr( struct Chip *chip, Bit32u port, Bit8u val );
void Chip_GenerateBlock2( struct Chip *chip, Bitu total, Bit32s* output );
void Chip_GenerateBlock3( struct Chip *chip, Bitu total, Bit32s* output );
void Chip_GenerateBlock2( void *chip, Bitu total, Bit32s* output );
void Chip_GenerateBlock3( void *chip, Bitu total, Bit32s* output );

View File

@ -9,6 +9,9 @@
** It's just an accurate FastTracker II replayer port for people to enjoy.
**
**
** non-FT2 effects:
** - E8x - set panning
**
** (extreme) non-FT2 extensions:
** - Max 127 channels (was 32)
** - Any amount-of-channels number (FT2 supports *even* numbers only)
@ -967,6 +970,13 @@ CheckEffects:
// E7x - set tremolo waveform
else if ((ch->Eff & 0xF0) == 0x70) ch->WaveCtrl = ((ch->Eff & 0x0F) << 4) | (ch->WaveCtrl & 0x0F);
// E8x - set panning - *non-FT2*
else if ((ch->Eff & 0xF0) == 0x80)
{
ch->OutPan = (ch->Eff & 0x0F) << 4;
ch->Status |= IS_Pan;
}
// EAx - fine volume slide up
else if ((ch->Eff & 0xF0) == 0xA0)
{