1 | // Copyright (C) 2024 The Qt Company Ltd. |
---|---|
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only |
3 | |
4 | #include "qsinewavevalidator_p.h" |
5 | |
6 | #include <QtCore/qmath.h> |
7 | #include <QtCore/QDebug> |
8 | |
9 | QSineWaveValidator::QSineWaveValidator(float notchFrequency, float sampleRate) |
10 | { |
11 | using namespace std; |
12 | float pi = static_cast<float>(M_PI); |
13 | float f0 = notchFrequency; |
14 | float Fs = sampleRate; |
15 | float Q = 1 / sqrt(x: 2.f); // higher Q gives narrow bandwidth, but requires a larger number of |
16 | // frames during the transient |
17 | |
18 | // compare https://webaudio.github.io/Audio-EQ-Cookbook/Audio-EQ-Cookbook.txt |
19 | float w0 = 2 * pi * f0 / Fs; |
20 | float alpha = sin(x: w0) / (2 * Q); |
21 | |
22 | b0 = 1; |
23 | b1 = -2 * cos(x: w0); |
24 | b2 = 1; |
25 | a0 = 1 + alpha; |
26 | a1 = -2 * cos(x: w0); |
27 | a2 = 1 - alpha; |
28 | } |
29 | |
30 | void QSineWaveValidator::feedSample(float sample) |
31 | { |
32 | if (pendingFramesBeforeAnalysis == framesBeforeAnalysis) { |
33 | x.fill(u: sample); |
34 | y.fill(u: b0 / a0 * sample); |
35 | } |
36 | |
37 | x[2] = x[1]; |
38 | x[1] = x[0]; |
39 | x[0] = sample; |
40 | |
41 | y[2] = y[1]; |
42 | y[1] = y[0]; |
43 | y[0] = (b0 / a0) * x[0] + (b1 / a0) * x[1] + (b2 / a0) * x[2] - (a1 / a0) * y[1] |
44 | - (a2 / a0) * y[2]; |
45 | |
46 | accumPeak = std::max(a: std::abs(x: sample), b: accumPeak); |
47 | |
48 | if (pendingFramesBeforeAnalysis) { |
49 | pendingFramesBeforeAnalysis -= 1; |
50 | return; |
51 | } |
52 | |
53 | accumNotchPeak = std::max(a: std::abs(x: y[0]), b: accumNotchPeak); |
54 | } |
55 | |
56 | float QSineWaveValidator::notchPeak() const |
57 | { |
58 | if (pendingFramesBeforeAnalysis) |
59 | qWarning() << "notchPeak during initial frames. Result will not be accurate"; |
60 | return accumNotchPeak; |
61 | } |
62 |