1 /*
2 * Hydrogen
3 * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
4 *
5 * http://www.hydrogen-music.org
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY, without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 *
21 */
22
23 #include <hydrogen/basics/adsr.h>
24
25 #include "exponential_tables.h"
26
27 namespace H2Core
28 {
29
30 const char* ADSR::__class_name = "ADSR";
31
linear_interpolation(float fVal_A,float fVal_B,double fVal)32 inline static float linear_interpolation( float fVal_A, float fVal_B, double fVal )
33 {
34 return fVal_A * ( 1 - fVal ) + fVal_B * fVal;
35 //return fVal_A + fVal * ( fVal_B - fVal_A );
36 //return fVal_A + ((fVal_B - fVal_A) * fVal);
37 }
38
normalise()39 void ADSR::normalise()
40 {
41 if (__attack < 0.0) {
42 __attack = 0.0;
43 }
44 if (__decay < 0.0) {
45 __decay = 0.0;
46 }
47 if (__sustain < 0.0) {
48 __sustain = 0.0;
49 }
50 if (__release < 256) {
51 __release = 256;
52 }
53 if (__attack > 100000) {
54 __attack = 100000;
55 }
56 if (__decay > 100000) {
57 __decay = 100000;
58 }
59 if (__sustain > 1.0) {
60 __sustain = 1.0;
61 }
62 if (__release > 100256) {
63 __release = 100256;
64 }
65 }
66
ADSR(unsigned int attack,unsigned int decay,float sustain,unsigned int release)67 ADSR::ADSR( unsigned int attack, unsigned int decay, float sustain, unsigned int release ) : Object( __class_name ),
68 __attack( attack ),
69 __decay( decay ),
70 __sustain( sustain ),
71 __release( release ),
72 __state( ATTACK ),
73 __ticks( 0.0 ),
74 __value( 0.0 ),
75 __release_value( 0.0 )
76 {
77 normalise();
78 }
79
ADSR(const ADSR * other)80 ADSR::ADSR( const ADSR* other ) : Object( __class_name ),
81 __attack( other->__attack ),
82 __decay( other->__decay ),
83 __sustain( other->__sustain ),
84 __release( other->__release ),
85 __state( other->__state ),
86 __ticks( other->__ticks ),
87 __value( other->__value ),
88 __release_value( other->__release_value )
89 {
90 normalise();
91 }
92
~ADSR()93 ADSR::~ADSR() { }
94
95 //#define convex_exponant
96 //#define concave_exponant
97
get_value(float step)98 float ADSR::get_value( float step )
99 {
100 switch ( __state ) {
101 case ATTACK:
102 if ( __attack == 0 ) {
103 __value = 1.0;
104 } else {
105 __value = convex_exponant( linear_interpolation( 0.0, 1.0, ( __ticks * 1.0 / __attack ) ) );
106 }
107 __ticks += step;
108 if ( __ticks > __attack ) {
109 __state = DECAY;
110 __ticks = 0;
111 }
112 break;
113
114 case DECAY:
115 if ( __decay == 0 ) {
116 __value = __sustain;
117 } else {
118 __value = concave_exponant( linear_interpolation( 1.0, 0.0, ( __ticks * 1.0 / __decay ) ) ) * (1 - __sustain) + __sustain;
119 }
120 __ticks += step;
121 if ( __ticks > __decay ) {
122 __state = SUSTAIN;
123 __ticks = 0;
124 }
125 break;
126
127 case SUSTAIN:
128 __value = __sustain;
129 break;
130
131 case RELEASE:
132 if ( __release < 256 ) {
133 __release = 256;
134 }
135 __value = concave_exponant( linear_interpolation( 1.0, 0.0, ( __ticks * 1.0 / __release ) ) ) * __release_value;
136 __ticks += step;
137 if ( __ticks > __release ) {
138 __state = IDLE;
139 __ticks = 0;
140 }
141 break;
142
143 case IDLE:
144 default:
145 __value = 0;
146 };
147
148 return __value;
149 }
150
attack()151 void ADSR::attack()
152 {
153 __state = ATTACK;
154 __ticks = 0;
155 }
156
release()157 float ADSR::release()
158 {
159 if ( __state == IDLE ) return 0;
160 if ( __state == RELEASE ) return __value;
161 __release_value = __value;
162 __state = RELEASE;
163 __ticks = 0;
164 return __release_value;
165 }
166
167 };
168
169 /* vim: set softtabstop=4 noexpandtab: */
170