root/trunk/libs/hydrogen/src/adsr.cpp @ 889

Revision 889, 3.2 KB (checked in by gabriel@…, 4 years ago)

Trigger note release instead of abrupt cutoff on note-off events.

(Thanks to Krzysztof Foltman for the patch.)

Issue was reported to the forums [1] that bass drum kicks on TR808
created a clicking sound when used with a MIDI controller. In the
sampler, NOTE OFF events create an abrupt mute on the instrument,
which creates a high-frequency click. This patch instead triggers a
release on the instrument, respecting the mute group of the
instrument.

[1]  http://www.hydrogen-music.org/forum/?action=show_thread&fid=0&thread=1034&page=1

Line 
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/adsr.h>
24#include "table/getTableValue.h"
25#include "table/TableExponential.h"
26
27namespace H2Core
28{
29
30inline static float linear_interpolation( float fVal_A, float fVal_B, float fVal )
31{
32        return fVal_A * ( 1 - fVal ) + fVal_B * fVal;
33//      return fVal_A + fVal * ( fVal_B - fVal_A );
34//      return fVal_A + ((fVal_B - fVal_A) * fVal);
35}
36
37
38ADSR::ADSR(
39    float attack,
40    float decay,
41    float sustain,
42    float release
43)
44                : Object( "ADSR" )
45                , __attack( attack )
46                , __decay( decay )
47                , __sustain( sustain )
48                , __release( release )
49                , __state( ATTACK )
50                , __ticks( 0.0 )
51                , __value( 0.0 )
52{
53        //INFOLOG( "INIT" );
54}
55
56
57
58ADSR::ADSR( const ADSR& orig )
59                : Object( "ADSR" )
60                , __attack( orig.__attack )
61                , __decay( orig.__decay )
62                , __sustain( orig.__sustain )
63                , __release( orig.__release )
64                , __state( orig.__state )
65                , __ticks( orig.__ticks )
66                , __value( orig.__value )
67{
68        //INFOLOG( "INIT - copy ctr" );
69}
70
71
72
73ADSR::~ADSR()
74{
75        //INFOLOG( "DESTROY" );
76}
77
78
79float ADSR::get_value( float step )
80{
81        switch ( __state ) {
82        case ATTACK:
83                if ( __attack == 0 ) {
84                        __value = 1.0;
85                } else {
86                        __value = getTableValue ( linear_interpolation( 0.0, 1.0, ( __ticks * 1.0 / __attack ) ), tableExponentConvex, tableExponentConvexSize );
87                }
88
89                __ticks += step;
90                if ( __ticks > __attack ) {
91                        __state = DECAY;
92                        __ticks = 0;
93                }
94                break;
95
96        case DECAY:
97                if ( __decay == 0 ) {
98                        __value = __sustain;
99                } else {
100                        __value = getTableValue ( linear_interpolation( 1.0, __sustain, ( __ticks * 1.0 / __decay ) ), tableExponentConcave, tableExponentConcaveSize );
101                }
102
103                __ticks += step;
104                if ( __ticks > __decay ) {
105                        __state = SUSTAIN;
106                        __ticks = 0;
107                }
108                break;
109
110        case SUSTAIN:
111                __value = __sustain;
112                break;
113
114        case RELEASE:
115                if ( __release == 0 ) {
116                        __value = 0.0;
117                } else {
118                        __value = getTableValue ( linear_interpolation( __release_value, 0.0, ( __ticks * 1.0 / __release ) ), tableExponentConcave, tableExponentConcaveSize );
119                }
120
121                __ticks += step;
122                if ( __ticks > __release ) {
123                        __state = IDLE;
124                        __ticks = 0;
125                }
126                break;
127
128        case IDLE:
129        default:
130                __value = 0;
131        };
132
133        return __value;
134}
135
136
137///
138/// Retuns the current value. Returns 0 if the note is ended.
139///
140float ADSR::release()
141{
142        if ( __state == IDLE ) {
143                return 0;
144        }
145
146        if ( __state != RELEASE ) {
147                __release_value = __value;
148                __state = RELEASE;
149                __ticks = 0;
150                return __release_value;
151        }
152
153        return 1;
154}
155
156};
157
Note: See TracBrowser for help on using the browser.