[Scummvm-cvs-logs] SF.net SVN: scummvm:[48179] scummvm/trunk/sound

lordhoto at users.sourceforge.net lordhoto at users.sourceforge.net
Mon Mar 8 01:33:37 CET 2010


Revision: 48179
          http://scummvm.svn.sourceforge.net/scummvm/?rev=48179&view=rev
Author:   lordhoto
Date:     2010-03-08 00:33:36 +0000 (Mon, 08 Mar 2010)

Log Message:
-----------
Switch to the other DOSBox OPL emulator as suggested by the DOSBox developers.

Modified Paths:
--------------
    scummvm/trunk/sound/module.mk
    scummvm/trunk/sound/softsynth/opl/dosbox.cpp
    scummvm/trunk/sound/softsynth/opl/dosbox.h

Added Paths:
-----------
    scummvm/trunk/sound/softsynth/opl/dbopl.cpp
    scummvm/trunk/sound/softsynth/opl/dbopl.h

Removed Paths:
-------------
    scummvm/trunk/sound/softsynth/opl/opl_impl.h
    scummvm/trunk/sound/softsynth/opl/opl_inc.h

Modified: scummvm/trunk/sound/module.mk
===================================================================
--- scummvm/trunk/sound/module.mk	2010-03-07 23:07:32 UTC (rev 48178)
+++ scummvm/trunk/sound/module.mk	2010-03-08 00:33:36 UTC (rev 48179)
@@ -32,6 +32,7 @@
 	mods/soundfx.o \
 	mods/tfmx.o \
 	softsynth/adlib.o \
+	softsynth/opl/dbopl.o \
 	softsynth/opl/dosbox.o \
 	softsynth/opl/mame.o \
 	softsynth/ym2612.o \

Added: scummvm/trunk/sound/softsynth/opl/dbopl.cpp
===================================================================
--- scummvm/trunk/sound/softsynth/opl/dbopl.cpp	                        (rev 0)
+++ scummvm/trunk/sound/softsynth/opl/dbopl.cpp	2010-03-08 00:33:36 UTC (rev 48179)
@@ -0,0 +1,1511 @@
+/*
+ *  Copyright (C) 2002-2010  The DOSBox Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/*
+	DOSBox implementation of a combined Yamaha YMF262 and Yamaha YM3812 emulator.
+	Enabling the opl3 bit will switch the emulator to stereo opl3 output instead of regular mono opl2
+	Except for the table generation it's all integer math
+	Can choose different types of generators, using muls and bigger tables, try different ones for slower platforms
+	The generation was based on the MAME implementation but tried to have it use less memory and be faster in general
+	MAME uses much bigger envelope tables and this will be the biggest cause of it sounding different at times
+
+	//TODO Don't delay first operator 1 sample in opl3 mode
+	//TODO Maybe not use class method pointers but a regular function pointers with operator as first parameter
+	//TODO Fix panning for the Percussion channels, would any opl3 player use it and actually really change it though?
+	//TODO Check if having the same accuracy in all frequency multipliers sounds better or not
+
+	//DUNNO Keyon in 4op, switch to 2op without keyoff.
+*/
+
+/* $Id: dbopl.cpp,v 1.10 2009-06-10 19:54:51 harekiet Exp $ */
+
+
+#include "dbopl.h"
+
+#ifndef DISABLE_DOSBOX_OPL
+
+namespace OPL {
+namespace DOSBox {
+
+#ifndef PI
+#define PI 3.14159265358979323846
+#endif
+
+namespace DBOPL {
+
+#define OPLRATE		((double)(14318180.0 / 288.0))
+#define TREMOLO_TABLE 52
+
+//Try to use most precision for frequencies
+//Else try to keep different waves in synch
+//#define WAVE_PRECISION	1
+#ifndef WAVE_PRECISION
+//Wave bits available in the top of the 32bit range
+//Original adlib uses 10.10, we use 10.22
+#define WAVE_BITS	10
+#else
+//Need some extra bits at the top to have room for octaves and frequency multiplier
+//We support to 8 times lower rate
+//128 * 15 * 8 = 15350, 2^13.9, so need 14 bits
+#define WAVE_BITS	14
+#endif
+#define WAVE_SH		( 32 - WAVE_BITS )
+#define WAVE_MASK	( ( 1 << WAVE_SH ) - 1 )
+
+//Use the same accuracy as the waves
+#define LFO_SH ( WAVE_SH - 10 )
+//LFO is controlled by our tremolo 256 sample limit
+#define LFO_MAX ( 256 << ( LFO_SH ) )
+
+
+//Maximum amount of attenuation bits
+//Envelope goes to 511, 9 bits
+#if (DBOPL_WAVE == WAVE_TABLEMUL )
+//Uses the value directly
+#define ENV_BITS	( 9 )
+#else
+//Add 3 bits here for more accuracy and would have to be shifted up either way
+#define ENV_BITS	( 9 )
+#endif
+//Limits of the envelope with those bits and when the envelope goes silent
+#define ENV_MIN		0
+#define ENV_EXTRA	( ENV_BITS - 9 )
+#define ENV_MAX		( 511 << ENV_EXTRA )
+#define ENV_LIMIT	( ( 12 * 256) >> ( 3 - ENV_EXTRA ) )
+#define ENV_SILENT( _X_ ) ( (_X_) >= ENV_LIMIT )
+
+//Attack/decay/release rate counter shift
+#define RATE_SH		24
+#define RATE_MASK	( ( 1 << RATE_SH ) - 1 )
+//Has to fit within 16bit lookuptable
+#define MUL_SH		16
+
+//Check some ranges
+#if ENV_EXTRA > 3
+#error Too many envelope bits
+#endif
+
+
+//How much to substract from the base value for the final attenuation
+static const Bit8u KslCreateTable[16] = {
+	//0 will always be be lower than 7 * 8
+	64, 32, 24, 19, 
+	16, 12, 11, 10, 
+	 8,  6,  5,  4,
+	 3,  2,  1,  0,
+};
+
+#define M(_X_) ((Bit8u)( (_X_) * 2))
+static const Bit8u FreqCreateTable[16] = {
+	M(0.5), M(1 ), M(2 ), M(3 ), M(4 ), M(5 ), M(6 ), M(7 ),
+	M(8  ), M(9 ), M(10), M(10), M(12), M(12), M(15), M(15)
+};
+#undef M
+
+//We're not including the highest attack rate, that gets a special value
+static const Bit8u AttackSamplesTable[13] = {
+	69, 55, 46, 40,
+	35, 29, 23, 20,
+	19, 15, 11, 10,
+	9
+};
+//On a real opl these values take 8 samples to reach and are based upon larger tables
+static const Bit8u EnvelopeIncreaseTable[13] = {
+	4,  5,  6,  7,
+	8, 10, 12, 14,
+	16, 20, 24, 28,
+	32, 
+};
+
+#if ( DBOPL_WAVE == WAVE_HANDLER ) || ( DBOPL_WAVE == WAVE_TABLELOG )
+static Bit16u ExpTable[ 256 ];
+#endif
+
+#if ( DBOPL_WAVE == WAVE_HANDLER )
+//PI table used by WAVEHANDLER
+static Bit16u SinTable[ 512 ];
+#endif
+
+#if ( DBOPL_WAVE > WAVE_HANDLER )
+//Layout of the waveform table in 512 entry intervals
+//With overlapping waves we reduce the table to half it's size
+
+//	|    |//\\|____|WAV7|//__|/\  |____|/\/\|
+//	|\\//|    |    |WAV7|    |  \/|    |    |
+//	|06  |0126|17  |7   |3   |4   |4 5 |5   |
+
+//6 is just 0 shifted and masked
+
+static Bit16s WaveTable[ 8 * 512 ];
+//Distance into WaveTable the wave starts
+static const Bit16u WaveBaseTable[8] = {
+	0x000, 0x200, 0x200, 0x800,
+	0xa00, 0xc00, 0x100, 0x400,
+
+};
+//Mask the counter with this
+static const Bit16u WaveMaskTable[8] = {
+	1023, 1023, 511, 511,
+	1023, 1023, 512, 1023,
+};
+
+//Where to start the counter on at keyon
+static const Bit16u WaveStartTable[8] = {
+	512, 0, 0, 0,
+	0, 512, 512, 256,
+};
+#endif
+
+#if ( DBOPL_WAVE == WAVE_TABLEMUL )
+static Bit16u MulTable[ 384 ];
+#endif
+
+static Bit8u KslTable[ 8 * 16 ];
+static Bit8u TremoloTable[ TREMOLO_TABLE ];
+//Start of a channel behind the chip struct start
+static Bit16u ChanOffsetTable[32];
+//Start of an operator behind the chip struct start
+static Bit16u OpOffsetTable[64];
+
+//The lower bits are the shift of the operator vibrato value
+//The highest bit is right shifted to generate -1 or 0 for negation
+//So taking the highest input value of 7 this gives 3, 7, 3, 0, -3, -7, -3, 0
+static const Bit8s VibratoTable[ 8 ] = {	
+	1 - 0x00, 0 - 0x00, 1 - 0x00, 30 - 0x00, 
+	1 - 0x80, 0 - 0x80, 1 - 0x80, 30 - 0x80 
+};
+
+//Shift strength for the ksl value determined by ksl strength
+static const Bit8u KslShiftTable[4] = {
+	31,1,2,0
+};
+
+//Generate a table index and table shift value using input value from a selected rate
+static void EnvelopeSelect( Bit8u val, Bit8u& index, Bit8u& shift ) {
+	if ( val < 13 * 4 ) {				//Rate 0 - 12
+		shift = 12 - ( val >> 2 );
+		index = val & 3;
+	} else if ( val < 15 * 4 ) {		//rate 13 - 14
+		shift = 0;
+		index = val - 12 * 4;
+	} else {							//rate 15 and up
+		shift = 0;
+		index = 12;
+	}
+}
+
+#if ( DBOPL_WAVE == WAVE_HANDLER )
+/*
+	Generate the different waveforms out of the sine/exponetial table using handlers
+*/
+static inline Bits MakeVolume( Bitu wave, Bitu volume ) {
+	Bitu total = wave + volume;
+	Bitu index = total & 0xff;
+	Bitu sig = ExpTable[ index ];
+	Bitu exp = total >> 8;
+#if 0
+	//Check if we overflow the 31 shift limit
+	if ( exp >= 32 ) {
+		LOG_MSG( "WTF %d %d", total, exp );
+	}
+#endif
+	return (sig >> exp);
+};
+
+static Bits DB_FASTCALL WaveForm0( Bitu i, Bitu volume ) {
+	Bits neg = 0 - (( i >> 9) & 1);//Create ~0 or 0
+	Bitu wave = SinTable[i & 511];
+	return (MakeVolume( wave, volume ) ^ neg) - neg;
+}
+static Bits DB_FASTCALL WaveForm1( Bitu i, Bitu volume ) {
+	Bit32u wave = SinTable[i & 511];
+	wave |= ( ( (i ^ 512 ) & 512) - 1) >> ( 32 - 12 );
+	return MakeVolume( wave, volume );
+}
+static Bits DB_FASTCALL WaveForm2( Bitu i, Bitu volume ) {
+	Bitu wave = SinTable[i & 511];
+	return MakeVolume( wave, volume );
+}
+static Bits DB_FASTCALL WaveForm3( Bitu i, Bitu volume ) {
+	Bitu wave = SinTable[i & 255];
+	wave |= ( ( (i ^ 256 ) & 256) - 1) >> ( 32 - 12 );
+	return MakeVolume( wave, volume );
+}
+static Bits DB_FASTCALL WaveForm4( Bitu i, Bitu volume ) {
+	//Twice as fast
+	i <<= 1;
+	Bits neg = 0 - (( i >> 9) & 1);//Create ~0 or 0
+	Bitu wave = SinTable[i & 511];
+	wave |= ( ( (i ^ 512 ) & 512) - 1) >> ( 32 - 12 );
+	return (MakeVolume( wave, volume ) ^ neg) - neg;
+}
+static Bits DB_FASTCALL WaveForm5( Bitu i, Bitu volume ) {
+	//Twice as fast
+	i <<= 1;
+	Bitu wave = SinTable[i & 511];
+	wave |= ( ( (i ^ 512 ) & 512) - 1) >> ( 32 - 12 );
+	return MakeVolume( wave, volume );
+}
+static Bits DB_FASTCALL WaveForm6( Bitu i, Bitu volume ) {
+	Bits neg = 0 - (( i >> 9) & 1);//Create ~0 or 0
+	return (MakeVolume( 0, volume ) ^ neg) - neg;
+}
+static Bits DB_FASTCALL WaveForm7( Bitu i, Bitu volume ) {
+	//Negative is reversed here
+	Bits neg = (( i >> 9) & 1) - 1;
+	Bitu wave = (i << 3);
+	//When negative the volume also runs backwards
+	wave = ((wave ^ neg) - neg) & 4095;
+	return (MakeVolume( wave, volume ) ^ neg) - neg;
+}
+
+static const WaveHandler WaveHandlerTable[8] = {
+	WaveForm0, WaveForm1, WaveForm2, WaveForm3,
+	WaveForm4, WaveForm5, WaveForm6, WaveForm7
+};
+
+#endif
+
+/*
+	Operator
+*/
+
+//We zero out when rate == 0
+inline void Operator::UpdateAttack( const Chip* chip ) {
+	Bit8u rate = reg60 >> 4;
+	if ( rate ) {
+		Bit8u val = (rate << 2) + ksr;
+		attackAdd = chip->attackRates[ val ];
+		rateZero &= ~(1 << ATTACK);
+	} else {
+		attackAdd = 0;
+		rateZero |= (1 << ATTACK);
+	}
+}
+inline void Operator::UpdateDecay( const Chip* chip ) {
+	Bit8u rate = reg60 & 0xf;
+	if ( rate ) {
+		Bit8u val = (rate << 2) + ksr;
+		decayAdd = chip->linearRates[ val ];
+		rateZero &= ~(1 << DECAY);
+	} else {
+		decayAdd = 0;
+		rateZero |= (1 << DECAY);
+	}
+}
+inline void Operator::UpdateRelease( const Chip* chip ) {
+	Bit8u rate = reg80 & 0xf;
+	if ( rate ) {
+		Bit8u val = (rate << 2) + ksr;
+		releaseAdd = chip->linearRates[ val ];
+		rateZero &= ~(1 << RELEASE);
+		if ( !(reg20 & MASK_SUSTAIN ) ) {
+			rateZero &= ~( 1 << SUSTAIN );
+		}	
+	} else {
+		rateZero |= (1 << RELEASE);
+		releaseAdd = 0;
+		if ( !(reg20 & MASK_SUSTAIN ) ) {
+			rateZero |= ( 1 << SUSTAIN );
+		}	
+	}
+}
+
+inline void Operator::UpdateAttenuation( ) {
+	Bit8u kslBase = (Bit8u)((chanData >> SHIFT_KSLBASE) & 0xff);
+	Bit32u tl = reg40 & 0x3f;
+	Bit8u kslShift = KslShiftTable[ reg40 >> 6 ];
+	//Make sure the attenuation goes to the right bits
+	totalLevel = tl << ( ENV_BITS - 7 );	//Total level goes 2 bits below max
+	totalLevel += ( kslBase << ENV_EXTRA ) >> kslShift;
+}
+
+void Operator::UpdateFrequency(  ) {
+	Bit32u freq = chanData & (( 1 << 10 ) - 1);
+	Bit32u block = (chanData >> 10) & 0xff;
+#ifdef WAVE_PRECISION
+	block = 7 - block;
+	waveAdd = ( freq * freqMul ) >> block;
+#else
+	waveAdd = ( freq << block ) * freqMul;
+#endif
+	if ( reg20 & MASK_VIBRATO ) {
+		vibStrength = (Bit8u)(freq >> 7);
+
+#ifdef WAVE_PRECISION
+		vibrato = ( vibStrength * freqMul ) >> block;
+#else
+		vibrato = ( vibStrength << block ) * freqMul;
+#endif
+	} else {
+		vibStrength = 0;
+		vibrato = 0;
+	}
+}
+
+void Operator::UpdateRates( const Chip* chip ) {
+	//Mame seems to reverse this where enabling ksr actually lowers
+	//the rate, but pdf manuals says otherwise?
+	Bit8u newKsr = (Bit8u)((chanData >> SHIFT_KEYCODE) & 0xff);
+	if ( !( reg20 & MASK_KSR ) ) {
+		newKsr >>= 2;
+	}
+	if ( ksr == newKsr )
+		return;
+	ksr = newKsr;
+	UpdateAttack( chip );
+	UpdateDecay( chip );
+	UpdateRelease( chip );
+}
+
+INLINE Bit32s Operator::RateForward( Bit32u add ) {
+	rateIndex += add;
+	Bit32s ret = rateIndex >> RATE_SH;
+	rateIndex = rateIndex & RATE_MASK;
+	return ret;
+}
+
+template< Operator::State yes>
+Bits Operator::TemplateVolume(  ) {
+	Bit32s vol = volume;
+	Bit32s change;
+	switch ( yes ) {
+	case OFF:
+		return ENV_MAX;
+	case ATTACK:
+		change = RateForward( attackAdd );
+		if ( !change )
+			return vol;
+		vol += ( (~vol) * change ) >> 3;
+		if ( vol < ENV_MIN ) {
+			volume = ENV_MIN;
+			rateIndex = 0;
+			SetState( DECAY );
+			return ENV_MIN;
+		}
+		break;
+	case DECAY:
+		vol += RateForward( decayAdd );
+		if ( GCC_UNLIKELY(vol >= sustainLevel) ) {
+			//Check if we didn't overshoot max attenuation, then just go off
+			if ( GCC_UNLIKELY(vol >= ENV_MAX) ) {
+				volume = ENV_MAX;
+				SetState( OFF );
+				return ENV_MAX;
+			}
+			//Continue as sustain
+			rateIndex = 0;
+			SetState( SUSTAIN );
+		}
+		break;
+	case SUSTAIN:
+		if ( reg20 & MASK_SUSTAIN ) {
+			return vol;
+		}
+		//In sustain phase, but not sustaining, do regular release
+	case RELEASE: 
+		vol += RateForward( releaseAdd );;
+		if ( GCC_UNLIKELY(vol >= ENV_MAX) ) {
+			volume = ENV_MAX;
+			SetState( OFF );
+			return ENV_MAX;
+		}
+		break;
+	}
+	volume = vol;
+	return vol;
+}
+
+static const VolumeHandler VolumeHandlerTable[5] = {
+	&Operator::TemplateVolume< Operator::OFF >,
+	&Operator::TemplateVolume< Operator::RELEASE >,
+	&Operator::TemplateVolume< Operator::SUSTAIN >,
+	&Operator::TemplateVolume< Operator::DECAY >,
+	&Operator::TemplateVolume< Operator::ATTACK >
+};
+
+INLINE Bitu Operator::ForwardVolume() {
+	return currentLevel + (this->*volHandler)();
+}
+
+
+INLINE Bitu Operator::ForwardWave() {
+	waveIndex += waveCurrent;	
+	return waveIndex >> WAVE_SH;
+}
+
+void Operator::Write20( const Chip* chip, Bit8u val ) {
+	Bit8u change = (reg20 ^ val );
+	if ( !change ) 
+		return;
+	reg20 = val;
+	//Shift the tremolo bit over the entire register, saved a branch, YES!
+	tremoloMask = (Bit8s)(val) >> 7;
+	tremoloMask &= ~(( 1 << ENV_EXTRA ) -1);
+	//Update specific features based on changes
+	if ( change & MASK_KSR ) {
+		UpdateRates( chip );
+	}
+	//With sustain enable the volume doesn't change
+	if ( reg20 & MASK_SUSTAIN || ( !releaseAdd ) ) {
+		rateZero |= ( 1 << SUSTAIN );
+	} else {
+		rateZero &= ~( 1 << SUSTAIN );
+	}
+	//Frequency multiplier or vibrato changed
+	if ( change & (0xf | MASK_VIBRATO) ) {
+		freqMul = chip->freqMul[ val & 0xf ];
+		UpdateFrequency();
+	}
+}
+
+void Operator::Write40( const Chip* /*chip*/, Bit8u val ) {
+	if (!(reg40 ^ val )) 
+		return;
+	reg40 = val;
+	UpdateAttenuation( );
+}
+
+void Operator::Write60( const Chip* chip, Bit8u val ) {
+	Bit8u change = reg60 ^ val;
+	reg60 = val;
+	if ( change & 0x0f ) {
+		UpdateDecay( chip );
+	}
+	if ( change & 0xf0 ) {
+		UpdateAttack( chip );
+	}
+}
+
+void Operator::Write80( const Chip* chip, Bit8u val ) {
+	Bit8u change = (reg80 ^ val );
+	if ( !change ) 
+		return;
+	reg80 = val;
+	Bit8u sustain = val >> 4;
+	//Turn 0xf into 0x1f
+	sustain |= ( sustain + 1) & 0x10;
+	sustainLevel = sustain << ( ENV_BITS - 5 );
+	if ( change & 0x0f ) {
+		UpdateRelease( chip );
+	}
+}
+
+void Operator::WriteE0( const Chip* chip, Bit8u val ) {
+	if ( !(regE0 ^ val) ) 
+		return;
+	//in opl3 mode you can always selet 7 waveforms regardless of waveformselect
+	Bit8u waveForm = val & ( ( 0x3 & chip->waveFormMask ) | (0x7 & chip->opl3Active ) );
+	regE0 = val;
+#if ( DBOPL_WAVE == WAVE_HANDLER )
+	waveHandler = WaveHandlerTable[ waveForm ];
+#else
+	waveBase = WaveTable + WaveBaseTable[ waveForm ];
+	waveStart = WaveStartTable[ waveForm ] << WAVE_SH;
+	waveMask = WaveMaskTable[ waveForm ];
+#endif
+}
+
+INLINE void Operator::SetState( Bit8u s ) {
+	state = s;
+	volHandler = VolumeHandlerTable[ s ];
+}
+
+INLINE bool Operator::Silent() const {
+	if ( !ENV_SILENT( totalLevel + volume ) )
+		return false;
+	if ( !(rateZero & ( 1 << state ) ) )
+		return false;
+	return true;
+}
+
+INLINE void Operator::Prepare( const Chip* chip )  {
+	currentLevel = totalLevel + (chip->tremoloValue & tremoloMask);
+	waveCurrent = waveAdd;
+	if ( vibStrength >> chip->vibratoShift ) {
+		Bit32s add = vibrato >> chip->vibratoShift;
+		//Sign extend over the shift value
+		Bit32s neg = chip->vibratoSign;
+		//Negate the add with -1 or 0
+		add = ( add ^ neg ) - neg; 
+		waveCurrent += add;
+	}
+}
+
+void Operator::KeyOn( Bit8u mask ) {
+	if ( !keyOn ) {
+		//Restart the frequency generator
+#if ( DBOPL_WAVE > WAVE_HANDLER )
+		waveIndex = waveStart;
+#else
+		waveIndex = 0;
+#endif
+		rateIndex = 0;
+		SetState( ATTACK );
+	}
+	keyOn |= mask;
+}
+
+void Operator::KeyOff( Bit8u mask ) {
+	keyOn &= ~mask;
+	if ( !keyOn ) {
+		if ( state != OFF ) {
+			SetState( RELEASE );
+		}
+	}
+}
+
+INLINE Bits Operator::GetWave( Bitu index, Bitu vol ) {
+#if ( DBOPL_WAVE == WAVE_HANDLER )
+	return waveHandler( index, vol << ( 3 - ENV_EXTRA ) );
+#elif ( DBOPL_WAVE == WAVE_TABLEMUL )
+	return (waveBase[ index & waveMask ] * MulTable[ vol >> ENV_EXTRA ]) >> MUL_SH;
+#elif ( DBOPL_WAVE == WAVE_TABLELOG )
+	Bit32s wave = waveBase[ index & waveMask ];
+	Bit32u total = ( wave & 0x7fff ) + vol << ( 3 - ENV_EXTRA );
+	Bit32s sig = ExpTable[ total & 0xff ];
+	Bit32u exp = total >> 8;
+	Bit32s neg = wave >> 16;
+	return ((sig ^ neg) - neg) >> exp;
+#else
+#error "No valid wave routine"
+#endif
+}
+
+Bits INLINE Operator::GetSample( Bits modulation ) {
+	Bitu vol = ForwardVolume();
+	if ( ENV_SILENT( vol ) ) {
+		//Simply forward the wave
+		waveIndex += waveCurrent;
+		return 0;
+	} else {
+		Bitu index = ForwardWave();
+		index += modulation;
+		return GetWave( index, vol );
+	}
+}
+
+Operator::Operator() {
+	chanData = 0;
+	freqMul = 0;
+	waveIndex = 0;
+	waveAdd = 0;
+	waveCurrent = 0;
+	keyOn = 0;
+	ksr = 0;
+	reg20 = 0;
+	reg40 = 0;
+	reg60 = 0;
+	reg80 = 0;
+	regE0 = 0;
+	SetState( OFF );
+	rateZero = (1 << OFF);
+	sustainLevel = ENV_MAX;
+	currentLevel = ENV_MAX;
+	totalLevel = ENV_MAX;
+	volume = ENV_MAX;
+}
+
+/*
+	Channel
+*/
+
+Channel::Channel() {
+	old[0] = old[1] = 0;
+	chanData = 0;
+	regB0 = 0;
+	regC0 = 0;
+	maskLeft = -1;
+	maskRight = -1;
+	feedback = 31;
+	fourMask = 0;
+	synthHandler = &Channel::BlockTemplate< sm2FM >;
+}
+
+void Channel::SetChanData( const Chip* chip, Bit32u data ) {
+	Bit32u change = chanData ^ data;
+	chanData = data;
+	Op( 0 )->chanData = data;
+	Op( 1 )->chanData = data;
+	//Since a frequency update triggered this, always update frequency
+	Op( 0 )->UpdateFrequency();
+	Op( 1 )->UpdateFrequency();
+	if ( change & ( 0xff << SHIFT_KSLBASE ) ) {
+		Op( 0 )->UpdateAttenuation();
+		Op( 1 )->UpdateAttenuation();
+	}
+	if ( change & ( 0xff << SHIFT_KEYCODE ) ) {
+		Op( 0 )->UpdateRates( chip );
+		Op( 1 )->UpdateRates( chip );
+	}
+}
+
+void Channel::UpdateFrequency( const Chip* chip, Bit8u fourOp ) {
+	//Extrace the frequency bits
+	Bit32u data = chanData & 0xffff;
+	Bit32u kslBase = KslTable[ data >> 6 ];
+	Bit32u keyCode = ( data & 0x1c00) >> 9;
+	if ( chip->reg08 & 0x40 ) {
+		keyCode |= ( data & 0x100)>>8;	/* notesel == 1 */
+	} else {
+		keyCode |= ( data & 0x200)>>9;	/* notesel == 0 */
+	}
+	//Add the keycode and ksl into the highest bits of chanData
+	data |= (keyCode << SHIFT_KEYCODE) | ( kslBase << SHIFT_KSLBASE );
+	( this + 0 )->SetChanData( chip, data );
+	if ( fourOp & 0x3f ) {
+		( this + 1 )->SetChanData( chip, data );
+	}
+}
+
+void Channel::WriteA0( const Chip* chip, Bit8u val ) {
+	Bit8u fourOp = chip->reg104 & chip->opl3Active & fourMask;
+	//Don't handle writes to silent fourop channels
+	if ( fourOp > 0x80 )
+		return;
+	Bit32u change = (chanData ^ val ) & 0xff;
+	if ( change ) {
+		chanData ^= change;
+		UpdateFrequency( chip, fourOp );
+	}
+}
+
+void Channel::WriteB0( const Chip* chip, Bit8u val ) {
+	Bit8u fourOp = chip->reg104 & chip->opl3Active & fourMask;
+	//Don't handle writes to silent fourop channels
+	if ( fourOp > 0x80 )
+		return;
+	Bitu change = (chanData ^ ( val << 8 ) ) & 0x1f00;
+	if ( change ) {
+		chanData ^= change;
+		UpdateFrequency( chip, fourOp );
+	}
+	//Check for a change in the keyon/off state
+	if ( !(( val ^ regB0) & 0x20))
+		return;
+	regB0 = val;
+	if ( val & 0x20 ) {
+		Op(0)->KeyOn( 0x1 );
+		Op(1)->KeyOn( 0x1 );
+		if ( fourOp & 0x3f ) {
+			( this + 1 )->Op(0)->KeyOn( 1 );
+			( this + 1 )->Op(1)->KeyOn( 1 );
+		}
+	} else {
+		Op(0)->KeyOff( 0x1 );
+		Op(1)->KeyOff( 0x1 );
+		if ( fourOp & 0x3f ) {
+			( this + 1 )->Op(0)->KeyOff( 1 );
+			( this + 1 )->Op(1)->KeyOff( 1 );
+		}
+	}
+}
+
+void Channel::WriteC0( const Chip* chip, Bit8u val ) {
+	Bit8u change = val ^ regC0;
+	if ( !change )
+		return;
+	regC0 = val;
+	feedback = ( val >> 1 ) & 7;
+	if ( feedback ) {
+		//We shift the input to the right 10 bit wave index value
+		feedback = 9 - feedback;
+	} else {
+		feedback = 31;
+	}
+	//Select the new synth mode
+	if ( chip->opl3Active ) {
+		//4-op mode enabled for this channel
+		if ( (chip->reg104 & fourMask) & 0x3f ) {
+			Channel* chan0, *chan1;
+			//Check if it's the 2nd channel in a 4-op
+			if ( !(fourMask & 0x80 ) ) {
+				chan0 = this;
+				chan1 = this + 1;
+			} else {
+				chan0 = this - 1;
+				chan1 = this;
+			}
+
+			Bit8u synth = ( (chan0->regC0 & 1) << 0 )| (( chan1->regC0 & 1) << 1 );
+			switch ( synth ) {
+			case 0:
+				chan0->synthHandler = &Channel::BlockTemplate< sm3FMFM >;
+				break;
+			case 1:
+				chan0->synthHandler = &Channel::BlockTemplate< sm3AMFM >;
+				break;
+			case 2:
+				chan0->synthHandler = &Channel::BlockTemplate< sm3FMAM >;
+				break;
+			case 3:
+				chan0->synthHandler = &Channel::BlockTemplate< sm3AMAM >;
+				break;
+			}
+		//Disable updating percussion channels
+		} else if ((fourMask & 0x40) && ( chip->regBD & 0x20) ) {
+
+		//Regular dual op, am or fm
+		} else if ( val & 1 ) {
+			synthHandler = &Channel::BlockTemplate< sm3AM >;
+		} else {
+			synthHandler = &Channel::BlockTemplate< sm3FM >;
+		}
+		maskLeft = ( val & 0x10 ) ? -1 : 0;
+		maskRight = ( val & 0x20 ) ? -1 : 0;
+	//opl2 active
+	} else { 
+		//Disable updating percussion channels
+		if ( (fourMask & 0x40) && ( chip->regBD & 0x20 ) ) {
+
+		//Regular dual op, am or fm
+		} else if ( val & 1 ) {
+			synthHandler = &Channel::BlockTemplate< sm2AM >;
+		} else {
+			synthHandler = &Channel::BlockTemplate< sm2FM >;
+		}
+	}
+}
+
+void Channel::ResetC0( const Chip* chip ) {
+	Bit8u val = regC0;
+	regC0 ^= 0xff;
+	WriteC0( chip, val );
+}
+
+template< bool opl3Mode>
+INLINE void Channel::GeneratePercussion( Chip* chip, Bit32s* output ) {
+	Channel* chan = this;
+
+	//BassDrum
+	Bit32s mod = (Bit32u)((old[0] + old[1])) >> feedback;
+	old[0] = old[1];
+	old[1] = Op(0)->GetSample( mod ); 
+
+	//When bassdrum is in AM mode first operator is ignoed
+	if ( chan->regC0 & 1 ) {
+		mod = 0;
+	} else {
+		mod = old[0];
+	}
+	Bit32s sample = Op(1)->GetSample( mod ); 
+
+
+	//Precalculate stuff used by other outputs
+	Bit32u noiseBit = chip->ForwardNoise() & 0x1;
+	Bit32u c2 = Op(2)->ForwardWave();
+	Bit32u c5 = Op(5)->ForwardWave();
+	Bit32u phaseBit = (((c2 & 0x88) ^ ((c2<<5) & 0x80)) | ((c5 ^ (c5<<2)) & 0x20)) ? 0x02 : 0x00;
+
+	//Hi-Hat
+	Bit32u hhVol = Op(2)->ForwardVolume();
+	if ( !ENV_SILENT( hhVol ) ) {
+		Bit32u hhIndex = (phaseBit<<8) | (0x34 << ( phaseBit ^ (noiseBit << 1 )));
+		sample += Op(2)->GetWave( hhIndex, hhVol );
+	}
+	//Snare Drum
+	Bit32u sdVol = Op(3)->ForwardVolume();
+	if ( !ENV_SILENT( sdVol ) ) {
+		Bit32u sdIndex = ( 0x100 + (c2 & 0x100) ) ^ ( noiseBit << 8 );
+		sample += Op(3)->GetWave( sdIndex, sdVol );
+	}
+	//Tom-tom
+	sample += Op(4)->GetSample( 0 );
+
+	//Top-Cymbal
+	Bit32u tcVol = Op(5)->ForwardVolume();
+	if ( !ENV_SILENT( tcVol ) ) {
+		Bit32u tcIndex = (1 + phaseBit) << 8;
+		sample += Op(5)->GetWave( tcIndex, tcVol );
+	}
+	sample <<= 1;
+	if ( opl3Mode ) {
+		output[0] += sample;
+		output[1] += sample;
+	} else {
+		output[0] += sample;
+	}
+}
+
+template<SynthMode mode>
+Channel* Channel::BlockTemplate( Chip* chip, Bit32u samples, Bit32s* output ) {
+	switch( mode ) {
+	case sm2AM:
+	case sm3AM:
+		if ( Op(0)->Silent() && Op(1)->Silent() ) {
+			old[0] = old[1] = 0;
+			return (this + 1);
+		}
+		break;
+	case sm2FM:
+	case sm3FM:
+		if ( Op(1)->Silent() ) {
+			old[0] = old[1] = 0;
+			return (this + 1);
+		}
+		break;
+	case sm3FMFM:
+		if ( Op(3)->Silent() ) {
+			old[0] = old[1] = 0;
+			return (this + 2);
+		}
+		break;
+	case sm3AMFM:
+		if ( Op(0)->Silent() && Op(3)->Silent() ) {
+			old[0] = old[1] = 0;
+			return (this + 2);
+		}
+		break;
+	case sm3FMAM:
+		if ( Op(1)->Silent() && Op(3)->Silent() ) {
+			old[0] = old[1] = 0;
+			return (this + 2);
+		}
+		break;
+	case sm3AMAM:
+		if ( Op(0)->Silent() && Op(2)->Silent() && Op(3)->Silent() ) {
+			old[0] = old[1] = 0;
+			return (this + 2);
+		}
+		break;
+	case sm2Percussion:
+		// This case was not handled in the DOSBox code either
+		// thus we leave this blank.
+		// TODO: Consider checking this.
+		break;
+	case sm3Percussion:
+		// This case was not handled in the DOSBox code either
+		// thus we leave this blank.
+		// TODO: Consider checking this.
+		break;
+	}
+	//Init the operators with the the current vibrato and tremolo values
+	Op( 0 )->Prepare( chip );
+	Op( 1 )->Prepare( chip );
+	if ( mode > sm4Start ) {
+		Op( 2 )->Prepare( chip );
+		Op( 3 )->Prepare( chip );
+	}
+	if ( mode > sm6Start ) {
+		Op( 4 )->Prepare( chip );
+		Op( 5 )->Prepare( chip );
+	}
+	for ( Bitu i = 0; i < samples; i++ ) {
+		//Early out for percussion handlers
+		if ( mode == sm2Percussion ) {
+			GeneratePercussion<false>( chip, output + i );
+			continue;	//Prevent some unitialized value bitching
+		} else if ( mode == sm3Percussion ) {
+			GeneratePercussion<true>( chip, output + i * 2 );
+			continue;	//Prevent some unitialized value bitching
+		}
+
+		//Do unsigned shift so we can shift out all bits but still stay in 10 bit range otherwise
+		Bit32s mod = (Bit32u)((old[0] + old[1])) >> feedback;
+		old[0] = old[1];
+		old[1] = Op(0)->GetSample( mod );
+		Bit32s sample;
+		Bit32s out0 = old[0];
+		if ( mode == sm2AM || mode == sm3AM ) {
+			sample = out0 + Op(1)->GetSample( 0 );
+		} else if ( mode == sm2FM || mode == sm3FM ) {
+			sample = Op(1)->GetSample( out0 );
+		} else if ( mode == sm3FMFM ) {
+			Bits next = Op(1)->GetSample( out0 ); 
+			next = Op(2)->GetSample( next );
+			sample = Op(3)->GetSample( next );
+		} else if ( mode == sm3AMFM ) {
+			sample = out0;
+			Bits next = Op(1)->GetSample( 0 ); 
+			next = Op(2)->GetSample( next );
+			sample += Op(3)->GetSample( next );
+		} else if ( mode == sm3FMAM ) {
+			sample = Op(1)->GetSample( out0 );
+			Bits next = Op(2)->GetSample( 0 );
+			sample += Op(3)->GetSample( next );
+		} else if ( mode == sm3AMAM ) {
+			sample = out0;
+			Bits next = Op(1)->GetSample( 0 ); 
+			sample += Op(2)->GetSample( next );
+			sample += Op(3)->GetSample( 0 );
+		}
+		switch( mode ) {
+		case sm2AM:
+		case sm2FM:
+			output[ i ] += sample;
+			break;
+		case sm3AM:
+		case sm3FM:
+		case sm3FMFM:
+		case sm3AMFM:
+		case sm3FMAM:
+		case sm3AMAM:
+			output[ i * 2 + 0 ] += sample & maskLeft;
+			output[ i * 2 + 1 ] += sample & maskRight;
+			break;
+		case sm2Percussion:
+			// This case was not handled in the DOSBox code either
+			// thus we leave this blank.
+			// TODO: Consider checking this.
+			break;
+		case sm3Percussion:
+			// This case was not handled in the DOSBox code either
+			// thus we leave this blank.
+			// TODO: Consider checking this.
+			break;
+		}
+	}
+	switch( mode ) {
+	case sm2AM:
+	case sm2FM:
+	case sm3AM:
+	case sm3FM:
+		return ( this + 1 );
+	case sm3FMFM:
+	case sm3AMFM:
+	case sm3FMAM:
+	case sm3AMAM:
+		return( this + 2 );
+	case sm2Percussion:
+	case sm3Percussion:
+		return( this + 3 );
+	}
+	return 0;
+}
+
+/*
+	Chip
+*/
+
+Chip::Chip() {
+	reg08 = 0;
+	reg04 = 0;
+	regBD = 0;
+	reg104 = 0;
+	opl3Active = 0;
+}
+
+INLINE Bit32u Chip::ForwardNoise() {
+	noiseCounter += noiseAdd;
+	Bitu count = noiseCounter >> LFO_SH;
+	noiseCounter &= WAVE_MASK;
+	for ( ; count > 0; --count ) {
+		//Noise calculation from mame
+		noiseValue ^= ( 0x800302 ) & ( 0 - (noiseValue & 1 ) );
+		noiseValue >>= 1;
+	}
+	return noiseValue;
+}
+
+INLINE Bit32u Chip::ForwardLFO( Bit32u samples ) {
+	//Current vibrato value, runs 4x slower than tremolo
+	vibratoSign = ( VibratoTable[ vibratoIndex >> 2] ) >> 7;
+	vibratoShift = ( VibratoTable[ vibratoIndex >> 2] & 7) + vibratoStrength; 
+	tremoloValue = TremoloTable[ tremoloIndex ] >> tremoloStrength;
+
+	//Check hom many samples there can be done before the value changes
+	Bit32u todo = LFO_MAX - lfoCounter;
+	Bit32u count = (todo + lfoAdd - 1) / lfoAdd;
+	if ( count > samples ) {
+		count = samples;
+		lfoCounter += count * lfoAdd;
+	} else {
+		lfoCounter += count * lfoAdd;
+		lfoCounter &= (LFO_MAX - 1);
+		//Maximum of 7 vibrato value * 4
+		vibratoIndex = ( vibratoIndex + 1 ) & 31;
+		//Clip tremolo to the the table size
+		if ( tremoloIndex + 1 < TREMOLO_TABLE  )
+			++tremoloIndex;
+		else
+			tremoloIndex = 0;
+	}
+	return count;
+}
+
+
+void Chip::WriteBD( Bit8u val ) {
+	Bit8u change = regBD ^ val;
+	if ( !change )
+		return;
+	regBD = val;
+	//TODO could do this with shift and xor?
+	vibratoStrength = (val & 0x40) ? 0x00 : 0x01;
+	tremoloStrength = (val & 0x80) ? 0x00 : 0x02;
+	if ( val & 0x20 ) {
+		//Drum was just enabled, make sure channel 6 has the right synth
+		if ( change & 0x20 ) {
+			if ( opl3Active ) {
+				chan[6].synthHandler = &Channel::BlockTemplate< sm3Percussion >; 
+			} else {
+				chan[6].synthHandler = &Channel::BlockTemplate< sm2Percussion >; 
+			}
+		}
+		//Bass Drum
+		if ( val & 0x10 ) {
+			chan[6].op[0].KeyOn( 0x2 );
+			chan[6].op[1].KeyOn( 0x2 );
+		} else {
+			chan[6].op[0].KeyOff( 0x2 );
+			chan[6].op[1].KeyOff( 0x2 );
+		}
+		//Hi-Hat
+		if ( val & 0x1 ) {
+			chan[7].op[0].KeyOn( 0x2 );
+		} else {
+			chan[7].op[0].KeyOff( 0x2 );
+		}
+		//Snare
+		if ( val & 0x8 ) {
+			chan[7].op[1].KeyOn( 0x2 );
+		} else {
+			chan[7].op[1].KeyOff( 0x2 );
+		}
+		//Tom-Tom
+		if ( val & 0x4 ) {
+			chan[8].op[0].KeyOn( 0x2 );
+		} else {
+			chan[8].op[0].KeyOff( 0x2 );
+		}
+		//Top Cymbal
+		if ( val & 0x2 ) {
+			chan[8].op[1].KeyOn( 0x2 );
+		} else {
+			chan[8].op[1].KeyOff( 0x2 );
+		}
+	//Toggle keyoffs when we turn off the percussion
+	} else if ( change & 0x20 ) {
+		//Trigger a reset to setup the original synth handler
+		chan[6].ResetC0( this );
+		chan[6].op[0].KeyOff( 0x2 );
+		chan[6].op[1].KeyOff( 0x2 );
+		chan[7].op[0].KeyOff( 0x2 );
+		chan[7].op[1].KeyOff( 0x2 );
+		chan[8].op[0].KeyOff( 0x2 );
+		chan[8].op[1].KeyOff( 0x2 );
+	}
+}
+
+
+#define REGOP( _FUNC_ )															\
+	index = ( ( reg >> 3) & 0x20 ) | ( reg & 0x1f );								\
+	if ( OpOffsetTable[ index ] ) {													\
+		Operator* regOp = (Operator*)( ((char *)this ) + OpOffsetTable[ index ] );	\
+		regOp->_FUNC_( this, val );													\
+	}
+
+#define REGCHAN( _FUNC_ )																\
+	index = ( ( reg >> 4) & 0x10 ) | ( reg & 0xf );										\
+	if ( ChanOffsetTable[ index ] ) {													\
+		Channel* regChan = (Channel*)( ((char *)this ) + ChanOffsetTable[ index ] );	\
+		regChan->_FUNC_( this, val );													\
+	}
+
+void Chip::WriteReg( Bit32u reg, Bit8u val ) {
+	Bitu index;
+	switch ( (reg & 0xf0) >> 4 ) {
+	case 0x00 >> 4:
+		if ( reg == 0x01 ) {
+			waveFormMask = ( val & 0x20 ) ? 0x7 : 0x0; 
+		} else if ( reg == 0x104 ) {
+			//Only detect changes in lowest 6 bits
+			if ( !((reg104 ^ val) & 0x3f) )
+				return;
+			//Always keep the highest bit enabled, for checking > 0x80
+			reg104 = 0x80 | ( val & 0x3f );
+		} else if ( reg == 0x105 ) {
+			//MAME says the real opl3 doesn't reset anything on opl3 disable/enable till the next write in another register
+			if ( !((opl3Active ^ val) & 1 ) )
+				return;
+			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++ ) {
+				chan[i].ResetC0( this );
+			}
+		} else if ( reg == 0x08 ) {
+			reg08 = val;
+		}
+	case 0x10 >> 4:
+		break;
+	case 0x20 >> 4:
+	case 0x30 >> 4:
+		REGOP( Write20 );
+		break;
+	case 0x40 >> 4:
+	case 0x50 >> 4:
+		REGOP( Write40 );
+		break;
+	case 0x60 >> 4:
+	case 0x70 >> 4:
+		REGOP( Write60 );
+		break;
+	case 0x80 >> 4:
+	case 0x90 >> 4:
+		REGOP( Write80 );
+		break;
+	case 0xa0 >> 4:
+		REGCHAN( WriteA0 );
+		break;
+	case 0xb0 >> 4:
+		if ( reg == 0xbd ) {
+			WriteBD( val );
+		} else {
+			REGCHAN( WriteB0 );
+		}
+		break;
+	case 0xc0 >> 4:
+		REGCHAN( WriteC0 );
+	case 0xd0 >> 4:
+		break;
+	case 0xe0 >> 4:
+	case 0xf0 >> 4:
+		REGOP( WriteE0 );
+		break;
+	}
+}
+
+
+Bit32u Chip::WriteAddr( Bit32u port, Bit8u val ) {
+	switch ( port & 3 ) {
+	case 0:
+		return val;
+	case 2:
+		if ( opl3Active || (val == 0x05) )
+			return 0x100 | val;
+		else 
+			return val;
+	}
+	return 0;
+}
+
+void Chip::GenerateBlock2( Bitu total, Bit32s* output ) {
+	while ( total > 0 ) {
+		Bit32u samples = ForwardLFO( total );
+		for ( Bitu i = 0; i < samples; i++ ) {
+			output[i] = 0;
+		}
+		int count = 0;
+		for( Channel* ch = chan; ch < chan + 9; ) {
+			count++;
+			ch = (ch->*(ch->synthHandler))( this, samples, output );
+		}
+		total -= samples;
+		output += samples;
+	}
+}
+
+void Chip::GenerateBlock3( Bitu total, Bit32s* output  ) {
+	while ( total > 0 ) {
+		Bit32u samples = ForwardLFO( total );
+		for ( Bitu i = 0; i < samples; i++ ) {
+			output[i * 2 + 0 ] = 0;
+			output[i * 2 + 1 ] = 0;
+		}
+		int count = 0;
+		for( Channel* ch = chan; ch < chan + 18; ) {
+			count++;
+			ch = (ch->*(ch->synthHandler))( this, samples, output );
+		}
+		total -= samples;
+		output += samples * 2;
+	}
+}
+
+void Chip::Setup( Bit32u rate ) {
+	double scale = OPLRATE / (double)rate;
+
+	//Noise counter is run at the same precision as general waves
+	noiseAdd = (Bit32u)( 0.5 + scale * ( 1 << LFO_SH ) );
+	noiseCounter = 0;
+	noiseValue = 1;	//Make sure it triggers the noise xor the first time
+	//The low frequency oscillation counter
+	//Every time his overflows vibrato and tremoloindex are increased
+	lfoAdd = (Bit32u)( 0.5 + scale * ( 1 << LFO_SH ) );
+	lfoCounter = 0;
+	vibratoIndex = 0;
+	tremoloIndex = 0;
+
+	//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++ ) {
+		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++ ) {
+		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++ ) {
+		Bit8u index, shift;
+		EnvelopeSelect( i, index, shift );
+		linearRates[i] = (Bit32u)( scale * (EnvelopeIncreaseTable[ index ] << ( RATE_SH + ENV_EXTRA - shift - 3 )));
+	}
+	//Generate the best matching attack rate
+	for ( Bit8u i = 0; i < 62; i++ ) {
+		Bit8u index, shift;
+		EnvelopeSelect( i, index, shift );
+		//Original amount of samples the attack would take
+		Bit32s 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 ++ ) {
+			Bit32s volume = ENV_MAX;
+			Bit32s samples = 0;
+			Bit32u count = 0;
+			while ( volume > 0 && samples < original * 2 ) {
+				count += guessAdd;
+				Bit32s change = count >> RATE_SH;
+				count &= RATE_MASK;
+				if ( GCC_UNLIKELY(change) ) { // less than 1 % 
+					volume += ( ~volume * change ) >> 3;
+				}
+				samples++;
+
+			}
+			Bit32s diff = original - samples;
+			Bit32u lDiff = labs( diff );
+			//Init last on first pass
+			if ( lDiff < bestDiff ) {
+				bestDiff = lDiff;
+				bestAdd = guessAdd;
+				if ( !bestDiff )
+					break;
+			}
+			//Below our target
+			if ( diff < 0 ) {
+				//Better than the last time
+				Bit32s mul = ((original - diff) << 12) / original;
+				guessAdd = ((guessAdd * mul) >> 12);
+				guessAdd++;
+			} else if ( diff > 0 ) {
+				Bit32s mul = ((original - diff) << 12) / original;
+				guessAdd = (guessAdd * mul) >> 12;
+				guessAdd--;
+			}
+		}
+		attackRates[i] = bestAdd;
+	}
+	for ( Bit8u i = 62; i < 76; i++ ) {
+		//This should provide instant volume maximizing
+		attackRates[i] = 8 << RATE_SH;
+	}
+	//Setup the channels with the correct four op flags
+	//Channels are accessed through a table so they appear linear here
+	chan[ 0].fourMask = 0x00 | ( 1 << 0 );
+	chan[ 1].fourMask = 0x80 | ( 1 << 0 );
+	chan[ 2].fourMask = 0x00 | ( 1 << 1 );
+	chan[ 3].fourMask = 0x80 | ( 1 << 1 );
+	chan[ 4].fourMask = 0x00 | ( 1 << 2 );
+	chan[ 5].fourMask = 0x80 | ( 1 << 2 );
+
+	chan[ 9].fourMask = 0x00 | ( 1 << 3 );
+	chan[10].fourMask = 0x80 | ( 1 << 3 );
+	chan[11].fourMask = 0x00 | ( 1 << 4 );
+	chan[12].fourMask = 0x80 | ( 1 << 4 );
+	chan[13].fourMask = 0x00 | ( 1 << 5 );
+	chan[14].fourMask = 0x80 | ( 1 << 5 );
+
+	//mark the percussion channels
+	chan[ 6].fourMask = 0x40;
+	chan[ 7].fourMask = 0x40;
+	chan[ 8].fourMask = 0x40;
+
+	//Clear Everything in opl3 mode
+	WriteReg( 0x105, 0x1 );
+	for ( int i = 0; i < 512; i++ ) {
+		if ( i == 0x105 )
+			continue;
+		WriteReg( i, 0xff );
+		WriteReg( i, 0x0 );
+	}
+	WriteReg( 0x105, 0x0 );
+	//Clear everything in opl2 mode
+	for ( int i = 0; i < 255; i++ ) {
+		WriteReg( i, 0xff );
+		WriteReg( i, 0x0 );
+	}
+}
+
+static bool doneTables = false;
+void InitTables( void ) {
+	if ( doneTables )
+		return;
+	doneTables = true;
+#if ( DBOPL_WAVE == WAVE_HANDLER ) || ( DBOPL_WAVE == WAVE_TABLELOG )
+	//Exponential volume table, same as the real adlib
+	for ( int i = 0; i < 256; i++ ) {
+		//Save them in reverse
+		ExpTable[i] = (int)( 0.5 + ( pow(2.0, ( 255 - i) * ( 1.0 /256 ) )-1) * 1024 );
+		ExpTable[i] += 1024; //or remove the -1 oh well :)
+		//Preshift to the left once so the final volume can shift to the right
+		ExpTable[i] *= 2;
+	}
+#endif
+#if ( DBOPL_WAVE == WAVE_HANDLER )
+	//Add 0.5 for the trunc rounding of the integer cast
+	//Do a PI sinetable instead of the original 0.5 PI
+	for ( int i = 0; i < 512; i++ ) {
+		SinTable[i] = (Bit16s)( 0.5 - log10( sin( (i + 0.5) * (PI / 512.0) ) ) / log10(2.0)*256 );
+	}
+#endif
+#if ( DBOPL_WAVE == WAVE_TABLEMUL )
+	//Multiplication based tables
+	for ( int 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 ));
+		MulTable[i] = (Bit16u)(val);
+	}
+
+	//Sine Wave Base
+	for ( int 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++ ) {
+		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++ ) {
+		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++ ) {
+		WaveTable[ 0x700 + i ] = i * 8;
+		WaveTable[ 0x6ff - i ] = ((Bit16s)0x8000) | i * 8;
+	} 
+#endif
+
+	//	|    |//\\|____|WAV7|//__|/\  |____|/\/\|
+	//	|\\//|    |    |WAV7|    |  \/|    |    |
+	//	|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++ ) {
+		//Fill silence gaps
+		WaveTable[ 0x400 + i ] = WaveTable[0];
+		WaveTable[ 0x500 + i ] = WaveTable[0];
+		WaveTable[ 0x900 + i ] = WaveTable[0];
+		WaveTable[ 0xc00 + i ] = WaveTable[0];
+		WaveTable[ 0xd00 + i ] = WaveTable[0];
+		//Replicate sines in other pieces
+		WaveTable[ 0x800 + i ] = WaveTable[ 0x200 + i ];
+		//double speed sines
+		WaveTable[ 0xa00 + i ] = WaveTable[ 0x200 + i * 2 ];
+		WaveTable[ 0xb00 + i ] = WaveTable[ 0x000 + i * 2 ];
+		WaveTable[ 0xe00 + i ] = WaveTable[ 0x200 + i * 2 ];
+		WaveTable[ 0xf00 + i ] = WaveTable[ 0x200 + i * 2 ];
+	} 
+#endif
+
+	//Create the ksl table
+	for ( int oct = 0; oct < 8; oct++ ) {
+		int base = oct * 8;
+		for ( int 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;
+		}
+	}
+	//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;
+	}
+	//Create a table with offsets of the channels from the start of the chip
+	DBOPL::Chip* chip = 0;
+	for ( Bitu i = 0; i < 32; i++ ) {
+		Bitu index = i & 0xf;
+		if ( index >= 9 ) {
+			ChanOffsetTable[i] = 0;
+			continue;
+		}
+		//Make sure the four op channels follow eachother
+		if ( index < 6 ) {
+			index = (index % 3) * 2 + ( index / 3 );
+		}
+		//Add back the bits for highest ones
+		if ( i >= 16 )
+			index += 9;
+		Bitu blah = reinterpret_cast<long>( &(chip->chan[ index ]) );
+		ChanOffsetTable[i] = blah;
+	}
+	//Same for operators
+	for ( Bitu i = 0; i < 64; i++ ) {
+		if ( i % 8 >= 6 || ( (i / 8) % 4 == 3 ) ) {
+			OpOffsetTable[i] = 0;
+			continue;
+		}
+		Bitu chNum = (i / 8) * 3 + (i % 8) % 3;
+		//Make sure we use 16 and up for the 2nd range to match the chanoffset gap
+		if ( chNum >= 12 )
+			chNum += 16 - 12;
+		Bitu opNum = ( i % 8 ) / 3;
+		DBOPL::Channel* chan = 0;
+		Bitu blah = reinterpret_cast<long>( &(chan->op[opNum]) );
+		OpOffsetTable[i] = 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++ ) {
+			if ( ChanOffsetTable[c] == find ) {
+				find = 0;
+				break;
+			}
+		}
+		if ( find ) {
+			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++ ) {
+			if ( OpOffsetTable[c] == find ) {
+				find = 0;
+				break;
+			}
+		}
+		if ( find ) {
+			find = find;
+		}
+	}
+#endif
+}
+
+}		//Namespace DBOPL
+} // End of namespace DOSBox
+} // End of namespace OPL
+
+#endif // !DISABLE_DOSBOX_OPL


Property changes on: scummvm/trunk/sound/softsynth/opl/dbopl.cpp
___________________________________________________________________
Added: svn:mime-type
   + text/plain
Added: svn:keywords
   + Date Rev Author URL Id
Added: svn:eol-style
   + native

Added: scummvm/trunk/sound/softsynth/opl/dbopl.h
===================================================================
--- scummvm/trunk/sound/softsynth/opl/dbopl.h	                        (rev 0)
+++ scummvm/trunk/sound/softsynth/opl/dbopl.h	2010-03-08 00:33:36 UTC (rev 48179)
@@ -0,0 +1,281 @@
+/*
+ *  Copyright (C) 2002-2010  The DOSBox Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef SOUND_SOFTSYNTH_OPL_DBOPL_H
+#define SOUND_SOFTSYNTH_OPL_DBOPL_H
+
+#include "common/scummsys.h"
+
+#ifndef DISABLE_DOSBOX_OPL
+
+namespace OPL {
+namespace DOSBox {
+
+//Use 8 handlers based on a small logatirmic wavetabe and an exponential table for volume
+#define WAVE_HANDLER	10
+//Use a logarithmic wavetable with an exponential table for volume
+#define WAVE_TABLELOG	11
+//Use a linear wavetable with a multiply table for volume
+#define WAVE_TABLEMUL	12
+
+//Select the type of wave generator routine
+#define DBOPL_WAVE WAVE_TABLEMUL
+
+namespace DBOPL {
+
+// Type aliases for the DBOPL code
+typedef int Bits;
+typedef uint Bitu;
+
+typedef int8 Bit8s;
+typedef uint8 Bit8u;
+
+typedef int16 Bit16s;
+typedef uint16 Bit16u;
+
+typedef int32 Bit32s;
+typedef uint32 Bit32u;
+
+#define DB_FASTCALL
+#define GCC_UNLIKELY(x) (x)
+#define INLINE inline
+// -------------------------------
+
+struct Chip;
+struct Operator;
+struct Channel;
+
+#if (DBOPL_WAVE == WAVE_HANDLER)
+typedef Bits ( DB_FASTCALL *WaveHandler) ( Bitu i, Bitu volume );
+#endif
+
+typedef Bits ( DBOPL::Operator::*VolumeHandler) ( );
+typedef Channel* ( DBOPL::Channel::*SynthHandler) ( Chip* chip, Bit32u samples, Bit32s* output );
+
+//Different synth modes that can generate blocks of data
+typedef enum {
+	sm2AM,
+	sm2FM,
+	sm3AM,
+	sm3FM,
+	sm4Start,
+	sm3FMFM,
+	sm3AMFM,
+	sm3FMAM,
+	sm3AMAM,
+	sm6Start,
+	sm2Percussion,
+	sm3Percussion
+} SynthMode;
+
+//Shifts for the values contained in chandata variable
+enum {
+	SHIFT_KSLBASE = 16,
+	SHIFT_KEYCODE = 24
+};
+
+struct Operator {
+public:
+	//Masks for operator 20 values
+	enum {
+		MASK_KSR = 0x10,
+		MASK_SUSTAIN = 0x20,
+		MASK_VIBRATO = 0x40,
+		MASK_TREMOLO = 0x80
+	};
+
+	typedef enum {
+		OFF,
+		RELEASE,
+		SUSTAIN,
+		DECAY,
+		ATTACK
+	} State;
+
+	VolumeHandler volHandler;
+
+#if (DBOPL_WAVE == WAVE_HANDLER)
+	WaveHandler waveHandler;	//Routine that generate a wave 
+#else
+	Bit16s* waveBase;
+	Bit32u waveMask;
+	Bit32u waveStart;
+#endif
+	Bit32u waveIndex;			//WAVE_BITS shifted counter of the frequency index
+	Bit32u waveAdd;				//The base frequency without vibrato
+	Bit32u waveCurrent;			//waveAdd + vibratao
+
+	Bit32u chanData;			//Frequency/octave and derived data coming from whatever channel controls this
+	Bit32u freqMul;				//Scale channel frequency with this, TODO maybe remove?
+	Bit32u vibrato;				//Scaled up vibrato strength
+	Bit32s sustainLevel;		//When stopping at sustain level stop here
+	Bit32s totalLevel;			//totalLevel is added to every generated volume
+	Bit32u currentLevel;		//totalLevel + tremolo
+	Bit32s volume;				//The currently active volume
+	
+	Bit32u attackAdd;			//Timers for the different states of the envelope
+	Bit32u decayAdd;
+	Bit32u releaseAdd;
+	Bit32u rateIndex;			//Current position of the evenlope
+
+	Bit8u rateZero;				//Bits for the different states of the envelope having no changes
+	Bit8u keyOn;				//Bitmask of different values that can generate keyon
+	//Registers, also used to check for changes
+	Bit8u reg20, reg40, reg60, reg80, regE0;
+	//Active part of the envelope we're in
+	Bit8u state;
+	//0xff when tremolo is enabled
+	Bit8u tremoloMask;
+	//Strength of the vibrato
+	Bit8u vibStrength;
+	//Keep track of the calculated KSR so we can check for changes
+	Bit8u ksr;
+private:
+	void SetState( Bit8u s );
+	void UpdateAttack( const Chip* chip );
+	void UpdateRelease( const Chip* chip );
+	void UpdateDecay( const Chip* chip );
+public:
+	void UpdateAttenuation();
+	void UpdateRates( const Chip* chip );
+	void UpdateFrequency( );
+
+	void Write20( const Chip* chip, Bit8u val );
+	void Write40( const Chip* chip, Bit8u val );
+	void Write60( const Chip* chip, Bit8u val );
+	void Write80( const Chip* chip, Bit8u val );
+	void WriteE0( const Chip* chip, Bit8u val );
+
+	bool Silent() const;
+	void Prepare( const Chip* chip );
+
+	void KeyOn( Bit8u mask);
+	void KeyOff( Bit8u mask);
+
+	template< State state>
+	Bits TemplateVolume( );
+
+	Bit32s RateForward( Bit32u add );
+	Bitu ForwardWave();
+	Bitu ForwardVolume();
+
+	Bits GetSample( Bits modulation );
+	Bits GetWave( Bitu index, Bitu vol );
+public:
+	Operator();
+};
+
+struct Channel {
+	Operator op[2];
+	inline Operator* Op( Bitu index ) {
+		return &( ( this + (index >> 1) )->op[ index & 1 ]);
+	}
+	SynthHandler synthHandler;
+	Bit32u chanData;		//Frequency/octave and derived values
+	Bit32s old[2];			//Old data for feedback
+
+	Bit8u feedback;			//Feedback shift
+	Bit8u regB0;			//Register values to check for changes
+	Bit8u regC0;
+	//This should correspond with reg104, bit 6 indicates a Percussion channel, bit 7 indicates a silent channel
+	Bit8u fourMask;
+	Bit8s maskLeft;		//Sign extended values for both channel's panning
+	Bit8s maskRight;
+
+	//Forward the channel data to the operators of the channel
+	void SetChanData( const Chip* chip, Bit32u data );
+	//Change in the chandata, check for new values and if we have to forward to operators
+	void UpdateFrequency( const Chip* chip, Bit8u fourOp );
+	void WriteA0( const Chip* chip, Bit8u val );
+	void WriteB0( const Chip* chip, Bit8u val );
+	void WriteC0( const Chip* chip, Bit8u val );
+	void ResetC0( const Chip* chip );
+
+	//call this for the first channel
+	template< bool opl3Mode >
+	void GeneratePercussion( Chip* chip, Bit32s* output );
+
+	//Generate blocks of data in specific modes
+	template<SynthMode mode>
+	Channel* BlockTemplate( Chip* chip, Bit32u samples, Bit32s* output );
+	Channel();
+};
+
+struct Chip {
+	//This is used as the base counter for vibrato and tremolo
+	Bit32u lfoCounter;
+	Bit32u lfoAdd;
+	
+
+	Bit32u noiseCounter;
+	Bit32u noiseAdd;
+	Bit32u noiseValue;
+
+	//Frequency scales for the different multiplications
+	Bit32u freqMul[16];
+	//Rates for decay and release for rate of this chip
+	Bit32u linearRates[76];
+	//Best match attack rates for the rate of this chip
+	Bit32u attackRates[76];
+
+	//18 channels with 2 operators each
+	Channel chan[18];
+
+	Bit8u reg104;
+	Bit8u reg08;
+	Bit8u reg04;
+	Bit8u regBD;
+	Bit8u vibratoIndex;
+	Bit8u tremoloIndex;
+	Bit8s vibratoSign;
+	Bit8u vibratoShift;
+	Bit8u tremoloValue;
+	Bit8u vibratoStrength;
+	Bit8u tremoloStrength;
+	//Mask for allowed wave forms
+	Bit8u waveFormMask;
+	//0 or -1 when enabled
+	Bit8s opl3Active;
+
+	//Return the maximum amount of samples before and LFO change
+	Bit32u ForwardLFO( Bit32u samples );
+	Bit32u ForwardNoise();
+
+	void WriteBD( Bit8u val );
+	void WriteReg(Bit32u reg, Bit8u val );
+
+	Bit32u WriteAddr( Bit32u port, Bit8u val );
+
+	void GenerateBlock2( Bitu samples, Bit32s* output );
+	void GenerateBlock3( Bitu samples, Bit32s* output );
+
+	void Generate( Bit32u samples );
+	void Setup( Bit32u r );
+
+	Chip();
+};
+
+void InitTables();
+
+}		//Namespace
+} // End of namespace DOSBox
+} // End of namespace OPL
+
+#endif // !DISABLE_DOSBOX_OPL
+
+#endif


Property changes on: scummvm/trunk/sound/softsynth/opl/dbopl.h
___________________________________________________________________
Added: svn:mime-type
   + text/plain
Added: svn:keywords
   + Date Rev Author URL Id
Added: svn:eol-style
   + native

Modified: scummvm/trunk/sound/softsynth/opl/dosbox.cpp
===================================================================
--- scummvm/trunk/sound/softsynth/opl/dosbox.cpp	2010-03-07 23:07:32 UTC (rev 48178)
+++ scummvm/trunk/sound/softsynth/opl/dosbox.cpp	2010-03-08 00:33:36 UTC (rev 48179)
@@ -144,53 +144,7 @@
 	return ret;
 }
 
-namespace OPL2 {
-#include "opl_impl.h"
-
-struct Handler : public DOSBox::Handler {
-	void writeReg(uint32 reg, uint8 val) {
-		adlib_write(reg, val);
-	}
-
-	uint32 writeAddr(uint32 port, uint8 val) {
-		return val;
-	}
-
-	void generate(int16 *chan, uint samples) {
-		adlib_getsample(chan, samples);
-	}
-
-	void init(uint rate) {
-		adlib_init(rate);
-	}
-};
-} // End of namespace OPL2
-
-namespace OPL3 {
-#define OPLTYPE_IS_OPL3
-#include "opl_impl.h"
-
-struct Handler : public DOSBox::Handler {
-	void writeReg(uint32 reg, uint8 val) {
-		adlib_write(reg, val);
-	}
-
-	uint32 writeAddr(uint32 port, uint8 val) {
-		adlib_write_index(port, val);
-		return opl_index;
-	}
-
-	void generate(int16 *chan, uint samples) {
-		adlib_getsample(chan, samples);
-	}
-
-	void init(uint rate) {
-		adlib_init(rate);
-	}
-};
-} // End of namespace OPL3
-
-OPL::OPL(Config::OplType type) : _type(type), _rate(0), _handler(0) {
+OPL::OPL(Config::OplType type) : _type(type), _rate(0), _emulator(0) {
 }
 
 OPL::~OPL() {
@@ -198,8 +152,8 @@
 }
 
 void OPL::free() {
-	delete _handler;
-	_handler = 0;
+	delete _emulator;
+	_emulator = 0;
 }
 
 bool OPL::init(int rate) {
@@ -208,25 +162,16 @@
 	memset(&_reg, 0, sizeof(_reg));
 	memset(_chip, 0, sizeof(_chip));
 
-	switch (_type) {
-	case Config::kOpl2:
-		_handler = new OPL2::Handler();
-		break;
-
-	case Config::kDualOpl2:
-	case Config::kOpl3:
-		_handler = new OPL3::Handler();
-		break;
-
-	default:
+	_emulator = new DBOPL::Chip();
+	if (!_emulator)
 		return false;
-	}
 
-	_handler->init(rate);
+	DBOPL::InitTables();
+	_emulator->Setup(rate);
 
 	if (_type == Config::kDualOpl2) {
 		// Setup opl3 mode in the hander
-		_handler->writeReg(0x105, 1);
+		_emulator->WriteReg(0x105, 1);
 	}
 
 	_rate = rate;
@@ -243,7 +188,7 @@
 		case Config::kOpl2:
 		case Config::kOpl3:
 			if (!_chip[0].write(_reg.normal, val))
-				_handler->writeReg(_reg.normal, val);
+				_emulator->WriteReg(_reg.normal, val);
 			break;
 		case Config::kDualOpl2:
 			// Not a 0x??8 port, then write to a specific port
@@ -262,10 +207,10 @@
 		// Make sure to clip them in the right range
 		switch (_type) {
 		case Config::kOpl2:
-			_reg.normal = _handler->writeAddr(port, val) & 0xff;
+			_reg.normal = _emulator->WriteAddr(port, val) & 0xff;
 			break;
 		case Config::kOpl3:
-			_reg.normal = _handler->writeAddr(port, val) & 0x1ff;
+			_reg.normal = _emulator->WriteAddr(port, val) & 0x1ff;
 			break;
 		case Config::kDualOpl2:
 			// Not a 0x?88 port, when write to a specific side
@@ -344,7 +289,7 @@
 	}
 
 	uint32 fullReg = reg + (index ? 0x100 : 0);
-	_handler->writeReg(fullReg, val);
+	_emulator->WriteReg(fullReg, val);
 }
 
 void OPL::readBuffer(int16 *buffer, int length) {
@@ -353,7 +298,34 @@
 	if (_type != Config::kOpl2)
 		length >>= 1;
 
-	_handler->generate(buffer, length);
+	const uint bufferLength = 512;
+	int32 tempBuffer[bufferLength * 2];
+
+	if (_emulator->opl3Active) {
+		while (length > 0) {
+			const uint readSamples = MIN<uint>(length, bufferLength);
+
+			_emulator->GenerateBlock3(readSamples, tempBuffer);
+
+			for (uint i = 0; i < (readSamples << 1); ++i)
+				buffer[i] = tempBuffer[i];
+
+			buffer += (readSamples << 1);
+			length -= readSamples;
+		}
+	} else {
+		while (length > 0) {
+			const uint readSamples = MIN<uint>(length, bufferLength << 1);
+
+			_emulator->GenerateBlock2(readSamples, tempBuffer);
+
+			for (uint i = 0; i < readSamples; ++i)
+				buffer[i] = tempBuffer[i];
+
+			buffer += readSamples;
+			length -= readSamples;
+		}
+	}
 }
 
 } // End of namespace DOSBox

Modified: scummvm/trunk/sound/softsynth/opl/dosbox.h
===================================================================
--- scummvm/trunk/sound/softsynth/opl/dosbox.h	2010-03-07 23:07:32 UTC (rev 48178)
+++ scummvm/trunk/sound/softsynth/opl/dosbox.h	2010-03-08 00:33:36 UTC (rev 48179)
@@ -36,6 +36,8 @@
 
 #include "sound/fmopl.h"
 
+#include "dbopl.h"
+
 namespace OPL {
 namespace DOSBox {
 
@@ -69,26 +71,12 @@
 	uint8 read();
 };
 
-class Handler {
-public:
-	virtual ~Handler() {}
-
-	// Write an address to a chip, returns the address the chip sets
-	virtual uint32 writeAddr(uint32 port, uint8 val) = 0;
-	// Write to a specific register in the chip
-	virtual void writeReg(uint32 addr, uint8 val) = 0;
-	// Generate a certain amount of samples
-	virtual void generate(int16 *chan, uint samples) = 0;
-	// Initialize at a specific sample rate and mode
-	virtual void init(uint rate) = 0;
-};
-
 class OPL : public ::OPL::OPL {
 private:
 	Config::OplType _type;
 	uint _rate;
 
-	Handler *_handler;
+	DBOPL::Chip *_emulator;
 	Chip _chip[2];
 	union {
 		uint16 normal;

Deleted: scummvm/trunk/sound/softsynth/opl/opl_impl.h
===================================================================
--- scummvm/trunk/sound/softsynth/opl/opl_impl.h	2010-03-07 23:07:32 UTC (rev 48178)
+++ scummvm/trunk/sound/softsynth/opl/opl_impl.h	2010-03-08 00:33:36 UTC (rev 48179)
@@ -1,1463 +0,0 @@
-/*
- *  Copyright (C) 2002-2009  The DOSBox Team
- *  OPL2/OPL3 emulation library
- *
- *  This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Lesser General Public
- *  License as published by the Free Software Foundation; either
- *  version 2.1 of the License, or (at your option) any later version.
- *
- *  This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Lesser General Public License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public
- *  License along with this library; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-
-/*
- * Originally based on ADLIBEMU.C, an AdLib/OPL2 emulation library by Ken Silverman
- * Copyright (C) 1998-2001 Ken Silverman
- * Ken Silverman's official web site: "http://www.advsys.net/ken"
- */
-
-#include "opl_inc.h"
-
-
-static fltype recipsamp;	// inverse of sampling rate
-static Bit16s wavtable[WAVEPREC*3];	// wave form table
-
-// vibrato/tremolo tables
-static Bit32s vib_table[VIBTAB_SIZE];
-static Bit32s trem_table[TREMTAB_SIZE*2];
-
-static Bit32s vibval_const[BLOCKBUF_SIZE];
-static Bit32s tremval_const[BLOCKBUF_SIZE];
-
-// vibrato value tables (used per-operator)
-static Bit32s vibval_var1[BLOCKBUF_SIZE];
-static Bit32s vibval_var2[BLOCKBUF_SIZE];
-
-// vibrato/trmolo value table pointers
-static Bit32s *vibval1, *vibval2, *vibval3, *vibval4;
-static Bit32s *tremval1, *tremval2, *tremval3, *tremval4;
-
-
-// key scale level lookup table
-static const fltype kslmul[4] = {
-	0.0, 0.5, 0.25, 1.0		// -> 0, 3, 1.5, 6 dB/oct
-};
-
-// frequency multiplicator lookup table
-static const fltype frqmul_tab[16] = {
-	0.5,1,2,3,4,5,6,7,8,9,10,10,12,12,15,15
-};
-// calculated frequency multiplication values (depend on sampling rate)
-static fltype frqmul[16];
-
-// key scale levels
-static Bit8u kslev[8][16];
-
-// map a channel number to the register offset of the modulator (=register base)
-static const Bit8u modulatorbase[9]	= {
-	0,1,2,
-	8,9,10,
-	16,17,18
-};
-
-// map a register base to a modulator operator number or operator number
-#if defined(OPLTYPE_IS_OPL3)
-static const Bit8u regbase2modop[44] = {
-	0,1,2,0,1,2,0,0,3,4,5,3,4,5,0,0,6,7,8,6,7,8,					// first set
-	18,19,20,18,19,20,0,0,21,22,23,21,22,23,0,0,24,25,26,24,25,26	// second set
-};
-static const Bit8u regbase2op[44] = {
-	0,1,2,9,10,11,0,0,3,4,5,12,13,14,0,0,6,7,8,15,16,17,			// first set
-	18,19,20,27,28,29,0,0,21,22,23,30,31,32,0,0,24,25,26,33,34,35	// second set
-};
-#else
-static const Bit8u regbase2modop[22] = {
-	0,1,2,0,1,2,0,0,3,4,5,3,4,5,0,0,6,7,8,6,7,8
-};
-static const Bit8u regbase2op[22] = {
-	0,1,2,9,10,11,0,0,3,4,5,12,13,14,0,0,6,7,8,15,16,17
-};
-#endif
-
-
-// start of the waveform
-static Bit32u waveform[8] = {
-	WAVEPREC,
-	WAVEPREC>>1,
-	WAVEPREC,
-	(WAVEPREC*3)>>2,
-	0,
-	0,
-	(WAVEPREC*5)>>2,
-	WAVEPREC<<1
-};
-
-// length of the waveform as mask
-static Bit32u wavemask[8] = {
-	WAVEPREC-1,
-	WAVEPREC-1,
-	(WAVEPREC>>1)-1,
-	(WAVEPREC>>1)-1,
-	WAVEPREC-1,
-	((WAVEPREC*3)>>2)-1,
-	WAVEPREC>>1,
-	WAVEPREC-1
-};
-
-// where the first entry resides
-static Bit32u wavestart[8] = {
-	0,
-	WAVEPREC>>1,
-	0,
-	WAVEPREC>>2,
-	0,
-	0,
-	0,
-	WAVEPREC>>3
-};
-
-// envelope generator function constants
-static fltype attackconst[4] = {
-	(fltype)(1/2.82624),
-	(fltype)(1/2.25280),
-	(fltype)(1/1.88416),
-	(fltype)(1/1.59744)
-};
-static fltype decrelconst[4] = {
-	(fltype)(1/39.28064),
-	(fltype)(1/31.41608),
-	(fltype)(1/26.17344),
-	(fltype)(1/22.44608)
-};
-
-
-void operator_advance(op_type* op_pt, Bit32s vib) {
-	op_pt->wfpos = op_pt->tcount;						// waveform position
-
-	// advance waveform time
-	op_pt->tcount += op_pt->tinc;
-	op_pt->tcount += (Bit32s)(op_pt->tinc)*vib/FIXEDPT;
-
-	op_pt->generator_pos += generator_add;
-}
-
-void operator_advance_drums(op_type* op_pt1, Bit32s vib1, op_type* op_pt2, Bit32s vib2, op_type* op_pt3, Bit32s vib3) {
-	Bit32u c1 = op_pt1->tcount/FIXEDPT;
-	Bit32u c3 = op_pt3->tcount/FIXEDPT;
-	Bit32u phasebit = (((c1 & 0x88) ^ ((c1<<5) & 0x80)) | ((c3 ^ (c3<<2)) & 0x20)) ? 0x02 : 0x00;
-
-	Bit32u noisebit = rand()&1;
-
-	Bit32u snare_phase_bit = (((Bitu)((op_pt1->tcount/FIXEDPT) / 0x100))&1);
-
-	//Hihat
-	Bit32u inttm = (phasebit<<8) | (0x34<<(phasebit ^ (noisebit<<1)));
-	op_pt1->wfpos = inttm*FIXEDPT;				// waveform position
-	// advance waveform time
-	op_pt1->tcount += op_pt1->tinc;
-	op_pt1->tcount += (Bit32s)(op_pt1->tinc)*vib1/FIXEDPT;
-	op_pt1->generator_pos += generator_add;
-
-	//Snare
-	inttm = ((1+snare_phase_bit) ^ noisebit)<<8;
-	op_pt2->wfpos = inttm*FIXEDPT;				// waveform position
-	// advance waveform time
-	op_pt2->tcount += op_pt2->tinc;
-	op_pt2->tcount += (Bit32s)(op_pt2->tinc)*vib2/FIXEDPT;
-	op_pt2->generator_pos += generator_add;
-
-	//Cymbal
-	inttm = (1+phasebit)<<8;
-	op_pt3->wfpos = inttm*FIXEDPT;				// waveform position
-	// advance waveform time
-	op_pt3->tcount += op_pt3->tinc;
-	op_pt3->tcount += (Bit32s)(op_pt3->tinc)*vib3/FIXEDPT;
-	op_pt3->generator_pos += generator_add;
-}
-
-
-// output level is sustained, mode changes only when operator is turned off (->release)
-// or when the keep-sustained bit is turned off (->sustain_nokeep)
-void operator_output(op_type* op_pt, Bit32s modulator, Bit32s trem) {
-	if (op_pt->op_state != OF_TYPE_OFF) {
-		op_pt->lastcval = op_pt->cval;
-		Bit32u i = (Bit32u)((op_pt->wfpos+modulator)/FIXEDPT);
-
-		// wform: -16384 to 16383 (0x4000)
-		// trem :  32768 to 65535 (0x10000)
-		// step_amp: 0.0 to 1.0
-		// vol  : 1/2^14 to 1/2^29 (/0x4000; /1../0x8000)
-
-		op_pt->cval = (Bit32s)(op_pt->step_amp*op_pt->vol*op_pt->cur_wform[i&op_pt->cur_wmask]*trem/16.0);
-	}
-}
-
-
-// no action, operator is off
-void operator_off(op_type* /*op_pt*/) {
-}
-
-// output level is sustained, mode changes only when operator is turned off (->release)
-// or when the keep-sustained bit is turned off (->sustain_nokeep)
-void operator_sustain(op_type* op_pt) {
-	Bit32u num_steps_add = op_pt->generator_pos/FIXEDPT;	// number of (standardized) samples
-	for (Bit32u ct=0; ct<num_steps_add; ct++) {
-		op_pt->cur_env_step++;
-	}
-	op_pt->generator_pos -= num_steps_add*FIXEDPT;
-}
-
-// operator in release mode, if output level reaches zero the operator is turned off
-void operator_release(op_type* op_pt) {
-	// ??? boundary?
-	if (op_pt->amp > 0.00000001) {
-		// release phase
-		op_pt->amp *= op_pt->releasemul;
-	}
-
-	Bit32u num_steps_add = op_pt->generator_pos/FIXEDPT;	// number of (standardized) samples
-	for (Bit32u ct=0; ct<num_steps_add; ct++) {
-		op_pt->cur_env_step++;						// sample counter
-		if ((op_pt->cur_env_step & op_pt->env_step_r)==0) {
-			if (op_pt->amp <= 0.00000001) {
-				// release phase finished, turn off this operator
-				op_pt->amp = 0.0;
-				if (op_pt->op_state == OF_TYPE_REL) {
-					op_pt->op_state = OF_TYPE_OFF;
-				}
-			}
-			op_pt->step_amp = op_pt->amp;
-		}
-	}
-	op_pt->generator_pos -= num_steps_add*FIXEDPT;
-}
-
-// operator in decay mode, if sustain level is reached the output level is either
-// kept (sustain level keep enabled) or the operator is switched into release mode
-void operator_decay(op_type* op_pt) {
-	if (op_pt->amp > op_pt->sustain_level) {
-		// decay phase
-		op_pt->amp *= op_pt->decaymul;
-	}
-
-	Bit32u num_steps_add = op_pt->generator_pos/FIXEDPT;	// number of (standardized) samples
-	for (Bit32u ct=0; ct<num_steps_add; ct++) {
-		op_pt->cur_env_step++;
-		if ((op_pt->cur_env_step & op_pt->env_step_d)==0) {
-			if (op_pt->amp <= op_pt->sustain_level) {
-				// decay phase finished, sustain level reached
-				if (op_pt->sus_keep) {
-					// keep sustain level (until turned off)
-					op_pt->op_state = OF_TYPE_SUS;
-					op_pt->amp = op_pt->sustain_level;
-				} else {
-					// next: release phase
-					op_pt->op_state = OF_TYPE_SUS_NOKEEP;
-				}
-			}
-			op_pt->step_amp = op_pt->amp;
-		}
-	}
-	op_pt->generator_pos -= num_steps_add*FIXEDPT;
-}
-
-// operator in attack mode, if full output level is reached,
-// the operator is switched into decay mode
-void operator_attack(op_type* op_pt) {
-	op_pt->amp = ((op_pt->a3*op_pt->amp + op_pt->a2)*op_pt->amp + op_pt->a1)*op_pt->amp + op_pt->a0;
-
-	Bit32u num_steps_add = op_pt->generator_pos/FIXEDPT;		// number of (standardized) samples
-	for (Bit32u ct=0; ct<num_steps_add; ct++) {
-		op_pt->cur_env_step++;	// next sample
-		if ((op_pt->cur_env_step & op_pt->env_step_a)==0) {		// check if next step already reached
-			if (op_pt->amp > 1.0) {
-				// attack phase finished, next: decay
-				op_pt->op_state = OF_TYPE_DEC;
-				op_pt->amp = 1.0;
-				op_pt->step_amp = 1.0;
-			}
-			op_pt->step_skip_pos_a <<= 1;
-			if (op_pt->step_skip_pos_a==0) op_pt->step_skip_pos_a = 1;
-			if (op_pt->step_skip_pos_a & op_pt->env_step_skip_a) {	// check if required to skip next step
-				op_pt->step_amp = op_pt->amp;
-			}
-		}
-	}
-	op_pt->generator_pos -= num_steps_add*FIXEDPT;
-}
-
-
-typedef void (*optype_fptr)(op_type*);
-
-optype_fptr opfuncs[6] = {
-	operator_attack,
-	operator_decay,
-	operator_release,
-	operator_sustain,	// sustain phase (keeping level)
-	operator_release,	// sustain_nokeep phase (release-style)
-	operator_off
-};
-
-void change_attackrate(Bitu regbase, op_type* op_pt) {
-	Bits attackrate = adlibreg[ARC_ATTR_DECR+regbase]>>4;
-	if (attackrate) {
-		fltype f = (fltype)(pow(FL2,(fltype)attackrate+(op_pt->toff>>2)-1)*attackconst[op_pt->toff&3]*recipsamp);
-		// attack rate coefficients
-		op_pt->a0 = (fltype)(0.0377*f);
-		op_pt->a1 = (fltype)(10.73*f+1);
-		op_pt->a2 = (fltype)(-17.57*f);
-		op_pt->a3 = (fltype)(7.42*f);
-
-		Bits step_skip = attackrate*4 + op_pt->toff;
-		Bits steps = step_skip >> 2;
-		op_pt->env_step_a = (1<<(steps<=12?12-steps:0))-1;
-
-		Bits step_num = (step_skip<=48)?(4-(step_skip&3)):0;
-		static Bit8u step_skip_mask[5] = {0xff, 0xfe, 0xee, 0xba, 0xaa};
-		op_pt->env_step_skip_a = step_skip_mask[step_num];
-
-#if defined(OPLTYPE_IS_OPL3)
-		if (step_skip>=60) {
-#else
-		if (step_skip>=62) {
-#endif
-			op_pt->a0 = (fltype)(2.0);	// something that triggers an immediate transition to amp:=1.0
-			op_pt->a1 = (fltype)(0.0);
-			op_pt->a2 = (fltype)(0.0);
-			op_pt->a3 = (fltype)(0.0);
-		}
-	} else {
-		// attack disabled
-		op_pt->a0 = 0.0;
-		op_pt->a1 = 1.0;
-		op_pt->a2 = 0.0;
-		op_pt->a3 = 0.0;
-		op_pt->env_step_a = 0;
-		op_pt->env_step_skip_a = 0;
-	}
-}
-
-void change_decayrate(Bitu regbase, op_type* op_pt) {
-	Bits decayrate = adlibreg[ARC_ATTR_DECR+regbase]&15;
-	// decaymul should be 1.0 when decayrate==0
-	if (decayrate) {
-		fltype f = (fltype)(-7.4493*decrelconst[op_pt->toff&3]*recipsamp);
-		op_pt->decaymul = (fltype)(pow(FL2,f*pow(FL2,(fltype)(decayrate+(op_pt->toff>>2)))));
-		Bits steps = (decayrate*4 + op_pt->toff) >> 2;
-		op_pt->env_step_d = (1<<(steps<=12?12-steps:0))-1;
-	} else {
-		op_pt->decaymul = 1.0;
-		op_pt->env_step_d = 0;
-	}
-}
-
-void change_releaserate(Bitu regbase, op_type* op_pt) {
-	Bits releaserate = adlibreg[ARC_SUSL_RELR+regbase]&15;
-	// releasemul should be 1.0 when releaserate==0
-	if (releaserate) {
-		fltype f = (fltype)(-7.4493*decrelconst[op_pt->toff&3]*recipsamp);
-		op_pt->releasemul = (fltype)(pow(FL2,f*pow(FL2,(fltype)(releaserate+(op_pt->toff>>2)))));
-		Bits steps = (releaserate*4 + op_pt->toff) >> 2;
-		op_pt->env_step_r = (1<<(steps<=12?12-steps:0))-1;
-	} else {
-		op_pt->releasemul = 1.0;
-		op_pt->env_step_r = 0;
-	}
-}
-
-void change_sustainlevel(Bitu regbase, op_type* op_pt) {
-	Bits sustainlevel = adlibreg[ARC_SUSL_RELR+regbase]>>4;
-	// sustainlevel should be 0.0 when sustainlevel==15 (max)
-	if (sustainlevel<15) {
-		op_pt->sustain_level = (fltype)(pow(FL2,(fltype)sustainlevel * (-FL05)));
-	} else {
-		op_pt->sustain_level = 0.0;
-	}
-}
-
-void change_waveform(Bitu regbase, op_type* op_pt) {
-#if defined(OPLTYPE_IS_OPL3)
-	if (regbase>=ARC_SECONDSET) regbase -= (ARC_SECONDSET-22);	// second set starts at 22
-#endif
-	// waveform selection
-	op_pt->cur_wmask = wavemask[wave_sel[regbase]];
-	op_pt->cur_wform = &wavtable[waveform[wave_sel[regbase]]];
-	// (might need to be adapted to waveform type here...)
-}
-
-void change_keepsustain(Bitu regbase, op_type* op_pt) {
-	op_pt->sus_keep = (adlibreg[ARC_TVS_KSR_MUL+regbase]&0x20)>0;
-	if (op_pt->op_state==OF_TYPE_SUS) {
-		if (!op_pt->sus_keep) op_pt->op_state = OF_TYPE_SUS_NOKEEP;
-	} else if (op_pt->op_state==OF_TYPE_SUS_NOKEEP) {
-		if (op_pt->sus_keep) op_pt->op_state = OF_TYPE_SUS;
-	}
-}
-
-// enable/disable vibrato/tremolo LFO effects
-void change_vibrato(Bitu regbase, op_type* op_pt) {
-	op_pt->vibrato = (adlibreg[ARC_TVS_KSR_MUL+regbase]&0x40)!=0;
-	op_pt->tremolo = (adlibreg[ARC_TVS_KSR_MUL+regbase]&0x80)!=0;
-}
-
-// change amount of self-feedback
-void change_feedback(Bitu chanbase, op_type* op_pt) {
-	Bits feedback = adlibreg[ARC_FEEDBACK+chanbase]&14;
-	if (feedback) op_pt->mfbi = (Bit32s)(pow(FL2,(fltype)((feedback>>1)+8)));
-	else op_pt->mfbi = 0;
-}
-
-void change_frequency(Bitu chanbase, Bitu regbase, op_type* op_pt) {
-	// frequency
-	Bit32u frn = ((((Bit32u)adlibreg[ARC_KON_BNUM+chanbase])&3)<<8) + (Bit32u)adlibreg[ARC_FREQ_NUM+chanbase];
-	// block number/octave
-	Bit32u oct = ((((Bit32u)adlibreg[ARC_KON_BNUM+chanbase])>>2)&7);
-	op_pt->freq_high = (Bit32s)((frn>>7)&7);
-
-	// keysplit
-	Bit32u note_sel = (adlibreg[8]>>6)&1;
-	op_pt->toff = ((frn>>9)&(note_sel^1)) | ((frn>>8)&note_sel);
-	op_pt->toff += (oct<<1);
-
-	// envelope scaling (KSR)
-	if (!(adlibreg[ARC_TVS_KSR_MUL+regbase]&0x10)) op_pt->toff >>= 2;
-
-	// 20+a0+b0:
-	op_pt->tinc = (Bit32u)((((fltype)(frn<<oct))*frqmul[adlibreg[ARC_TVS_KSR_MUL+regbase]&15]));
-	// 40+a0+b0:
-	fltype vol_in = (fltype)((fltype)(adlibreg[ARC_KSL_OUTLEV+regbase]&63) +
-							kslmul[adlibreg[ARC_KSL_OUTLEV+regbase]>>6]*kslev[oct][frn>>6]);
-	op_pt->vol = (fltype)(pow(FL2,(fltype)(vol_in * -0.125 - 14)));
-
-	// operator frequency changed, care about features that depend on it
-	change_attackrate(regbase,op_pt);
-	change_decayrate(regbase,op_pt);
-	change_releaserate(regbase,op_pt);
-}
-
-void enable_operator(Bitu regbase, op_type* op_pt, Bit32u act_type) {
-	// check if this is really an off-on transition
-	if (op_pt->act_state == OP_ACT_OFF) {
-		Bits wselbase = regbase;
-		if (wselbase>=ARC_SECONDSET) wselbase -= (ARC_SECONDSET-22);	// second set starts at 22
-
-		op_pt->tcount = wavestart[wave_sel[wselbase]]*FIXEDPT;
-
-		// start with attack mode
-		op_pt->op_state = OF_TYPE_ATT;
-		op_pt->act_state |= act_type;
-	}
-}
-
-void disable_operator(op_type* op_pt, Bit32u act_type) {
-	// check if this is really an on-off transition
-	if (op_pt->act_state != OP_ACT_OFF) {
-		op_pt->act_state &= (~act_type);
-		if (op_pt->act_state == OP_ACT_OFF) {
-			if (op_pt->op_state != OF_TYPE_OFF) op_pt->op_state = OF_TYPE_REL;
-		}
-	}
-}
-
-void adlib_init(Bit32u samplerate) {
-	Bits i, j, oct;
-
-	int_samplerate = samplerate;
-
-	generator_add = (Bit32u)(INTFREQU*FIXEDPT/int_samplerate);
-
-
-	memset((void *)adlibreg,0,sizeof(adlibreg));
-	memset((void *)op,0,sizeof(op_type)*MAXOPERATORS);
-	memset((void *)wave_sel,0,sizeof(wave_sel));
-
-	for (i=0;i<MAXOPERATORS;i++) {
-		op[i].op_state = OF_TYPE_OFF;
-		op[i].act_state = OP_ACT_OFF;
-		op[i].amp = 0.0;
-		op[i].step_amp = 0.0;
-		op[i].vol = 0.0;
-		op[i].tcount = 0;
-		op[i].tinc = 0;
-		op[i].toff = 0;
-		op[i].cur_wmask = wavemask[0];
-		op[i].cur_wform = &wavtable[waveform[0]];
-		op[i].freq_high = 0;
-
-		op[i].generator_pos = 0;
-		op[i].cur_env_step = 0;
-		op[i].env_step_a = 0;
-		op[i].env_step_d = 0;
-		op[i].env_step_r = 0;
-		op[i].step_skip_pos_a = 0;
-		op[i].env_step_skip_a = 0;
-
-#if defined(OPLTYPE_IS_OPL3)
-		op[i].is_4op = false;
-		op[i].is_4op_attached = false;
-		op[i].left_pan = 1;
-		op[i].right_pan = 1;
-#endif
-	}
-
-	recipsamp = 1.0 / (fltype)int_samplerate;
-	for (i=15;i>=0;i--) {
-		frqmul[i] = (fltype)(frqmul_tab[i]*INTFREQU/(fltype)WAVEPREC*(fltype)FIXEDPT*recipsamp);
-	}
-
-	status = 0;
-	opl_index = 0;
-
-
-	// create vibrato table
-	vib_table[0] = 8;
-	vib_table[1] = 4;
-	vib_table[2] = 0;
-	vib_table[3] = -4;
-	for (i=4; i<VIBTAB_SIZE; i++) vib_table[i] = vib_table[i-4]*-1;
-
-	// vibrato at ~6.1 ?? (opl3 docs say 6.1, opl4 docs say 6.0, y8950 docs say 6.4)
-	vibtab_add = static_cast<Bit32u>(VIBTAB_SIZE*FIXEDPT_LFO/8192*INTFREQU/int_samplerate);
-	vibtab_pos = 0;
-
-	for (i=0; i<BLOCKBUF_SIZE; i++) vibval_const[i] = 0;
-
-
-	// create tremolo table
-	Bit32s trem_table_int[TREMTAB_SIZE];
-	for (i=0; i<14; i++)	trem_table_int[i] = i-13;		// upwards (13 to 26 -> -0.5/6 to 0)
-	for (i=14; i<41; i++)	trem_table_int[i] = -i+14;		// downwards (26 to 0 -> 0 to -1/6)
-	for (i=41; i<53; i++)	trem_table_int[i] = i-40-26;	// upwards (1 to 12 -> -1/6 to -0.5/6)
-
-	for (i=0; i<TREMTAB_SIZE; i++) {
-		// 0.0 .. -26/26*4.8/6 == [0.0 .. -0.8], 4/53 steps == [1 .. 0.57]
-		fltype trem_val1=(fltype)(((fltype)trem_table_int[i])*4.8/26.0/6.0);				// 4.8db
-		fltype trem_val2=(fltype)((fltype)((Bit32s)(trem_table_int[i]/4))*1.2/6.0/6.0);		// 1.2db (larger stepping)
-
-		trem_table[i] = (Bit32s)(pow(FL2,trem_val1)*FIXEDPT);
-		trem_table[TREMTAB_SIZE+i] = (Bit32s)(pow(FL2,trem_val2)*FIXEDPT);
-	}
-
-	// tremolo at 3.7hz
-	tremtab_add = (Bit32u)((fltype)TREMTAB_SIZE * TREM_FREQ * FIXEDPT_LFO / (fltype)int_samplerate);
-	tremtab_pos = 0;
-
-	for (i=0; i<BLOCKBUF_SIZE; i++) tremval_const[i] = FIXEDPT;
-
-
-	static Bitu initfirstime = 0;
-	if (!initfirstime) {
-		initfirstime = 1;
-
-		// create waveform tables
-		for (i=0;i<(WAVEPREC>>1);i++) {
-			wavtable[(i<<1)  +WAVEPREC]	= (Bit16s)(16384*sin((fltype)((i<<1)  )*PI*2/WAVEPREC));
-			wavtable[(i<<1)+1+WAVEPREC]	= (Bit16s)(16384*sin((fltype)((i<<1)+1)*PI*2/WAVEPREC));
-			wavtable[i]					= wavtable[(i<<1)  +WAVEPREC];
-			// alternative: (zero-less)
-/*			wavtable[(i<<1)  +WAVEPREC]	= (Bit16s)(16384*sin((fltype)((i<<2)+1)*PI/WAVEPREC));
-			wavtable[(i<<1)+1+WAVEPREC]	= (Bit16s)(16384*sin((fltype)((i<<2)+3)*PI/WAVEPREC));
-			wavtable[i]					= wavtable[(i<<1)-1+WAVEPREC]; */
-		}
-		for (i=0;i<(WAVEPREC>>3);i++) {
-			wavtable[i+(WAVEPREC<<1)]		= wavtable[i+(WAVEPREC>>3)]-16384;
-			wavtable[i+((WAVEPREC*17)>>3)]	= wavtable[i+(WAVEPREC>>2)]+16384;
-		}
-
-		// key scale level table verified ([table in book]*8/3)
-		kslev[7][0] = 0;	kslev[7][1] = 24;	kslev[7][2] = 32;	kslev[7][3] = 37;
-		kslev[7][4] = 40;	kslev[7][5] = 43;	kslev[7][6] = 45;	kslev[7][7] = 47;
-		kslev[7][8] = 48;
-		for (i=9;i<16;i++) kslev[7][i] = (Bit8u)(i+41);
-		for (j=6;j>=0;j--) {
-			for (i=0;i<16;i++) {
-				oct = (Bits)kslev[j+1][i]-8;
-				if (oct < 0) oct = 0;
-				kslev[j][i] = (Bit8u)oct;
-			}
-		}
-	}
-
-}
-
-
-
-void adlib_write(Bitu idx, Bit8u val) {
-	Bit32u second_set = idx&0x100;
-	adlibreg[idx] = val;
-
-	switch (idx&0xf0) {
-	case ARC_CONTROL:
-		// here we check for the second set registers, too:
-		switch (idx) {
-		case 0x02:	// timer1 counter
-		case 0x03:	// timer2 counter
-			break;
-		case 0x04:
-			// IRQ reset, timer mask/start
-			if (val&0x80) {
-				// clear IRQ bits in status register
-				status &= ~0x60;
-			} else {
-				status = 0;
-			}
-			break;
-#if defined(OPLTYPE_IS_OPL3)
-		case 0x04|ARC_SECONDSET:
-			// 4op enable/disable switches for each possible channel
-			op[0].is_4op = (val&1)>0;
-			op[3].is_4op_attached = op[0].is_4op;
-			op[1].is_4op = (val&2)>0;
-			op[4].is_4op_attached = op[1].is_4op;
-			op[2].is_4op = (val&4)>0;
-			op[5].is_4op_attached = op[2].is_4op;
-			op[18].is_4op = (val&8)>0;
-			op[21].is_4op_attached = op[18].is_4op;
-			op[19].is_4op = (val&16)>0;
-			op[22].is_4op_attached = op[19].is_4op;
-			op[20].is_4op = (val&32)>0;
-			op[23].is_4op_attached = op[20].is_4op;
-			break;
-		case 0x05|ARC_SECONDSET:
-			break;
-#endif
-		case 0x08:
-			// CSW, note select
-			break;
-		default:
-			break;
-		}
-		break;
-	case ARC_TVS_KSR_MUL:
-	case ARC_TVS_KSR_MUL+0x10: {
-		// tremolo/vibrato/sustain keeping enabled; key scale rate; frequency multiplication
-		int num = idx&7;
-		Bitu base = (idx-ARC_TVS_KSR_MUL)&0xff;
-		if ((num<6) && (base<22)) {
-#if defined(OPLTYPE_IS_OPL3)
-			Bitu modop = regbase2modop[second_set?(base+22):base];
-#else
-			Bitu modop = regbase2modop[base];
-#endif
-			Bitu regbase = base+second_set;
-			Bitu chanbase = second_set?(modop-18+ARC_SECONDSET):modop;
-
-			// change tremolo/vibrato and sustain keeping of this operator
-			op_type* op_ptr = &op[modop+((num<3) ? 0 : 9)];
-			change_keepsustain(regbase,op_ptr);
-			change_vibrato(regbase,op_ptr);
-
-			// change frequency calculations of this operator as
-			// key scale rate and frequency multiplicator can be changed
-#if defined(OPLTYPE_IS_OPL3)
-			if ((adlibreg[0x105]&1) && (op[modop].is_4op_attached)) {
-				// operator uses frequency of channel
-				change_frequency(chanbase-3,regbase,op_ptr);
-			} else {
-				change_frequency(chanbase,regbase,op_ptr);
-			}
-#else
-			change_frequency(chanbase,base,op_ptr);
-#endif
-		}
-		}
-		break;
-	case ARC_KSL_OUTLEV:
-	case ARC_KSL_OUTLEV+0x10: {
-		// key scale level; output rate
-		int num = idx&7;
-		Bitu base = (idx-ARC_KSL_OUTLEV)&0xff;
-		if ((num<6) && (base<22)) {
-#if defined(OPLTYPE_IS_OPL3)
-			Bitu modop = regbase2modop[second_set?(base+22):base];
-#else
-			Bitu modop = regbase2modop[base];
-#endif
-			Bitu chanbase = second_set?(modop-18+ARC_SECONDSET):modop;
-
-			// change frequency calculations of this operator as
-			// key scale level and output rate can be changed
-			op_type* op_ptr = &op[modop+((num<3) ? 0 : 9)];
-#if defined(OPLTYPE_IS_OPL3)
-			Bitu regbase = base+second_set;
-			if ((adlibreg[0x105]&1) && (op[modop].is_4op_attached)) {
-				// operator uses frequency of channel
-				change_frequency(chanbase-3,regbase,op_ptr);
-			} else {
-				change_frequency(chanbase,regbase,op_ptr);
-			}
-#else
-			change_frequency(chanbase,base,op_ptr);
-#endif
-		}
-		}
-		break;
-	case ARC_ATTR_DECR:
-	case ARC_ATTR_DECR+0x10: {
-		// attack/decay rates
-		int num = idx&7;
-		Bitu base = (idx-ARC_ATTR_DECR)&0xff;
-		if ((num<6) && (base<22)) {
-			Bitu regbase = base+second_set;
-
-			// change attack rate and decay rate of this operator
-			op_type* op_ptr = &op[regbase2op[second_set?(base+22):base]];
-			change_attackrate(regbase,op_ptr);
-			change_decayrate(regbase,op_ptr);
-		}
-		}
-		break;
-	case ARC_SUSL_RELR:
-	case ARC_SUSL_RELR+0x10: {
-		// sustain level; release rate
-		int num = idx&7;
-		Bitu base = (idx-ARC_SUSL_RELR)&0xff;
-		if ((num<6) && (base<22)) {
-			Bitu regbase = base+second_set;
-
-			// change sustain level and release rate of this operator
-			op_type* op_ptr = &op[regbase2op[second_set?(base+22):base]];
-			change_releaserate(regbase,op_ptr);
-			change_sustainlevel(regbase,op_ptr);
-		}
-		}
-		break;
-	case ARC_FREQ_NUM: {
-		// 0xa0-0xa8 low8 frequency
-		Bitu base = (idx-ARC_FREQ_NUM)&0xff;
-		if (base<9) {
-			Bits opbase = second_set?(base+18):base;
-#if defined(OPLTYPE_IS_OPL3)
-			if ((adlibreg[0x105]&1) && op[opbase].is_4op_attached) break;
-#endif
-			// regbase of modulator:
-			Bits modbase = modulatorbase[base]+second_set;
-
-			Bitu chanbase = base+second_set;
-
-			change_frequency(chanbase,modbase,&op[opbase]);
-			change_frequency(chanbase,modbase+3,&op[opbase+9]);
-#if defined(OPLTYPE_IS_OPL3)
-			// for 4op channels all four operators are modified to the frequency of the channel
-			if ((adlibreg[0x105]&1) && op[second_set?(base+18):base].is_4op) {
-				change_frequency(chanbase,modbase+8,&op[opbase+3]);
-				change_frequency(chanbase,modbase+3+8,&op[opbase+3+9]);
-			}
-#endif
-		}
-		}
-		break;
-	case ARC_KON_BNUM: {
-		if (idx == ARC_PERC_MODE) {
-#if defined(OPLTYPE_IS_OPL3)
-			if (second_set) return;
-#endif
-
-			if ((val&0x30) == 0x30) {		// BassDrum active
-				enable_operator(16,&op[6],OP_ACT_PERC);
-				change_frequency(6,16,&op[6]);
-				enable_operator(16+3,&op[6+9],OP_ACT_PERC);
-				change_frequency(6,16+3,&op[6+9]);
-			} else {
-				disable_operator(&op[6],OP_ACT_PERC);
-				disable_operator(&op[6+9],OP_ACT_PERC);
-			}
-			if ((val&0x28) == 0x28) {		// Snare active
-				enable_operator(17+3,&op[16],OP_ACT_PERC);
-				change_frequency(7,17+3,&op[16]);
-			} else {
-				disable_operator(&op[16],OP_ACT_PERC);
-			}
-			if ((val&0x24) == 0x24) {		// TomTom active
-				enable_operator(18,&op[8],OP_ACT_PERC);
-				change_frequency(8,18,&op[8]);
-			} else {
-				disable_operator(&op[8],OP_ACT_PERC);
-			}
-			if ((val&0x22) == 0x22) {		// Cymbal active
-				enable_operator(18+3,&op[8+9],OP_ACT_PERC);
-				change_frequency(8,18+3,&op[8+9]);
-			} else {
-				disable_operator(&op[8+9],OP_ACT_PERC);
-			}
-			if ((val&0x21) == 0x21) {		// Hihat active
-				enable_operator(17,&op[7],OP_ACT_PERC);
-				change_frequency(7,17,&op[7]);
-			} else {
-				disable_operator(&op[7],OP_ACT_PERC);
-			}
-
-			break;
-		}
-		// regular 0xb0-0xb8
-		Bitu base = (idx-ARC_KON_BNUM)&0xff;
-		if (base<9) {
-			Bits opbase = second_set?(base+18):base;
-#if defined(OPLTYPE_IS_OPL3)
-			if ((adlibreg[0x105]&1) && op[opbase].is_4op_attached) break;
-#endif
-			// regbase of modulator:
-			Bits modbase = modulatorbase[base]+second_set;
-
-			if (val&32) {
-				// operator switched on
-				enable_operator(modbase,&op[opbase],OP_ACT_NORMAL);		// modulator (if 2op)
-				enable_operator(modbase+3,&op[opbase+9],OP_ACT_NORMAL);	// carrier (if 2op)
-#if defined(OPLTYPE_IS_OPL3)
-				// for 4op channels all four operators are switched on
-				if ((adlibreg[0x105]&1) && op[opbase].is_4op) {
-					// turn on chan+3 operators as well
-					enable_operator(modbase+8,&op[opbase+3],OP_ACT_NORMAL);
-					enable_operator(modbase+3+8,&op[opbase+3+9],OP_ACT_NORMAL);
-				}
-#endif
-			} else {
-				// operator switched off
-				disable_operator(&op[opbase],OP_ACT_NORMAL);
-				disable_operator(&op[opbase+9],OP_ACT_NORMAL);
-#if defined(OPLTYPE_IS_OPL3)
-				// for 4op channels all four operators are switched off
-				if ((adlibreg[0x105]&1) && op[opbase].is_4op) {
-					// turn off chan+3 operators as well
-					disable_operator(&op[opbase+3],OP_ACT_NORMAL);
-					disable_operator(&op[opbase+3+9],OP_ACT_NORMAL);
-				}
-#endif
-			}
-
-			Bitu chanbase = base+second_set;
-
-			// change frequency calculations of modulator and carrier (2op) as
-			// the frequency of the channel has changed
-			change_frequency(chanbase,modbase,&op[opbase]);
-			change_frequency(chanbase,modbase+3,&op[opbase+9]);
-#if defined(OPLTYPE_IS_OPL3)
-			// for 4op channels all four operators are modified to the frequency of the channel
-			if ((adlibreg[0x105]&1) && op[second_set?(base+18):base].is_4op) {
-				// change frequency calculations of chan+3 operators as well
-				change_frequency(chanbase,modbase+8,&op[opbase+3]);
-				change_frequency(chanbase,modbase+3+8,&op[opbase+3+9]);
-			}
-#endif
-		}
-		}
-		break;
-	case ARC_FEEDBACK: {
-		// 0xc0-0xc8 feedback/modulation type (AM/FM)
-		Bitu base = (idx-ARC_FEEDBACK)&0xff;
-		if (base<9) {
-			Bits opbase = second_set?(base+18):base;
-			Bitu chanbase = base+second_set;
-			change_feedback(chanbase,&op[opbase]);
-#if defined(OPLTYPE_IS_OPL3)
-			// OPL3 panning
-			op[opbase].left_pan = ((val&0x10)>>4);
-			op[opbase].right_pan = ((val&0x20)>>5);
-#endif
-		}
-		}
-		break;
-	case ARC_WAVE_SEL:
-	case ARC_WAVE_SEL+0x10: {
-		int num = idx&7;
-		Bitu base = (idx-ARC_WAVE_SEL)&0xff;
-		if ((num<6) && (base<22)) {
-#if defined(OPLTYPE_IS_OPL3)
-			Bits wselbase = second_set?(base+22):base;	// for easier mapping onto wave_sel[]
-			// change waveform
-			if (adlibreg[0x105]&1) wave_sel[wselbase] = val&7;	// opl3 mode enabled, all waveforms accessible
-			else wave_sel[wselbase] = val&3;
-			op_type* op_ptr = &op[regbase2modop[wselbase]+((num<3) ? 0 : 9)];
-			change_waveform(wselbase,op_ptr);
-#else
-			if (adlibreg[0x01]&0x20) {
-				// wave selection enabled, change waveform
-				wave_sel[base] = val&3;
-				op_type* op_ptr = &op[regbase2modop[base]+((num<3) ? 0 : 9)];
-				change_waveform(base,op_ptr);
-			}
-#endif
-		}
-		}
-		break;
-	default:
-		break;
-	}
-}
-
-
-Bitu adlib_reg_read(Bitu port) {
-#if defined(OPLTYPE_IS_OPL3)
-	// opl3-detection routines require ret&6 to be zero
-	if ((port&1)==0) {
-		return status;
-	}
-	return 0x00;
-#else
-	// opl2-detection routines require ret&6 to be 6
-	if ((port&1)==0) {
-		return status|6;
-	}
-	return 0xff;
-#endif
-}
-
-void adlib_write_index(Bitu port, Bit8u val) {
-	opl_index = val;
-#if defined(OPLTYPE_IS_OPL3)
-	if ((port&3)!=0) {
-		// possibly second set
-		if (((adlibreg[0x105]&1)!=0) || (opl_index==5)) opl_index |= ARC_SECONDSET;
-	}
-#endif
-}
-
-static inline void clipit16(Bit32s ival, Bit16s* outval) {
-	if (ival<32768) {
-		if (ival>-32769) {
-			*outval=(Bit16s)ival;
-		} else {
-			*outval = -32768;
-		}
-	} else {
-		*outval = 32767;
-	}
-}
-
-
-
-// be careful with this
-// uses cptr and chanval, outputs into outbufl(/outbufr)
-// for opl3 check if opl3-mode is enabled (which uses stereo panning)
-#undef CHANVAL_OUT
-#if defined(OPLTYPE_IS_OPL3)
-#define CHANVAL_OUT									\
-	if (adlibreg[0x105]&1) {						\
-		outbufl[i] += chanval*cptr[0].left_pan;		\
-		outbufr[i] += chanval*cptr[0].right_pan;	\
-	} else {										\
-		outbufl[i] += chanval;						\
-	}
-#else
-#define CHANVAL_OUT									\
-	outbufl[i] += chanval;
-#endif
-
-void adlib_getsample(Bit16s* sndptr, Bits numsamples) {
-	Bits i, endsamples;
-	op_type* cptr;
-
-	Bit32s outbufl[BLOCKBUF_SIZE];
-#if defined(OPLTYPE_IS_OPL3)
-	// second output buffer (right channel for opl3 stereo)
-	Bit32s outbufr[BLOCKBUF_SIZE];
-#endif
-
-	// vibrato/tremolo lookup tables (global, to possibly be used by all operators)
-	Bit32s vib_lut[BLOCKBUF_SIZE];
-	Bit32s trem_lut[BLOCKBUF_SIZE];
-
-	Bits samples_to_process = numsamples;
-
-	for (Bits cursmp=0; cursmp<samples_to_process; cursmp+=endsamples) {
-		endsamples = samples_to_process-cursmp;
-		if (endsamples>BLOCKBUF_SIZE) endsamples = BLOCKBUF_SIZE;
-
-		memset((void*)&outbufl,0,endsamples*sizeof(Bit32s));
-#if defined(OPLTYPE_IS_OPL3)
-		// clear second output buffer (opl3 stereo)
-		if (adlibreg[0x105]&1) memset((void*)&outbufr,0,endsamples*sizeof(Bit32s));
-#endif
-
-		// calculate vibrato/tremolo lookup tables
-		Bit32s vib_tshift = ((adlibreg[ARC_PERC_MODE]&0x40)==0) ? 1 : 0;	// 14cents/7cents switching
-		for (i=0;i<endsamples;i++) {
-			// cycle through vibrato table
-			vibtab_pos += vibtab_add;
-			if (vibtab_pos/FIXEDPT_LFO>=VIBTAB_SIZE) vibtab_pos-=VIBTAB_SIZE*FIXEDPT_LFO;
-			vib_lut[i] = vib_table[vibtab_pos/FIXEDPT_LFO]>>vib_tshift;		// 14cents (14/100 of a semitone) or 7cents
-
-			// cycle through tremolo table
-			tremtab_pos += tremtab_add;
-			if (tremtab_pos/FIXEDPT_LFO>=TREMTAB_SIZE) tremtab_pos-=TREMTAB_SIZE*FIXEDPT_LFO;
-			if (adlibreg[ARC_PERC_MODE]&0x80) trem_lut[i] = trem_table[tremtab_pos/FIXEDPT_LFO];
-			else trem_lut[i] = trem_table[TREMTAB_SIZE+tremtab_pos/FIXEDPT_LFO];
-		}
-
-		if (adlibreg[ARC_PERC_MODE]&0x20) {
-			//BassDrum
-			cptr = &op[6];
-			if (adlibreg[ARC_FEEDBACK+6]&1) {
-				// additive synthesis
-				if (cptr[9].op_state != OF_TYPE_OFF) {
-					if (cptr[9].vibrato) {
-						vibval1 = vibval_var1;
-						for (i=0;i<endsamples;i++)
-							vibval1[i] = (Bit32s)((vib_lut[i]*cptr[9].freq_high/8)*FIXEDPT*VIBFAC);
-					} else vibval1 = vibval_const;
-					if (cptr[9].tremolo) tremval1 = trem_lut;	// tremolo enabled, use table
-					else tremval1 = tremval_const;
-
-					// calculate channel output
-					for (i=0;i<endsamples;i++) {
-						operator_advance(&cptr[9],vibval1[i]);
-						opfuncs[cptr[9].op_state](&cptr[9]);
-						operator_output(&cptr[9],0,tremval1[i]);
-
-						Bit32s chanval = cptr[9].cval*2;
-						CHANVAL_OUT
-					}
-				}
-			} else {
-				// frequency modulation
-				if ((cptr[9].op_state != OF_TYPE_OFF) || (cptr[0].op_state != OF_TYPE_OFF)) {
-					if ((cptr[0].vibrato) && (cptr[0].op_state != OF_TYPE_OFF)) {
-						vibval1 = vibval_var1;
-						for (i=0;i<endsamples;i++)
-							vibval1[i] = (Bit32s)((vib_lut[i]*cptr[0].freq_high/8)*FIXEDPT*VIBFAC);
-					} else vibval1 = vibval_const;
-					if ((cptr[9].vibrato) && (cptr[9].op_state != OF_TYPE_OFF)) {
-						vibval2 = vibval_var2;
-						for (i=0;i<endsamples;i++)
-							vibval2[i] = (Bit32s)((vib_lut[i]*cptr[9].freq_high/8)*FIXEDPT*VIBFAC);
-					} else vibval2 = vibval_const;
-					if (cptr[0].tremolo) tremval1 = trem_lut;	// tremolo enabled, use table
-					else tremval1 = tremval_const;
-					if (cptr[9].tremolo) tremval2 = trem_lut;	// tremolo enabled, use table
-					else tremval2 = tremval_const;
-
-					// calculate channel output
-					for (i=0;i<endsamples;i++) {
-						operator_advance(&cptr[0],vibval1[i]);
-						opfuncs[cptr[0].op_state](&cptr[0]);
-						operator_output(&cptr[0],(cptr[0].lastcval+cptr[0].cval)*cptr[0].mfbi/2,tremval1[i]);
-
-						operator_advance(&cptr[9],vibval2[i]);
-						opfuncs[cptr[9].op_state](&cptr[9]);
-						operator_output(&cptr[9],cptr[0].cval*FIXEDPT,tremval2[i]);
-
-						Bit32s chanval = cptr[9].cval*2;
-						CHANVAL_OUT
-					}
-				}
-			}
-
-			//TomTom (j=8)
-			if (op[8].op_state != OF_TYPE_OFF) {
-				cptr = &op[8];
-				if (cptr[0].vibrato) {
-					vibval3 = vibval_var1;
-					for (i=0;i<endsamples;i++)
-						vibval3[i] = (Bit32s)((vib_lut[i]*cptr[0].freq_high/8)*FIXEDPT*VIBFAC);
-				} else vibval3 = vibval_const;
-
-				if (cptr[0].tremolo) tremval3 = trem_lut;	// tremolo enabled, use table
-				else tremval3 = tremval_const;
-
-				// calculate channel output
-				for (i=0;i<endsamples;i++) {
-					operator_advance(&cptr[0],vibval3[i]);
-					opfuncs[cptr[0].op_state](&cptr[0]);		//TomTom
-					operator_output(&cptr[0],0,tremval3[i]);
-					Bit32s chanval = cptr[0].cval*2;
-					CHANVAL_OUT
-				}
-			}
-
-			//Snare/Hihat (j=7), Cymbal (j=8)
-			if ((op[7].op_state != OF_TYPE_OFF) || (op[16].op_state != OF_TYPE_OFF) ||
-				(op[17].op_state != OF_TYPE_OFF)) {
-				cptr = &op[7];
-				if ((cptr[0].vibrato) && (cptr[0].op_state != OF_TYPE_OFF)) {
-					vibval1 = vibval_var1;
-					for (i=0;i<endsamples;i++)
-						vibval1[i] = (Bit32s)((vib_lut[i]*cptr[0].freq_high/8)*FIXEDPT*VIBFAC);
-				} else vibval1 = vibval_const;
-				if ((cptr[9].vibrato) && (cptr[9].op_state == OF_TYPE_OFF)) {
-					vibval2 = vibval_var2;
-					for (i=0;i<endsamples;i++)
-						vibval2[i] = (Bit32s)((vib_lut[i]*cptr[9].freq_high/8)*FIXEDPT*VIBFAC);
-				} else vibval2 = vibval_const;
-
-				if (cptr[0].tremolo) tremval1 = trem_lut;	// tremolo enabled, use table
-				else tremval1 = tremval_const;
-				if (cptr[9].tremolo) tremval2 = trem_lut;	// tremolo enabled, use table
-				else tremval2 = tremval_const;
-
-				cptr = &op[8];
-				if ((cptr[9].vibrato) && (cptr[9].op_state == OF_TYPE_OFF)) {
-					vibval4 = vibval_var2;
-					for (i=0;i<endsamples;i++)
-						vibval4[i] = (Bit32s)((vib_lut[i]*cptr[9].freq_high/8)*FIXEDPT*VIBFAC);
-				} else vibval4 = vibval_const;
-
-				if (cptr[9].tremolo) tremval4 = trem_lut;	// tremolo enabled, use table
-				else tremval4 = tremval_const;
-
-				// calculate channel output
-				for (i=0;i<endsamples;i++) {
-					operator_advance_drums(&op[7],vibval1[i],&op[7+9],vibval2[i],&op[8+9],vibval4[i]);
-
-					opfuncs[op[7].op_state](&op[7]);			//Hihat
-					operator_output(&op[7],0,tremval1[i]);
-
-					opfuncs[op[7+9].op_state](&op[7+9]);		//Snare
-					operator_output(&op[7+9],0,tremval2[i]);
-
-					opfuncs[op[8+9].op_state](&op[8+9]);		//Cymbal
-					operator_output(&op[8+9],0,tremval4[i]);
-
-					Bit32s chanval = (op[7].cval + op[7+9].cval + op[8+9].cval)*2;
-					CHANVAL_OUT
-				}
-			}
-		}
-
-		Bitu max_channel = NUM_CHANNELS;
-#if defined(OPLTYPE_IS_OPL3)
-		if ((adlibreg[0x105]&1)==0) max_channel = NUM_CHANNELS/2;
-#endif
-		for (Bits cur_ch=max_channel-1; cur_ch>=0; cur_ch--) {
-			// skip drum/percussion operators
-			if ((adlibreg[ARC_PERC_MODE]&0x20) && (cur_ch >= 6) && (cur_ch < 9)) continue;
-
-			Bitu k = cur_ch;
-#if defined(OPLTYPE_IS_OPL3)
-			if (cur_ch < 9) {
-				cptr = &op[cur_ch];
-			} else {
-				cptr = &op[cur_ch+9];	// second set is operator18-operator35
-				k += (-9+256);		// second set uses registers 0x100 onwards
-			}
-			// check if this operator is part of a 4-op
-			if ((adlibreg[0x105]&1) && cptr->is_4op_attached) continue;
-#else
-			cptr = &op[cur_ch];
-#endif
-
-			// check for FM/AM
-			if (adlibreg[ARC_FEEDBACK+k]&1) {
-#if defined(OPLTYPE_IS_OPL3)
-				if ((adlibreg[0x105]&1) && cptr->is_4op) {
-					if (adlibreg[ARC_FEEDBACK+k+3]&1) {
-						// AM-AM-style synthesis (op1[fb] + (op2 * op3) + op4)
-						if (cptr[0].op_state != OF_TYPE_OFF) {
-							if (cptr[0].vibrato) {
-								vibval1 = vibval_var1;
-								for (i=0;i<endsamples;i++)
-									vibval1[i] = (Bit32s)((vib_lut[i]*cptr[0].freq_high/8)*FIXEDPT*VIBFAC);
-							} else vibval1 = vibval_const;
-							if (cptr[0].tremolo) tremval1 = trem_lut;	// tremolo enabled, use table
-							else tremval1 = tremval_const;
-
-							// calculate channel output
-							for (i=0;i<endsamples;i++) {
-								operator_advance(&cptr[0],vibval1[i]);
-								opfuncs[cptr[0].op_state](&cptr[0]);
-								operator_output(&cptr[0],(cptr[0].lastcval+cptr[0].cval)*cptr[0].mfbi/2,tremval1[i]);
-
-								Bit32s chanval = cptr[0].cval;
-								CHANVAL_OUT
-							}
-						}
-
-						if ((cptr[3].op_state != OF_TYPE_OFF) || (cptr[9].op_state != OF_TYPE_OFF)) {
-							if ((cptr[9].vibrato) && (cptr[9].op_state != OF_TYPE_OFF)) {
-								vibval1 = vibval_var1;
-								for (i=0;i<endsamples;i++)
-									vibval1[i] = (Bit32s)((vib_lut[i]*cptr[9].freq_high/8)*FIXEDPT*VIBFAC);
-							} else vibval1 = vibval_const;
-							if (cptr[9].tremolo) tremval1 = trem_lut;	// tremolo enabled, use table
-							else tremval1 = tremval_const;
-							if (cptr[3].tremolo) tremval2 = trem_lut;	// tremolo enabled, use table
-							else tremval2 = tremval_const;
-
-							// calculate channel output
-							for (i=0;i<endsamples;i++) {
-								operator_advance(&cptr[9],vibval1[i]);
-								opfuncs[cptr[9].op_state](&cptr[9]);
-								operator_output(&cptr[9],0,tremval1[i]);
-
-								operator_advance(&cptr[3],0);
-								opfuncs[cptr[3].op_state](&cptr[3]);
-								operator_output(&cptr[3],cptr[9].cval*FIXEDPT,tremval2[i]);
-
-								Bit32s chanval = cptr[3].cval;
-								CHANVAL_OUT
-							}
-						}
-
-						if (cptr[3+9].op_state != OF_TYPE_OFF) {
-							if (cptr[3+9].tremolo) tremval1 = trem_lut;	// tremolo enabled, use table
-							else tremval1 = tremval_const;
-
-							// calculate channel output
-							for (i=0;i<endsamples;i++) {
-								operator_advance(&cptr[3+9],0);
-								opfuncs[cptr[3+9].op_state](&cptr[3+9]);
-								operator_output(&cptr[3+9],0,tremval1[i]);
-
-								Bit32s chanval = cptr[3+9].cval;
-								CHANVAL_OUT
-							}
-						}
-					} else {
-						// AM-FM-style synthesis (op1[fb] + (op2 * op3 * op4))
-						if (cptr[0].op_state != OF_TYPE_OFF) {
-							if (cptr[0].vibrato) {
-								vibval1 = vibval_var1;
-								for (i=0;i<endsamples;i++)
-									vibval1[i] = (Bit32s)((vib_lut[i]*cptr[0].freq_high/8)*FIXEDPT*VIBFAC);
-							} else vibval1 = vibval_const;
-							if (cptr[0].tremolo) tremval1 = trem_lut;	// tremolo enabled, use table
-							else tremval1 = tremval_const;
-
-							// calculate channel output
-							for (i=0;i<endsamples;i++) {
-								operator_advance(&cptr[0],vibval1[i]);
-								opfuncs[cptr[0].op_state](&cptr[0]);
-								operator_output(&cptr[0],(cptr[0].lastcval+cptr[0].cval)*cptr[0].mfbi/2,tremval1[i]);
-
-								Bit32s chanval = cptr[0].cval;
-								CHANVAL_OUT
-							}
-						}
-
-						if ((cptr[9].op_state != OF_TYPE_OFF) || (cptr[3].op_state != OF_TYPE_OFF) || (cptr[3+9].op_state != OF_TYPE_OFF)) {
-							if ((cptr[9].vibrato) && (cptr[9].op_state != OF_TYPE_OFF)) {
-								vibval1 = vibval_var1;
-								for (i=0;i<endsamples;i++)
-									vibval1[i] = (Bit32s)((vib_lut[i]*cptr[9].freq_high/8)*FIXEDPT*VIBFAC);
-							} else vibval1 = vibval_const;
-							if (cptr[9].tremolo) tremval1 = trem_lut;	// tremolo enabled, use table
-							else tremval1 = tremval_const;
-							if (cptr[3].tremolo) tremval2 = trem_lut;	// tremolo enabled, use table
-							else tremval2 = tremval_const;
-							if (cptr[3+9].tremolo) tremval3 = trem_lut;	// tremolo enabled, use table
-							else tremval3 = tremval_const;
-
-							// calculate channel output
-							for (i=0;i<endsamples;i++) {
-								operator_advance(&cptr[9],vibval1[i]);
-								opfuncs[cptr[9].op_state](&cptr[9]);
-								operator_output(&cptr[9],0,tremval1[i]);
-
-								operator_advance(&cptr[3],0);
-								opfuncs[cptr[3].op_state](&cptr[3]);
-								operator_output(&cptr[3],cptr[9].cval*FIXEDPT,tremval2[i]);
-
-								operator_advance(&cptr[3+9],0);
-								opfuncs[cptr[3+9].op_state](&cptr[3+9]);
-								operator_output(&cptr[3+9],cptr[3].cval*FIXEDPT,tremval3[i]);
-
-								Bit32s chanval = cptr[3+9].cval;
-								CHANVAL_OUT
-							}
-						}
-					}
-					continue;
-				}
-#endif
-				// 2op additive synthesis
-				if ((cptr[9].op_state == OF_TYPE_OFF) && (cptr[0].op_state == OF_TYPE_OFF)) continue;
-				if ((cptr[0].vibrato) && (cptr[0].op_state != OF_TYPE_OFF)) {
-					vibval1 = vibval_var1;
-					for (i=0;i<endsamples;i++)
-						vibval1[i] = (Bit32s)((vib_lut[i]*cptr[0].freq_high/8)*FIXEDPT*VIBFAC);
-				} else vibval1 = vibval_const;
-				if ((cptr[9].vibrato) && (cptr[9].op_state != OF_TYPE_OFF)) {
-					vibval2 = vibval_var2;
-					for (i=0;i<endsamples;i++)
-						vibval2[i] = (Bit32s)((vib_lut[i]*cptr[9].freq_high/8)*FIXEDPT*VIBFAC);
-				} else vibval2 = vibval_const;
-				if (cptr[0].tremolo) tremval1 = trem_lut;	// tremolo enabled, use table
-				else tremval1 = tremval_const;
-				if (cptr[9].tremolo) tremval2 = trem_lut;	// tremolo enabled, use table
-				else tremval2 = tremval_const;
-
-				// calculate channel output
-				for (i=0;i<endsamples;i++) {
-					// carrier1
-					operator_advance(&cptr[0],vibval1[i]);
-					opfuncs[cptr[0].op_state](&cptr[0]);
-					operator_output(&cptr[0],(cptr[0].lastcval+cptr[0].cval)*cptr[0].mfbi/2,tremval1[i]);
-
-					// carrier2
-					operator_advance(&cptr[9],vibval2[i]);
-					opfuncs[cptr[9].op_state](&cptr[9]);
-					operator_output(&cptr[9],0,tremval2[i]);
-
-					Bit32s chanval = cptr[9].cval + cptr[0].cval;
-					CHANVAL_OUT
-				}
-			} else {
-#if defined(OPLTYPE_IS_OPL3)
-				if ((adlibreg[0x105]&1) && cptr->is_4op) {
-					if (adlibreg[ARC_FEEDBACK+k+3]&1) {
-						// FM-AM-style synthesis ((op1[fb] * op2) + (op3 * op4))
-						if ((cptr[0].op_state != OF_TYPE_OFF) || (cptr[9].op_state != OF_TYPE_OFF)) {
-							if ((cptr[0].vibrato) && (cptr[0].op_state != OF_TYPE_OFF)) {
-								vibval1 = vibval_var1;
-								for (i=0;i<endsamples;i++)
-									vibval1[i] = (Bit32s)((vib_lut[i]*cptr[0].freq_high/8)*FIXEDPT*VIBFAC);
-							} else vibval1 = vibval_const;
-							if ((cptr[9].vibrato) && (cptr[9].op_state != OF_TYPE_OFF)) {
-								vibval2 = vibval_var2;
-								for (i=0;i<endsamples;i++)
-									vibval2[i] = (Bit32s)((vib_lut[i]*cptr[9].freq_high/8)*FIXEDPT*VIBFAC);
-							} else vibval2 = vibval_const;
-							if (cptr[0].tremolo) tremval1 = trem_lut;	// tremolo enabled, use table
-							else tremval1 = tremval_const;
-							if (cptr[9].tremolo) tremval2 = trem_lut;	// tremolo enabled, use table
-							else tremval2 = tremval_const;
-
-							// calculate channel output
-							for (i=0;i<endsamples;i++) {
-								operator_advance(&cptr[0],vibval1[i]);
-								opfuncs[cptr[0].op_state](&cptr[0]);
-								operator_output(&cptr[0],(cptr[0].lastcval+cptr[0].cval)*cptr[0].mfbi/2,tremval1[i]);
-
-								operator_advance(&cptr[9],vibval2[i]);
-								opfuncs[cptr[9].op_state](&cptr[9]);
-								operator_output(&cptr[9],cptr[0].cval*FIXEDPT,tremval2[i]);
-
-								Bit32s chanval = cptr[9].cval;
-								CHANVAL_OUT
-							}
-						}
-
-						if ((cptr[3].op_state != OF_TYPE_OFF) || (cptr[3+9].op_state != OF_TYPE_OFF)) {
-							if (cptr[3].tremolo) tremval1 = trem_lut;	// tremolo enabled, use table
-							else tremval1 = tremval_const;
-							if (cptr[3+9].tremolo) tremval2 = trem_lut;	// tremolo enabled, use table
-							else tremval2 = tremval_const;
-
-							// calculate channel output
-							for (i=0;i<endsamples;i++) {
-								operator_advance(&cptr[3],0);
-								opfuncs[cptr[3].op_state](&cptr[3]);
-								operator_output(&cptr[3],0,tremval1[i]);
-
-								operator_advance(&cptr[3+9],0);
-								opfuncs[cptr[3+9].op_state](&cptr[3+9]);
-								operator_output(&cptr[3+9],cptr[3].cval*FIXEDPT,tremval2[i]);
-
-								Bit32s chanval = cptr[3+9].cval;
-								CHANVAL_OUT
-							}
-						}
-
-					} else {
-						// FM-FM-style synthesis (op1[fb] * op2 * op3 * op4)
-						if ((cptr[0].op_state != OF_TYPE_OFF) || (cptr[9].op_state != OF_TYPE_OFF) ||
-							(cptr[3].op_state != OF_TYPE_OFF) || (cptr[3+9].op_state != OF_TYPE_OFF)) {
-							if ((cptr[0].vibrato) && (cptr[0].op_state != OF_TYPE_OFF)) {
-								vibval1 = vibval_var1;
-								for (i=0;i<endsamples;i++)
-									vibval1[i] = (Bit32s)((vib_lut[i]*cptr[0].freq_high/8)*FIXEDPT*VIBFAC);
-							} else vibval1 = vibval_const;
-							if ((cptr[9].vibrato) && (cptr[9].op_state != OF_TYPE_OFF)) {
-								vibval2 = vibval_var2;
-								for (i=0;i<endsamples;i++)
-									vibval2[i] = (Bit32s)((vib_lut[i]*cptr[9].freq_high/8)*FIXEDPT*VIBFAC);
-							} else vibval2 = vibval_const;
-							if (cptr[0].tremolo) tremval1 = trem_lut;	// tremolo enabled, use table
-							else tremval1 = tremval_const;
-							if (cptr[9].tremolo) tremval2 = trem_lut;	// tremolo enabled, use table
-							else tremval2 = tremval_const;
-							if (cptr[3].tremolo) tremval3 = trem_lut;	// tremolo enabled, use table
-							else tremval3 = tremval_const;
-							if (cptr[3+9].tremolo) tremval4 = trem_lut;	// tremolo enabled, use table
-							else tremval4 = tremval_const;
-
-							// calculate channel output
-							for (i=0;i<endsamples;i++) {
-								operator_advance(&cptr[0],vibval1[i]);
-								opfuncs[cptr[0].op_state](&cptr[0]);
-								operator_output(&cptr[0],(cptr[0].lastcval+cptr[0].cval)*cptr[0].mfbi/2,tremval1[i]);
-
-								operator_advance(&cptr[9],vibval2[i]);
-								opfuncs[cptr[9].op_state](&cptr[9]);
-								operator_output(&cptr[9],cptr[0].cval*FIXEDPT,tremval2[i]);
-
-								operator_advance(&cptr[3],0);
-								opfuncs[cptr[3].op_state](&cptr[3]);
-								operator_output(&cptr[3],cptr[9].cval*FIXEDPT,tremval3[i]);
-
-								operator_advance(&cptr[3+9],0);
-								opfuncs[cptr[3+9].op_state](&cptr[3+9]);
-								operator_output(&cptr[3+9],cptr[3].cval*FIXEDPT,tremval4[i]);
-
-								Bit32s chanval = cptr[3+9].cval;
-								CHANVAL_OUT
-							}
-						}

@@ Diff output truncated at 100000 characters. @@

This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.




More information about the Scummvm-git-logs mailing list