| /* |
| * 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; |
| } |
| |
| } |