From cec99d15ad920457eea61bc442b5ba610c13430e Mon Sep 17 00:00:00 2001 From: "Steinar H. Gunderson" Date: Thu, 12 Mar 2015 20:00:28 +0100 Subject: [PATCH] Split the filter code into a class. --- Makefile | 4 ++-- filter.cpp | 25 +++++++++++++++++++++++++ filter.h | 26 ++++++++++++++++++++++++++ level.cpp | 53 ++++++++++------------------------------------------- 4 files changed, 63 insertions(+), 45 deletions(-) create mode 100644 filter.cpp create mode 100644 filter.h diff --git a/Makefile b/Makefile index fe8c404..a3cf95f 100644 --- a/Makefile +++ b/Makefile @@ -6,12 +6,12 @@ all: synth decode sync cleaner %.o: %.cpp $(CXX) -MMD -MP $(CPPFLAGS) $(CXXFLAGS) -o $@ -c $< -OBJS=decode.o synth.o synth_main.o interpolate.o sync.o level.o +OBJS=decode.o synth.o synth_main.o interpolate.o sync.o level.o filter.o DEPS=$(OBJS:.o=.d) -include $(DEPS) -decode: interpolate.o audioreader.o decode.o level.o +decode: interpolate.o audioreader.o decode.o level.o filter.o $(CXX) -o $@ $^ $(LDLIBS) $(LDFLAGS) synth: synth.o synth_main.o diff --git a/filter.cpp b/filter.cpp new file mode 100644 index 0000000..d8f9701 --- /dev/null +++ b/filter.cpp @@ -0,0 +1,25 @@ +#include + +#include "filter.h" + +void Filter::reset() +{ + d0 = d1 = 0.0f; +} + +Filter Filter::lpf(float cutoff_radians) +{ + float resonance = 1.0f / sqrt(2.0f); + float sn = sin(cutoff_radians), cs = cos(cutoff_radians); + float alpha = float(sn / (2 * resonance)); + + // coefficients for lowpass filter + float a0 = 1 + alpha; + float b0 = (1 - cs) * 0.5f; + float b1 = 1 - cs; + float b2 = b0; + float a1 = -2 * cs; + float a2 = 1 - alpha; + + return Filter(a0, a1, a2, b0, b1, b2); +} diff --git a/filter.h b/filter.h new file mode 100644 index 0000000..a67f98a --- /dev/null +++ b/filter.h @@ -0,0 +1,26 @@ +#ifndef _FILTER_H +#define _FILTER_H 1 + +class Filter { +public: + Filter(float a0, float a1, float a2, float b0, float b1, float b2) + : a1(a1 / a0), a2(a2 / a0), b0(b0 / a0), b1(b1 / a0), b2(b2 / a0), d0(0.0f), d1(0.0f) {} + + inline float update(float in) + { + float out = b0*in + d0; + d0 = b1 * in - a1 * out + d1; + d1 = b2 * in - a2 * out; + return out; + } + + void reset(); + + static Filter lpf(float cutoff_radians); + +private: + float a1, a2, b0, b1, b2; + float d0, d1; +}; + +#endif // !defined(_FILTER_H) diff --git a/level.cpp b/level.cpp index e95b48e..6e63d26 100644 --- a/level.cpp +++ b/level.cpp @@ -6,6 +6,8 @@ #include #include +#include "filter.h" + // The frequency to filter on, in Hertz. Larger values makes the // compressor react faster, but if it is too large, you'll // ruin the waveforms themselves. @@ -18,41 +20,6 @@ // 6dB/oct per round. #define FILTER_DEPTH 4 -static float a1, a2, b0, b1, b2; -static float d0, d1; - -static void filter_init(float cutoff_radians) -{ - float resonance = 1.0f / sqrt(2.0f); - float sn = sin(cutoff_radians), cs = cos(cutoff_radians); - float alpha = float(sn / (2 * resonance)); - - // coefficients for lowpass filter - float a0 = 1 + alpha; - b0 = (1 - cs) * 0.5f; - b1 = 1 - cs; - b2 = b0; - a1 = -2 * cs; - a2 = 1 - alpha; - - b0 /= a0; - b1 /= a0; - b2 /= a0; - a1 /= a0; - a2 /= a0; - - // reset filter delays - d0 = d1 = 0.0f; -} - -static float filter_update(float in) -{ - float out = b0*in + d0; - d0 = b1 * in - a1 * out + d1; - d1 = b2 * in - a2 * out; - return out; -} - std::vector level_samples(const std::vector &pcm, float min_level, int sample_rate) { // filter forwards, then backwards (perfect phase filtering) @@ -61,23 +28,23 @@ std::vector level_samples(const std::vector &pcm, float min_level, refiltered_samples.resize(pcm.size()); leveled_samples.resize(pcm.size()); - filter_init(M_PI * LPFILTER_FREQ / sample_rate); + Filter filter = Filter::lpf(M_PI * LPFILTER_FREQ / sample_rate); for (unsigned i = 0; i < pcm.size(); ++i) { - filtered_samples[i] = filter_update(fabs(pcm[i])); + filtered_samples[i] = filter.update(fabs(pcm[i])); } - filter_init(M_PI * LPFILTER_FREQ / sample_rate); + filter.reset(); for (unsigned i = pcm.size(); i --> 0; ) { - refiltered_samples[i] = filter_update(filtered_samples[i]); + refiltered_samples[i] = filter.update(filtered_samples[i]); } for (int i = 1; i < FILTER_DEPTH; ++i) { - filter_init(M_PI * LPFILTER_FREQ / sample_rate); + filter.reset(); for (unsigned i = 0; i < pcm.size(); ++i) { - filtered_samples[i] = filter_update(refiltered_samples[i]); + filtered_samples[i] = filter.update(refiltered_samples[i]); } - filter_init(M_PI * LPFILTER_FREQ / sample_rate); + filter.reset(); for (unsigned i = pcm.size(); i --> 0; ) { - refiltered_samples[i] = filter_update(filtered_samples[i]); + refiltered_samples[i] = filter.update(filtered_samples[i]); } } -- 2.39.2