-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSimpleBiquad.h
More file actions
92 lines (86 loc) · 4.32 KB
/
SimpleBiquad.h
File metadata and controls
92 lines (86 loc) · 4.32 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
// ./SimpleBiquad.h
#pragma once
#include <string>
#include <cmath>
#include <algorithm>
#include <stdexcept>
#include <nlohmann/json.hpp>
// jsonエイリアスを追加
using json = nlohmann::json;
// --- Utilities ---
inline double db_to_linear(double db) {
if (!std::isfinite(db)) return 1.0;
return std::pow(10.0, db / 20.0);
}
// --- Simple Biquad Filter ---
class SimpleBiquad {
public:
SimpleBiquad(std::string name = "Unnamed") : filter_name_(name) { reset(); }
void reset() { a1 = 0.0; a2 = 0.0; b0 = 1.0; b1 = 0.0; b2 = 0.0; z1 = 0.0; z2 = 0.0; is_bypassed_ = false; }
void set_lpf(double sr, double freq, double q) {
reset();
q = std::max(0.1, q); freq = std::max(10.0, std::min(freq, sr / 2.2));
double w0 = 2.0 * M_PI * freq / sr, cos_w0 = std::cos(w0), sin_w0 = std::sin(w0);
double alpha = sin_w0 / (2.0 * q), a0 = 1.0 + alpha;
b0 = (1.0 - cos_w0) / 2.0 / a0; b1 = (1.0 - cos_w0) / a0; b2 = b0;
a1 = -2.0 * cos_w0 / a0; a2 = (1.0 - alpha) / a0;
}
void set_hpf(double sr, double freq, double q) {
reset();
q = std::max(0.1, q); freq = std::max(10.0, std::min(freq, sr / 2.2));
double w0 = 2.0 * M_PI * freq / sr, cos_w0 = std::cos(w0), sin_w0 = std::sin(w0);
double alpha = sin_w0 / (2.0 * q), a0 = 1.0 + alpha;
b0 = (1.0 + cos_w0) / 2.0 / a0; b1 = -(1.0 + cos_w0) / a0; b2 = b0;
a1 = -2.0 * cos_w0 / a0; a2 = (1.0 - alpha) / a0;
}
void set_peaking(double sr, double freq, double q, double gain_db) {
reset();
q = std::max(0.1, q); freq = std::max(10.0, std::min(freq, sr / 2.2));
double A = db_to_linear(gain_db / 2.0);
double w0 = 2.0 * M_PI * freq / sr, cos_w0 = std::cos(w0), sin_w0 = std::sin(w0);
double alpha = sin_w0 / (2.0 * q), a0 = 1.0 + alpha / A;
b0 = (1.0 + alpha * A) / a0; b1 = -2.0 * cos_w0 / a0; b2 = (1.0 - alpha * A) / a0;
a1 = b1; a2 = (1.0 - alpha / A) / a0;
}
// ◾️◾️◾️◾️◾️◾️◾️◾️◾️◾️◾️↓修正開始◾️◾️◾️◾️◾️◾️◾️◾️◾️◾️◾️
void set_lowshelf(double sr, double freq, double q, double gain_db) {
reset();
q = std::max(0.1, q); freq = std::max(10.0, std::min(freq, sr / 2.2));
double A = db_to_linear(gain_db / 2.0);
double w0 = 2.0 * M_PI * freq / sr, cos_w0 = std::cos(w0), sin_w0 = std::sin(w0);
double alpha = sin_w0 / (2.0 * q);
double two_sqrt_A_alpha = 2.0 * sqrt(A) * alpha;
double a0 = (A + 1.0) + (A - 1.0) * cos_w0 + two_sqrt_A_alpha;
b0 = A * ((A + 1.0) - (A - 1.0) * cos_w0 + two_sqrt_A_alpha) / a0;
b1 = 2.0 * A * ((A - 1.0) - (A + 1.0) * cos_w0) / a0;
b2 = A * ((A + 1.0) - (A - 1.0) * cos_w0 - two_sqrt_A_alpha) / a0;
a1 = -2.0 * ((A - 1.0) + (A + 1.0) * cos_w0) / a0;
a2 = ((A + 1.0) + (A - 1.0) * cos_w0 - two_sqrt_A_alpha) / a0;
}
void set_highshelf(double sr, double freq, double q, double gain_db) {
reset();
q = std::max(0.1, q); freq = std::max(10.0, std::min(freq, sr / 2.2));
double A = db_to_linear(gain_db / 2.0);
double w0 = 2.0 * M_PI * freq / sr, cos_w0 = std::cos(w0), sin_w0 = std::sin(w0);
double alpha = sin_w0 / (2.0 * q);
double two_sqrt_A_alpha = 2.0 * sqrt(A) * alpha;
double a0 = (A + 1.0) - (A - 1.0) * cos_w0 + two_sqrt_A_alpha;
b0 = A * ((A + 1.0) + (A - 1.0) * cos_w0 + two_sqrt_A_alpha) / a0;
b1 = -2.0 * A * ((A - 1.0) + (A + 1.0) * cos_w0) / a0;
b2 = A * ((A + 1.0) + (A - 1.0) * cos_w0 - two_sqrt_A_alpha) / a0;
a1 = 2.0 * ((A - 1.0) - (A + 1.0) * cos_w0) / a0;
a2 = ((A + 1.0) - (A - 1.0) * cos_w0 - two_sqrt_A_alpha) / a0;
}
// ◾️◾️◾️◾️◾️◾️◾️◾️◾️◾️◾️↑修正終わり◾️◾️◾️◾️◾️◾️◾️◾️◾️◾️◾️
float process(float in) {
if (is_bypassed_ || std::isnan(in) || std::isinf(in)) return in;
if (std::isnan(z1) || std::isinf(z1) || std::isnan(z2) || std::isinf(z2)) reset();
double out = b0 * in + z1;
z1 = b1 * in - a1 * out + z2;
z2 = b2 * in - a2 * out;
return static_cast<float>(out);
}
private:
std::string filter_name_; bool is_bypassed_ = false;
double a1, a2, b0, b1, b2, z1, z2;
};