diff --git a/libs/audio/include/psemek/audio/effect/butterworth.hpp b/libs/audio/include/psemek/audio/effect/butterworth.hpp new file mode 100644 index 00000000..8178bfde --- /dev/null +++ b/libs/audio/include/psemek/audio/effect/butterworth.hpp @@ -0,0 +1,12 @@ +#pragma once + +#include + +namespace psemek::audio +{ + + // Second-order + stream_ptr butterworth_low_pass(stream_ptr stream, float cutoff_frequency); + stream_ptr butterworth_high_pass(stream_ptr stream, float cutoff_frequency); + +} diff --git a/libs/audio/source/butterworth.cpp b/libs/audio/source/butterworth.cpp new file mode 100644 index 00000000..521d8789 --- /dev/null +++ b/libs/audio/source/butterworth.cpp @@ -0,0 +1,59 @@ +#include +#include +#include +#include + +namespace psemek::audio +{ + + stream_ptr butterworth_low_pass(stream_ptr stream, float cutoff_frequency) + { + float omega = 2.f * static_cast(math::pi) * cutoff_frequency * audio::inv_frequency; + omega = 2.f * audio::frequency * std::tan(omega / 2.f); + + float gamma = 2.f * audio::frequency / omega; + float sqrt2 = std::sqrt(2.f); + + float a0 = gamma * gamma + sqrt2 * gamma + 1.f; + float a1 = - 2.f * gamma * gamma + 2.f; + float a2 = gamma * gamma - sqrt2 * gamma + 1.f; + + float b0 = 1.f; + float b1 = 2.f; + float b2 = 1.f; + + a1 /= a0; + a2 /= a0; + b0 /= a0; + b1 /= a0; + b2 /= a0; + + return linear_filter(std::move(stream), {a1, a2}, {b0, b1, b2}); + } + + stream_ptr butterworth_high_pass(stream_ptr stream, float cutoff_frequency) + { + float omega = 2.f * static_cast(math::pi) * (audio::frequency / 2.f - cutoff_frequency) * audio::inv_frequency; + omega = 2.f * audio::frequency * std::tan(omega / 2.f); + + float gamma = 2.f * audio::frequency / omega; + float sqrt2 = std::sqrt(2.f); + + float a0 = gamma * gamma + sqrt2 * gamma + 1.f; + float a1 = 2.f * gamma * gamma - 2.f; + float a2 = gamma * gamma - sqrt2 * gamma + 1.f; + + float b0 = 1.f; + float b1 = - 2.f; + float b2 = 1.f; + + a1 /= a0; + a2 /= a0; + b0 /= a0; + b1 /= a0; + b2 /= a0; + + return linear_filter(std::move(stream), {a1, a2}, {b0, b1, b2}); + } + +}