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 
EnvelopeADSR()40     public EnvelopeADSR() {
41         setAttackTime(0.003f);
42         setDecayTime(0.08f);
43         setSustainLevel(0.3f);
44         setReleaseTime(1.0f);
45     }
46 
setAttackTime(float time)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 
setDecayTime(float time)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 
setSustainLevel(float level)59     public void setSustainLevel(float level) {
60         if (level < 0.0f)
61             level = 0.0f;
62         mSustainLevel = level;
63     }
64 
setReleaseTime(float time)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 
on()71     public void on() {
72         mSstate = ATTACK;
73     }
74 
off()75     public void off() {
76         mSstate = RELEASE;
77     }
78 
79     @Override
render()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 
isDone()107     public boolean isDone() {
108         return mSstate == FINISHED;
109     }
110 
111 }
112