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