Vital
Loading...
Searching...
No Matches
wave_frame.cpp
Go to the documentation of this file.
1#include "wave_frame.h"
2#include "futils.h"
3#include "fourier_transform.h"
4
5namespace vital {
6
10 for (int i = 0; i < kWaveformSize; ++i) {
11 frequency_domain[i] = 0.0f;
12 time_domain[i] = 0.0f;
13 }
14 }
15
17 for (int i = 0; i < kWaveformSize; ++i) {
18 time_domain[i] *= value;
19 frequency_domain[i] *= value;
20 }
21 }
22
23 void WaveFrame::loadTimeDomain(float* buffer) {
24 for (int i = 0; i < kWaveformSize; ++i)
25 time_domain[i] = buffer[i];
26
28 }
29
31 mono_float max = 0.0f;
32 for (int i = 0; i < kWaveformSize; ++i)
33 max = std::max(max, fabsf(time_domain[i]));
34
35 return max;
36 }
37
38 void WaveFrame::normalize(bool allow_positive_gain) {
39 constexpr mono_float kMaxInverseMult = 0.0000001f;
41 mono_float min = 1.0f;
42 if (allow_positive_gain)
43 min = kMaxInverseMult;
44
45 mono_float normalization = 1.0f / std::max(min, max);
46 for (int i = 0; i < kWaveformSize; ++i)
47 time_domain[i] *= normalization;
48 }
49
51 for (int i = 0; i < kWaveformSize; ++i) {
52 time_domain[i] += source->time_domain[i];
53 frequency_domain[i] += source->frequency_domain[i];
54 }
55 }
56
57 void WaveFrame::copy(const WaveFrame* other) {
58 for (int i = 0; i < kWaveformSize; ++i) {
60 time_domain[i] = other->time_domain[i];
61 }
62 }
63
71 float* frequency_data = getFrequencyData();
72 memcpy(frequency_data, time_domain, kWaveformSize * sizeof(float));
73 memset(frequency_data + kWaveformSize, 0, kWaveformSize * sizeof(float));
75 }
76
84 float* frequency_data = getFrequencyData();
85 memcpy(time_domain, frequency_domain, 2 * kNumRealComplex * sizeof(float));
86 memset(frequency_data + 2 * kNumRealComplex, 0, 2 * kNumExtraComplex * sizeof(float));
88 }
89
97 float offset = frequency_domain[0].imag();
98 frequency_domain[0] = 0.0f;
99 for (int i = 0; i < kWaveformSize; ++i)
100 time_domain[i] -= offset;
101 }
102
107 createSin(wave_frames_[kSin]);
108 createSaturatedSin(wave_frames_[kSaturatedSin]);
109 createTriangle(wave_frames_[kTriangle]);
110 createSquare(wave_frames_[kSquare]);
111 createSaw(wave_frames_[kSaw]);
112 createPulse(wave_frames_[kPulse]);
113 }
114
115 void PredefinedWaveFrames::createSin(WaveFrame& wave_frame) {
122 int half_waveform = WaveFrame::kWaveformSize / 2;
123 wave_frame.frequency_domain[1] = half_waveform;
124 wave_frame.toTimeDomain();
125 }
126
127 void PredefinedWaveFrames::createSaturatedSin(WaveFrame& wave_frame) {
132 wave_frame.frequency_domain[1] = WaveFrame::kWaveformSize;
133 wave_frame.toTimeDomain();
134 for (int i = 0; i < WaveFrame::kWaveformSize; ++i) {
135 wave_frame.time_domain[i] = futils::tanh(wave_frame.time_domain[i]);
136 }
137 wave_frame.toFrequencyDomain();
138 }
139
140 void PredefinedWaveFrames::createTriangle(WaveFrame& wave_frame) {
145 int section_size = WaveFrame::kWaveformSize / 4;
146 for (int i = 0; i < section_size; ++i) {
147 mono_float t = i / (section_size * 1.0f);
148 wave_frame.time_domain[i] = 1.0f - t;
149 wave_frame.time_domain[i + section_size] = -t;
150 wave_frame.time_domain[i + 2 * section_size] = t - 1.0f;
151 wave_frame.time_domain[i + 3 * section_size] = t;
152 }
153 wave_frame.toFrequencyDomain();
154 }
155
156 void PredefinedWaveFrames::createSquare(WaveFrame& wave_frame) {
161 int section_size = WaveFrame::kWaveformSize / 4;
162 for (int i = 0; i < section_size; ++i) {
163 wave_frame.time_domain[i] = 1.0f;
164 wave_frame.time_domain[i + section_size] = -1.0f;
165 wave_frame.time_domain[i + 2 * section_size] = -1.0f;
166 wave_frame.time_domain[i + 3 * section_size] = 1.0f;
167 }
168 wave_frame.toFrequencyDomain();
169 }
170
171 void PredefinedWaveFrames::createPulse(WaveFrame& wave_frame) {
176 int sections = 4;
177 int pulse_size = WaveFrame::kWaveformSize / sections;
178
179 for (int i = 0; i < pulse_size; ++i) {
180 wave_frame.time_domain[i + (sections - 1) * pulse_size] = 1.0f;
181 for (int s = 0; s < sections - 1; ++s)
182 wave_frame.time_domain[i + s * pulse_size] = -1.0f;
183 }
184 wave_frame.toFrequencyDomain();
185 }
186
187 void PredefinedWaveFrames::createSaw(WaveFrame& wave_frame) {
192 int section_size = WaveFrame::kWaveformSize / 2;
193 for (int i = 0; i < section_size; ++i) {
194 mono_float t = i / (section_size * 1.0f);
195 wave_frame.time_domain[(i + WaveFrame::kWaveformSize / 4) % WaveFrame::kWaveformSize] = t - 1.0f;
196 wave_frame.time_domain[(i + section_size + WaveFrame::kWaveformSize / 4) % WaveFrame::kWaveformSize] = t;
197 }
198 wave_frame.toFrequencyDomain();
199 }
200
201} // namespace vital
static FourierTransform * transform()
Provides access to a static FourierTransform instance for the specified bits.
Definition fourier_transform.h:298
void transformRealForward(float *data)
Performs an in-place forward real FFT using KissFFT.
Definition fourier_transform.h:234
void transformRealInverse(float *data)
Performs an in-place inverse real FFT using KissFFT.
Definition fourier_transform.h:257
PredefinedWaveFrames()
Constructs the PredefinedWaveFrames, initializing all predefined shapes.
Definition wave_frame.cpp:103
@ kSaturatedSin
Definition wave_frame.h:148
@ kTriangle
Definition wave_frame.h:149
@ kSquare
Definition wave_frame.h:150
@ kSaw
Definition wave_frame.h:152
@ kPulse
Definition wave_frame.h:151
@ kSin
Definition wave_frame.h:147
Represents a single frame of a wavetable, containing both time-domain and frequency-domain data.
Definition wave_frame.h:16
void copy(const WaveFrame *other)
Copies another WaveFrame's time and frequency domain data into this one.
Definition wave_frame.cpp:57
static constexpr float kDefaultSampleRate
The default sample rate for a WaveFrame.
Definition wave_frame.h:29
float sample_rate
The sample rate associated with this frame.
Definition wave_frame.h:123
void addFrom(WaveFrame *source)
Adds another WaveFrame's data to this one, sample-by-sample, in both time and frequency domains.
Definition wave_frame.cpp:50
float frequency_ratio
The frequency ratio for this frame (e.g., for pitch scaling).
Definition wave_frame.h:122
std::complex< float > frequency_domain[kWaveformSize]
The frequency-domain representation (complex spectrum).
Definition wave_frame.h:125
void toFrequencyDomain()
Converts the currently loaded time-domain data into frequency-domain representation.
Definition wave_frame.cpp:64
static constexpr int kWaveformSize
The size of the waveform (number of samples per frame).
Definition wave_frame.h:21
static constexpr float kDefaultFrequencyRatio
The default frequency ratio for a WaveFrame (usually 1.0f).
Definition wave_frame.h:27
mono_float time_domain[2 *kWaveformSize]
The time-domain data, extended buffer size for FFT alignment.
Definition wave_frame.h:124
static constexpr int kNumExtraComplex
The number of "extra" complex bins to pad after the real frequency components.
Definition wave_frame.h:25
void toTimeDomain()
Converts the currently loaded frequency-domain data into time-domain representation.
Definition wave_frame.cpp:77
float * getFrequencyData()
Gets a pointer to the frequency-domain data interpreted as floats.
Definition wave_frame.h:132
void removedDc()
Removes the DC offset from the waveform.
Definition wave_frame.cpp:90
static constexpr int kNumRealComplex
The number of real-valued frequency components (half the size + 1).
Definition wave_frame.h:23
mono_float getMaxZeroOffset() const
Retrieves the maximum absolute amplitude in the time-domain waveform.
Definition wave_frame.cpp:30
void multiply(mono_float value)
Multiplies all samples in both time and frequency domains by a given value.
Definition wave_frame.cpp:16
void loadTimeDomain(float *buffer)
Loads time-domain data from a given buffer and updates the frequency domain accordingly.
Definition wave_frame.cpp:23
void normalize(bool allow_positive_gain=false)
Normalizes the time-domain waveform samples to have a maximum absolute value of 1....
Definition wave_frame.cpp:38
void clear()
Clears the waveform data, resetting it to default states.
Definition wave_frame.cpp:7
Contains faster but less accurate versions of utility math functions, such as exponential,...
force_inline poly_float tanh(poly_float value)
Approximates tanh function using a complex polynomial.
Definition futils.h:347
Contains classes and functions used within the Vital synthesizer framework.
float mono_float
Definition common.h:33