FastLED 3.9.15
Loading...
Searching...
No Matches
synth.cpp.hpp
Go to the documentation of this file.
1// synth.cpp.hpp - Implementation of bandlimited audio synthesizer oscillator
2//
3// This file implements the fl::ISynthOscillator interface and related APIs
4// that wrap the low-level stb_hexwave library.
5
6#include "fl/audio/synth.h"
7#include "fl/stl/cstring.h"
8#include "fl/stl/malloc.h"
9// IWYU pragma: begin_keep
11#include "fl/stl/noexcept.h"
12// IWYU pragma: end_keep
13
14namespace fl {
15namespace audio {
16
17// Short alias for third_party hexwave namespace to avoid verbose qualification
18// without polluting fl:: namespace in unity builds.
19namespace hw = third_party::hexwave;
20
21
23// SynthEngineImpl - Implementation of ISynthEngine interface
25
27public:
28 SynthEngineImpl(i32 width, i32 oversample);
30
31 // Non-copyable
34
35 // ISynthEngine interface
36 bool isValid() const override;
37 i32 getWidth() const override { return mWidth; }
38 i32 getOversample() const override { return mOversample; }
39
40 // Internal access for SynthOscillatorImpl (same compilation unit)
41 hw::HexWaveEngine* getEngineInternal() const { return mEngine; }
42
43private:
44 hw::HexWaveEngine* mEngine = nullptr;
45 i32 mWidth;
47};
48
50// SynthOscillatorImpl - Implementation of ISynthOscillator interface
52
54public:
57
58 // Non-copyable
61
62 // ISynthOscillator interface
63 void generateSamples(float* output, i32 numSamples, float freq) override;
64 void generateSamples(fl::span<float> output, float freq) override;
65 void setShape(SynthShape shape) override;
66 void setParams(const SynthParams& params) override;
67 SynthParams getParams() const override;
68 void reset() override;
69 ISynthEnginePtr getEngine() const override { return mEngine; }
70
71private:
72 fl::shared_ptr<SynthEngineImpl> mEngine; // Shared pointer to engine (keeps it alive)
73 hw::HexWave* mHexWave = nullptr; // Typed pointer to HexWave structure
75};
76
77// SynthParams implementation
79 switch (shape) {
81 return SynthParams(1, 0.0f, 0.0f, 0.0f);
83 return SynthParams(1, 0.0f, 1.0f, 0.0f);
85 return SynthParams(1, 0.5f, 0.0f, 0.0f);
87 return SynthParams(0, 0.0f, 0.0f, 0.0f);
89 default:
90 return SynthParams(); // Default to sawtooth
91 }
92}
93
95// ISynthEngine static factory method
97
98ISynthEnginePtr ISynthEngine::create(i32 width, i32 oversample) {
99 return fl::make_shared<SynthEngineImpl>(width, oversample);
100}
101
103// SynthEngineImpl implementation
105
107 : mWidth(width), mOversample(oversample) {
108 // Clamp width to valid range
109 if (mWidth < 4) mWidth = 4;
111
112 // Clamp oversample to minimum
113 if (mOversample < 2) mOversample = 2;
114
115 mEngine = hw::hexwave_engine_create(mWidth, mOversample, nullptr);
116}
117
119 if (mEngine) {
120 hw::hexwave_engine_destroy(mEngine);
121 mEngine = nullptr;
122 }
123}
124
126 return mEngine != nullptr;
127}
128
130// ISynthOscillator static factory methods
132
133ISynthOscillatorPtr ISynthOscillator::create(ISynthEnginePtr engine, SynthShape shape) {
134 return create(engine, SynthParams::fromShape(shape));
135}
136
137ISynthOscillatorPtr ISynthOscillator::create(ISynthEnginePtr engine, const SynthParams& params) {
138 if (!engine || !engine->isValid()) {
139 return nullptr;
140 }
141 // Safe downcast - we control the factory, so we know the concrete type
142 auto engineImpl = fl::static_pointer_cast<SynthEngineImpl>(engine);
143 return fl::make_shared<SynthOscillatorImpl>(engineImpl, params);
144}
145
147// SynthOscillatorImpl implementation
149
151 : mEngine(engine), mCurrentParams(params) {
152 // Allocate HexWave structure
153 mHexWave = static_cast<hw::HexWave*>(fl::malloc(sizeof(hw::HexWave)));
154 fl::memset(mHexWave, 0, sizeof(hw::HexWave));
155
156 // Initialize the oscillator with the engine
157 hw::hexwave_create(
158 mHexWave,
159 engine->getEngineInternal(),
160 params.reflect,
161 params.peakTime,
162 params.halfHeight,
163 params.zeroWait
164 );
165}
166
173
174void SynthOscillatorImpl::generateSamples(float* output, i32 numSamples, float freq) {
175 if (mHexWave && output && numSamples > 0) {
176 hw::hexwave_generate_samples(output, numSamples, mHexWave, freq);
177 }
178}
179
181 generateSamples(output.data(), static_cast<i32>(output.size()), freq);
182}
183
187
189 if (mHexWave) {
190 mCurrentParams = params;
191 hw::hexwave_change(
192 mHexWave,
193 params.reflect,
194 params.peakTime,
195 params.halfHeight,
196 params.zeroWait
197 );
198 }
199}
200
204
206 if (mHexWave && mEngine) {
207 // Re-create the oscillator with current parameters
208 hw::hexwave_create(
209 mHexWave,
210 mEngine->getEngineInternal(),
211 mCurrentParams.reflect,
212 mCurrentParams.peakTime,
213 mCurrentParams.halfHeight,
214 mCurrentParams.zeroWait
215 );
216 }
217}
218
219} // namespace audio
220} // namespace fl
static ISynthEnginePtr create(i32 width=32, i32 oversample=16)
Factory function to create an engine with the specified quality settings.
Definition synth.cpp.hpp:98
Interface for synth engine that holds BLEP/BLAMP tables.
Definition synth.h:90
static ISynthOscillatorPtr create(ISynthEnginePtr engine, const SynthParams &params)
Factory function to create an oscillator with specified engine and parameters.
Interface class for synth oscillator.
Definition synth.h:117
i32 getWidth() const override
Get the width setting.
Definition synth.cpp.hpp:37
hw::HexWaveEngine * getEngineInternal() const
Definition synth.cpp.hpp:41
i32 getOversample() const override
Get the oversample setting.
Definition synth.cpp.hpp:38
hw::HexWaveEngine * mEngine
Definition synth.cpp.hpp:44
~SynthEngineImpl() FL_NOEXCEPT override
SynthEngineImpl(const SynthEngineImpl &) FL_NOEXCEPT=delete
bool isValid() const override
Check if engine was initialized successfully.
SynthEngineImpl(i32 width, i32 oversample)
SynthEngineImpl & operator=(const SynthEngineImpl &) FL_NOEXCEPT=delete
ISynthEnginePtr getEngine() const override
Get the engine this oscillator uses.
Definition synth.cpp.hpp:69
SynthOscillatorImpl & operator=(const SynthOscillatorImpl &) FL_NOEXCEPT=delete
~SynthOscillatorImpl() FL_NOEXCEPT override
void setParams(const SynthParams &params) override
Change waveform parameters (takes effect at next cycle boundary)
SynthOscillatorImpl(const SynthOscillatorImpl &) FL_NOEXCEPT=delete
SynthOscillatorImpl(fl::shared_ptr< SynthEngineImpl > engine, const SynthParams &params)
void generateSamples(float *output, i32 numSamples, float freq) override
Generate audio samples.
void setShape(SynthShape shape) override
Change waveform shape (takes effect at next cycle boundary)
void reset() override
Reset oscillator to beginning of cycle.
SynthParams getParams() const override
Get current waveform parameters.
fl::shared_ptr< SynthEngineImpl > mEngine
Definition synth.cpp.hpp:72
SynthShape
Predefined waveform shapes for synth oscillator.
Definition synth.h:59
void * memset(void *s, int c, size_t n) FL_NOEXCEPT
void * malloc(size_t size)
Definition malloc.cpp.hpp:9
u8 width
Definition blur.h:186
shared_ptr< T > make_shared(Args &&... args) FL_NOEXCEPT
Definition shared_ptr.h:414
void free(void *ptr)
shared_ptr< T > static_pointer_cast(const shared_ptr< Y > &other) FL_NOEXCEPT
Definition shared_ptr.h:514
Base definition for an LED controller.
Definition crgb.hpp:179
#define FL_NOEXCEPT
#define FL_STB_HEXWAVE_MAX_BLEP_LENGTH
Definition stb_hexwave.h:67
float peakTime
Position of peak in cycle [0..1].
Definition synth.h:70
SynthParams() FL_NOEXCEPT=default
Default constructor - sawtooth wave.
float halfHeight
Height at half-cycle point.
Definition synth.h:71
static SynthParams fromShape(SynthShape shape)
Create parameters for a predefined shape.
Definition synth.cpp.hpp:78
float zeroWait
Wait time at zero [0..1].
Definition synth.h:72
i32 reflect
Mirror second half of waveform (0 or 1)
Definition synth.h:69
Waveform parameters for custom waveforms.
Definition synth.h:68
Bandlimited audio synthesizer - waveform oscillator module.