X-Git-Url: https://main.carlh.net/gitweb/?p=dcpomatic.git;a=blobdiff_plain;f=src%2Flib%2Faudio_filter.cc;h=281ac966831c8e80de73609a96a12132a763d67a;hp=59b5684ea62e2cd7e447599b215c6d1b6a44fc0e;hb=2d4e8c5f69cc694625ad95dcee554499605f823b;hpb=fc56dc97103d00437843a31e1ef0c4915900ad1a diff --git a/src/lib/audio_filter.cc b/src/lib/audio_filter.cc index 59b5684ea..281ac9668 100644 --- a/src/lib/audio_filter.cc +++ b/src/lib/audio_filter.cc @@ -1,37 +1,43 @@ /* - Copyright (C) 2014 Carl Hetherington + Copyright (C) 2014-2021 Carl Hetherington - This program is free software; you can redistribute it and/or modify + This file is part of DCP-o-matic. + + DCP-o-matic is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, + DCP-o-matic is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + along with DCP-o-matic. If not, see . */ -#include + #include "audio_filter.h" #include "audio_buffers.h" +#include "util.h" +#include -using std::vector; + +using std::make_shared; using std::min; -using boost::shared_ptr; +using std::shared_ptr; + -vector +/** @return array of floats which the caller must destroy with delete[] */ +float * AudioFilter::sinc_blackman (float cutoff, bool invert) const { - vector ir (_M + 1); - + float* ir = new float[_M + 1]; + /* Impulse response */ - + for (int i = 0; i <= _M; ++i) { if (i == (_M / 2)) { ir[i] = 2 * M_PI * cutoff; @@ -42,70 +48,85 @@ AudioFilter::sinc_blackman (float cutoff, bool invert) const ir[i] *= (0.42 - 0.5 * cos (2 * M_PI * i / _M) + 0.08 * cos (4 * M_PI * i / _M)); } } - + /* Normalise */ - + float sum = 0; for (int i = 0; i <= _M; ++i) { sum += ir[i]; } - + for (int i = 0; i <= _M; ++i) { ir[i] /= sum; } - + /* Frequency inversion (swapping low-pass for high-pass, or whatever) */ - + if (invert) { for (int i = 0; i <= _M; ++i) { ir[i] = -ir[i]; } ir[_M / 2] += 1; } - + return ir; } + +AudioFilter::~AudioFilter () +{ + delete[] _ir; +} + + shared_ptr -AudioFilter::run (shared_ptr in) +AudioFilter::run (shared_ptr in) { - shared_ptr out (new AudioBuffers (in->channels(), in->frames())); - + auto out = make_shared(in->channels(), in->frames()); + if (!_tail) { _tail.reset (new AudioBuffers (in->channels(), _M + 1)); _tail->make_silent (); } - - for (int i = 0; i < in->channels(); ++i) { - for (int j = 0; j < in->frames(); ++j) { + + int const channels = in->channels (); + int const frames = in->frames (); + + for (int i = 0; i < channels; ++i) { + auto tail_p = _tail->data (i); + auto in_p = in->data (i); + auto out_p = out->data (i); + for (int j = 0; j < frames; ++j) { float s = 0; for (int k = 0; k <= _M; ++k) { if ((j - k) < 0) { - s += _tail->data(i)[j - k + _M + 1] * _ir[k]; + s += tail_p[j - k + _M + 1] * _ir[k]; } else { - s += in->data(i)[j - k] * _ir[k]; + s += in_p[j - k] * _ir[k]; } } - - out->data(i)[j] = s; + + out_p[j] = s; } } - + int const amount = min (in->frames(), _tail->frames()); if (amount < _tail->frames ()) { - _tail->move (amount, 0, _tail->frames() - amount); + _tail->move (_tail->frames() - amount, amount, 0); } _tail->copy_from (in.get(), amount, in->frames() - amount, _tail->frames () - amount); - + return out; } + void AudioFilter::flush () { _tail.reset (); } + LowPassAudioFilter::LowPassAudioFilter (float transition_bandwidth, float cutoff) : AudioFilter (transition_bandwidth) { @@ -119,21 +140,26 @@ HighPassAudioFilter::HighPassAudioFilter (float transition_bandwidth, float cuto _ir = sinc_blackman (cutoff, true); } + BandPassAudioFilter::BandPassAudioFilter (float transition_bandwidth, float lower, float higher) : AudioFilter (transition_bandwidth) { - vector lpf = sinc_blackman (lower, false); - vector hpf = sinc_blackman (higher, true); - - _ir.resize (_M + 1); + auto lpf = sinc_blackman (lower, false); + auto hpf = sinc_blackman (higher, true); + + delete[] _ir; + _ir = new float[_M + 1]; for (int i = 0; i <= _M; ++i) { _ir[i] = lpf[i] + hpf[i]; } - + + delete[] lpf; + delete[] hpf; + /* We now have a band-stop, so invert for band-pass */ for (int i = 0; i <= _M; ++i) { _ir[i] = -_ir[i]; } - + _ir[_M / 2] += 1; }