Deluge Firmware 1.3.0
Build date: 2026.06.26
Loading...
Searching...
No Matches
cosine_oscillator.hpp
1// Copyright 2014 Emilie Gillet. MIT License.
2// Cosine oscillator. Generates a cosine between 0.0 and 1.0 with minimal
3// CPU use. Fixed frequency.
4
5#pragma once
6#include "argon.hpp"
7#include <cmath>
8#include <initializer_list>
9
10class DualCosineOscillator {
11public:
12 enum class Mode { APPROX, EXACT };
13
14 template <Mode mode = Mode::APPROX>
15 constexpr DualCosineOscillator(std::array<float, 2> frequencies)
16 : frequencies_(ArgonHalf<float>::Load(frequencies.data())) {
17 Init<mode>();
18 }
19 ~DualCosineOscillator() = default;
20
21 template <Mode mode = Mode::APPROX>
22 inline void SetFrequency(int index, float frequency) {
23 frequencies_[index] = frequency;
24 Init<mode>();
25 }
26
27 inline void InitApproximate() {
28 ArgonHalf<float> sign = 16.0f;
29 ArgonHalf<float> frequencies = frequencies_;
30 frequencies = frequencies.each_lane_with_index([&](float& frequency, int i) {
31 frequency -= 0.25f;
32 if (frequency < 0.0f) {
33 frequency = -frequency;
34 }
35 else if (frequency > 0.5f) {
36 frequency -= 0.5f;
37 }
38 else {
39 sign[i] = -16.0f;
40 }
41 });
42 iir_coefficient_ = sign * frequencies * (1.0f - (2.0f * frequencies));
43 initial_amplitude_ = iir_coefficient_ * 0.25f;
44 }
45
46 constexpr void Start() {
47 y_0 = initial_amplitude_;
48 y_1 = 0.5f;
49 }
50
51 [[nodiscard]] inline ArgonHalf<float> values() const { return y_0 + 0.5f; }
52
53 inline ArgonHalf<float> Next() {
54 ArgonHalf<float> temp = y_1;
55 y_1 = iir_coefficient_ * y_1 - y_0;
56 y_0 = temp;
57 return temp + 0.5f;
58 }
59
60private:
61 template <Mode mode = Mode::APPROX>
62 inline void Init() {
63 if constexpr (mode == Mode::APPROX) {
64 InitApproximate();
65 }
66 else {
67 for (size_t i = 0; i < frequencies_.size(); ++i) {
68 iir_coefficient_[i] = 2.0f * std::cos(2.0f * std::numbers::pi_v<float> * frequencies_[i]);
69 initial_amplitude_[i] = iir_coefficient_[i] * 0.25f;
70 }
71 }
72 Start();
73 }
74
75 ArgonHalf<float> frequencies_;
76 ArgonHalf<float> y_0;
77 ArgonHalf<float> y_1;
78 ArgonHalf<float> iir_coefficient_;
79 ArgonHalf<float> initial_amplitude_;
80};