36#ifndef FL_STB_HEXWAVE_HEADER_ONLY
57#define hexwave_clamp(v,a,b) ((v) < (a) ? (a) : (v) > (b) ? (b) : (v))
61 hex->pending.reflect = reflect;
63 hex->pending.half_height = half_height;
66 hex->have_pending = 1;
74 hex->current =
hex->pending;
75 hex->have_pending = 0;
94 int32_t slot = (
int32_t) (time_since_transition * engine->oversample);
95 if (slot >= engine->oversample)
96 slot = engine->oversample-1;
98 d1 = &data[ slot *bw];
99 d2 = &data[(slot+1)*bw];
101 lerpweight = time_since_transition * engine->oversample - slot;
102 for (i=0; i < bw; ++i)
103 output[i] +=
scale * (d1[i] + (d2[i]-d1[i])*lerpweight);
126 float min_len = dt / 256.0f;
130 vert[1].t =
hex->current.zero_wait*0.5f;
132 vert[2].t = 0.5f*
hex->current.peak_time + vert[1].t*(1-
hex->current.peak_time);
135 vert[3].v =
hex->current.half_height;
137 if (
hex->current.reflect) {
138 for (j=4; j <= 7; ++j) {
139 vert[j].t = 1 - vert[7-j].t;
140 vert[j].v = - vert[7-j].v;
143 for (j=4; j <= 7; ++j) {
144 vert[j].t = 0.5f + vert[j-4].t;
145 vert[j].v = - vert[j-4].v;
151 for (j=0; j < 8; ++j) {
152 if (vert[j+1].
t <= vert[j].
t + min_len) {
165 vert[j+1].t = vert[j].t;
169 if (vert[8].
t != 1.0f) {
173 for (j=5; j <= 8; ++j)
179 for (j=0; j < 8; ++j)
180 if (vert[j+1].
t == vert[j].
t)
183 vert[j].s = (vert[j+1].v - vert[j].v) / (vert[j+1].
t - vert[j].
t);
187 vert[8].v = vert[0].v;
188 vert[8].s = vert[0].s;
199 float dt = (float)
fabs(freq);
200 float recip_dt = (dt == 0.0f) ? 0.0f : 1.0f / dt;
205 if (num_samples <= 0)
211 if (
hex->prev_dt != dt) {
214 for (j=1; j < 6; ++j)
219 hex_blamp(output, 0, (dt -
hex->prev_dt)*slope, engine);
224 memset(output, 0,
sizeof(
float)*num_samples);
225 memset(temp_output, 0, 2*engine->
width*
sizeof(
float));
227 if (num_samples >= engine->
width) {
228 memcpy(output,
hex->buffer, buffered_length);
231 memcpy(temp_output,
hex->buffer, buffered_length);
234 for (pass=0; pass < 2; ++pass) {
245 if (num_samples < engine->
width)
250 i1 = num_samples - engine->
width;
255 if (num_samples >= engine->
width)
262 for (j=0; j < 8; ++j)
268 while (
t < vert[j+1].
t) {
271 out[i+halfw] += vert[j].
v + vert[j].
s*(
t - vert[j].
t);
277 if (vert[j].
t == vert[j+1].
t)
278 hex_blep(out+i, recip_dt*(
t-vert[j+1].
t), (vert[j+1].v - vert[j].v), engine);
279 hex_blamp(out+i, recip_dt*(
t-vert[j+1].
t), dt*(vert[j+1].s - vert[j].s), engine);
286 if (
hex->have_pending) {
287 float prev_s0 = vert[j].
s;
288 float prev_v0 = vert[j].
v;
289 hex->current =
hex->pending;
290 hex->have_pending = 0;
294 if (vert[j].v != prev_v0)
295 hex_blep (out+i, recip_dt*
t, (vert[j].v - prev_v0), engine);
296 if (vert[j].s != prev_s0)
297 hex_blamp(out+i, recip_dt*
t, dt*(vert[j].s - prev_s0), engine);
306 if (num_samples >= engine->
width) {
308 for (i=0; i < engine->
width; ++i)
309 output[num_samples-engine->
width + i] += temp_output[i];
312 for (i=0; i < num_samples; ++i)
313 output[i] = temp_output[i];
314 memcpy(
hex->buffer, temp_output+num_samples, buffered_length);
322 if (engine ==
nullptr)
325 #ifndef FL_STB_HEXWAVE_NO_ALLOCATION
326 if (engine->ownsBuffers) {
341 int32_t half = halfwidth*oversample;
345 #ifdef FL_STB_HEXWAVE_NO_ALLOCATION
346 (void)blep_buffer_count;
347 if (user_buffer ==
nullptr)
349 float *buffers = user_buffer;
351 float *buffers = user_buffer ? user_buffer : (
float *)
malloc(
sizeof(
float) * n * 2);
354 float *
step = buffers+0*n;
355 float *ramp = buffers+1*n;
356 float *blep_buffer, *blamp_buffer;
357 double integrate_impulse=0, integrate_step=0;
360 bool ownsBuffers =
false;
361 if (user_buffer == 0) {
362 #ifndef FL_STB_HEXWAVE_NO_ALLOCATION
363 blep_buffer = (
float *)
malloc(
sizeof(
float)*blep_buffer_count);
364 blamp_buffer = (
float *)
malloc(
sizeof(
float)*blep_buffer_count);
367 blep_buffer =
nullptr;
368 blamp_buffer =
nullptr;
371 blep_buffer = ramp+n;
372 blamp_buffer = blep_buffer + blep_buffer_count;
376 for (i=0; i < n; ++i) {
377 for (j=0; j < 16; ++j) {
378 float sinc_t = 3.141592f* (i-half) / oversample;
379 float sinc = (i==half) ? 1.0f : (float)
sin(
static_cast<double>(sinc_t)) / (sinc_t);
380 float wt = 2.0f*3.1415926f * i / (n-1);
381 float window = (float) (0.355768 - 0.487396*
cos(
static_cast<double>(wt)) + 0.144232*
cos(2*
static_cast<double>(wt)) - 0.012604*
cos(3*
static_cast<double>(wt)));
382 double value = window * sinc;
383 integrate_impulse +=
value/16;
384 integrate_step += integrate_impulse/16;
386 step[i] = (float) integrate_impulse;
387 ramp[i] = (float) integrate_step;
391 for (i=0; i < n; ++i) {
393 ramp[i] = ramp[i] * (float) (halfwidth / ramp[n-1]);
397 for (j=0; j <= oversample; ++j) {
398 for (i=0; i <
width; ++i) {
399 blep_buffer [j*
width+i] =
step[j+i*oversample];
400 blamp_buffer[j*
width+i] = ramp[j+i*oversample];
407 for (j=0; j <= oversample; ++j) {
409 for (i=halfwidth; i <
width; ++i)
410 blep_buffer [j*
width+i] -= 1.0f;
412 for (i=halfwidth; i <
width; ++i)
413 blamp_buffer[j*
width+i] -= (j+i*oversample-half)*(1.0f/oversample);
417 #ifndef FL_STB_HEXWAVE_NO_ALLOCATION
419 engine->
blep = blep_buffer;
420 engine->
blamp = blamp_buffer;
425 if (user_buffer == 0)
fl::UISlider scale("Scale", 4,.1, 4,.1)
void hexwave_engine_destroy(HexWaveEngine *engine) FL_NOEXCEPT
Destroy a HexWaveEngine and free its resources.
void * memcpy(void *dest, const void *src, size_t n) FL_NOEXCEPT
static HexWaveEngine * sGlobalEngine
double fabs(double value) FL_NOEXCEPT
static void hex_blep(float *output, float time_since_transition, float scale, HexWaveEngine *engine) FL_NOEXCEPT
void * memset(void *s, int c, size_t n) FL_NOEXCEPT
static void hex_add_oversampled_bleplike(float *output, float time_since_transition, float scale, float *data, HexWaveEngine *engine) FL_NOEXCEPT
void hexwave_create(HexWave *hex, HexWaveEngine *engine, int32_t reflect, float peak_time, float half_height, float zero_wait) FL_NOEXCEPT
Create a new oscillator with the given waveform parameters.
void hexwave_change(HexWave *hex, int32_t reflect, float peak_time, float half_height, float zero_wait) FL_NOEXCEPT
Change oscillator waveform parameters (takes effect at next cycle boundary)
void * malloc(size_t size)
void hexwave_create_legacy(HexWave *hex, int32_t reflect, float peak_time, float half_height, float zero_wait) FL_NOEXCEPT
Create oscillator using global engine (DEPRECATED)
enable_if< is_fixed_point< T >::value, T >::type cos(T angle) FL_NOEXCEPT
void hexwave_init(int32_t width, int32_t oversample, float *user_buffer) FL_NOEXCEPT
Initialize the hexwave library (DEPRECATED - use hexwave_engine_create)
enable_if< is_fixed_point< T >::value, T >::type sin(T angle) FL_NOEXCEPT
void hexwave_shutdown(float *user_buffer) FL_NOEXCEPT
Shutdown the hexwave library (DEPRECATED - use hexwave_engine_destroy)
HexWaveEngine * hexwave_engine_create(int32_t width, int32_t oversample, float *user_buffer) FL_NOEXCEPT
Create and initialize a new HexWaveEngine.
static void hexwave_generate_linesegs(hexvert vert[9], HexWave *hex, float dt) FL_NOEXCEPT
void hexwave_generate_samples(float *output, int32_t num_samples, HexWave *hex, float freq) FL_NOEXCEPT
Generate audio samples.
static void hex_blamp(float *output, float time_since_transition, float scale, HexWaveEngine *engine) FL_NOEXCEPT
float * blep
Band-limited step table.
bool ownsBuffers
True if engine allocated blep/blamp (vs user-provided)
float * blamp
Band-limited ramp table.
int32_t oversample
Number of oversampled versions.
int32_t width
Width of fixup in samples (4..64)
Engine state holding BLEP/BLAMP tables.
void * memcpy(void *dest, const void *src, size_t n) FL_NOEXCEPT
double fabs(double value) FL_NOEXCEPT
constexpr int type_rank< T >::value
void * memset(void *s, int c, size_t n) FL_NOEXCEPT
void * malloc(size_t size)
void * memmove(void *dest, const void *src, size_t n) FL_NOEXCEPT
enable_if< is_fixed_point< T >::value, T >::type cos(T angle) FL_NOEXCEPT
constexpr enable_if< is_fixed_point< T >::value, T >::type step(T edge, T x) FL_NOEXCEPT
enable_if< is_fixed_point< T >::value, T >::type sin(T angle) FL_NOEXCEPT
Base definition for an LED controller.
#define hexwave_clamp(v, a, b)
#define FL_STB_HEXWAVE_MAX_BLEP_LENGTH