Updated st3play with experimental AdLib support

CQTexperiment
Chris Moeller 2014-03-31 19:00:27 -07:00
parent 55eec18bfe
commit c4288a8e61
6 changed files with 352 additions and 102 deletions

View File

@ -11,6 +11,8 @@
838A72E618DEC9A1007C8A7D /* resampler.c in Sources */ = {isa = PBXBuildFile; fileRef = 838A72E418DEC9A1007C8A7D /* resampler.c */; };
838A72E718DEC9A1007C8A7D /* resampler.h in Headers */ = {isa = PBXBuildFile; fileRef = 838A72E518DEC9A1007C8A7D /* resampler.h */; };
839CAC4018DA746000D67EA9 /* ft2play.c in Sources */ = {isa = PBXBuildFile; fileRef = 839CAC3F18DA746000D67EA9 /* ft2play.c */; };
83EAF76818E8F70400C896A6 /* dbopl.c in Sources */ = {isa = PBXBuildFile; fileRef = 83EAF76618E8F70400C896A6 /* dbopl.c */; };
83EAF76918E8F70400C896A6 /* dbopl.h in Headers */ = {isa = PBXBuildFile; fileRef = 83EAF76718E8F70400C896A6 /* dbopl.h */; };
83F4D54818D82105009B2DE6 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 83F4D54618D82105009B2DE6 /* InfoPlist.strings */; };
83F4D57718D821D2009B2DE6 /* st3play.c in Sources */ = {isa = PBXBuildFile; fileRef = 83F4D57318D821D2009B2DE6 /* st3play.c */; };
83F4D57818D821D2009B2DE6 /* st3play.h in Headers */ = {isa = PBXBuildFile; fileRef = 83F4D57418D821D2009B2DE6 /* st3play.h */; settings = {ATTRIBUTES = (Public, ); }; };
@ -21,6 +23,8 @@
838A72E518DEC9A1007C8A7D /* resampler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = resampler.h; sourceTree = "<group>"; };
839CAC3E18DA744700D67EA9 /* ft2play.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ft2play.h; sourceTree = "<group>"; };
839CAC3F18DA746000D67EA9 /* ft2play.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ft2play.c; sourceTree = "<group>"; };
83EAF76618E8F70400C896A6 /* dbopl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dbopl.c; sourceTree = "<group>"; };
83EAF76718E8F70400C896A6 /* dbopl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dbopl.h; sourceTree = "<group>"; };
83F4D53A18D82105009B2DE6 /* modplay.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = modplay.framework; sourceTree = BUILT_PRODUCTS_DIR; };
83F4D54518D82105009B2DE6 /* modplay-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "modplay-Info.plist"; sourceTree = "<group>"; };
83F4D54718D82105009B2DE6 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
@ -74,6 +78,8 @@
83F4D54318D82105009B2DE6 /* modplay */ = {
isa = PBXGroup;
children = (
83EAF76618E8F70400C896A6 /* dbopl.c */,
83EAF76718E8F70400C896A6 /* dbopl.h */,
838A72E418DEC9A1007C8A7D /* resampler.c */,
838A72E518DEC9A1007C8A7D /* resampler.h */,
83F4D57318D821D2009B2DE6 /* st3play.c */,
@ -103,6 +109,7 @@
files = (
838A72E718DEC9A1007C8A7D /* resampler.h in Headers */,
835CBC8218DA95AC0087A03E /* ft2play.h in Headers */,
83EAF76918E8F70400C896A6 /* dbopl.h in Headers */,
83F4D57818D821D2009B2DE6 /* st3play.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
@ -171,6 +178,7 @@
buildActionMask = 2147483647;
files = (
838A72E618DEC9A1007C8A7D /* resampler.c in Sources */,
83EAF76818E8F70400C896A6 /* dbopl.c in Sources */,
83F4D57718D821D2009B2DE6 /* st3play.c in Sources */,
839CAC4018DA746000D67EA9 /* ft2play.c in Sources */,
);

View File

@ -524,18 +524,14 @@ static void Operator_UpdateRates( struct Operator *o, const struct Chip* chip )
}
static INLINE Bit32s Operator_RateForward( struct Operator *o, Bit32u add ) {
Bit32s ret;
o->rateIndex += add;
Bit32s ret = o->rateIndex >> RATE_SH;
ret = o->rateIndex >> RATE_SH;
o->rateIndex = o->rateIndex & RATE_MASK;
return ret;
}
static const Operator_VolumeHandler VolumeHandlerTable[5];
static INLINE void Operator_SetState( struct Operator *o, Bit8u s ) {
o->state = s;
o->volHandler = VolumeHandlerTable[ s ];
}
static INLINE void Operator_SetState( struct Operator *o, Bit8u s );
static Bits Operator_Volume_Attack( struct Operator *o ) {
Bit32s vol = o->volume;
@ -556,7 +552,6 @@ static Bits Operator_Volume_Attack( struct Operator *o ) {
static Bits Operator_Volume_Decay( struct Operator *o ) {
Bit32s vol = o->volume;
Bit32s change;
vol += Operator_RateForward( o, o->decayAdd );
if ( vol >= o->sustainLevel ) {
//Check if we didn't overshoot max attenuation, then just go off
@ -575,7 +570,6 @@ static Bits Operator_Volume_Decay( struct Operator *o ) {
static Bits Operator_Volume_Sustain( struct Operator *o ) {
Bit32s vol = o->volume;
Bit32s change;
if ( o->reg20 & MASK_SUSTAIN ) {
return vol;
}
@ -592,7 +586,6 @@ static Bits Operator_Volume_Sustain( struct Operator *o ) {
static Bits Operator_Volume_Release( struct Operator *o ) {
Bit32s vol = o->volume;
Bit32s change;
vol += Operator_RateForward( o, o->releaseAdd );;
if ( vol >= ENV_MAX ) {
o->volume = ENV_MAX;
@ -616,6 +609,11 @@ static const Operator_VolumeHandler VolumeHandlerTable[5] = {
&Operator_Volume_Attack
};
static INLINE void Operator_SetState( struct Operator *o, Bit8u s ) {
o->state = s;
o->volHandler = VolumeHandlerTable[ s ];
}
static INLINE Bitu Operator_ForwardVolume(struct Operator *o) {
return o->currentLevel + (o->volHandler)(o);
}
@ -672,10 +670,11 @@ static void Operator_Write60( struct Operator *o, const struct Chip* chip, Bit8u
static void Operator_Write80( struct Operator *o, const struct Chip* chip, Bit8u val ) {
Bit8u change = (o->reg80 ^ val );
Bit8u sustain;
if ( !change )
return;
o->reg80 = val;
Bit8u sustain = val >> 4;
sustain = val >> 4;
//Turn 0xf into 0x1f
sustain |= ( sustain + 1) & 0x10;
o->sustainLevel = sustain << ( ENV_BITS - 5 );
@ -685,10 +684,11 @@ static void Operator_Write80( struct Operator *o, const struct Chip* chip, Bit8u
}
static void Operator_WriteE0( struct Operator *o, const struct Chip* chip, Bit8u val ) {
Bit8u waveForm;
if ( !(o->regE0 ^ val) )
return;
//in opl3 mode you can always selet 7 waveforms regardless of waveformselect
Bit8u waveForm = val & ( ( 0x3 & chip->waveFormMask ) | (0x7 & chip->opl3Active ) );
waveForm = val & ( ( 0x3 & chip->waveFormMask ) | (0x7 & chip->opl3Active ) );
o->regE0 = val;
#if ( DBOPL_WAVE == WAVE_HANDLER )
o->waveHandler = WaveHandlerTable[ waveForm ];
@ -803,7 +803,9 @@ static INLINE struct Operator* Channel_Op( struct Channel *c, Bitu index ) {
}
static struct Channel* Channel_Block_sm2AM( struct Channel *c, struct Chip* chip, Bit32u samples, Bit32s* output ) {
if ( Operator_Silent( Channel_Op(c, 0) ) && Operator_Silent( Channel_Op(c, 1) ) ) {
Bitu i;
if ( Operator_Silent( Channel_Op(c, 0) ) && Operator_Silent( Channel_Op(c, 1) ) ) {
c->old[0] = c->old[1] = 0;
return (c + 1);
}
@ -811,7 +813,7 @@ static struct Channel* Channel_Block_sm2AM( struct Channel *c, struct Chip* chip
Operator_Prepare( Channel_Op( c, 0 ), chip );
Operator_Prepare( Channel_Op( c, 1 ), chip );
for ( Bitu i = 0; i < samples; i++ ) {
for ( i = 0; i < samples; i++ ) {
//Do unsigned shift so we can shift out all bits but still stay in 10 bit range otherwise
Bit32s mod = (Bit32u)((c->old[0] + c->old[1])) >> c->feedback;
Bit32s sample;
@ -827,6 +829,8 @@ static struct Channel* Channel_Block_sm2AM( struct Channel *c, struct Chip* chip
}
static struct Channel* Channel_Block_sm2FM( struct Channel *c, struct Chip* chip, Bit32u samples, Bit32s* output ) {
Bitu i;
if ( Operator_Silent( Channel_Op(c, 1) ) ) {
c->old[0] = c->old[1] = 0;
return (c + 1);
@ -836,7 +840,7 @@ static struct Channel* Channel_Block_sm2FM( struct Channel *c, struct Chip* chip
Operator_Prepare( Channel_Op( c, 0 ), chip );
Operator_Prepare( Channel_Op( c, 1 ), chip );
for ( Bitu i = 0; i < samples; i++ ) {
for ( i = 0; i < samples; i++ ) {
//Do unsigned shift so we can shift out all bits but still stay in 10 bit range otherwise
Bit32s mod = (Bit32u)((c->old[0] + c->old[1])) >> c->feedback;
Bit32s sample;
@ -852,7 +856,9 @@ static struct Channel* Channel_Block_sm2FM( struct Channel *c, struct Chip* chip
}
static struct Channel* Channel_Block_sm3AM( struct Channel *c, struct Chip* chip, Bit32u samples, Bit32s* output ) {
if ( Operator_Silent( Channel_Op( c, 0 ) ) && Operator_Silent( Channel_Op( c, 1 ) ) ) {
Bitu i;
if ( Operator_Silent( Channel_Op( c, 0 ) ) && Operator_Silent( Channel_Op( c, 1 ) ) ) {
c->old[0] = c->old[1] = 0;
return (c + 1);
}
@ -861,7 +867,7 @@ static struct Channel* Channel_Block_sm3AM( struct Channel *c, struct Chip* chip
Operator_Prepare( Channel_Op( c, 0 ), chip );
Operator_Prepare( Channel_Op( c, 1 ), chip );
for ( Bitu i = 0; i < samples; i++ ) {
for ( i = 0; i < samples; i++ ) {
//Do unsigned shift so we can shift out all bits but still stay in 10 bit range otherwise
Bit32s mod = (Bit32u)((c->old[0] + c->old[1])) >> c->feedback;
Bit32s sample;
@ -878,7 +884,9 @@ static struct Channel* Channel_Block_sm3AM( struct Channel *c, struct Chip* chip
}
static struct Channel* Channel_Block_sm3FM( struct Channel *c, struct Chip* chip, Bit32u samples, Bit32s* output ) {
if ( Operator_Silent( Channel_Op( c, 1 ) ) ) {
Bitu i;
if ( Operator_Silent( Channel_Op( c, 1 ) ) ) {
c->old[0] = c->old[1] = 0;
return (c + 1);
}
@ -887,7 +895,7 @@ static struct Channel* Channel_Block_sm3FM( struct Channel *c, struct Chip* chip
Operator_Prepare( Channel_Op( c, 0 ), chip );
Operator_Prepare( Channel_Op( c, 1 ), chip );
for ( Bitu i = 0; i < samples; i++ ) {
for ( i = 0; i < samples; i++ ) {
//Do unsigned shift so we can shift out all bits but still stay in 10 bit range otherwise
Bit32s mod = (Bit32u)((c->old[0] + c->old[1])) >> c->feedback;
Bit32s sample;
@ -904,6 +912,8 @@ static struct Channel* Channel_Block_sm3FM( struct Channel *c, struct Chip* chip
}
static struct Channel* Channel_Block_sm3FMFM( struct Channel *c, struct Chip* chip, Bit32u samples, Bit32s* output ) {
Bitu i;
if ( Operator_Silent( Channel_Op( c, 3 ) ) ) {
c->old[0] = c->old[1] = 0;
return (c + 2);
@ -915,7 +925,7 @@ static struct Channel* Channel_Block_sm3FMFM( struct Channel *c, struct Chip* ch
Operator_Prepare( Channel_Op( c, 2 ), chip );
Operator_Prepare( Channel_Op( c, 3 ), chip );
for ( Bitu i = 0; i < samples; i++ ) {
for ( i = 0; i < samples; i++ ) {
//Do unsigned shift so we can shift out all bits but still stay in 10 bit range otherwise
Bit32s mod = (Bit32u)((c->old[0] + c->old[1])) >> c->feedback;
Bit32s sample;
@ -935,6 +945,8 @@ static struct Channel* Channel_Block_sm3FMFM( struct Channel *c, struct Chip* ch
}
static struct Channel* Channel_Block_sm3AMFM( struct Channel *c, struct Chip* chip, Bit32u samples, Bit32s* output ) {
Bitu i;
if ( Operator_Silent( Channel_Op( c, 0 ) ) && Operator_Silent( Channel_Op( c, 3 ) ) ) {
c->old[0] = c->old[1] = 0;
return (c + 2);
@ -946,7 +958,7 @@ static struct Channel* Channel_Block_sm3AMFM( struct Channel *c, struct Chip* ch
Operator_Prepare( Channel_Op( c, 2 ), chip );
Operator_Prepare( Channel_Op( c, 3 ), chip );
for ( Bitu i = 0; i < samples; i++ ) {
for ( i = 0; i < samples; i++ ) {
//Do unsigned shift so we can shift out all bits but still stay in 10 bit range otherwise
Bit32s mod = (Bit32u)((c->old[0] + c->old[1])) >> c->feedback;
Bit32s sample;
@ -967,6 +979,8 @@ static struct Channel* Channel_Block_sm3AMFM( struct Channel *c, struct Chip* ch
}
static struct Channel* Channel_Block_sm3FMAM( struct Channel *c, struct Chip* chip, Bit32u samples, Bit32s* output ) {
Bitu i;
if ( Operator_Silent( Channel_Op( c, 1) ) && Operator_Silent( Channel_Op( c, 3 ) ) ) {
c->old[0] = c->old[1] = 0;
return (c + 2);
@ -978,7 +992,7 @@ static struct Channel* Channel_Block_sm3FMAM( struct Channel *c, struct Chip* ch
Operator_Prepare( Channel_Op( c, 2 ), chip );
Operator_Prepare( Channel_Op( c, 3 ), chip );
for ( Bitu i = 0; i < samples; i++ ) {
for ( i = 0; i < samples; i++ ) {
//Do unsigned shift so we can shift out all bits but still stay in 10 bit range otherwise
Bit32s mod = (Bit32u)((c->old[0] + c->old[1])) >> c->feedback;
Bit32s sample;
@ -998,6 +1012,8 @@ static struct Channel* Channel_Block_sm3FMAM( struct Channel *c, struct Chip* ch
}
static struct Channel* Channel_Block_sm3AMAM( struct Channel *c, struct Chip* chip, Bit32u samples, Bit32s* output ) {
Bitu i;
if ( Operator_Silent( Channel_Op( c, 0 ) ) && Operator_Silent( Channel_Op( c, 2 ) ) && Operator_Silent( Channel_Op( c, 3 ) ) ) {
c->old[0] = c->old[1] = 0;
return (c + 2);
@ -1009,16 +1025,17 @@ static struct Channel* Channel_Block_sm3AMAM( struct Channel *c, struct Chip* ch
Operator_Prepare( Channel_Op( c, 2 ), chip );
Operator_Prepare( Channel_Op( c, 3 ), chip );
for ( Bitu i = 0; i < samples; i++ ) {
for ( i = 0; i < samples; i++ ) {
//Do unsigned shift so we can shift out all bits but still stay in 10 bit range otherwise
Bit32s mod = (Bit32u)((c->old[0] + c->old[1])) >> c->feedback;
Bit32s sample;
Bit32s out0;
Bits next;
c->old[0] = c->old[1];
c->old[1] = Operator_GetSample( Channel_Op( c, 0 ), mod );
out0 = c->old[0];
sample = out0;
Bits next = Operator_GetSample( Channel_Op( c, 1 ), 0 );
next = Operator_GetSample( Channel_Op( c, 1 ), 0 );
sample += Operator_GetSample( Channel_Op( c, 2 ), next );
sample += Operator_GetSample( Channel_Op( c, 3 ), 0 );
output[ i * 2 + 0 ] += sample & c->maskLeft;
@ -1085,6 +1102,8 @@ static Bit32s Channel_GeneratePercussion( struct Channel *chan, struct Chip* chi
}
static struct Channel* Channel_Block_sm2Percussion( struct Channel *c, struct Chip* chip, Bit32u samples, Bit32s* output ) {
Bitu i;
//Init the operators with the the current vibrato and tremolo values
Operator_Prepare( Channel_Op( c, 0 ), chip );
Operator_Prepare( Channel_Op( c, 1 ), chip );
@ -1093,7 +1112,7 @@ static struct Channel* Channel_Block_sm2Percussion( struct Channel *c, struct Ch
Operator_Prepare( Channel_Op( c, 4 ), chip );
Operator_Prepare( Channel_Op( c, 5 ), chip );
for ( Bitu i = 0; i < samples; i++ ) {
for ( i = 0; i < samples; i++ ) {
output[i] = Channel_GeneratePercussion( c, chip );
}
@ -1101,6 +1120,8 @@ static struct Channel* Channel_Block_sm2Percussion( struct Channel *c, struct Ch
}
static struct Channel* Channel_Block_sm3Percussion( struct Channel *c, struct Chip* chip, Bit32u samples, Bit32s* output ) {
Bitu i;
//Init the operators with the the current vibrato and tremolo values
Operator_Prepare( Channel_Op( c, 0 ), chip );
Operator_Prepare( Channel_Op( c, 1 ), chip );
@ -1109,7 +1130,7 @@ static struct Channel* Channel_Block_sm3Percussion( struct Channel *c, struct Ch
Operator_Prepare( Channel_Op( c, 4 ), chip );
Operator_Prepare( Channel_Op( c, 5 ), chip );
for ( Bitu i = 0; i < samples; i++ ) {
for ( i = 0; i < samples; i++ ) {
output[i * 2] = output[i * 2 + 1] = Channel_GeneratePercussion( c, chip );
}
@ -1181,10 +1202,11 @@ static void Channel_WriteA0( struct Channel *c, const struct Chip* chip, Bit8u v
static void Channel_WriteB0( struct Channel *c, const struct Chip* chip, Bit8u val ) {
Bit8u fourOp = chip->reg104 & chip->opl3Active & c->fourMask;
Bitu change;
//Don't handle writes to silent fourop channels
if ( fourOp > 0x80 )
return;
Bitu change = ( c->chanData ^ ( val << 8 ) ) & 0x1f00;
change = ( c->chanData ^ ( val << 8 ) ) & 0x1f00;
if ( change ) {
c->chanData ^= change;
Channel_UpdateFrequency( c, chip, fourOp );
@ -1227,6 +1249,7 @@ static void Channel_WriteC0( struct Channel *c, const struct Chip* chip, Bit8u v
//4-op mode enabled for this channel
if ( (chip->reg104 & c->fourMask) & 0x3f ) {
struct Channel* chan0, *chan1;
Bit8u synth;
//Check if it's the 2nd channel in a 4-op
if ( !(c->fourMask & 0x80 ) ) {
chan0 = c;
@ -1236,7 +1259,7 @@ static void Channel_WriteC0( struct Channel *c, const struct Chip* chip, Bit8u v
chan1 = c;
}
Bit8u synth = ( (chan0->regC0 & 1) << 0 )| (( chan1->regC0 & 1) << 1 );
synth = ( (chan0->regC0 & 1) << 0 )| (( chan1->regC0 & 1) << 1 );
switch ( synth ) {
case 0:
chan0->synthHandler = &Channel_Block_sm3FMFM;
@ -1307,8 +1330,9 @@ void Chip_Init(void *_chip) {
}
static INLINE Bit32u Chip_ForwardNoise(struct Chip *chip) {
Bitu count;
chip->noiseCounter += chip->noiseAdd;
Bitu count = chip->noiseCounter >> LFO_SH;
count = chip->noiseCounter >> LFO_SH;
chip->noiseCounter &= WAVE_MASK;
for ( ; count > 0; --count ) {
//Noise calculation from mame
@ -1437,12 +1461,13 @@ void Chip_WriteReg( void *_chip, Bit32u reg, Bit8u val ) {
//Always keep the highest bit enabled, for checking > 0x80
chip->reg104 = 0x80 | ( val & 0x3f );
} else if ( reg == 0x105 ) {
int i;
//MAME says the real opl3 doesn't reset anything on opl3 disable/enable till the next write in another register
if ( !((chip->opl3Active ^ val) & 1 ) )
return;
chip->opl3Active = ( val & 1 ) ? 0xff : 0;
//Update the 0xc0 register for all channels to signal the switch to mono/stereo handlers
for ( int i = 0; i < 18;i++ ) {
for ( i = 0; i < 18; i++ ) {
Channel_ResetC0( &chip->chan[i], chip );
}
} else if ( reg == 0x08 ) {
@ -1507,7 +1532,8 @@ void Chip_GenerateBlock2( void *_chip, Bitu total, Bit32s* output ) {
struct Channel* ch;
int count;
Bit32u samples = Chip_ForwardLFO( chip, total );
for ( Bitu i = 0; i < samples; i++ ) {
Bitu i;
for ( i = 0; i < samples; i++ ) {
output[i] = 0;
}
count = 0;
@ -1526,7 +1552,8 @@ void Chip_GenerateBlock3( void *_chip, Bitu total, Bit32s* output ) {
struct Channel* ch;
int count;
Bit32u samples = Chip_ForwardLFO( chip, total );
for ( Bitu i = 0; i < samples; i++ ) {
Bitu i;
for ( i = 0; i < samples; i++ ) {
output[i * 2 + 0 ] = 0;
output[i * 2 + 1 ] = 0;
}
@ -1544,6 +1571,14 @@ 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;
#ifdef WAVE_PRECISION
double freqScale;
#else
Bit32u freqScale;
#endif
int i;
Bit8u j;
if (fabs(scale - 1.0) < 0.00001)
scale = 1.0;
@ -1561,41 +1596,46 @@ void Chip_Setup( void *_chip, Bit32u clock, Bit32u rate ) {
//With higher octave this gets shifted up
//-1 since the freqCreateTable = *2
#ifdef WAVE_PRECISION
double freqScale = ( 1 << 7 ) * scale * ( 1 << ( WAVE_SH - 1 - 10));
for ( int i = 0; i < 16; i++ ) {
freqScale = ( 1 << 7 ) * scale * ( 1 << ( WAVE_SH - 1 - 10));
for ( i = 0; i < 16; i++ ) {
//Use rounding with 0.5
chip->freqMul[i] = (Bit32u)( 0.5 + freqScale * FreqCreateTable[ i ] );
}
#else
Bit32u freqScale = (Bit32u)( 0.5 + scale * ( 1 << ( WAVE_SH - 1 - 10)));
for ( int i = 0; i < 16; i++ ) {
freqScale = (Bit32u)( 0.5 + scale * ( 1 << ( WAVE_SH - 1 - 10)));
for ( i = 0; i < 16; i++ ) {
chip->freqMul[i] = freqScale * FreqCreateTable[ i ];
}
#endif
//-3 since the real envelope takes 8 steps to reach the single value we supply
for ( Bit8u i = 0; i < 76; i++ ) {
for ( j = 0; j < 76; j++ ) {
Bit8u index, shift;
EnvelopeSelect( i, &index, &shift );
chip->linearRates[i] = (Bit32u)( scale * (EnvelopeIncreaseTable[ index ] << ( RATE_SH + ENV_EXTRA - shift - 3 )));
EnvelopeSelect( j, &index, &shift );
chip->linearRates[j] = (Bit32u)( scale * (EnvelopeIncreaseTable[ index ] << ( RATE_SH + ENV_EXTRA - shift - 3 )));
}
//Generate the best matching attack rate
for ( Bit8u i = 0; i < 62; i++ ) {
for ( j = 0; j < 62; j++ ) {
Bit8u index, shift;
EnvelopeSelect( i, &index, &shift );
Bit32s original, guessAdd, bestAdd;
Bit32u bestDiff, passes;
EnvelopeSelect( j, &index, &shift );
//Original amount of samples the attack would take
Bit32s original = (Bit32u)( (AttackSamplesTable[ index ] << shift) / scale);
original = (Bit32u)( (AttackSamplesTable[ index ] << shift) / scale);
Bit32s guessAdd = (Bit32u)( scale * (EnvelopeIncreaseTable[ index ] << ( RATE_SH - shift - 3 )));
Bit32s bestAdd = guessAdd;
Bit32u bestDiff = 1 << 30;
for( Bit32u passes = 0; passes < 16; passes ++ ) {
guessAdd = (Bit32u)( scale * (EnvelopeIncreaseTable[ index ] << ( RATE_SH - shift - 3 )));
bestAdd = guessAdd;
bestDiff = 1 << 30;
for( passes = 0; passes < 16; passes ++ ) {
Bit32s volume = ENV_MAX;
Bit32s samples = 0;
Bit32u count = 0;
Bit32s diff;
Bit32u lDiff;
while ( volume > 0 && samples < original * 2 ) {
Bit32s change;
count += guessAdd;
Bit32s change = count >> RATE_SH;
change = count >> RATE_SH;
count &= RATE_MASK;
if ( change ) {
volume += ( ~volume * change ) >> 3;
@ -1603,8 +1643,8 @@ void Chip_Setup( void *_chip, Bit32u clock, Bit32u rate ) {
samples++;
}
Bit32s diff = original - samples;
Bit32u lDiff = labs( diff );
diff = original - samples;
lDiff = labs( diff );
//Init last on first pass
if ( lDiff < bestDiff ) {
bestDiff = lDiff;
@ -1624,11 +1664,11 @@ void Chip_Setup( void *_chip, Bit32u clock, Bit32u rate ) {
guessAdd--;
}
}
chip->attackRates[i] = bestAdd;
chip->attackRates[j] = bestAdd;
}
for ( Bit8u i = 62; i < 76; i++ ) {
for ( j = 62; j < 76; j++ ) {
//This should provide instant volume maximizing
chip->attackRates[i] = 8 << RATE_SH;
chip->attackRates[j] = 8 << RATE_SH;
}
//Setup the channels with the correct four op flags
//Channels are accessed through a table so they appear linear here
@ -1653,7 +1693,7 @@ void Chip_Setup( void *_chip, Bit32u clock, Bit32u rate ) {
//Clear Everything in opl3 mode
Chip_WriteReg( chip, 0x105, 0x1 );
for ( int i = 0; i < 512; i++ ) {
for ( i = 0; i < 512; i++ ) {
if ( i == 0x105 )
continue;
Chip_WriteReg( chip, i, 0xff );
@ -1661,7 +1701,7 @@ void Chip_Setup( void *_chip, Bit32u clock, Bit32u rate ) {
}
Chip_WriteReg( chip, 0x105, 0x0 );
//Clear everything in opl2 mode
for ( int i = 0; i < 256; i++ ) {
for ( i = 0; i < 256; i++ ) {
Chip_WriteReg( chip, i, 0xff );
Chip_WriteReg( chip, i, 0x0 );
}
@ -1669,6 +1709,9 @@ void Chip_Setup( void *_chip, Bit32u clock, Bit32u rate ) {
static unsigned char doneTables = 0;
static void InitTables( void ) {
int i, oct;
Bit8u j;
Bitu k;
if ( doneTables )
return;
#if ( DBOPL_WAVE == WAVE_HANDLER ) || ( DBOPL_WAVE == WAVE_TABLELOG )
@ -1690,7 +1733,7 @@ static void InitTables( void ) {
#endif
#if ( DBOPL_WAVE == WAVE_TABLEMUL )
//Multiplication based tables
for ( int i = 0; i < 384; i++ ) {
for ( i = 0; i < 384; i++ ) {
int s = i * 8;
//TODO maybe keep some of the precision errors of the original table?
double val = ( 0.5 + ( pow(2.0, -1.0 + ( 255 - s) * ( 1.0 /256 ) )) * ( 1 << MUL_SH ));
@ -1698,24 +1741,24 @@ static void InitTables( void ) {
}
//Sine Wave Base
for ( int i = 0; i < 512; i++ ) {
for ( i = 0; i < 512; i++ ) {
WaveTable[ 0x0200 + i ] = (Bit16s)(sin( (i + 0.5) * (PI / 512.0) ) * 4084);
WaveTable[ 0x0000 + i ] = -WaveTable[ 0x200 + i ];
}
//Exponential wave
for ( int i = 0; i < 256; i++ ) {
for ( i = 0; i < 256; i++ ) {
WaveTable[ 0x700 + i ] = (Bit16s)( 0.5 + ( pow(2.0, -1.0 + ( 255 - i * 8) * ( 1.0 /256 ) ) ) * 4085 );
WaveTable[ 0x6ff - i ] = -WaveTable[ 0x700 + i ];
}
#endif
#if ( DBOPL_WAVE == WAVE_TABLELOG )
//Sine Wave Base
for ( int i = 0; i < 512; i++ ) {
for ( i = 0; i < 512; i++ ) {
WaveTable[ 0x0200 + i ] = (Bit16s)( 0.5 - log10( sin( (i + 0.5) * (PI / 512.0) ) ) / log10(2.0)*256 );
WaveTable[ 0x0000 + i ] = ((Bit16s)0x8000) | WaveTable[ 0x200 + i];
}
//Exponential wave
for ( int i = 0; i < 256; i++ ) {
for ( i = 0; i < 256; i++ ) {
WaveTable[ 0x700 + i ] = i * 8;
WaveTable[ 0x6ff - i ] = ((Bit16s)0x8000) | i * 8;
}
@ -1726,7 +1769,7 @@ static void InitTables( void ) {
// |06 |0126|27 |7 |3 |4 |4 5 |5 |
#if (( DBOPL_WAVE == WAVE_TABLELOG ) || ( DBOPL_WAVE == WAVE_TABLEMUL ))
for ( int i = 0; i < 256; i++ ) {
for ( i = 0; i < 256; i++ ) {
//Fill silence gaps
WaveTable[ 0x400 + i ] = WaveTable[0];
WaveTable[ 0x500 + i ] = WaveTable[0];
@ -1744,29 +1787,29 @@ static void InitTables( void ) {
#endif
//Create the ksl table
for ( int oct = 0; oct < 8; oct++ ) {
for ( oct = 0; oct < 8; oct++ ) {
int base = oct * 8;
for ( int i = 0; i < 16; i++ ) {
for ( i = 0; i < 16; i++ ) {
int val = base - KslCreateTable[i];
if ( val < 0 )
val = 0;
//*4 for the final range to match attenuation range
KslTable[ oct * 16 + i ] = val * 4;
KslTable[ oct * 16 + i ] = (Bit8u)(val * 4);
}
}
//Create the Tremolo table, just increase and decrease a triangle wave
for ( Bit8u i = 0; i < TREMOLO_TABLE / 2; i++ ) {
Bit8u val = i << ENV_EXTRA;
TremoloTable[i] = val;
TremoloTable[TREMOLO_TABLE - 1 - i] = val;
for ( j = 0; j < TREMOLO_TABLE / 2; j++ ) {
Bit8u val = j << ENV_EXTRA;
TremoloTable[j] = val;
TremoloTable[TREMOLO_TABLE - 1 - j] = val;
}
//Create a table with offsets of the channels from the start of the chip
struct Chip* chip = 0;
for ( Bitu i = 0; i < 32; i++ ) {
Bitu index = i & 0xf;
for ( k = 0; k < 32; k++ ) {
Bitu index = k & 0xf;
Bitu blah;
struct Chip *chip = 0;
if ( index >= 9 ) {
ChanOffsetTable[i] = 0;
ChanOffsetTable[k] = 0;
continue;
}
//Make sure the four op channels follow eachother
@ -1774,34 +1817,35 @@ static void InitTables( void ) {
index = (index % 3) * 2 + ( index / 3 );
}
//Add back the bits for highest ones
if ( i >= 16 )
if ( k >= 16 )
index += 9;
blah = (Bitu)( (unsigned long)( &(chip->chan[ index ]) ) );
ChanOffsetTable[i] = blah;
ChanOffsetTable[k] = (Bit16u)blah;
}
//Same for operators
for ( Bitu i = 0; i < 64; i++ ) {
for ( k = 0; k < 64; k++ ) {
Bitu chNum;
Bitu opNum;
Bitu blah;
struct Channel* chan = 0;
if ( i % 8 >= 6 || ( (i / 8) % 4 == 3 ) ) {
OpOffsetTable[i] = 0;
if ( k % 8 >= 6 || ( (k / 8) % 4 == 3 ) ) {
OpOffsetTable[k] = 0;
continue;
}
chNum = (i / 8) * 3 + (i % 8) % 3;
chNum = (k / 8) * 3 + (k % 8) % 3;
//Make sure we use 16 and up for the 2nd range to match the chanoffset gap
if ( chNum >= 12 )
chNum += 16 - 12;
opNum = ( i % 8 ) / 3;
opNum = ( k % 8 ) / 3;
blah = (Bitu)( (unsigned long) ( &(chan->op[opNum]) ) );
OpOffsetTable[i] = ChanOffsetTable[ chNum ] + blah;
OpOffsetTable[k] = (Bit16u)(ChanOffsetTable[ chNum ] + blah);
}
#if 0
//Stupid checks if table's are correct
for ( Bitu i = 0; i < 18; i++ ) {
Bit32u find = (Bit16u)( &(chip->chan[ i ]) );
for ( Bitu c = 0; c < 32; c++ ) {
for ( k = 0; k < 18; k++ ) {
Bit32u find = (Bit16u)( &(chip->chan[ k ]) );
Bitu c;
for ( c = 0; c < 32; c++ ) {
if ( ChanOffsetTable[c] == find ) {
find = 0;
break;
@ -1811,9 +1855,10 @@ static void InitTables( void ) {
find = find;
}
}
for ( Bitu i = 0; i < 36; i++ ) {
Bit32u find = (Bit16u)( &(chip->chan[ i / 2 ].op[i % 2]) );
for ( Bitu c = 0; c < 64; c++ ) {
for ( k = 0; k < 36; k++ ) {
Bit32u find = (Bit16u)( &(chip->chan[ k / 2 ].op[k % 2]) );
Bitu c;
for ( c = 0; c < 64; c++ ) {
if ( OpOffsetTable[c] == find ) {
find = 0;
break;

View File

@ -43,8 +43,8 @@ typedef unsigned char Bit8u;
typedef signed char Bit8s;
typedef unsigned short Bit16u;
typedef signed short Bit16s;
typedef unsigned long Bit32u;
typedef signed long Bit32s;
typedef unsigned int Bit32u;
typedef signed int Bit32s;
#ifdef _MSC_VER
typedef unsigned __int64 Bit64u;
typedef signed __int64 Bit64s;

View File

@ -283,6 +283,24 @@ void resampler_write_sample(void *_r, short s)
}
}
void resampler_write_sample_fixed(void *_r, int s, unsigned char depth)
{
resampler * r = ( resampler * ) _r;
if ( r->write_filled < resampler_buffer_size )
{
float s32 = s;
s32 /= (double)(1 << (depth - 1));
r->buffer_in[ r->write_pos ] = s32;
r->buffer_in[ r->write_pos + resampler_buffer_size ] = s32;
++r->write_filled;
r->write_pos = ( r->write_pos + 1 ) % resampler_buffer_size;
}
}
static int resampler_run_zoh(resampler * r, float ** out_, float * out_end)
{
int in_size = r->write_filled;

View File

@ -13,6 +13,7 @@
#define resampler_set_quality EVALUATE(RESAMPLER_DECORATE,_resampler_set_quality)
#define resampler_get_free_count EVALUATE(RESAMPLER_DECORATE,_resampler_get_free_count)
#define resampler_write_sample EVALUATE(RESAMPLER_DECORATE,_resampler_write_sample)
#define resampler_write_sample_fixed EVALUATE(RESAMPLER_DECORATE,_resampler_write_sample_fixed)
#define resampler_set_rate EVALUATE(RESAMPLER_DECORATE,_resampler_set_rate)
#define resampler_ready EVALUATE(RESAMPLER_DECORATE,_resampler_ready)
#define resampler_clear EVALUATE(RESAMPLER_DECORATE,_resampler_clear)
@ -43,6 +44,7 @@ void resampler_set_quality(void *, int quality);
int resampler_get_free_count(void *);
void resampler_write_sample(void *, short sample);
void resampler_write_sample_fixed(void *, int sample, unsigned char depth);
void resampler_set_rate( void *, double new_factor );
int resampler_ready(void *);
void resampler_clear(void *);

View File

@ -1,5 +1,5 @@
/*
** ST3PLAY v0.45
** ST3PLAY v0.47
** =============
**
** C port of Scream Tracker 3's replayer, by 8bitbubsy (Olav Sørensen)
@ -63,6 +63,8 @@
#define inline __forceinline
#endif
#include "dbopl.h"
#include "resampler.h"
#include "st3play.h"
@ -199,6 +201,12 @@ typedef struct
void *resampler[64];
#endif
void *fmChip;
void *fmResampler;
const uint8_t *fmPatchTable[9];
uint8_t fmLastB0[9];
float f_outputFreq;
float f_masterVolume;
@ -315,6 +323,7 @@ static const int16_t vibramp[64] =
192, 200, 208, 216, 224, 232, 240, 248
};
static const char Adlib_PortBases[9] = {0, 1, 2, 8, 9, 10, 16, 17, 18};
// FUNCTION DECLARATIONS
@ -534,6 +543,26 @@ void * st3play_Alloc(uint32_t outputFreq, int8_t interpolation, int8_t ramp_styl
return p;
}
static int st3play_AdlibInit(PLAYER *p)
{
p->fmChip = malloc( Chip_GetSize() );
if ( !p->fmChip )
return -1;
Chip_Init( p->fmChip );
Chip_Setup( p->fmChip, 3579545 * 4, 49716 );
Chip_WriteReg( p->fmChip, 0x01, 0x20 ); // enable wave select, but rather pointless with dbopl
p->fmResampler = resampler_create();
if ( !p->fmResampler )
return -1;
resampler_set_quality( p->fmResampler, RESAMPLER_QUALITY_MAX );
resampler_set_rate( p->fmResampler, 49716.0 / p->f_outputFreq );
return 0;
}
void st3play_Free(void *_p)
{
int i;
@ -542,6 +571,12 @@ void st3play_Free(void *_p)
FreeSong(p);
if ( p->fmResampler )
resampler_delete( p->fmResampler );
if ( p->fmChip )
free( p->fmChip );
#ifdef USE_VOL_RAMP
for (i = 0; i < 64 * 2; ++i)
#else
@ -601,9 +636,22 @@ static void settempo(PLAYER *p, uint16_t val)
}
}
static void st3play_AdlibHertzTouch(PLAYER *p, uint8_t ch, int Hertz, uint8_t keyoff)
{
int Oct;
for (Oct = 0; Hertz > 0x1FF; Oct++)
Hertz >>= 1;
Chip_WriteReg( p->fmChip, 0xA0 + ch, Hertz & 255 );
p->fmLastB0[ch] = (keyoff ? 0 : 0x20) | ((Hertz >> 8) & 3) | ((Oct & 7) << 2);
Chip_WriteReg( p->fmChip, 0xB0 + ch, p->fmLastB0[ch]);
}
static inline void setspd(PLAYER *p, uint8_t ch)
{
int32_t tmpspd;
uint8_t adlibChannel = (p->mseg[0x40 + ch] & 0x7F) - 16;
tmpspd = p->chn[ch].aspd;
@ -636,16 +684,43 @@ static inline void setspd(PLAYER *p, uint8_t ch)
// 14317056 is used in both the ST3 replayer and the S3M format docs
if (tmpspd)
voiceSetSamplingFrequency(p, ch, 14317056.0f / (float)tmpspd);
if (adlibChannel < 9)
st3play_AdlibHertzTouch(p, adlibChannel, 14317056.0f / (float)tmpspd, 0);
}
static void st3play_AdlibTouch(PLAYER *p, uint8_t ch, const uint8_t * patch, uint8_t vol)
{
int Operator;
if (!patch)
{
patch = p->fmPatchTable[ch];
if (!patch)
return;
}
p->fmPatchTable[ch] = patch;
Operator = Adlib_PortBases[ch];
Chip_WriteReg( p->fmChip, 0x40 + Operator, (patch[2] & 0xC0) |
(((int)(patch[2] & 63) - 63) * vol + 63 * 64 - 32) / 64 );
Chip_WriteReg( p->fmChip, 0x43 + Operator, (patch[3] & 0xC0) |
(((int)(patch[3] & 63) - 63) * vol + 63 * 64 - 32) / 64 );
}
static inline void setvol(PLAYER *p, uint8_t ch, uint8_t sharp)
{
uint8_t adlibChannel = (p->mseg[0x40 + ch] & 0x7F) - 16;
p->chn[ch].achannelused |= 0x80;
#ifdef USE_VOL_RAMP
voiceSetVolume(p, ch + ((sharp == 2) ? 32 : 0), (sharp == 2) ? 0.0f : ((float)(p->chn[ch].avol) / 63.0f) * ((float)(p->chn[ch].chanvol) / 64.0f) * ((float)(p->globalvol) / 64.0f), sharp);
#else
voiceSetVolume(p, ch, ((float)(p->chn[ch].avol) / 63.0f) * ((float)(p->chn[ch].chanvol) / 64.0f) * ((float)(p->globalvol) / 64.0f), sharp);
#endif
if (adlibChannel < 9)
st3play_AdlibTouch(p, adlibChannel, NULL, p->chn[ch].avol);
}
static inline void setpan(PLAYER *p, uint8_t ch)
@ -877,6 +952,30 @@ static inline uint8_t getnote(PLAYER *p)
return (ch);
}
static void st3play_AdlibPatch(PLAYER *p, uint8_t ch, const uint8_t *patch)
{
int Operator = Adlib_PortBases[ch];
p->fmPatchTable[ch] = patch;
Chip_WriteReg( p->fmChip, 0x20 + Operator, patch[0]);
Chip_WriteReg( p->fmChip, 0x60 + Operator, patch[4]);
Chip_WriteReg( p->fmChip, 0x80 + Operator, patch[6]);
Chip_WriteReg( p->fmChip, 0xE0 + Operator, patch[8] & 3);
Chip_WriteReg( p->fmChip, 0x23 + Operator, patch[1]);
Chip_WriteReg( p->fmChip, 0x63 + Operator, patch[5]);
Chip_WriteReg( p->fmChip, 0x83 + Operator, patch[7]);
Chip_WriteReg( p->fmChip, 0xE3 + Operator, patch[9] & 3);
Chip_WriteReg( p->fmChip, 0xC0 + ch, patch[10]);
}
static void st3play_AdlibNoteOff(PLAYER *p, uint8_t ch)
{
Chip_WriteReg( p->fmChip, 0xB0 + ch, p->fmLastB0[ch] & ~0x20 );
}
static inline void doamiga(PLAYER *p, uint8_t ch)
{
uint8_t *insdat;
@ -889,6 +988,10 @@ static inline void doamiga(PLAYER *p, uint8_t ch)
#ifdef USE_VOL_RAMP
uint8_t volassigned = 0;
#endif
uint8_t adlibChannel = (p->mseg[0x40 + ch] & 0x7F) - 16;
if (!p->fmChip || !p->fmResampler) // safety check
adlibChannel = 255;
if (p->chn[ch].ins)
{
@ -900,7 +1003,7 @@ static inline void doamiga(PLAYER *p, uint8_t ch)
insdat = &p->mseg[(uint32_t)(get_le16(&p->mseg[p->instrumentadd + ((p->chn[ch].ins - 1) << 1)])) << 4];
if (insdat[0])
{
if (insdat[0] == 1)
if (insdat[0] == 1 && adlibChannel >= 9)
{
p->chn[ch].ac2spd = get_le32(&insdat[0x20]);
@ -965,6 +1068,16 @@ static inline void doamiga(PLAYER *p, uint8_t ch)
insrepend - insrepbeg, insrepend, loop,
insdat[0x1F] & 4, insdat[0x1F] & 2, insdat[0x1E] == 4);
}
else if (insdat[0] == 2 && adlibChannel < 9 )
{
p->chn[ch].ac2spd = 8363 * 164 / 249;
p->chn[ch].avol = (int8_t)(insdat[0x1C]);
p->chn[ch].aorgvol = p->chn[ch].avol;
st3play_AdlibPatch(p, adlibChannel, &insdat[0x10]);
voiceSetSource(p, ch, NULL, 0, 0, 0, 0, 0, 0, 0);
voiceSetSamplePosition(p, ch, 0);
}
else
{
p->chn[ch].lastins = 0;
@ -997,19 +1110,28 @@ static inline void doamiga(PLAYER *p, uint8_t ch)
p->chn[ch].avol = 0;
p->chn[ch].asldspd = 65535;
setspd(p, ch);
setvol(p, ch, 0);
if (adlibChannel >= 9)
{
setspd(p, ch);
setvol(p, ch, 0);
}
// shutdown channel
voiceSetSource(p, ch, NULL, 0, 0, 0, 0, 0, 0, 0);
voiceSetSamplePosition(p, ch, 0);
if (adlibChannel < 9)
st3play_AdlibNoteOff(p, adlibChannel);
}
else
{
p->chn[ch].lastnote = p->chn[ch].note;
if ((p->chn[ch].cmd != ('G' - 64)) && (p->chn[ch].cmd != ('L' - 64)))
voiceSetSamplePosition(p, ch, p->chn[ch].astartoffset);
if (adlibChannel >= 9)
{
if ((p->chn[ch].cmd != ('G' - 64)) && (p->chn[ch].cmd != ('L' - 64)))
voiceSetSamplePosition(p, ch, p->chn[ch].astartoffset);
}
if (!p->chn[ch].aorgspd || ((p->chn[ch].cmd != ('G' - 64)) && (p->chn[ch].cmd != ('L' - 64))))
{
@ -1017,11 +1139,18 @@ static inline void doamiga(PLAYER *p, uint8_t ch)
p->chn[ch].aorgspd = p->chn[ch].aspd;
p->chn[ch].avibcnt = 0;
p->chn[ch].apancnt = 0;
setspd(p, ch);
}
p->chn[ch].asldspd = scalec2spd(p, ch, stnote2herz(p, p->chn[ch].note));
if (adlibChannel < 9)
{
st3play_AdlibNoteOff(p, adlibChannel);
setspd(p, ch);
st3play_AdlibTouch(p, adlibChannel, NULL, p->chn[ch].avol);
}
}
}
@ -1099,7 +1228,7 @@ static inline void donotes(PLAYER *p)
ch = getnote(p);
if (ch == 255) break; // end of row/channels
if ((p->mseg[0x40 + ch] & 0x7F) <= 15) // no adlib channel types yet
if ((p->mseg[0x40 + ch] & 0x7F) <= 15 + 9)
donewnote(p, ch, 0);
}
}
@ -1362,7 +1491,7 @@ static void loadheaderparms(PLAYER *p)
insdat = &p->mseg[get_le16(&p->mseg[p->instrumentadd + (i << 1)]) << 4];
insoff = (uint32_t)(((uint32_t)(insdat[0x0D])<<16)|((uint16_t)(insdat[0x0F])<<8)|insdat[0x0E])<<4;
if (insoff && (insdat[0] == 1))
if (insoff && (insdat[0] == 1)) // PCM
{
if (insoff > p->mseg_len)
insoff = p->mseg_len;
@ -1391,6 +1520,11 @@ static void loadheaderparms(PLAYER *p)
p->mseg[insoff + j] = p->mseg[insoff + j] - 0x80;
}
}
else if (insdat[0] == 2) // AdLib melodic
{
if (!p->fmChip && st3play_AdlibInit(p) < 0)
break;
}
}
}
}
@ -1564,12 +1698,8 @@ static void s_setpanwave(PLAYER *p, chn_t *ch) // NON-ST3
static void s_setpanpos(PLAYER *p, chn_t *ch)
{
if (p->stereomode)
{
ch->apanpos = (ch->info & 0x0F) << 4;
setpan(p, ch->channelnum);
}
ch->apanpos = (ch->info & 0x0F) << 4;
setpan(p, ch->channelnum);
}
static void s_sndcntrl(PLAYER *p, chn_t *ch) // NON-ST3
@ -1636,7 +1766,12 @@ static void s_notecutb(PLAYER *p, chn_t *ch)
{
ch->anotecutcnt--;
if (!ch->anotecutcnt)
{
uint8_t adlibChannel = (p->mseg[0x40 + ch->channelnum] & 0x7F) - 16;
voiceSetSamplingFrequency(p, ch->channelnum, 0); // cut note
if (adlibChannel < 9)
st3play_AdlibNoteOff(p, adlibChannel);
}
}
}
@ -3570,6 +3705,45 @@ void mixSampleBlock(PLAYER *p, float *outputStream, uint32_t sampleBlockLength)
}
}
static void st3play_AdlibMix(PLAYER *p, float *buffer, int32_t count)
{
Bit32s tempbuffer[256];
int inbuffer_free, i;
int outbuffer_avail;
while (count)
{
inbuffer_free = resampler_get_free_count( p->fmResampler );
if (inbuffer_free > 256)
inbuffer_free = 256;
if (inbuffer_free)
{
Chip_GenerateBlock2( p->fmChip, inbuffer_free, tempbuffer );
for (i = 0; i < inbuffer_free; ++i)
resampler_write_sample_fixed( p->fmResampler, (int)tempbuffer[i], 16);
}
outbuffer_avail = resampler_get_sample_count( p->fmResampler );
if (outbuffer_avail > count)
outbuffer_avail = count;
for (i = 0; i < outbuffer_avail; ++i)
{
float sample = resampler_get_sample( p->fmResampler );
resampler_remove_sample( p->fmResampler );
buffer[i * 2 + 0] += sample;
buffer[i * 2 + 1] += sample;
}
buffer += outbuffer_avail * 2;
count -= outbuffer_avail;
}
}
void st3play_RenderFloat(void *_p, float *buffer, int32_t count)
{
PLAYER * p = (PLAYER *)_p;
@ -3591,6 +3765,9 @@ void st3play_RenderFloat(void *_p, float *buffer, int32_t count)
{
mixSampleBlock(p, outputStream, samplesTodo);
if (p->fmChip && p->fmResampler)
st3play_AdlibMix( p, outputStream, samplesTodo );
outputStream += (samplesTodo << 1);
}