Home | History | Annotate | Download | only in synth
      1 /*
      2  * Copyright (C) 2015 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.example.android.common.midi.synth;
     18 
     19 /**
     20  * Very simple Attack, Decay, Sustain, Release envelope with linear ramps.
     21  *
     22  * Times are in seconds.
     23  */
     24 public class EnvelopeADSR extends SynthUnit {
     25     private static final int IDLE = 0;
     26     private static final int ATTACK = 1;
     27     private static final int DECAY = 2;
     28     private static final int SUSTAIN = 3;
     29     private static final int RELEASE = 4;
     30     private static final int FINISHED = 5;
     31     private static final float MIN_TIME = 0.001f;
     32 
     33     private float mAttackRate;
     34     private float mRreleaseRate;
     35     private float mSustainLevel;
     36     private float mDecayRate;
     37     private float mCurrent;
     38     private int mSstate = IDLE;
     39 
     40     public EnvelopeADSR() {
     41         setAttackTime(0.003f);
     42         setDecayTime(0.08f);
     43         setSustainLevel(0.3f);
     44         setReleaseTime(1.0f);
     45     }
     46 
     47     public void setAttackTime(float time) {
     48         if (time < MIN_TIME)
     49             time = MIN_TIME;
     50         mAttackRate = 1.0f / (SynthEngine.FRAME_RATE * time);
     51     }
     52 
     53     public void setDecayTime(float time) {
     54         if (time < MIN_TIME)
     55             time = MIN_TIME;
     56         mDecayRate = 1.0f / (SynthEngine.FRAME_RATE * time);
     57     }
     58 
     59     public void setSustainLevel(float level) {
     60         if (level < 0.0f)
     61             level = 0.0f;
     62         mSustainLevel = level;
     63     }
     64 
     65     public void setReleaseTime(float time) {
     66         if (time < MIN_TIME)
     67             time = MIN_TIME;
     68         mRreleaseRate = 1.0f / (SynthEngine.FRAME_RATE * time);
     69     }
     70 
     71     public void on() {
     72         mSstate = ATTACK;
     73     }
     74 
     75     public void off() {
     76         mSstate = RELEASE;
     77     }
     78 
     79     @Override
     80     public float render() {
     81         switch (mSstate) {
     82         case ATTACK:
     83             mCurrent += mAttackRate;
     84             if (mCurrent > 1.0f) {
     85                 mCurrent = 1.0f;
     86                 mSstate = DECAY;
     87             }
     88             break;
     89         case DECAY:
     90             mCurrent -= mDecayRate;
     91             if (mCurrent < mSustainLevel) {
     92                 mCurrent = mSustainLevel;
     93                 mSstate = SUSTAIN;
     94             }
     95             break;
     96         case RELEASE:
     97             mCurrent -= mRreleaseRate;
     98             if (mCurrent < 0.0f) {
     99                 mCurrent = 0.0f;
    100                 mSstate = FINISHED;
    101             }
    102             break;
    103         }
    104         return mCurrent;
    105     }
    106 
    107     public boolean isDone() {
    108         return mSstate == FINISHED;
    109     }
    110 
    111 }
    112