Deluge Firmware 1.3.0
Build date: 2026.10.14
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#include <numbers>
10
11class DualCosineOscillator {
12public:
13 enum class Mode { APPROX, EXACT };
14
15 template <Mode mode = Mode::APPROX>
16 constexpr DualCosineOscillator(std::array<float, 2> frequencies)
17 : frequencies_(ArgonHalf<float>::Load(frequencies.data())) {
18 Init<mode>();
19 }
20 ~DualCosineOscillator() = default;
21
22 template <Mode mode = Mode::APPROX>
23 inline void SetFrequency(int index, float frequency) {
24 frequencies_[index] = frequency;
25 Init<mode>();
26 }
27
28 inline void InitApproximate() {
29 ArgonHalf<float> sign = 16.0f;
30 ArgonHalf<float> frequencies = frequencies_;
31 frequencies = frequencies.each_lane_with_index([&](float& frequency, int i) {
32 frequency -= 0.25f;
33 if (frequency < 0.0f) {
34 frequency = -frequency;
35 }
36 else if (frequency > 0.5f) {
37 frequency -= 0.5f;
38 }
39 else {
40 sign[i] = -16.0f;
41 }
42 });
43 iir_coefficient_ = sign * frequencies * (1.0f - (2.0f * frequencies));
44 initial_amplitude_ = iir_coefficient_ * 0.25f;
45 }
46
47 constexpr void Start() {
48 y_0 = initial_amplitude_;
49 y_1 = 0.5f;
50 }
51
52 [[nodiscard]] inline ArgonHalf<float> values() const { return y_0 + 0.5f; }
53
54 inline ArgonHalf<float> Next() {
55 ArgonHalf<float> temp = y_1;
56 y_1 = iir_coefficient_ * y_1 - y_0;
57 y_0 = temp;
58 return temp + 0.5f;
59 }
60
61private:
62 template <Mode mode = Mode::APPROX>
63 inline void Init() {
64 if constexpr (mode == Mode::APPROX) {
65 InitApproximate();
66 }
67 else {
68 for (size_t i = 0; i < frequencies_.size(); ++i) {
69 iir_coefficient_[i] = 2.0f * std::cos(2.0f * std::numbers::pi_v<float> * frequencies_[i]);
70 initial_amplitude_[i] = iir_coefficient_[i] * 0.25f;
71 }
72 }
73 Start();
74 }
75
76 ArgonHalf<float> frequencies_;
77 ArgonHalf<float> y_0;
78 ArgonHalf<float> y_1;
79 ArgonHalf<float> iir_coefficient_;
80 ArgonHalf<float> initial_amplitude_;
81};