xref: /aosp_15_r20/external/oboe/apps/OboeTester/app/src/main/cpp/synth/DifferentiatedParabola.h (revision 05767d913155b055644481607e6fa1e35e2fe72c)
1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  * This code was translated from the JSyn Java code.
17  * JSyn is Copyright 2009 Phil Burk, Mobileer Inc
18  * JSyn is licensed under the Apache License, Version 2.0
19  */
20 
21 #ifndef SYNTHMARK_DIFFERENTIATED_PARABOLA_H
22 #define SYNTHMARK_DIFFERENTIATED_PARABOLA_H
23 
24 #include <cstdint>
25 #include <math.h>
26 #include "SynthTools.h"
27 
28 namespace marksynth {
29 
30 constexpr double kDPWVeryLowFrequency  = 2.0 * 0.1 / kSynthmarkSampleRate;
31 
32 /**
33  * DPW is a tool for generating band-limited waveforms
34  * based on a paper by Antti Huovilainen and Vesa Valimaki:
35  *  "New Approaches to Digital Subtractive Synthesis"
36  */
37 class DifferentiatedParabola
38 {
39 public:
DifferentiatedParabola()40     DifferentiatedParabola()
41     : mZ1(0)
42     , mZ2(0) {}
43 
44     virtual ~DifferentiatedParabola() = default;
45 
next(synth_float_t phase,synth_float_t phaseIncrement)46     synth_float_t next(synth_float_t phase, synth_float_t phaseIncrement) {
47         synth_float_t dpw;
48         synth_float_t positivePhaseIncrement = (phaseIncrement < 0.0)
49                 ? phaseIncrement
50                 : 0.0 - phaseIncrement;
51 
52         // If the frequency is very low then just use the raw sawtooth.
53         // This avoids divide by zero problems and scaling problems.
54         if (positivePhaseIncrement < kDPWVeryLowFrequency) {
55             dpw = phase;
56         } else {
57             // Calculate the parabola.
58             synth_float_t squared = phase * phase;
59             // Differentiate using a delayed value.
60             synth_float_t diffed = squared - mZ2;
61             // Delay line.
62             // TODO - Why Z2. Vesa's paper says use Z1?
63             mZ2 = mZ1;
64             mZ1 = squared;
65 
66             // Calculate scaling
67             dpw = diffed * 0.25f / positivePhaseIncrement; // TODO extract and optimize
68         }
69         return dpw;
70     }
71 
72 private:
73     synth_float_t mZ1;
74     synth_float_t mZ2;
75 };
76 
77 };
78 #endif // SYNTHMARK_DIFFERENTIATED_PARABOLA_H
79