diff --git a/Frameworks/modplay/modplay/dbopl.c b/Frameworks/modplay/modplay/dbopl.c index f0e37c6b3..f4de574b7 100644 --- a/Frameworks/modplay/modplay/dbopl.c +++ b/Frameworks/modplay/modplay/dbopl.c @@ -153,6 +153,8 @@ struct Channel { Bit8u fourMask; Bit8s maskLeft; //Sign extended values for both channel's panning Bit8s maskRight; + Bit8s mask; + Bit8u chanActive; }; struct Chip { @@ -807,8 +809,11 @@ static struct Channel* Channel_Block_sm2AM( struct Channel *c, struct Chip* chip if ( Operator_Silent( Channel_Op(c, 0) ) && Operator_Silent( Channel_Op(c, 1) ) ) { c->old[0] = c->old[1] = 0; + c->chanActive = 0; return (c + 1); } + c->chanActive = 1; + //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 ); @@ -822,7 +827,7 @@ static struct Channel* Channel_Block_sm2AM( struct Channel *c, struct Chip* chip c->old[1] = Operator_GetSample( Channel_Op( c, 0 ), mod ); out0 = c->old[0]; sample = out0 + Operator_GetSample( Channel_Op( c, 1), 0 ); - output[ i ] += sample; + output[ i ] += sample & c->mask; } return ( c + 1 ); @@ -833,9 +838,11 @@ static struct Channel* Channel_Block_sm2FM( struct Channel *c, struct Chip* chip if ( Operator_Silent( Channel_Op(c, 1) ) ) { c->old[0] = c->old[1] = 0; + c->chanActive = 0; return (c + 1); } - + c->chanActive = 1; + //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 ); @@ -849,7 +856,7 @@ static struct Channel* Channel_Block_sm2FM( struct Channel *c, struct Chip* chip c->old[1] = Operator_GetSample( Channel_Op( c, 0 ), mod ); out0 = c->old[0]; sample = Operator_GetSample( Channel_Op( c, 1 ), out0 ); - output[ i ] += sample; + output[ i ] += sample & c->mask; } return ( c + 1 ); @@ -860,8 +867,10 @@ static struct Channel* Channel_Block_sm3AM( struct Channel *c, struct Chip* chip if ( Operator_Silent( Channel_Op( c, 0 ) ) && Operator_Silent( Channel_Op( c, 1 ) ) ) { c->old[0] = c->old[1] = 0; + c->chanActive = 0; return (c + 1); } + c->chanActive = 1; //Init the operators with the the current vibrato and tremolo values Operator_Prepare( Channel_Op( c, 0 ), chip ); @@ -876,8 +885,8 @@ static struct Channel* Channel_Block_sm3AM( struct Channel *c, struct Chip* chip c->old[1] = Operator_GetSample( Channel_Op( c, 0 ), mod ); out0 = c->old[0]; sample = out0 + Operator_GetSample( Channel_Op( c, 1 ), 0 ); - output[ i * 2 + 0 ] += sample & c->maskLeft; - output[ i * 2 + 1 ] += sample & c->maskRight; + output[ i * 2 + 0 ] += sample & c->maskLeft & c->mask; + output[ i * 2 + 1 ] += sample & c->maskRight & c->mask; } return ( c + 1 ); @@ -888,8 +897,10 @@ static struct Channel* Channel_Block_sm3FM( struct Channel *c, struct Chip* chip if ( Operator_Silent( Channel_Op( c, 1 ) ) ) { c->old[0] = c->old[1] = 0; + c->chanActive = 0; return (c + 1); } + c->chanActive = 1; //Init the operators with the the current vibrato and tremolo values Operator_Prepare( Channel_Op( c, 0 ), chip ); @@ -904,8 +915,8 @@ static struct Channel* Channel_Block_sm3FM( struct Channel *c, struct Chip* chip c->old[1] = Operator_GetSample( Channel_Op( c, 0 ), mod ); out0 = c->old[0]; sample = Operator_GetSample( Channel_Op( c, 1 ), out0 ); - output[ i * 2 + 0 ] += sample & c->maskLeft; - output[ i * 2 + 1 ] += sample & c->maskRight; + output[ i * 2 + 0 ] += sample & c->maskLeft & c->mask; + output[ i * 2 + 1 ] += sample & c->maskRight & c->mask; } return ( c + 1 ); @@ -916,8 +927,10 @@ static struct Channel* Channel_Block_sm3FMFM( struct Channel *c, struct Chip* ch if ( Operator_Silent( Channel_Op( c, 3 ) ) ) { c->old[0] = c->old[1] = 0; + c->chanActive = 0; return (c + 2); } + c->chanActive = 1; //Init the operators with the the current vibrato and tremolo values Operator_Prepare( Channel_Op( c, 0 ), chip ); @@ -937,8 +950,8 @@ static struct Channel* Channel_Block_sm3FMFM( struct Channel *c, struct Chip* ch next = Operator_GetSample( Channel_Op( c, 1 ), out0 ); next = Operator_GetSample( Channel_Op( c, 2 ), next ); sample = Operator_GetSample( Channel_Op( c, 3 ), next ); - output[ i * 2 + 0 ] += sample & c->maskLeft; - output[ i * 2 + 1 ] += sample & c->maskRight; + output[ i * 2 + 0 ] += sample & c->maskLeft & c->mask; + output[ i * 2 + 1 ] += sample & c->maskRight & c->mask; } return( c + 2 ); @@ -949,8 +962,10 @@ static struct Channel* Channel_Block_sm3AMFM( struct Channel *c, struct Chip* ch if ( Operator_Silent( Channel_Op( c, 0 ) ) && Operator_Silent( Channel_Op( c, 3 ) ) ) { c->old[0] = c->old[1] = 0; + c->chanActive = 0; return (c + 2); } + c->chanActive = 1; //Init the operators with the the current vibrato and tremolo values Operator_Prepare( Channel_Op( c, 0 ), chip ); @@ -971,8 +986,8 @@ static struct Channel* Channel_Block_sm3AMFM( struct Channel *c, struct Chip* ch next = Operator_GetSample( Channel_Op( c, 1 ), 0 ); next = Operator_GetSample( Channel_Op( c, 2 ), next ); sample += Operator_GetSample( Channel_Op( c, 3 ), next ); - output[ i * 2 + 0 ] += sample & c->maskLeft; - output[ i * 2 + 1 ] += sample & c->maskRight; + output[ i * 2 + 0 ] += sample & c->maskLeft & c->mask; + output[ i * 2 + 1 ] += sample & c->maskRight & c->mask; } return( c + 2 ); @@ -983,8 +998,10 @@ static struct Channel* Channel_Block_sm3FMAM( struct Channel *c, struct Chip* ch if ( Operator_Silent( Channel_Op( c, 1) ) && Operator_Silent( Channel_Op( c, 3 ) ) ) { c->old[0] = c->old[1] = 0; + c->chanActive = 0; return (c + 2); } + c->chanActive = 1; //Init the operators with the the current vibrato and tremolo values Operator_Prepare( Channel_Op( c, 0 ), chip ); @@ -1004,8 +1021,8 @@ static struct Channel* Channel_Block_sm3FMAM( struct Channel *c, struct Chip* ch sample = Operator_GetSample( Channel_Op( c, 1 ), out0 ); next = Operator_GetSample( Channel_Op( c, 2 ), 0 ); sample += Operator_GetSample( Channel_Op( c, 3 ), next ); - output[ i * 2 + 0 ] += sample & c->maskLeft; - output[ i * 2 + 1 ] += sample & c->maskRight; + output[ i * 2 + 0 ] += sample & c->maskLeft & c->mask; + output[ i * 2 + 1 ] += sample & c->maskRight & c->mask; } return( c + 2 ); @@ -1016,8 +1033,10 @@ static struct Channel* Channel_Block_sm3AMAM( struct Channel *c, struct Chip* ch 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->chanActive = 0; return (c + 2); } + c->chanActive = 1; //Init the operators with the the current vibrato and tremolo values Operator_Prepare( Channel_Op( c, 0 ), chip ); @@ -1038,8 +1057,8 @@ static struct Channel* Channel_Block_sm3AMAM( struct Channel *c, struct Chip* ch 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; - output[ i * 2 + 1 ] += sample & c->maskRight; + output[ i * 2 + 0 ] += sample & c->maskLeft & c->mask; + output[ i * 2 + 1 ] += sample & c->maskRight & c->mask; } return( c + 2 ); @@ -1057,6 +1076,13 @@ static Bit32s Channel_GeneratePercussion( struct Channel *chan, struct Chip* chi Bit32u hhVol; Bit32u sdVol; Bit32u tcVol; + + chan->chanActive = 0; + + if ( !Operator_Silent( Channel_Op(chan, 1) ) ) + chan->chanActive++; + if ( !Operator_Silent( Channel_Op(chan, 4) ) ) + chan->chanActive++; chan->old[0] = chan->old[1]; chan->old[1] = Operator_GetSample( Channel_Op( chan, 0 ), mod ); @@ -1081,12 +1107,14 @@ static Bit32s Channel_GeneratePercussion( struct Channel *chan, struct Chip* chi if ( !ENV_SILENT( hhVol ) ) { Bit32u hhIndex = (phaseBit<<8) | (0x34 << ( phaseBit ^ (noiseBit << 1 ))); sample += Operator_GetWave( Channel_Op( chan, 2 ), hhIndex, hhVol ); + chan->chanActive++; } //Snare Drum sdVol = Operator_ForwardVolume( Channel_Op( chan, 3 ) ); if ( !ENV_SILENT( sdVol ) ) { Bit32u sdIndex = ( 0x100 + (c2 & 0x100) ) ^ ( noiseBit << 8 ); sample += Operator_GetWave( Channel_Op( chan, 3 ), sdIndex, sdVol ); + chan->chanActive++; } //Tom-tom sample += Operator_GetSample( Channel_Op( chan, 4 ), 0 ); @@ -1096,6 +1124,7 @@ static Bit32s Channel_GeneratePercussion( struct Channel *chan, struct Chip* chi if ( !ENV_SILENT( tcVol ) ) { Bit32u tcIndex = (1 + phaseBit) << 8; sample += Operator_GetWave( Channel_Op( chan, 5 ), tcIndex, tcVol ); + chan->chanActive++; } sample <<= 1; return sample; @@ -1113,7 +1142,7 @@ static struct Channel* Channel_Block_sm2Percussion( struct Channel *c, struct Ch Operator_Prepare( Channel_Op( c, 5 ), chip ); for ( i = 0; i < samples; i++ ) { - output[i] = Channel_GeneratePercussion( c, chip ); + output[i] += Channel_GeneratePercussion( c, chip ) & c->mask; } return( c + 3 ); @@ -1131,7 +1160,9 @@ static struct Channel* Channel_Block_sm3Percussion( struct Channel *c, struct Ch Operator_Prepare( Channel_Op( c, 5 ), chip ); for ( i = 0; i < samples; i++ ) { - output[i * 2] = output[i * 2 + 1] = Channel_GeneratePercussion( c, chip ); + Bit32s sample = Channel_GeneratePercussion( c, chip ) & c->mask; + output[i * 2 ] += sample; + output[i * 2 + 1] += sample; } return( c + 3 ); @@ -1144,8 +1175,10 @@ static void Channel_Init(struct Channel *c) { c->regC0 = 0; c->maskLeft = -1; c->maskRight = -1; + c->mask = -1; c->feedback = 31; c->fourMask = 0; + c->chanActive = 0; c->synthHandler = &Channel_Block_sm2FM; Operator_Init(&c->op[0]); Operator_Init(&c->op[1]); @@ -1593,6 +1626,23 @@ void Chip_GenerateBlock_Stereo( void *_chip, Bitu total, Bit32s* output) { Chip_GenerateBlock3( chip, total, output ); } +Bitu Chip_GetActiveChannels( void *_chip ) { + struct Chip *chip = (struct Chip *)_chip; + int totalChannels = (chip->opl3Active) ? 18 : 9; + int i; + Bitu active = 0; + for ( i = 0; i < totalChannels; ++i ) + active += chip->chan[i].chanActive; + return active; +} + +void Chip_Mute( void *_chip, Bit8u channel, Bit8u mute ) { + struct Chip *chip = (struct Chip *)_chip; + if (channel >= 18) + return; + chip->chan[channel].mask = mute ? 0 : -1; +} + void Chip_Setup( void *_chip, Bit32u clock, Bit32u rate ) { struct Chip *chip = (struct Chip *)_chip; double original = (double)clock / 288.0; diff --git a/Frameworks/modplay/modplay/dbopl.h b/Frameworks/modplay/modplay/dbopl.h index c710eca8f..a9970d640 100644 --- a/Frameworks/modplay/modplay/dbopl.h +++ b/Frameworks/modplay/modplay/dbopl.h @@ -67,3 +67,7 @@ Bit32u Chip_WriteAddr( void *chip, Bit32u port, Bit8u val ); void Chip_GenerateBlock_Mono( void *chip, Bitu total, Bit32s* output ); void Chip_GenerateBlock_Stereo( void *chip, Bitu total, Bit32s* output ); + +Bitu Chip_GetActiveChannels( void *_chip ); + +void Chip_Mute( void *_chip, Bit8u channel, Bit8u mute ); diff --git a/Frameworks/modplay/modplay/st3play.c b/Frameworks/modplay/modplay/st3play.c index b72917048..c78f7040e 100644 --- a/Frameworks/modplay/modplay/st3play.c +++ b/Frameworks/modplay/modplay/st3play.c @@ -551,7 +551,7 @@ static int st3play_AdlibInit(PLAYER *p) Chip_Init( p->fmChip ); Chip_Setup( p->fmChip, 3579545 * 4, 49716 ); - Chip_WriteReg( p->fmChip, 0x01, 0x20 ); // enable wave select, necessary in OPL2 mode + Chip_WriteReg( p->fmChip, 0x01, 0x20 ); // enable wave select, but rather pointless with dbopl p->fmResampler = resampler_create(); if ( !p->fmResampler ) @@ -3838,12 +3838,16 @@ void st3play_Mute(void *_p, int8_t channel, int8_t mute) { PLAYER * p = (PLAYER *)_p; int8_t mask = 1 << (channel % 8); + uint8_t adlibChannel; if (channel > 31) return; + adlibChannel = (p->mseg[0x40 + channel] & 0x7F) - 16; if (mute) p->muted[channel / 8] |= mask; else p->muted[channel / 8] &= ~mask; + if (adlibChannel < 9) + Chip_Mute( p->fmChip, adlibChannel, mute ); } int32_t st3play_GetLoopCount(void *_p) @@ -3869,6 +3873,7 @@ void st3play_GetInfo(void *_p, st3_info *info) if (p->voice[i].mixing) ++channels_playing; } + channels_playing += Chip_GetActiveChannels( p->fmChip ); } info->channels_playing = (int8_t)channels_playing; }