Line data Source code
1 : /*
2 : * SPDX-License-Identifier: GPL-3.0-only
3 : * MuseScore-CLA-applies
4 : *
5 : * MuseScore Studio
6 : * Music Composition & Notation
7 : *
8 : * Copyright (C) 2023 MuseScore Limited and others
9 : *
10 : * This program is free software: you can redistribute it and/or modify
11 : * it under the terms of the GNU General Public License version 3 as
12 : * published by the Free Software Foundation.
13 : *
14 : * This program is distributed in the hope that it will be useful,
15 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 : * GNU General Public License for more details.
18 : *
19 : * You should have received a copy of the GNU General Public License
20 : * along with this program. If not, see <https://www.gnu.org/licenses/>.
21 : */
22 :
23 : #ifndef MUSE_AUDIO_ALLPASSMODULATEDDELAY_H
24 : #define MUSE_AUDIO_ALLPASSMODULATEDDELAY_H
25 :
26 : #include "circularsamplebuffer.h"
27 :
28 : namespace muse::audio::fx {
29 : class AllPassModulatedDelay
30 : {
31 : public:
32 0 : AllPassModulatedDelay()
33 0 : {
34 0 : }
35 :
36 0 : void allocateForMaxDelaySamples(int maxDelaySamples)
37 : {
38 0 : m_buffer.setSize(maxDelaySamples);
39 0 : }
40 :
41 0 : void setBaseDelay(float samples, float maxModulationOffset)
42 : {
43 0 : int allocSize = int(samples + maxModulationOffset + 16.f); // some extra space for interpolation
44 0 : if (samples != m_baseDelay || allocSize > m_buffer.getAllocatedSize()) {
45 0 : allocateForMaxDelaySamples(allocSize);
46 0 : m_baseDelay = samples;
47 0 : setModOffset(0.f);
48 0 : reset();
49 : }
50 0 : }
51 :
52 : float getBaseDelay() const
53 : {
54 : return m_baseDelay;
55 : }
56 :
57 0 : void setModOffset(float smpOffset)
58 : {
59 0 : float total = -m_baseDelay + smpOffset; // negative!
60 0 : float flr = std::floor(total);
61 0 : m_modFraction = total - flr;
62 0 : m_readOffset = int(flr);
63 0 : }
64 :
65 0 : void writeSampleAndAdvance(float sample)
66 : {
67 0 : m_buffer.writeOffset0(sample);
68 0 : m_buffer.advance(1);
69 0 : }
70 :
71 0 : float readSample()
72 : {
73 0 : auto res = m_buffer.read(m_readOffset);
74 0 : auto x1 = m_buffer.read(m_readOffset + 1);
75 :
76 0 : res += m_modFraction * (x1 - m_y1);
77 0 : m_y1 = res;
78 0 : return res;
79 : }
80 :
81 : float processSample(float sample)
82 : {
83 : writeSampleAndAdvance(sample);
84 : return readSample();
85 : }
86 :
87 0 : void reset()
88 : {
89 0 : m_buffer.reset();
90 0 : m_y1 = 0.f;
91 0 : }
92 :
93 : private:
94 : int m_readOffset = 0;
95 : float m_modFraction = 0.f;
96 : float m_baseDelay = 0.f;
97 :
98 : CircularSampleBuffer<float> m_buffer;
99 : float m_y1 = 0.f;
100 : };
101 : } // namespace muse::audio::fx
102 :
103 : #endif // MUSE_AUDIO_ALLPASSMODULATEDDELAY_H
|