/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.android.common.midi.synth;
/**
* Very simple Attack, Decay, Sustain, Release envelope with linear ramps.
*
* Times are in seconds.
*/
public class EnvelopeADSR extends SynthUnit {
private static final int IDLE = 0;
private static final int ATTACK = 1;
private static final int DECAY = 2;
private static final int SUSTAIN = 3;
private static final int RELEASE = 4;
private static final int FINISHED = 5;
private static final float MIN_TIME = 0.001f;
private float mAttackRate;
private float mRreleaseRate;
private float mSustainLevel;
private float mDecayRate;
private float mCurrent;
private int mSstate = IDLE;
public EnvelopeADSR() {
setAttackTime(0.003f);
setDecayTime(0.08f);
setSustainLevel(0.3f);
setReleaseTime(1.0f);
}
public void setAttackTime(float time) {
if (time < MIN_TIME)
time = MIN_TIME;
mAttackRate = 1.0f / (SynthEngine.FRAME_RATE * time);
}
public void setDecayTime(float time) {
if (time < MIN_TIME)
time = MIN_TIME;
mDecayRate = 1.0f / (SynthEngine.FRAME_RATE * time);
}
public void setSustainLevel(float level) {
if (level < 0.0f)
level = 0.0f;
mSustainLevel = level;
}
public void setReleaseTime(float time) {
if (time < MIN_TIME)
time = MIN_TIME;
mRreleaseRate = 1.0f / (SynthEngine.FRAME_RATE * time);
}
public void on() {
mSstate = ATTACK;
}
public void off() {
mSstate = RELEASE;
}
@Override
public float render() {
switch (mSstate) {
case ATTACK:
mCurrent += mAttackRate;
if (mCurrent > 1.0f) {
mCurrent = 1.0f;
mSstate = DECAY;
}
break;
case DECAY:
mCurrent -= mDecayRate;
if (mCurrent < mSustainLevel) {
mCurrent = mSustainLevel;
mSstate = SUSTAIN;
}
break;
case RELEASE:
mCurrent -= mRreleaseRate;
if (mCurrent < 0.0f) {
mCurrent = 0.0f;
mSstate = FINISHED;
}
break;
}
return mCurrent;
}
public boolean isDone() {
return mSstate == FINISHED;
}
}