Klasse EnvelopeGenerator
In addition, another counter is used to implement the exponential envelope decay, in effect further dividing the clock to the envelope counter. The period of this counter is set to 1, 2, 4, 8, 16, 30 at the envelope counter values 255, 93, 54, 26, 14, 6, respectively.
- Autor:
- Ken Händel
-
Verschachtelte Klassen - Übersicht
Verschachtelte KlassenModifizierer und TypKlasseBeschreibungprivate static enumThe envelope state machine's distinct states. -
Feldübersicht
FelderModifizierer und TypFeldBeschreibungprivate intAttack registerprivate final float[]Emulated nonlinearity of the envelope DAC.private intDecay registerprivate static final int[]Lookup table to convert from attack, decay, or release value to rate counter period.private byteThe current digital value of envelope output.private floatThe current analog value of envelope output.private intDuring release mode, the SID arpproximates envelope decay via piecewise linear decay rate.private intComparison value (period) of the exponential decay counter before next decrement.private booleanGate bit(Package privat) booleanWhether hold is enabled.private booleanVoice mute (kill envelope output)private intXOR shift register emulated via normal integer which implements delay until the next envelope operation occurs.private intComparison value (period) of the rate counter before next event.private intRelease registerprivate EnvelopeGenerator.StateCurrent envelope stateprivate intSustain register -
Konstruktorübersicht
Konstruktoren -
Methodenübersicht
Modifizierer und TypMethodeBeschreibungprotected voidclock()SID clocking - 1 cycle.private voidcpuUpdateRatePeriod(int newRateCounterPeriod) When CPU updates rate period, check for ADSR delay bug before allowing the update to proceed.protected voidmute(boolean enable) Mute this voice.floatoutput()Return the analog value of envelope.bytereadENV()Return the envelope current value.protected voidreset()SID reset.protected voidsetNonLinearity(float nonLinearity) Set nonlinearity parameter for imperfect analog DAC emulation. 1.0 means perfect 8580-like linearity, values between 0.95 - 0.97 are probably realistic 6581 nonlinearity values.protected voidwriteATTACK_DECAY(byte attack_decay) protected voidwriteCONTROL_REG(byte control) protected voidwriteSUSTAIN_RELEASE(byte sustain_release)
-
Felddetails
-
hold
boolean holdWhether hold is enabled. Only switching to ATTACK can release envelope. -
rateCounter
private int rateCounterXOR shift register emulated via normal integer which implements delay until the next envelope operation occurs. The XOR shift register has 0x7fff different values to scan. -
rateCounterPeriod
private int rateCounterPeriodComparison value (period) of the rate counter before next event. -
exponentialCounter
private int exponentialCounterDuring release mode, the SID arpproximates envelope decay via piecewise linear decay rate. -
exponentialCounterPeriod
private int exponentialCounterPeriodComparison value (period) of the exponential decay counter before next decrement. -
envelopeValue
private byte envelopeValueThe current digital value of envelope output. -
envelopeValueDac
private float envelopeValueDacThe current analog value of envelope output. -
muted
private boolean mutedVoice mute (kill envelope output) -
attack
private int attackAttack register -
decay
private int decayDecay register -
sustain
private int sustainSustain register -
release
private int releaseRelease register -
gate
private boolean gateGate bit -
state
Current envelope state -
ENVELOPE_PERIOD
private static final int[] ENVELOPE_PERIODLookup table to convert from attack, decay, or release value to rate counter period.Rate counter periods are calculated from the Envelope Rates table in the Programmer's Reference Guide. The rate counter period is the number of cycles between each increment of the envelope counter. The rates have been verified by sampling ENV3.
The rate counter is a 16 bit register which is incremented each cycle. When the counter reaches a specific comparison value, the envelope counter is incremented (attack) or decremented (decay/release) and the counter is zeroed.
NB! Sampling ENV3 shows that the calculated values are not exact. It may seem like most calculated values have been rounded (.5 is rounded down) and 1 has beed added to the result. A possible explanation for this is that the SID designers have used the calculated values directly as rate counter comparison values, not considering a one cycle delay to zero the counter. This would yield an actual period of comparison value + 1.
The time of the first envelope count can not be exactly controlled, except possibly by resetting the chip. Because of this we cannot do cycle exact sampling and must devise another method to calculate the rate counter periods.
The exact rate counter periods can be determined e.g. by counting the number of cycles from envelope level 1 to envelope level 129, and dividing the number of cycles by 128. CIA1 timer A and B in linked mode can perform the cycle count. This is the method used to find the rates below.
To avoid the ADSR delay bug, sampling of ENV3 should be done using sustain = release = 0. This ensures that the attack state will not lower the current rate counter period.
The ENV3 sampling code below yields a maximum timing error of 14 cycles.
lda #$01 l1: cmp $d41c bne l1 ... lda #$ff l2: cmp $d41c bne l2This yields a maximum error for the calculated rate period of 14/128 cycles. The described method is thus sufficient for exact calculation of the rate periods. -
dac
private final float[] dacEmulated nonlinearity of the envelope DAC.- Siehe auch:
-
-
Konstruktordetails
-
EnvelopeGenerator
protected EnvelopeGenerator()Constructor.
-
-
Methodendetails
-
clock
protected void clock()SID clocking - 1 cycle. -
setNonLinearity
protected void setNonLinearity(float nonLinearity) Set nonlinearity parameter for imperfect analog DAC emulation. 1.0 means perfect 8580-like linearity, values between 0.95 - 0.97 are probably realistic 6581 nonlinearity values.- Parameter:
nonLinearity-
-
reset
protected void reset()SID reset. -
mute
protected void mute(boolean enable) Mute this voice. (Triggered at next envelope event.)- Parameter:
enable-
-
writeCONTROL_REG
protected void writeCONTROL_REG(byte control) - Parameter:
control- control register
-
writeATTACK_DECAY
protected void writeATTACK_DECAY(byte attack_decay) - Parameter:
attack_decay- attack/decay value
-
writeSUSTAIN_RELEASE
protected void writeSUSTAIN_RELEASE(byte sustain_release) - Parameter:
sustain_release- sustain/release value
-
readENV
public byte readENV()Return the envelope current value.- Gibt zurück:
- envelope counter
-
output
public float output()Return the analog value of envelope.- Gibt zurück:
- envelope analog output
-
cpuUpdateRatePeriod
private void cpuUpdateRatePeriod(int newRateCounterPeriod) When CPU updates rate period, check for ADSR delay bug before allowing the update to proceed.- Parameter:
newRateCounterPeriod-
-