Pulp 1.88.0
Cross-platform audio plugin framework
Loading...
Searching...
No Matches
fm_tables.hpp
Go to the documentation of this file.
1#pragma once
2
4
5#include <algorithm>
6#include <array>
7#include <cmath>
8
9namespace pulp::signal::drum {
10
17 static constexpr int wave_count = 26;
18 static constexpr int harmonic_count = 4;
19
20 static constexpr std::array<std::array<double, harmonic_count>, wave_count>
22 {{1.00, 0.00, 0.000, 0.00}},
23 {{1.00, 0.50, 0.333, 0.25}},
24 {{1.00, -0.50, 0.333, -0.25}},
25 {{1.00, 0.00, 0.333, 0.00}},
26 {{1.00, 0.00, -0.111, 0.00}},
27 {{1.00, 0.70, 0.000, 0.00}},
28 {{1.00, -0.70, 0.000, 0.00}},
29 {{1.00, 0.00, 0.700, 0.00}},
30 {{1.00, 0.00, -0.700, 0.00}},
31 {{1.00, 0.00, 0.000, 0.70}},
32 {{1.00, 0.00, 0.000, -0.70}},
33 {{0.50, 1.00, 0.000, 0.00}},
34 {{0.50, 0.00, 1.000, 0.00}},
35 {{0.50, 0.00, 0.000, 1.00}},
36 {{1.00, 0.50, -0.333, 0.25}},
37 {{1.00, -0.50, -0.333, -0.25}},
38 {{1.00, 0.25, 0.750, 0.125}},
39 {{1.00, -0.25, 0.750, -0.125}},
40 {{0.75, 1.00, 0.500, 0.25}},
41 {{0.75, -1.00, 0.500, -0.25}},
42 {{1.00, 1.00, 1.000, 1.00}},
43 {{1.00, -1.00, 1.000, -1.00}},
44 {{1.00, 0.80, 0.400, 0.10}},
45 {{1.00, 0.10, 0.400, 0.80}},
46 {{0.25, 0.50, 0.750, 1.00}},
47 {{1.00, -0.25, -0.500, 0.75}},
48 }};
49
50 static double read(int wave, double phase,
51 double phase_increment = 0.0) {
52 const auto index =
53 static_cast<std::size_t>(std::clamp(wave, 0, wave_count - 1));
54 phase -= std::floor(phase);
55 const double increment = std::fabs(phase_increment);
56 double sample = 0.0;
57 double normalization = 0.0;
58 for (int harmonic = 0; harmonic < harmonic_count; ++harmonic) {
59 const double coefficient =
60 harmonics[index][static_cast<std::size_t>(harmonic)];
61 double nyquist_gain = 1.0;
62 if (increment > 0.0) {
63 // Fade each partial through the upper tenth of the band. A
64 // hard integer harmonic count clicks whenever a pitch sweep
65 // crosses 0.5 / N, and renormalizing the surviving partials
66 // makes that discontinuity larger.
67 constexpr double kTransitionWidth = 0.05;
68 const double distance =
69 0.5 - static_cast<double>(harmonic + 1) * increment;
70 const double t =
71 std::clamp(distance / kTransitionWidth, 0.0, 1.0);
72 nyquist_gain = t * t * (3.0 - 2.0 * t);
73 }
74 const double weighted = coefficient * nyquist_gain;
75 sample += weighted *
76 std::sin(2.0 * 3.14159265358979323846 *
77 static_cast<double>(harmonic + 1) * phase);
78 normalization += std::fabs(weighted);
79 }
80 return normalization > 0.0 ? sample / normalization : 0.0;
81 }
82
85 static double warp(double phase, double amount) {
86 phase -= std::floor(phase);
87 const double d = 0.5 * (1.0 - 0.98 * std::clamp(amount, 0.0, 1.0));
88 return phase < d ? phase * (0.5 / d)
89 : 0.5 + (phase - d) * (0.5 / (1.0 - d));
90 }
91};
92
101
104inline constexpr std::array<FmTransient, 24> kFmTransients{{
105 {NoiseColor::white, 0.00, 3.0, 0.10, 9000.0, 0.7},
106 {NoiseColor::white, 0.05, 4.0, 0.14, 7500.0, 1.0},
107 {NoiseColor::white, 0.10, 5.0, 0.18, 6200.0, 1.3},
108 {NoiseColor::pink, 0.08, 7.0, 0.12, 5200.0, 1.8},
109 {NoiseColor::pink, 0.15, 10.0, 0.16, 4200.0, 2.4},
110 {NoiseColor::pink, 0.22, 14.0, 0.20, 3400.0, 3.0},
111 {NoiseColor::brown, 0.12, 18.0, 0.08, 2800.0, 3.8},
112 {NoiseColor::brown, 0.20, 24.0, 0.12, 2400.0, 4.8},
113 {NoiseColor::violet, 0.05, 2.0, 0.18, 12000.0, 0.5},
114 {NoiseColor::violet, 0.10, 3.0, 0.24, 10000.0, 0.8},
115 {NoiseColor::violet, 0.18, 5.0, 0.30, 8200.0, 1.1},
116 {NoiseColor::blue, 0.08, 7.0, 0.20, 7000.0, 1.5},
117 {NoiseColor::blue, 0.16, 10.0, 0.26, 5800.0, 2.0},
118 {NoiseColor::blue, 0.24, 14.0, 0.32, 4800.0, 2.7},
119 {NoiseColor::white, 0.30, 20.0, 0.10, 3600.0, 3.5},
120 {NoiseColor::pink, 0.35, 28.0, 0.14, 3000.0, 4.5},
121 {NoiseColor::brown, 0.30, 40.0, 0.08, 2200.0, 6.0},
122 {NoiseColor::violet, 0.28, 8.0, 0.36, 14000.0, 0.6},
123 {NoiseColor::blue, 0.32, 12.0, 0.40, 11000.0, 0.9},
124 {NoiseColor::white, 0.40, 18.0, 0.44, 8800.0, 1.4},
125 {NoiseColor::pink, 0.45, 26.0, 0.30, 6500.0, 2.2},
126 {NoiseColor::brown, 0.50, 38.0, 0.22, 4600.0, 3.4},
127 {NoiseColor::violet, 0.38, 16.0, 0.50, 12500.0, 1.0},
128 {NoiseColor::blue, 0.55, 30.0, 0.55, 7200.0, 2.8},
129}};
130
131} // namespace pulp::signal::drum
Definition clap.hpp:13
constexpr std::array< FmTransient, 24 > kFmTransients
Twenty-four original procedural strike recipes.
Definition fm_tables.hpp:104
NoiseColor
Spectral tilt of a NoiseSourceT, named by the usual colour convention.
Definition noise_source.hpp:17
@ blue
+3 dB/octave — the mirror of pink.
Definition noise_source.hpp:21
@ pink
-3 dB/octave — equal power per octave.
Definition noise_source.hpp:19
@ brown
-6 dB/octave — integrated white ("red" noise).
Definition noise_source.hpp:20
@ violet
+6 dB/octave — differentiated white ("purple" noise).
Definition noise_source.hpp:22
@ white
0 dB/octave — the raw generator output.
Definition noise_source.hpp:18
Definition fm_tables.hpp:93
double click_cutoff_hz
Definition fm_tables.hpp:98
double click_decay_ms
Definition fm_tables.hpp:99
NoiseColor color
Definition fm_tables.hpp:94
double click_level
Definition fm_tables.hpp:97
double noise_decay_ms
Definition fm_tables.hpp:96
double noise_level
Definition fm_tables.hpp:95
A compact, license-clean bank of 26 phase-readable FM waves.
Definition fm_tables.hpp:16
static constexpr int harmonic_count
Definition fm_tables.hpp:18
static double warp(double phase, double amount)
Casio-family phase warp: amount zero is identity; one moves the bend point close to the start of the ...
Definition fm_tables.hpp:85
static constexpr int wave_count
Definition fm_tables.hpp:17
static constexpr std::array< std::array< double, harmonic_count >, wave_count > harmonics
Definition fm_tables.hpp:21
static double read(int wave, double phase, double phase_increment=0.0)
Definition fm_tables.hpp:50