Updated st3play with experimental AdLib support
This commit is contained in:
parent
55eec18bfe
commit
c4288a8e61
6 changed files with 352 additions and 102 deletions
|
@ -11,6 +11,8 @@
|
||||||
838A72E618DEC9A1007C8A7D /* resampler.c in Sources */ = {isa = PBXBuildFile; fileRef = 838A72E418DEC9A1007C8A7D /* resampler.c */; };
|
838A72E618DEC9A1007C8A7D /* resampler.c in Sources */ = {isa = PBXBuildFile; fileRef = 838A72E418DEC9A1007C8A7D /* resampler.c */; };
|
||||||
838A72E718DEC9A1007C8A7D /* resampler.h in Headers */ = {isa = PBXBuildFile; fileRef = 838A72E518DEC9A1007C8A7D /* resampler.h */; };
|
838A72E718DEC9A1007C8A7D /* resampler.h in Headers */ = {isa = PBXBuildFile; fileRef = 838A72E518DEC9A1007C8A7D /* resampler.h */; };
|
||||||
839CAC4018DA746000D67EA9 /* ft2play.c in Sources */ = {isa = PBXBuildFile; fileRef = 839CAC3F18DA746000D67EA9 /* ft2play.c */; };
|
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 */; };
|
83F4D54818D82105009B2DE6 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 83F4D54618D82105009B2DE6 /* InfoPlist.strings */; };
|
||||||
83F4D57718D821D2009B2DE6 /* st3play.c in Sources */ = {isa = PBXBuildFile; fileRef = 83F4D57318D821D2009B2DE6 /* st3play.c */; };
|
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, ); }; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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; };
|
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>"; };
|
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>"; };
|
83F4D54718D82105009B2DE6 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
|
||||||
|
@ -74,6 +78,8 @@
|
||||||
83F4D54318D82105009B2DE6 /* modplay */ = {
|
83F4D54318D82105009B2DE6 /* modplay */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
83EAF76618E8F70400C896A6 /* dbopl.c */,
|
||||||
|
83EAF76718E8F70400C896A6 /* dbopl.h */,
|
||||||
838A72E418DEC9A1007C8A7D /* resampler.c */,
|
838A72E418DEC9A1007C8A7D /* resampler.c */,
|
||||||
838A72E518DEC9A1007C8A7D /* resampler.h */,
|
838A72E518DEC9A1007C8A7D /* resampler.h */,
|
||||||
83F4D57318D821D2009B2DE6 /* st3play.c */,
|
83F4D57318D821D2009B2DE6 /* st3play.c */,
|
||||||
|
@ -103,6 +109,7 @@
|
||||||
files = (
|
files = (
|
||||||
838A72E718DEC9A1007C8A7D /* resampler.h in Headers */,
|
838A72E718DEC9A1007C8A7D /* resampler.h in Headers */,
|
||||||
835CBC8218DA95AC0087A03E /* ft2play.h in Headers */,
|
835CBC8218DA95AC0087A03E /* ft2play.h in Headers */,
|
||||||
|
83EAF76918E8F70400C896A6 /* dbopl.h in Headers */,
|
||||||
83F4D57818D821D2009B2DE6 /* st3play.h in Headers */,
|
83F4D57818D821D2009B2DE6 /* st3play.h in Headers */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
@ -171,6 +178,7 @@
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
838A72E618DEC9A1007C8A7D /* resampler.c in Sources */,
|
838A72E618DEC9A1007C8A7D /* resampler.c in Sources */,
|
||||||
|
83EAF76818E8F70400C896A6 /* dbopl.c in Sources */,
|
||||||
83F4D57718D821D2009B2DE6 /* st3play.c in Sources */,
|
83F4D57718D821D2009B2DE6 /* st3play.c in Sources */,
|
||||||
839CAC4018DA746000D67EA9 /* ft2play.c in Sources */,
|
839CAC4018DA746000D67EA9 /* ft2play.c in Sources */,
|
||||||
);
|
);
|
||||||
|
|
|
@ -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 ) {
|
static INLINE Bit32s Operator_RateForward( struct Operator *o, Bit32u add ) {
|
||||||
|
Bit32s ret;
|
||||||
o->rateIndex += add;
|
o->rateIndex += add;
|
||||||
Bit32s ret = o->rateIndex >> RATE_SH;
|
ret = o->rateIndex >> RATE_SH;
|
||||||
o->rateIndex = o->rateIndex & RATE_MASK;
|
o->rateIndex = o->rateIndex & RATE_MASK;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const Operator_VolumeHandler VolumeHandlerTable[5];
|
static INLINE void Operator_SetState( struct Operator *o, Bit8u s );
|
||||||
|
|
||||||
static INLINE void Operator_SetState( struct Operator *o, Bit8u s ) {
|
|
||||||
o->state = s;
|
|
||||||
o->volHandler = VolumeHandlerTable[ s ];
|
|
||||||
}
|
|
||||||
|
|
||||||
static Bits Operator_Volume_Attack( struct Operator *o ) {
|
static Bits Operator_Volume_Attack( struct Operator *o ) {
|
||||||
Bit32s vol = o->volume;
|
Bit32s vol = o->volume;
|
||||||
|
@ -556,7 +552,6 @@ static Bits Operator_Volume_Attack( struct Operator *o ) {
|
||||||
|
|
||||||
static Bits Operator_Volume_Decay( struct Operator *o ) {
|
static Bits Operator_Volume_Decay( struct Operator *o ) {
|
||||||
Bit32s vol = o->volume;
|
Bit32s vol = o->volume;
|
||||||
Bit32s change;
|
|
||||||
vol += Operator_RateForward( o, o->decayAdd );
|
vol += Operator_RateForward( o, o->decayAdd );
|
||||||
if ( vol >= o->sustainLevel ) {
|
if ( vol >= o->sustainLevel ) {
|
||||||
//Check if we didn't overshoot max attenuation, then just go off
|
//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 ) {
|
static Bits Operator_Volume_Sustain( struct Operator *o ) {
|
||||||
Bit32s vol = o->volume;
|
Bit32s vol = o->volume;
|
||||||
Bit32s change;
|
|
||||||
if ( o->reg20 & MASK_SUSTAIN ) {
|
if ( o->reg20 & MASK_SUSTAIN ) {
|
||||||
return vol;
|
return vol;
|
||||||
}
|
}
|
||||||
|
@ -592,7 +586,6 @@ static Bits Operator_Volume_Sustain( struct Operator *o ) {
|
||||||
|
|
||||||
static Bits Operator_Volume_Release( struct Operator *o ) {
|
static Bits Operator_Volume_Release( struct Operator *o ) {
|
||||||
Bit32s vol = o->volume;
|
Bit32s vol = o->volume;
|
||||||
Bit32s change;
|
|
||||||
vol += Operator_RateForward( o, o->releaseAdd );;
|
vol += Operator_RateForward( o, o->releaseAdd );;
|
||||||
if ( vol >= ENV_MAX ) {
|
if ( vol >= ENV_MAX ) {
|
||||||
o->volume = ENV_MAX;
|
o->volume = ENV_MAX;
|
||||||
|
@ -616,6 +609,11 @@ static const Operator_VolumeHandler VolumeHandlerTable[5] = {
|
||||||
&Operator_Volume_Attack
|
&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) {
|
static INLINE Bitu Operator_ForwardVolume(struct Operator *o) {
|
||||||
return o->currentLevel + (o->volHandler)(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 ) {
|
static void Operator_Write80( struct Operator *o, const struct Chip* chip, Bit8u val ) {
|
||||||
Bit8u change = (o->reg80 ^ val );
|
Bit8u change = (o->reg80 ^ val );
|
||||||
|
Bit8u sustain;
|
||||||
if ( !change )
|
if ( !change )
|
||||||
return;
|
return;
|
||||||
o->reg80 = val;
|
o->reg80 = val;
|
||||||
Bit8u sustain = val >> 4;
|
sustain = val >> 4;
|
||||||
//Turn 0xf into 0x1f
|
//Turn 0xf into 0x1f
|
||||||
sustain |= ( sustain + 1) & 0x10;
|
sustain |= ( sustain + 1) & 0x10;
|
||||||
o->sustainLevel = sustain << ( ENV_BITS - 5 );
|
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 ) {
|
static void Operator_WriteE0( struct Operator *o, const struct Chip* chip, Bit8u val ) {
|
||||||
|
Bit8u waveForm;
|
||||||
if ( !(o->regE0 ^ val) )
|
if ( !(o->regE0 ^ val) )
|
||||||
return;
|
return;
|
||||||
//in opl3 mode you can always selet 7 waveforms regardless of waveformselect
|
//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;
|
o->regE0 = val;
|
||||||
#if ( DBOPL_WAVE == WAVE_HANDLER )
|
#if ( DBOPL_WAVE == WAVE_HANDLER )
|
||||||
o->waveHandler = WaveHandlerTable[ waveForm ];
|
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 ) {
|
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;
|
c->old[0] = c->old[1] = 0;
|
||||||
return (c + 1);
|
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, 0 ), chip );
|
||||||
Operator_Prepare( Channel_Op( c, 1 ), 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
|
//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 mod = (Bit32u)((c->old[0] + c->old[1])) >> c->feedback;
|
||||||
Bit32s sample;
|
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 ) {
|
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) ) ) {
|
if ( Operator_Silent( Channel_Op(c, 1) ) ) {
|
||||||
c->old[0] = c->old[1] = 0;
|
c->old[0] = c->old[1] = 0;
|
||||||
return (c + 1);
|
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, 0 ), chip );
|
||||||
Operator_Prepare( Channel_Op( c, 1 ), 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
|
//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 mod = (Bit32u)((c->old[0] + c->old[1])) >> c->feedback;
|
||||||
Bit32s sample;
|
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 ) {
|
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;
|
c->old[0] = c->old[1] = 0;
|
||||||
return (c + 1);
|
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, 0 ), chip );
|
||||||
Operator_Prepare( Channel_Op( c, 1 ), 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
|
//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 mod = (Bit32u)((c->old[0] + c->old[1])) >> c->feedback;
|
||||||
Bit32s sample;
|
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 ) {
|
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;
|
c->old[0] = c->old[1] = 0;
|
||||||
return (c + 1);
|
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, 0 ), chip );
|
||||||
Operator_Prepare( Channel_Op( c, 1 ), 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
|
//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 mod = (Bit32u)((c->old[0] + c->old[1])) >> c->feedback;
|
||||||
Bit32s sample;
|
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 ) {
|
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 ) ) ) {
|
if ( Operator_Silent( Channel_Op( c, 3 ) ) ) {
|
||||||
c->old[0] = c->old[1] = 0;
|
c->old[0] = c->old[1] = 0;
|
||||||
return (c + 2);
|
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, 2 ), chip );
|
||||||
Operator_Prepare( Channel_Op( c, 3 ), 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
|
//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 mod = (Bit32u)((c->old[0] + c->old[1])) >> c->feedback;
|
||||||
Bit32s sample;
|
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 ) {
|
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 ) ) ) {
|
if ( Operator_Silent( Channel_Op( c, 0 ) ) && Operator_Silent( Channel_Op( c, 3 ) ) ) {
|
||||||
c->old[0] = c->old[1] = 0;
|
c->old[0] = c->old[1] = 0;
|
||||||
return (c + 2);
|
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, 2 ), chip );
|
||||||
Operator_Prepare( Channel_Op( c, 3 ), 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
|
//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 mod = (Bit32u)((c->old[0] + c->old[1])) >> c->feedback;
|
||||||
Bit32s sample;
|
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 ) {
|
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 ) ) ) {
|
if ( Operator_Silent( Channel_Op( c, 1) ) && Operator_Silent( Channel_Op( c, 3 ) ) ) {
|
||||||
c->old[0] = c->old[1] = 0;
|
c->old[0] = c->old[1] = 0;
|
||||||
return (c + 2);
|
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, 2 ), chip );
|
||||||
Operator_Prepare( Channel_Op( c, 3 ), 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
|
//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 mod = (Bit32u)((c->old[0] + c->old[1])) >> c->feedback;
|
||||||
Bit32s sample;
|
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 ) {
|
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 ) ) ) {
|
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;
|
c->old[0] = c->old[1] = 0;
|
||||||
return (c + 2);
|
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, 2 ), chip );
|
||||||
Operator_Prepare( Channel_Op( c, 3 ), 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
|
//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 mod = (Bit32u)((c->old[0] + c->old[1])) >> c->feedback;
|
||||||
Bit32s sample;
|
Bit32s sample;
|
||||||
Bit32s out0;
|
Bit32s out0;
|
||||||
|
Bits next;
|
||||||
c->old[0] = c->old[1];
|
c->old[0] = c->old[1];
|
||||||
c->old[1] = Operator_GetSample( Channel_Op( c, 0 ), mod );
|
c->old[1] = Operator_GetSample( Channel_Op( c, 0 ), mod );
|
||||||
out0 = c->old[0];
|
out0 = c->old[0];
|
||||||
sample = out0;
|
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, 2 ), next );
|
||||||
sample += Operator_GetSample( Channel_Op( c, 3 ), 0 );
|
sample += Operator_GetSample( Channel_Op( c, 3 ), 0 );
|
||||||
output[ i * 2 + 0 ] += sample & c->maskLeft;
|
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 ) {
|
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
|
//Init the operators with the the current vibrato and tremolo values
|
||||||
Operator_Prepare( Channel_Op( c, 0 ), chip );
|
Operator_Prepare( Channel_Op( c, 0 ), chip );
|
||||||
Operator_Prepare( Channel_Op( c, 1 ), 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, 4 ), chip );
|
||||||
Operator_Prepare( Channel_Op( c, 5 ), 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 );
|
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 ) {
|
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
|
//Init the operators with the the current vibrato and tremolo values
|
||||||
Operator_Prepare( Channel_Op( c, 0 ), chip );
|
Operator_Prepare( Channel_Op( c, 0 ), chip );
|
||||||
Operator_Prepare( Channel_Op( c, 1 ), 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, 4 ), chip );
|
||||||
Operator_Prepare( Channel_Op( c, 5 ), 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 );
|
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 ) {
|
static void Channel_WriteB0( struct Channel *c, const struct Chip* chip, Bit8u val ) {
|
||||||
Bit8u fourOp = chip->reg104 & chip->opl3Active & c->fourMask;
|
Bit8u fourOp = chip->reg104 & chip->opl3Active & c->fourMask;
|
||||||
|
Bitu change;
|
||||||
//Don't handle writes to silent fourop channels
|
//Don't handle writes to silent fourop channels
|
||||||
if ( fourOp > 0x80 )
|
if ( fourOp > 0x80 )
|
||||||
return;
|
return;
|
||||||
Bitu change = ( c->chanData ^ ( val << 8 ) ) & 0x1f00;
|
change = ( c->chanData ^ ( val << 8 ) ) & 0x1f00;
|
||||||
if ( change ) {
|
if ( change ) {
|
||||||
c->chanData ^= change;
|
c->chanData ^= change;
|
||||||
Channel_UpdateFrequency( c, chip, fourOp );
|
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
|
//4-op mode enabled for this channel
|
||||||
if ( (chip->reg104 & c->fourMask) & 0x3f ) {
|
if ( (chip->reg104 & c->fourMask) & 0x3f ) {
|
||||||
struct Channel* chan0, *chan1;
|
struct Channel* chan0, *chan1;
|
||||||
|
Bit8u synth;
|
||||||
//Check if it's the 2nd channel in a 4-op
|
//Check if it's the 2nd channel in a 4-op
|
||||||
if ( !(c->fourMask & 0x80 ) ) {
|
if ( !(c->fourMask & 0x80 ) ) {
|
||||||
chan0 = c;
|
chan0 = c;
|
||||||
|
@ -1236,7 +1259,7 @@ static void Channel_WriteC0( struct Channel *c, const struct Chip* chip, Bit8u v
|
||||||
chan1 = c;
|
chan1 = c;
|
||||||
}
|
}
|
||||||
|
|
||||||
Bit8u synth = ( (chan0->regC0 & 1) << 0 )| (( chan1->regC0 & 1) << 1 );
|
synth = ( (chan0->regC0 & 1) << 0 )| (( chan1->regC0 & 1) << 1 );
|
||||||
switch ( synth ) {
|
switch ( synth ) {
|
||||||
case 0:
|
case 0:
|
||||||
chan0->synthHandler = &Channel_Block_sm3FMFM;
|
chan0->synthHandler = &Channel_Block_sm3FMFM;
|
||||||
|
@ -1307,8 +1330,9 @@ void Chip_Init(void *_chip) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static INLINE Bit32u Chip_ForwardNoise(struct Chip *chip) {
|
static INLINE Bit32u Chip_ForwardNoise(struct Chip *chip) {
|
||||||
|
Bitu count;
|
||||||
chip->noiseCounter += chip->noiseAdd;
|
chip->noiseCounter += chip->noiseAdd;
|
||||||
Bitu count = chip->noiseCounter >> LFO_SH;
|
count = chip->noiseCounter >> LFO_SH;
|
||||||
chip->noiseCounter &= WAVE_MASK;
|
chip->noiseCounter &= WAVE_MASK;
|
||||||
for ( ; count > 0; --count ) {
|
for ( ; count > 0; --count ) {
|
||||||
//Noise calculation from mame
|
//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
|
//Always keep the highest bit enabled, for checking > 0x80
|
||||||
chip->reg104 = 0x80 | ( val & 0x3f );
|
chip->reg104 = 0x80 | ( val & 0x3f );
|
||||||
} else if ( reg == 0x105 ) {
|
} 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
|
//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 ) )
|
if ( !((chip->opl3Active ^ val) & 1 ) )
|
||||||
return;
|
return;
|
||||||
chip->opl3Active = ( val & 1 ) ? 0xff : 0;
|
chip->opl3Active = ( val & 1 ) ? 0xff : 0;
|
||||||
//Update the 0xc0 register for all channels to signal the switch to mono/stereo handlers
|
//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 );
|
Channel_ResetC0( &chip->chan[i], chip );
|
||||||
}
|
}
|
||||||
} else if ( reg == 0x08 ) {
|
} else if ( reg == 0x08 ) {
|
||||||
|
@ -1507,7 +1532,8 @@ void Chip_GenerateBlock2( void *_chip, Bitu total, Bit32s* output ) {
|
||||||
struct Channel* ch;
|
struct Channel* ch;
|
||||||
int count;
|
int count;
|
||||||
Bit32u samples = Chip_ForwardLFO( chip, total );
|
Bit32u samples = Chip_ForwardLFO( chip, total );
|
||||||
for ( Bitu i = 0; i < samples; i++ ) {
|
Bitu i;
|
||||||
|
for ( i = 0; i < samples; i++ ) {
|
||||||
output[i] = 0;
|
output[i] = 0;
|
||||||
}
|
}
|
||||||
count = 0;
|
count = 0;
|
||||||
|
@ -1526,7 +1552,8 @@ void Chip_GenerateBlock3( void *_chip, Bitu total, Bit32s* output ) {
|
||||||
struct Channel* ch;
|
struct Channel* ch;
|
||||||
int count;
|
int count;
|
||||||
Bit32u samples = Chip_ForwardLFO( chip, total );
|
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 + 0 ] = 0;
|
||||||
output[i * 2 + 1 ] = 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;
|
struct Chip *chip = (struct Chip *)_chip;
|
||||||
double original = (double)clock / 288.0;
|
double original = (double)clock / 288.0;
|
||||||
double scale = original / (double)rate;
|
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)
|
if (fabs(scale - 1.0) < 0.00001)
|
||||||
scale = 1.0;
|
scale = 1.0;
|
||||||
|
|
||||||
|
@ -1561,41 +1596,46 @@ void Chip_Setup( void *_chip, Bit32u clock, Bit32u rate ) {
|
||||||
//With higher octave this gets shifted up
|
//With higher octave this gets shifted up
|
||||||
//-1 since the freqCreateTable = *2
|
//-1 since the freqCreateTable = *2
|
||||||
#ifdef WAVE_PRECISION
|
#ifdef WAVE_PRECISION
|
||||||
double freqScale = ( 1 << 7 ) * scale * ( 1 << ( WAVE_SH - 1 - 10));
|
freqScale = ( 1 << 7 ) * scale * ( 1 << ( WAVE_SH - 1 - 10));
|
||||||
for ( int i = 0; i < 16; i++ ) {
|
for ( i = 0; i < 16; i++ ) {
|
||||||
//Use rounding with 0.5
|
//Use rounding with 0.5
|
||||||
chip->freqMul[i] = (Bit32u)( 0.5 + freqScale * FreqCreateTable[ i ] );
|
chip->freqMul[i] = (Bit32u)( 0.5 + freqScale * FreqCreateTable[ i ] );
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
Bit32u freqScale = (Bit32u)( 0.5 + scale * ( 1 << ( WAVE_SH - 1 - 10)));
|
freqScale = (Bit32u)( 0.5 + scale * ( 1 << ( WAVE_SH - 1 - 10)));
|
||||||
for ( int i = 0; i < 16; i++ ) {
|
for ( i = 0; i < 16; i++ ) {
|
||||||
chip->freqMul[i] = freqScale * FreqCreateTable[ i ];
|
chip->freqMul[i] = freqScale * FreqCreateTable[ i ];
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//-3 since the real envelope takes 8 steps to reach the single value we supply
|
//-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;
|
Bit8u index, shift;
|
||||||
EnvelopeSelect( i, &index, &shift );
|
EnvelopeSelect( j, &index, &shift );
|
||||||
chip->linearRates[i] = (Bit32u)( scale * (EnvelopeIncreaseTable[ index ] << ( RATE_SH + ENV_EXTRA - shift - 3 )));
|
chip->linearRates[j] = (Bit32u)( scale * (EnvelopeIncreaseTable[ index ] << ( RATE_SH + ENV_EXTRA - shift - 3 )));
|
||||||
}
|
}
|
||||||
//Generate the best matching attack rate
|
//Generate the best matching attack rate
|
||||||
for ( Bit8u i = 0; i < 62; i++ ) {
|
for ( j = 0; j < 62; j++ ) {
|
||||||
Bit8u index, shift;
|
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
|
//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 )));
|
guessAdd = (Bit32u)( scale * (EnvelopeIncreaseTable[ index ] << ( RATE_SH - shift - 3 )));
|
||||||
Bit32s bestAdd = guessAdd;
|
bestAdd = guessAdd;
|
||||||
Bit32u bestDiff = 1 << 30;
|
bestDiff = 1 << 30;
|
||||||
for( Bit32u passes = 0; passes < 16; passes ++ ) {
|
for( passes = 0; passes < 16; passes ++ ) {
|
||||||
Bit32s volume = ENV_MAX;
|
Bit32s volume = ENV_MAX;
|
||||||
Bit32s samples = 0;
|
Bit32s samples = 0;
|
||||||
Bit32u count = 0;
|
Bit32u count = 0;
|
||||||
|
Bit32s diff;
|
||||||
|
Bit32u lDiff;
|
||||||
while ( volume > 0 && samples < original * 2 ) {
|
while ( volume > 0 && samples < original * 2 ) {
|
||||||
|
Bit32s change;
|
||||||
count += guessAdd;
|
count += guessAdd;
|
||||||
Bit32s change = count >> RATE_SH;
|
change = count >> RATE_SH;
|
||||||
count &= RATE_MASK;
|
count &= RATE_MASK;
|
||||||
if ( change ) {
|
if ( change ) {
|
||||||
volume += ( ~volume * change ) >> 3;
|
volume += ( ~volume * change ) >> 3;
|
||||||
|
@ -1603,8 +1643,8 @@ void Chip_Setup( void *_chip, Bit32u clock, Bit32u rate ) {
|
||||||
samples++;
|
samples++;
|
||||||
|
|
||||||
}
|
}
|
||||||
Bit32s diff = original - samples;
|
diff = original - samples;
|
||||||
Bit32u lDiff = labs( diff );
|
lDiff = labs( diff );
|
||||||
//Init last on first pass
|
//Init last on first pass
|
||||||
if ( lDiff < bestDiff ) {
|
if ( lDiff < bestDiff ) {
|
||||||
bestDiff = lDiff;
|
bestDiff = lDiff;
|
||||||
|
@ -1624,11 +1664,11 @@ void Chip_Setup( void *_chip, Bit32u clock, Bit32u rate ) {
|
||||||
guessAdd--;
|
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
|
//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
|
//Setup the channels with the correct four op flags
|
||||||
//Channels are accessed through a table so they appear linear here
|
//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
|
//Clear Everything in opl3 mode
|
||||||
Chip_WriteReg( chip, 0x105, 0x1 );
|
Chip_WriteReg( chip, 0x105, 0x1 );
|
||||||
for ( int i = 0; i < 512; i++ ) {
|
for ( i = 0; i < 512; i++ ) {
|
||||||
if ( i == 0x105 )
|
if ( i == 0x105 )
|
||||||
continue;
|
continue;
|
||||||
Chip_WriteReg( chip, i, 0xff );
|
Chip_WriteReg( chip, i, 0xff );
|
||||||
|
@ -1661,7 +1701,7 @@ void Chip_Setup( void *_chip, Bit32u clock, Bit32u rate ) {
|
||||||
}
|
}
|
||||||
Chip_WriteReg( chip, 0x105, 0x0 );
|
Chip_WriteReg( chip, 0x105, 0x0 );
|
||||||
//Clear everything in opl2 mode
|
//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, 0xff );
|
||||||
Chip_WriteReg( chip, i, 0x0 );
|
Chip_WriteReg( chip, i, 0x0 );
|
||||||
}
|
}
|
||||||
|
@ -1669,6 +1709,9 @@ void Chip_Setup( void *_chip, Bit32u clock, Bit32u rate ) {
|
||||||
|
|
||||||
static unsigned char doneTables = 0;
|
static unsigned char doneTables = 0;
|
||||||
static void InitTables( void ) {
|
static void InitTables( void ) {
|
||||||
|
int i, oct;
|
||||||
|
Bit8u j;
|
||||||
|
Bitu k;
|
||||||
if ( doneTables )
|
if ( doneTables )
|
||||||
return;
|
return;
|
||||||
#if ( DBOPL_WAVE == WAVE_HANDLER ) || ( DBOPL_WAVE == WAVE_TABLELOG )
|
#if ( DBOPL_WAVE == WAVE_HANDLER ) || ( DBOPL_WAVE == WAVE_TABLELOG )
|
||||||
|
@ -1690,7 +1733,7 @@ static void InitTables( void ) {
|
||||||
#endif
|
#endif
|
||||||
#if ( DBOPL_WAVE == WAVE_TABLEMUL )
|
#if ( DBOPL_WAVE == WAVE_TABLEMUL )
|
||||||
//Multiplication based tables
|
//Multiplication based tables
|
||||||
for ( int i = 0; i < 384; i++ ) {
|
for ( i = 0; i < 384; i++ ) {
|
||||||
int s = i * 8;
|
int s = i * 8;
|
||||||
//TODO maybe keep some of the precision errors of the original table?
|
//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 ));
|
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
|
//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[ 0x0200 + i ] = (Bit16s)(sin( (i + 0.5) * (PI / 512.0) ) * 4084);
|
||||||
WaveTable[ 0x0000 + i ] = -WaveTable[ 0x200 + i ];
|
WaveTable[ 0x0000 + i ] = -WaveTable[ 0x200 + i ];
|
||||||
}
|
}
|
||||||
//Exponential wave
|
//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[ 0x700 + i ] = (Bit16s)( 0.5 + ( pow(2.0, -1.0 + ( 255 - i * 8) * ( 1.0 /256 ) ) ) * 4085 );
|
||||||
WaveTable[ 0x6ff - i ] = -WaveTable[ 0x700 + i ];
|
WaveTable[ 0x6ff - i ] = -WaveTable[ 0x700 + i ];
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#if ( DBOPL_WAVE == WAVE_TABLELOG )
|
#if ( DBOPL_WAVE == WAVE_TABLELOG )
|
||||||
//Sine Wave Base
|
//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[ 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];
|
WaveTable[ 0x0000 + i ] = ((Bit16s)0x8000) | WaveTable[ 0x200 + i];
|
||||||
}
|
}
|
||||||
//Exponential wave
|
//Exponential wave
|
||||||
for ( int i = 0; i < 256; i++ ) {
|
for ( i = 0; i < 256; i++ ) {
|
||||||
WaveTable[ 0x700 + i ] = i * 8;
|
WaveTable[ 0x700 + i ] = i * 8;
|
||||||
WaveTable[ 0x6ff - i ] = ((Bit16s)0x8000) | 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 |
|
// |06 |0126|27 |7 |3 |4 |4 5 |5 |
|
||||||
|
|
||||||
#if (( DBOPL_WAVE == WAVE_TABLELOG ) || ( DBOPL_WAVE == WAVE_TABLEMUL ))
|
#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
|
//Fill silence gaps
|
||||||
WaveTable[ 0x400 + i ] = WaveTable[0];
|
WaveTable[ 0x400 + i ] = WaveTable[0];
|
||||||
WaveTable[ 0x500 + i ] = WaveTable[0];
|
WaveTable[ 0x500 + i ] = WaveTable[0];
|
||||||
|
@ -1744,29 +1787,29 @@ static void InitTables( void ) {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//Create the ksl table
|
//Create the ksl table
|
||||||
for ( int oct = 0; oct < 8; oct++ ) {
|
for ( oct = 0; oct < 8; oct++ ) {
|
||||||
int base = oct * 8;
|
int base = oct * 8;
|
||||||
for ( int i = 0; i < 16; i++ ) {
|
for ( i = 0; i < 16; i++ ) {
|
||||||
int val = base - KslCreateTable[i];
|
int val = base - KslCreateTable[i];
|
||||||
if ( val < 0 )
|
if ( val < 0 )
|
||||||
val = 0;
|
val = 0;
|
||||||
//*4 for the final range to match attenuation range
|
//*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
|
//Create the Tremolo table, just increase and decrease a triangle wave
|
||||||
for ( Bit8u i = 0; i < TREMOLO_TABLE / 2; i++ ) {
|
for ( j = 0; j < TREMOLO_TABLE / 2; j++ ) {
|
||||||
Bit8u val = i << ENV_EXTRA;
|
Bit8u val = j << ENV_EXTRA;
|
||||||
TremoloTable[i] = val;
|
TremoloTable[j] = val;
|
||||||
TremoloTable[TREMOLO_TABLE - 1 - i] = val;
|
TremoloTable[TREMOLO_TABLE - 1 - j] = val;
|
||||||
}
|
}
|
||||||
//Create a table with offsets of the channels from the start of the chip
|
//Create a table with offsets of the channels from the start of the chip
|
||||||
struct Chip* chip = 0;
|
for ( k = 0; k < 32; k++ ) {
|
||||||
for ( Bitu i = 0; i < 32; i++ ) {
|
Bitu index = k & 0xf;
|
||||||
Bitu index = i & 0xf;
|
|
||||||
Bitu blah;
|
Bitu blah;
|
||||||
|
struct Chip *chip = 0;
|
||||||
if ( index >= 9 ) {
|
if ( index >= 9 ) {
|
||||||
ChanOffsetTable[i] = 0;
|
ChanOffsetTable[k] = 0;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
//Make sure the four op channels follow eachother
|
//Make sure the four op channels follow eachother
|
||||||
|
@ -1774,34 +1817,35 @@ static void InitTables( void ) {
|
||||||
index = (index % 3) * 2 + ( index / 3 );
|
index = (index % 3) * 2 + ( index / 3 );
|
||||||
}
|
}
|
||||||
//Add back the bits for highest ones
|
//Add back the bits for highest ones
|
||||||
if ( i >= 16 )
|
if ( k >= 16 )
|
||||||
index += 9;
|
index += 9;
|
||||||
blah = (Bitu)( (unsigned long)( &(chip->chan[ index ]) ) );
|
blah = (Bitu)( (unsigned long)( &(chip->chan[ index ]) ) );
|
||||||
ChanOffsetTable[i] = blah;
|
ChanOffsetTable[k] = (Bit16u)blah;
|
||||||
}
|
}
|
||||||
//Same for operators
|
//Same for operators
|
||||||
for ( Bitu i = 0; i < 64; i++ ) {
|
for ( k = 0; k < 64; k++ ) {
|
||||||
Bitu chNum;
|
Bitu chNum;
|
||||||
Bitu opNum;
|
Bitu opNum;
|
||||||
Bitu blah;
|
Bitu blah;
|
||||||
struct Channel* chan = 0;
|
struct Channel* chan = 0;
|
||||||
if ( i % 8 >= 6 || ( (i / 8) % 4 == 3 ) ) {
|
if ( k % 8 >= 6 || ( (k / 8) % 4 == 3 ) ) {
|
||||||
OpOffsetTable[i] = 0;
|
OpOffsetTable[k] = 0;
|
||||||
continue;
|
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
|
//Make sure we use 16 and up for the 2nd range to match the chanoffset gap
|
||||||
if ( chNum >= 12 )
|
if ( chNum >= 12 )
|
||||||
chNum += 16 - 12;
|
chNum += 16 - 12;
|
||||||
opNum = ( i % 8 ) / 3;
|
opNum = ( k % 8 ) / 3;
|
||||||
blah = (Bitu)( (unsigned long) ( &(chan->op[opNum]) ) );
|
blah = (Bitu)( (unsigned long) ( &(chan->op[opNum]) ) );
|
||||||
OpOffsetTable[i] = ChanOffsetTable[ chNum ] + blah;
|
OpOffsetTable[k] = (Bit16u)(ChanOffsetTable[ chNum ] + blah);
|
||||||
}
|
}
|
||||||
#if 0
|
#if 0
|
||||||
//Stupid checks if table's are correct
|
//Stupid checks if table's are correct
|
||||||
for ( Bitu i = 0; i < 18; i++ ) {
|
for ( k = 0; k < 18; k++ ) {
|
||||||
Bit32u find = (Bit16u)( &(chip->chan[ i ]) );
|
Bit32u find = (Bit16u)( &(chip->chan[ k ]) );
|
||||||
for ( Bitu c = 0; c < 32; c++ ) {
|
Bitu c;
|
||||||
|
for ( c = 0; c < 32; c++ ) {
|
||||||
if ( ChanOffsetTable[c] == find ) {
|
if ( ChanOffsetTable[c] == find ) {
|
||||||
find = 0;
|
find = 0;
|
||||||
break;
|
break;
|
||||||
|
@ -1811,9 +1855,10 @@ static void InitTables( void ) {
|
||||||
find = find;
|
find = find;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for ( Bitu i = 0; i < 36; i++ ) {
|
for ( k = 0; k < 36; k++ ) {
|
||||||
Bit32u find = (Bit16u)( &(chip->chan[ i / 2 ].op[i % 2]) );
|
Bit32u find = (Bit16u)( &(chip->chan[ k / 2 ].op[k % 2]) );
|
||||||
for ( Bitu c = 0; c < 64; c++ ) {
|
Bitu c;
|
||||||
|
for ( c = 0; c < 64; c++ ) {
|
||||||
if ( OpOffsetTable[c] == find ) {
|
if ( OpOffsetTable[c] == find ) {
|
||||||
find = 0;
|
find = 0;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -43,8 +43,8 @@ typedef unsigned char Bit8u;
|
||||||
typedef signed char Bit8s;
|
typedef signed char Bit8s;
|
||||||
typedef unsigned short Bit16u;
|
typedef unsigned short Bit16u;
|
||||||
typedef signed short Bit16s;
|
typedef signed short Bit16s;
|
||||||
typedef unsigned long Bit32u;
|
typedef unsigned int Bit32u;
|
||||||
typedef signed long Bit32s;
|
typedef signed int Bit32s;
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
typedef unsigned __int64 Bit64u;
|
typedef unsigned __int64 Bit64u;
|
||||||
typedef signed __int64 Bit64s;
|
typedef signed __int64 Bit64s;
|
||||||
|
|
|
@ -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)
|
static int resampler_run_zoh(resampler * r, float ** out_, float * out_end)
|
||||||
{
|
{
|
||||||
int in_size = r->write_filled;
|
int in_size = r->write_filled;
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#define resampler_set_quality EVALUATE(RESAMPLER_DECORATE,_resampler_set_quality)
|
#define resampler_set_quality EVALUATE(RESAMPLER_DECORATE,_resampler_set_quality)
|
||||||
#define resampler_get_free_count EVALUATE(RESAMPLER_DECORATE,_resampler_get_free_count)
|
#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 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_set_rate EVALUATE(RESAMPLER_DECORATE,_resampler_set_rate)
|
||||||
#define resampler_ready EVALUATE(RESAMPLER_DECORATE,_resampler_ready)
|
#define resampler_ready EVALUATE(RESAMPLER_DECORATE,_resampler_ready)
|
||||||
#define resampler_clear EVALUATE(RESAMPLER_DECORATE,_resampler_clear)
|
#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 *);
|
int resampler_get_free_count(void *);
|
||||||
void resampler_write_sample(void *, short sample);
|
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 );
|
void resampler_set_rate( void *, double new_factor );
|
||||||
int resampler_ready(void *);
|
int resampler_ready(void *);
|
||||||
void resampler_clear(void *);
|
void resampler_clear(void *);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
** ST3PLAY v0.45
|
** ST3PLAY v0.47
|
||||||
** =============
|
** =============
|
||||||
**
|
**
|
||||||
** C port of Scream Tracker 3's replayer, by 8bitbubsy (Olav Sørensen)
|
** C port of Scream Tracker 3's replayer, by 8bitbubsy (Olav Sørensen)
|
||||||
|
@ -63,6 +63,8 @@
|
||||||
#define inline __forceinline
|
#define inline __forceinline
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "dbopl.h"
|
||||||
|
|
||||||
#include "resampler.h"
|
#include "resampler.h"
|
||||||
|
|
||||||
#include "st3play.h"
|
#include "st3play.h"
|
||||||
|
@ -199,6 +201,12 @@ typedef struct
|
||||||
void *resampler[64];
|
void *resampler[64];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void *fmChip;
|
||||||
|
void *fmResampler;
|
||||||
|
|
||||||
|
const uint8_t *fmPatchTable[9];
|
||||||
|
uint8_t fmLastB0[9];
|
||||||
|
|
||||||
float f_outputFreq;
|
float f_outputFreq;
|
||||||
float f_masterVolume;
|
float f_masterVolume;
|
||||||
|
|
||||||
|
@ -315,6 +323,7 @@ static const int16_t vibramp[64] =
|
||||||
192, 200, 208, 216, 224, 232, 240, 248
|
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
|
// FUNCTION DECLARATIONS
|
||||||
|
|
||||||
|
@ -534,6 +543,26 @@ void * st3play_Alloc(uint32_t outputFreq, int8_t interpolation, int8_t ramp_styl
|
||||||
return p;
|
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)
|
void st3play_Free(void *_p)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
@ -542,6 +571,12 @@ void st3play_Free(void *_p)
|
||||||
|
|
||||||
FreeSong(p);
|
FreeSong(p);
|
||||||
|
|
||||||
|
if ( p->fmResampler )
|
||||||
|
resampler_delete( p->fmResampler );
|
||||||
|
|
||||||
|
if ( p->fmChip )
|
||||||
|
free( p->fmChip );
|
||||||
|
|
||||||
#ifdef USE_VOL_RAMP
|
#ifdef USE_VOL_RAMP
|
||||||
for (i = 0; i < 64 * 2; ++i)
|
for (i = 0; i < 64 * 2; ++i)
|
||||||
#else
|
#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)
|
static inline void setspd(PLAYER *p, uint8_t ch)
|
||||||
{
|
{
|
||||||
int32_t tmpspd;
|
int32_t tmpspd;
|
||||||
|
uint8_t adlibChannel = (p->mseg[0x40 + ch] & 0x7F) - 16;
|
||||||
|
|
||||||
tmpspd = p->chn[ch].aspd;
|
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
|
// 14317056 is used in both the ST3 replayer and the S3M format docs
|
||||||
if (tmpspd)
|
if (tmpspd)
|
||||||
voiceSetSamplingFrequency(p, ch, 14317056.0f / (float)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)
|
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;
|
p->chn[ch].achannelused |= 0x80;
|
||||||
#ifdef USE_VOL_RAMP
|
#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);
|
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
|
#else
|
||||||
voiceSetVolume(p, ch, ((float)(p->chn[ch].avol) / 63.0f) * ((float)(p->chn[ch].chanvol) / 64.0f) * ((float)(p->globalvol) / 64.0f), sharp);
|
voiceSetVolume(p, ch, ((float)(p->chn[ch].avol) / 63.0f) * ((float)(p->chn[ch].chanvol) / 64.0f) * ((float)(p->globalvol) / 64.0f), sharp);
|
||||||
#endif
|
#endif
|
||||||
|
if (adlibChannel < 9)
|
||||||
|
st3play_AdlibTouch(p, adlibChannel, NULL, p->chn[ch].avol);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void setpan(PLAYER *p, uint8_t ch)
|
static inline void setpan(PLAYER *p, uint8_t ch)
|
||||||
|
@ -877,6 +952,30 @@ static inline uint8_t getnote(PLAYER *p)
|
||||||
return (ch);
|
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)
|
static inline void doamiga(PLAYER *p, uint8_t ch)
|
||||||
{
|
{
|
||||||
uint8_t *insdat;
|
uint8_t *insdat;
|
||||||
|
@ -889,6 +988,10 @@ static inline void doamiga(PLAYER *p, uint8_t ch)
|
||||||
#ifdef USE_VOL_RAMP
|
#ifdef USE_VOL_RAMP
|
||||||
uint8_t volassigned = 0;
|
uint8_t volassigned = 0;
|
||||||
#endif
|
#endif
|
||||||
|
uint8_t adlibChannel = (p->mseg[0x40 + ch] & 0x7F) - 16;
|
||||||
|
|
||||||
|
if (!p->fmChip || !p->fmResampler) // safety check
|
||||||
|
adlibChannel = 255;
|
||||||
|
|
||||||
if (p->chn[ch].ins)
|
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];
|
insdat = &p->mseg[(uint32_t)(get_le16(&p->mseg[p->instrumentadd + ((p->chn[ch].ins - 1) << 1)])) << 4];
|
||||||
if (insdat[0])
|
if (insdat[0])
|
||||||
{
|
{
|
||||||
if (insdat[0] == 1)
|
if (insdat[0] == 1 && adlibChannel >= 9)
|
||||||
{
|
{
|
||||||
p->chn[ch].ac2spd = get_le32(&insdat[0x20]);
|
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,
|
insrepend - insrepbeg, insrepend, loop,
|
||||||
insdat[0x1F] & 4, insdat[0x1F] & 2, insdat[0x1E] == 4);
|
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
|
else
|
||||||
{
|
{
|
||||||
p->chn[ch].lastins = 0;
|
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].avol = 0;
|
||||||
p->chn[ch].asldspd = 65535;
|
p->chn[ch].asldspd = 65535;
|
||||||
|
|
||||||
setspd(p, ch);
|
if (adlibChannel >= 9)
|
||||||
setvol(p, ch, 0);
|
{
|
||||||
|
setspd(p, ch);
|
||||||
|
setvol(p, ch, 0);
|
||||||
|
}
|
||||||
|
|
||||||
// shutdown channel
|
// shutdown channel
|
||||||
voiceSetSource(p, ch, NULL, 0, 0, 0, 0, 0, 0, 0);
|
voiceSetSource(p, ch, NULL, 0, 0, 0, 0, 0, 0, 0);
|
||||||
voiceSetSamplePosition(p, ch, 0);
|
voiceSetSamplePosition(p, ch, 0);
|
||||||
|
|
||||||
|
if (adlibChannel < 9)
|
||||||
|
st3play_AdlibNoteOff(p, adlibChannel);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
p->chn[ch].lastnote = p->chn[ch].note;
|
p->chn[ch].lastnote = p->chn[ch].note;
|
||||||
|
|
||||||
if ((p->chn[ch].cmd != ('G' - 64)) && (p->chn[ch].cmd != ('L' - 64)))
|
if (adlibChannel >= 9)
|
||||||
voiceSetSamplePosition(p, ch, p->chn[ch].astartoffset);
|
{
|
||||||
|
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))))
|
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].aorgspd = p->chn[ch].aspd;
|
||||||
p->chn[ch].avibcnt = 0;
|
p->chn[ch].avibcnt = 0;
|
||||||
p->chn[ch].apancnt = 0;
|
p->chn[ch].apancnt = 0;
|
||||||
|
|
||||||
setspd(p, ch);
|
setspd(p, ch);
|
||||||
}
|
}
|
||||||
|
|
||||||
p->chn[ch].asldspd = scalec2spd(p, ch, stnote2herz(p, p->chn[ch].note));
|
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);
|
ch = getnote(p);
|
||||||
if (ch == 255) break; // end of row/channels
|
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);
|
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];
|
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;
|
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)
|
if (insoff > p->mseg_len)
|
||||||
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;
|
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)
|
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
|
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--;
|
ch->anotecutcnt--;
|
||||||
if (!ch->anotecutcnt)
|
if (!ch->anotecutcnt)
|
||||||
|
{
|
||||||
|
uint8_t adlibChannel = (p->mseg[0x40 + ch->channelnum] & 0x7F) - 16;
|
||||||
voiceSetSamplingFrequency(p, ch->channelnum, 0); // cut note
|
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)
|
void st3play_RenderFloat(void *_p, float *buffer, int32_t count)
|
||||||
{
|
{
|
||||||
PLAYER * p = (PLAYER *)_p;
|
PLAYER * p = (PLAYER *)_p;
|
||||||
|
@ -3591,6 +3765,9 @@ void st3play_RenderFloat(void *_p, float *buffer, int32_t count)
|
||||||
{
|
{
|
||||||
mixSampleBlock(p, outputStream, samplesTodo);
|
mixSampleBlock(p, outputStream, samplesTodo);
|
||||||
|
|
||||||
|
if (p->fmChip && p->fmResampler)
|
||||||
|
st3play_AdlibMix( p, outputStream, samplesTodo );
|
||||||
|
|
||||||
outputStream += (samplesTodo << 1);
|
outputStream += (samplesTodo << 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue