optimize some performance bottlenecks; remove jack_nframes_t that crept back into...
[ardour.git] / libs / ardour / amp.cc
1 /*
2     Copyright (C) 2006 Paul Davis 
3     
4     This program is free software; you can redistribute it and/or modify it
5     under the terms of the GNU General Public License as published by the Free
6     Software Foundation; either version 2 of the License, or (at your option)
7     any later version.
8     
9     This program is distributed in the hope that it will be useful, but WITHOUT
10     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12     for more details.
13     
14     You should have received a copy of the GNU General Public License along
15     with this program; if not, write to the Free Software Foundation, Inc.,
16     675 Mass Ave, Cambridge, MA 02139, USA.
17 */
18
19 #include <ardour/amp.h>
20
21 #include <algorithm>
22 #include <cmath>
23 #include <ardour/buffer_set.h>
24 #include <ardour/buffer.h>
25
26 namespace ARDOUR {
27
28
29 /** Apply a declicked gain to the audio buffers of @a bufs */
30 void
31 Amp::run (BufferSet& bufs, nframes_t nframes, gain_t initial, gain_t target, bool invert_polarity)
32 {
33         if (nframes == 0)
34                 return;
35
36         if (bufs.count().get(DataType::AUDIO) == 0)
37                 return;
38
39         // assert(bufs.buffer_capacity(DataType::AUDIO) >= nframes);
40
41         // if we don't need to declick, defer to apply_simple_gain
42
43         if (initial == target) {
44                 for (BufferSet::audio_iterator i = bufs.audio_begin(); i != bufs.audio_end(); ++i) {
45                         apply_gain_to_buffer (i->data (), nframes, target);
46                 }
47                 return;
48         }
49
50         const nframes_t declick = std::min ((nframes_t)128, nframes);
51         gain_t         delta;
52         double         fractional_shift = -1.0/declick;
53         double         fractional_pos;
54         gain_t         polscale = invert_polarity ? -1.0f : 1.0f;
55
56         if (target < initial) {
57                 /* fade out: remove more and more of delta from initial */
58                 delta = -(initial - target);
59         } else {
60                 /* fade in: add more and more of delta from initial */
61                 delta = target - initial;
62         }
63
64         for (BufferSet::audio_iterator i = bufs.audio_begin(); i != bufs.audio_end(); ++i) {
65                 Sample* const buffer = i->data();
66
67                 fractional_pos = 1.0;
68
69                 for (nframes_t nx = 0; nx < declick; ++nx) {
70                         buffer[nx] *= polscale * (initial + (delta * (0.5 + 0.5 * cos (M_PI * fractional_pos))));
71                         fractional_pos += fractional_shift;
72                 }
73                 
74                 /* now ensure the rest of the buffer has the target value applied, if necessary. */
75                 
76                 if (declick != nframes) {
77
78                         if (invert_polarity) {
79                                 target = -target;
80                         }
81
82                         if (target == 0.0) {
83                                 memset (&buffer[declick], 0, sizeof (Sample) * (nframes - declick));
84                         } else if (target != 1.0) {
85                                 apply_gain_to_buffer (&buffer[declick], nframes - declick, target);
86                         }
87                 }
88         }
89 }
90
91 void
92 Amp::apply_simple_gain (BufferSet& bufs, nframes_t nframes, gain_t target)
93 {
94 }
95
96
97 } // namespace ARDOUR