/*
* Copyright (C) 2012 Brendan Robert (BLuRry) brendan.robert@gmail.com.
*
* 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
*/
package jace.hardware.mockingboard;
/**
* Envelope generator of the PSG sound chip
* Created on April 18, 2006, 5:49 PM
* @author Brendan Robert (BLuRry) brendan.robert@gmail.com
*/
public class EnvelopeGenerator extends TimedGenerator {
boolean hold = false;
boolean attk = false;
boolean alt = false;
boolean cont = false;
int direction;
int amplitude;
boolean start1high = false;
boolean start2high = false;
boolean oneShot = false;
boolean oddEven = false;
public EnvelopeGenerator(int _clock, int _sampleRate) {
super(_clock, _sampleRate);
}
@Override
public int stepsPerCycle() {
return 8;
}
@Override
public void setPeriod(int p) {
if (p > 0) {
super.setPeriod(p);
} else {
clocksPerPeriod = stepsPerCycle() / 2;
}
}
int effectiveAmplitude = 0;
public void step() {
int stateChanges = updateCounter();
int total = 0;
for (int i = 0; i < stateChanges; i++) {
amplitude += direction;
if (amplitude > 15 || amplitude < 0) {
setPhase(oddEven ? start1high : start2high);
oddEven = !oddEven;
if (hold) {
direction = 0;
}
}
total += amplitude;
}
if (stateChanges == 0) {
effectiveAmplitude = amplitude;
} else {
effectiveAmplitude = Math.min(15, total / stateChanges);
}
}
public void setShape(int shape) {
oddEven = false;
counter = 0;
cont = (shape & 8) != 0;
attk = (shape & 4) != 0;
alt = (shape & 2) != 0;
hold = ((shape ^ 8) & 9) != 0;
start1high = !attk;
start2high = cont && ! (attk ^ alt ^ hold);
setPhase(start1high);
}
public void setPhase(boolean isHigh) {
if (isHigh) {
amplitude = 15;
direction = -1;
} else {
amplitude = 0;
direction = 1;
}
}
public int getEffectiveAmplitude() {
return effectiveAmplitude;
}
public int getAmplitude() {
return amplitude;
}
@Override
public void reset() {
super.reset();
setShape(0);
}
}