2 Copyright (C) 2014 Carl Hetherington <cth@carlh.net>
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 #include "audio_filter.h"
21 #include "audio_buffers.h"
26 using boost::shared_ptr;
29 AudioFilter::sinc_blackman (float cutoff, bool invert) const
31 vector<float> ir (_M + 1);
33 /* Impulse response */
35 for (int i = 0; i <= _M; ++i) {
37 ir[i] = 2 * M_PI * cutoff;
40 ir[i] = sin (2 * M_PI * cutoff * (i - _M / 2)) / (i - _M / 2);
42 ir[i] *= (0.42 - 0.5 * cos (2 * M_PI * i / _M) + 0.08 * cos (4 * M_PI * i / _M));
49 for (int i = 0; i <= _M; ++i) {
53 for (int i = 0; i <= _M; ++i) {
57 /* Frequency inversion (swapping low-pass for high-pass, or whatever) */
60 for (int i = 0; i <= _M; ++i) {
69 shared_ptr<AudioBuffers>
70 AudioFilter::run (shared_ptr<AudioBuffers> in)
72 shared_ptr<AudioBuffers> out (new AudioBuffers (in->channels(), in->frames()));
75 _tail.reset (new AudioBuffers (in->channels(), _M + 1));
76 _tail->make_silent ();
79 for (int i = 0; i < in->channels(); ++i) {
80 for (int j = 0; j < in->frames(); ++j) {
82 for (int k = 0; k <= _M; ++k) {
84 s += _tail->data(i)[j - k + _M + 1] * _ir[k];
86 s += in->data(i)[j - k] * _ir[k];
94 int const amount = min (in->frames(), _tail->frames());
95 if (amount < _tail->frames ()) {
96 _tail->move (amount, 0, _tail->frames() - amount);
98 _tail->copy_from (in.get(), amount, in->frames() - amount, _tail->frames () - amount);
104 AudioFilter::flush ()
109 LowPassAudioFilter::LowPassAudioFilter (float transition_bandwidth, float cutoff)
110 : AudioFilter (transition_bandwidth)
112 _ir = sinc_blackman (cutoff, false);
116 HighPassAudioFilter::HighPassAudioFilter (float transition_bandwidth, float cutoff)
117 : AudioFilter (transition_bandwidth)
119 _ir = sinc_blackman (cutoff, true);
122 BandPassAudioFilter::BandPassAudioFilter (float transition_bandwidth, float lower, float higher)
123 : AudioFilter (transition_bandwidth)
125 vector<float> lpf = sinc_blackman (lower, false);
126 vector<float> hpf = sinc_blackman (higher, true);
129 for (int i = 0; i <= _M; ++i) {
130 _ir[i] = lpf[i] + hpf[i];
133 /* We now have a band-stop, so invert for band-pass */
134 for (int i = 0; i <= _M; ++i) {