FastLED 3.9.15
Loading...
Searching...
No Matches

◆ hexwave_generate_samples()

void fl::third_party::hexwave::hexwave_generate_samples ( float * output,
int32_t num_samples,
HexWave * hex,
float freq )

Generate audio samples.

Parameters
outputBuffer where the library will store generated floating point audio samples
num_samplesThe number of audio samples to generate
hexPointer to a HexWave initialized with hexwave_create
freqFrequency of the oscillator divided by the sample rate

The output samples will continue from where the samples generated by the previous hexwave_generate_samples() on this oscillator ended.

Definition at line 191 of file stb_hexwave.cpp.hpp.

192{
193 HexWaveEngine *engine = hex->engine;
194 hexvert vert[9];
195 int32_t pass,i,j;
196 float t = hex->t;
197 float temp_output[2*FL_STB_HEXWAVE_MAX_BLEP_LENGTH];
198 int32_t buffered_length = static_cast<int32_t>(sizeof(float)*engine->width);
199 float dt = (float) fabs(freq);
200 float recip_dt = (dt == 0.0f) ? 0.0f : 1.0f / dt;
201
202 int32_t halfw = engine->width/2;
203 // all sample times are biased by halfw to leave room for BLEP/BLAMP to go back in time
204
205 if (num_samples <= 0)
206 return;
207
208 // convert parameters to times and slopes
210
211 if (hex->prev_dt != dt) {
212 // if frequency changes, add a fixup at the derivative discontinuity starting at now
213 float slope;
214 for (j=1; j < 6; ++j)
215 if (t < vert[j].t)
216 break;
217 slope = vert[j].s;
218 if (slope != 0)
219 hex_blamp(output, 0, (dt - hex->prev_dt)*slope, engine);
220 hex->prev_dt = dt;
221 }
222
223 // copy the buffered data from last call and clear the rest of the output array
224 memset(output, 0, sizeof(float)*num_samples);
225 memset(temp_output, 0, 2*engine->width*sizeof(float));
226
227 if (num_samples >= engine->width) {
228 memcpy(output, hex->buffer, buffered_length);
229 } else {
230 // if the output is shorter than engine->width, we do all synthesis to temp_output
231 memcpy(temp_output, hex->buffer, buffered_length);
232 }
233
234 for (pass=0; pass < 2; ++pass) {
235 int32_t i0,i1;
236 float *out;
237
238 // we want to simulate having one buffer that is num_output + engine->width
239 // samples long, without putting that requirement on the user, and without
240 // allocating a temp buffer that's as long as the whole thing. so we use two
241 // overlapping buffers, one the user's buffer and one a fixed-length temp
242 // buffer.
243
244 if (pass == 0) {
245 if (num_samples < engine->width)
246 continue;
247 // run as far as we can without overwriting the end of the user's buffer
248 out = output;
249 i0 = 0;
250 i1 = num_samples - engine->width;
251 } else {
252 // generate the rest into a temp buffer
253 out = temp_output;
254 i0 = 0;
255 if (num_samples >= engine->width)
256 i1 = engine->width;
257 else
258 i1 = num_samples;
259 }
260
261 // determine current segment
262 for (j=0; j < 8; ++j)
263 if (t < vert[j+1].t)
264 break;
265
266 i = i0;
267 for(;;) {
268 while (t < vert[j+1].t) {
269 if (i == i1)
270 goto done;
271 out[i+halfw] += vert[j].v + vert[j].s*(t - vert[j].t);
272 t += dt;
273 ++i;
274 }
275 // transition from lineseg starting at j to lineseg starting at j+1
276
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);
280 ++j;
281
282 if (j == 8) {
283 // change to different waveform if there's a change pending
284 j = 0;
285 t -= 1.0f; // t was >= 1.f if j==8
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;
292 // the following never occurs with this oscillator, but it makes
293 // the code work in more general cases
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);
298 }
299 }
300 }
301 done:
302 ;
303 }
304
305 // at this point, we've written output[] and temp_output[]
306 if (num_samples >= engine->width) {
307 // the first half of temp[] overlaps the end of output, the second half will be the new start overlap
308 for (i=0; i < engine->width; ++i)
309 output[num_samples-engine->width + i] += temp_output[i];
310 memcpy(hex->buffer, temp_output+engine->width, buffered_length);
311 } else {
312 for (i=0; i < num_samples; ++i)
313 output[i] = temp_output[i];
314 memcpy(hex->buffer, temp_output+num_samples, buffered_length);
315 }
316
317 hex->t = t;
318}
bool done
void * memcpy(void *dest, const void *src, size_t n) FL_NOEXCEPT
double fabs(double value) FL_NOEXCEPT
Definition math.h:509
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 hexwave_generate_linesegs(hexvert vert[9], HexWave *hex, float dt) FL_NOEXCEPT
static void hex_blamp(float *output, float time_since_transition, float scale, HexWaveEngine *engine) FL_NOEXCEPT
int32_t width
Width of fixup in samples (4..64)
Definition stb_hexwave.h:99
Engine state holding BLEP/BLAMP tables.
Definition stb_hexwave.h:98
fl::i32 int32_t
Definition coder.h:220
const hex_t hex
Definition ios.cpp.hpp:6
u8 width
Definition blur.h:186
#define FL_STB_HEXWAVE_MAX_BLEP_LENGTH
Definition stb_hexwave.h:67

References done, fabs(), FL_NOEXCEPT, FL_STB_HEXWAVE_MAX_BLEP_LENGTH, fl::hex, hex_blamp(), hex_blep(), hexwave_generate_linesegs(), memcpy(), memset(), fl::third_party::hexwave::hexvert::s, fl::t, fl::third_party::hexwave::hexvert::t, fl::third_party::hexwave::hexvert::v, fl::third_party::hexwave::HexWaveEngine::width, and fl::width.

+ Here is the call graph for this function: