Plaquette
Loading...
Searching...
No Matches
pq_phase_utils.h
1/*
2 * pq_phase_utils.h
3 *
4 * Utility functions for phase quantization oscillators.
5 *
6 * (c) 2022 Sofian Audry :: info(@)sofianaudry(.)com
7 *
8 * This program is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21#ifndef PQ_PHASE_UTILS_H_
22#define PQ_PHASE_UTILS_H_
23
24#if (defined(ARDUINO) && ARDUINO >= 100) || defined(EPOXY_DUINO)
25#include <Arduino.h>
26#else
27#include <WProgram.h>
28#endif
29
30#include "pq_globals.h"
31#include "pq_fixed.h"
32#include "pq_fixed32_math.h"
33#include "pq_time.h"
34#include "pq_wrap.h"
35
36#include <stdint.h>
37#include <float.h>
38
39namespace pq {
40
41// Precomputed constant: FIXED_32_MAX * MICROS_TO_SECONDS.
42// Used to convert a delta time in microseconds directly to the fixed-point
43// phase increment per step, avoiding 64-bit arithmetic on 8-bit platforms.
44constexpr float MICROS_TO_SECONDS_TIMES_FIXED_32_MAX = MICROS_TO_SECONDS * (float)FIXED_32_MAX;
45
47inline q0_32u_t amplifyFixed32(q0_32u_t x, q0_32u_t amplitude) {
48 // Shift to signed range (-UINT32_MAX/2 to UINT32_MAX/2).
49 int32_t centered = (int32_t)(x ^ HALF_FIXED_32_MAX);
50
51 // Apply amplitude scaling (keeping within 32-bit range).
52 centered = ((int64_t)centered * amplitude) >> 32;
53
54 // Convert back to unsigned range.
55 return (q0_32u_t)(centered ^ HALF_FIXED_32_MAX);
56}
57
59inline float amplifyFloat(float x, q0_32u_t amplitude) {
60 return fixed32ToFloat(amplitude) * (x - 0.5f) + 0.5f;
61}
62
64inline q0_32u_t floatToPhase32(float x) { return floatToFixed32(x); }
65
67inline q0_32u_t fixed32Divide(q0_32u_t x, q0_32u_t y) { return divide_32div32(x, y); }
68
70inline q0_32u_t fixed32Multiply(q0_32u_t x, q0_32u_t y) { return multiply_32x32_rshift32(x,y) ;}
71
73inline float timeToPhase(float period, float time) { return period == 0 ? 0 : time / period; }
74
76inline float frequencyAndTimeToPhase(float frequency, float time) { return time * frequency; }
77
79inline float invert(float x) { return (x == 0) ? FLT_MAX : 1.0f / x; }
80
82inline float periodToFrequency(float period) { return invert(period); }
83
85inline float frequencyToPeriod(float frequency) { return invert(frequency); }
86
87// https://www.programiz.com/online-compiler/1hIyxD51PqRYE
88// inline float stepIntervalForNormalizedValue(int count) { return (count <= 1) ? 1.0f : 1.0f / (count-1); }
89
91q0_32u_t phase32AddPhase(q0_32u_t phase32, float phase);
92
94q0_32u_t phase32AddTime(q0_32u_t phase32, float period, float time);
95
97bool phase32UpdateFixed32(q0_32u_t& phase32, float frequency, float deltaTimeSecondsTimesFixed32Max, bool forward = true);
98
100bool phase32Update(q0_32u_t& phase32, float period, float sampleRate, bool forward = true);
101
102}
103
104#endif