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