πŸ‘ nectarine
Audio synthesis tools for C23
Loading...
Searching...
No Matches
waveforms.h
Go to the documentation of this file.
1/*
2 * πŸ‘ nectarine - waveforms.h
3 * Copyright (c) 2026 Fawn <rubiefawn@gmail.com>
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED β€œAS IS” AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
20#pragma once
21#include <stddef.h>
22#include <math.h>
23#include "vendor/prelude/hint.h"
24
35static constexpr long double NECTARINE_SINE_ERR_CORRECTION_WEIGHT = 0.225l;
36
51[[nodiscard, gnu::const]]
52static inline long double nec_wrapl(long double phase) [[unsequenced]] {
53 assume(0.l <= phase && phase < 1.l);
54 return phase - floorl(phase);
55}
56
58[[nodiscard, gnu::const]]
59static inline double nec_wrap(double phase) [[unsequenced]] {
60 assume(0.0 <= phase && phase < 1.0);
61 return phase - floor(phase);
62}
63
65[[nodiscard, gnu::const]]
66static inline float nec_wrapf(float phase) [[unsequenced]] {
67 assume(0.f <= phase && phase < 1.f);
68 return phase - floorf(phase);
69}
70
78[[gnu::reproducible, gnu::nonnull]]
79static inline void nec_fill_wrapl(
80 size_t len,
81#ifdef __cplusplus
82 long double *const __restrict phase,
83 long double *__restrict output
84#else
85 long double phase[const restrict static len],
86 long double output[restrict static len]
87#endif
88) [[reproducible]] {
89 assume(len > 0);
90 for (size_t i = 0; i < len; ++i) {
91 output[i] = nec_wrapl(phase[i]);
92 }
93}
94
96[[gnu::reproducible, gnu::nonnull]]
97static inline void nec_fill_wrap(
98 size_t len,
99#ifdef __cplusplus
100 double *const __restrict phase,
101 double *__restrict output
102#else
103 double phase[const restrict static len],
104 double output[restrict static len]
105#endif
106) [[reproducible]] {
107 assume(len > 0);
108 #pragma omp simd
109 for (size_t i = 0; i < len; ++i) {
110 output[i] = nec_wrap(phase[i]);
111 }
112}
113
115[[gnu::reproducible, gnu::nonnull]]
116static inline void nec_fill_wrapf(
117 size_t len,
118#ifdef __cplusplus
119 float *const __restrict phase,
120 float *__restrict output
121#else
122 float phase[const restrict static len],
123 float output[restrict static len]
124#endif
125) [[reproducible]] {
126 assume(len > 0);
127 #pragma omp simd
128 for (size_t i = 0; i < len; ++i) {
129 output[i] = nec_wrapf(phase[i]);
130 }
131}
132
144[[nodiscard, gnu::const]]
145static inline long double nec_analog_sawtoothl(long double phase) [[unsequenced]] {
146 assume(0.l <= phase && phase < 1.l);
147 return (-4.l * phase + 1.5l) / (phase + 1.5l);
148}
149
151[[nodiscard, gnu::const]]
152static inline double nec_analog_sawtooth(double phase) [[unsequenced]] {
153 assume(0.0 <= phase && phase < 1.0);
154 return (-4.0 * phase + 1.5) / (phase + 1.5);
155}
156
158[[nodiscard, gnu::const]]
159static inline float nec_analog_sawtoothf(float phase) [[unsequenced]] {
160 assume(0.f <= phase && phase < 1.f);
161 return (-4.f * phase + 1.5f) / (phase + 1.5f);
162}
163
171[[gnu::reproducible, gnu::nonnull]]
172static inline void nec_fill_analog_sawtoothl(
173 size_t len,
174#ifdef __cplusplus
175 long double *const __restrict phase,
176 long double *__restrict output
177#else
178 long double phase[const restrict static len],
179 long double output[restrict static len]
180#endif
181) [[reproducible]] {
182 assume(len > 0);
183 for (size_t i = 0; i < len; ++i) {
184 output[i] = nec_analog_sawtoothl(phase[i]);
185 }
186}
187
189[[gnu::reproducible, gnu::nonnull]]
190static inline void nec_fill_analog_sawtooth(
191 size_t len,
192#ifdef __cplusplus
193 double *const __restrict phase,
194 double *__restrict output
195#else
196 double phase[const restrict static len],
197 double output[restrict static len]
198#endif
199) [[reproducible]] {
200 assume(len > 0);
201 #pragma omp simd
202 for (size_t i = 0; i < len; ++i) {
203 output[i] = nec_analog_sawtooth(phase[i]);
204 }
205}
206
208[[gnu::reproducible, gnu::nonnull]]
209static inline void nec_fill_analog_sawtoothf(
210 size_t len,
211#ifdef __cplusplus
212 float *const __restrict phase,
213 float *__restrict output
214#else
215 float phase[const restrict static len],
216 float output[restrict static len]
217#endif
218) [[reproducible]] {
219 assume(len > 0);
220 #pragma omp simd
221 for (size_t i = 0; i < len; ++i) {
222 output[i] = nec_analog_sawtoothf(phase[i]);
223 }
224}
225
238[[nodiscard, gnu::const]]
239static inline long double nec_analog_squarel(long double phase, long double duty) [[unsequenced]] {
240 assume(0.l <= phase && phase < 1.l);
241 assume(0.l <= duty && duty <= 1.l);
242 const auto amplitude = (-phase + 6.l) / (4.l * phase + 6.l);
243 return copysignl(amplitude, duty - phase);
244}
245
247[[nodiscard, gnu::const]]
248static inline double nec_analog_square(double phase, double duty) [[unsequenced]] {
249 assume(0.0 <= phase && phase < 1.0);
250 assume(0.0 <= duty && duty <= 1.0);
251 const auto amplitude = (-phase + 6.0) / (4.0 * phase + 6.0);
252 return copysign(amplitude, duty - phase);
253}
254
256[[nodiscard, gnu::const]]
257static inline float nec_analog_squaref(float phase, float duty) [[unsequenced]] {
258 assume(0.f <= phase && phase < 1.f);
259 assume(0.f <= duty && duty <= 1.f);
260 const auto amplitude = (-phase + 6.f) / (4.f * phase + 6.f);
261 return copysignf(amplitude, duty - phase);
262}
263
272[[gnu::reproducible, gnu::nonnull]]
273static inline void nec_fill_analog_squarel(
274 size_t len,
275#ifdef __cplusplus
276 long double *const __restrict phase,
277 long double *const __restrict duty,
278 long double *__restrict output
279#else
280 long double phase[const restrict static len],
281 long double duty[const restrict static len],
282 long double output[restrict static len]
283#endif
284) [[reproducible]] {
285 assume(len > 0);
286 for (size_t i = 0; i < len; ++i) {
287 output[i] = nec_analog_squarel(phase[i], duty[i]);
288 }
289}
290
292[[gnu::reproducible, gnu::nonnull]]
293static inline void nec_fill_analog_square(
294 size_t len,
295#ifdef __cplusplus
296 double *const __restrict phase,
297 double *const __restrict duty,
298 double *__restrict output
299#else
300 double phase[const restrict static len],
301 double duty[const restrict static len],
302 double output[restrict static len]
303#endif
304) [[reproducible]] {
305 assume(len > 0);
306 #pragma omp simd
307 for (size_t i = 0; i < len; ++i) {
308 output[i] = nec_analog_square(phase[i], duty[i]);
309 }
310}
311
313[[gnu::reproducible, gnu::nonnull]]
314static inline void nec_fill_analog_squaref(
315 size_t len,
316#ifdef __cplusplus
317 float *const __restrict phase,
318 float *const __restrict duty,
319 float *__restrict output
320#else
321 float phase[const restrict static len],
322 float duty[const restrict static len],
323 float output[restrict static len]
324#endif
325) [[reproducible]] {
326 assume(len > 0);
327 #pragma omp simd
328 for (size_t i = 0; i < len; ++i) {
329 output[i] = nec_analog_squaref(phase[i], duty[i]);
330 }
331}
332
344[[nodiscard, gnu::const]]
345static inline long double nec_analog_trianglel(long double phase) [[unsequenced]] {
346 assume(0.l <= phase && phase < 1.l);
347 return 2.l * fabsl(nec_analog_sawtoothl(phase)) - 1.l;
348}
349
351[[nodiscard, gnu::const]]
352static inline double nec_analog_triangle(double phase) [[unsequenced]] {
353 assume(0.0 <= phase && phase < 1.0);
354 return 2.0 * fabs(nec_analog_sawtooth(phase)) - 1.0;
355}
356
358[[nodiscard, gnu::const]]
359static inline float nec_analog_trianglef(float phase) [[unsequenced]] {
360 assume(0.f <= phase && phase < 1.f);
361 return 2.f * fabsf(nec_analog_sawtoothf(phase)) - 1.f;
362}
363
371[[gnu::reproducible, gnu::nonnull]]
372static inline void nec_fill_analog_trianglel(
373 size_t len,
374#ifdef __cplusplus
375 long double *const __restrict phase,
376 long double *__restrict output
377#else
378 long double phase[const restrict static len],
379 long double output[restrict static len]
380#endif
381) [[reproducible]] {
382 assume(len > 0);
383 for (size_t i = 0; i < len; ++i) {
384 output[i] = nec_analog_trianglel(phase[i]);
385 }
386}
387
389[[gnu::reproducible, gnu::nonnull]]
390static inline void nec_fill_analog_triangle(
391 size_t len,
392#ifdef __cplusplus
393 double *const __restrict phase,
394 double *__restrict output
395#else
396 double phase[const restrict static len],
397 double output[restrict static len]
398#endif
399) [[reproducible]] {
400 assume(len > 0);
401 #pragma omp simd
402 for (size_t i = 0; i < len; ++i) {
403 output[i] = nec_analog_triangle(phase[i]);
404 }
405}
406
408[[gnu::reproducible, gnu::nonnull]]
409static inline void nec_fill_analog_trianglef(
410 size_t len,
411#ifdef __cplusplus
412 float *const __restrict phase,
413 float *__restrict output
414#else
415 float phase[const restrict static len],
416 float output[restrict static len]
417#endif
418) [[reproducible]] {
419 assume(len > 0);
420 #pragma omp simd
421 for (size_t i = 0; i < len; ++i) {
422 output[i] = nec_analog_trianglef(phase[i]);
423 }
424}
425
436[[nodiscard, gnu::const]]
437static inline long double nec_paraboll(long double phase) [[unsequenced]] {
438 assume(0.l <= phase && phase < 1.l);
439 const auto x = 4.l * phase - 2.l;
440 return x * (fabsl(x) - 2.l);
441}
442
444[[nodiscard, gnu::const]]
445static inline double nec_parabol(double phase) [[unsequenced]] {
446 assume(0.0 <= phase && phase < 1.0);
447 const auto x = 4.0 * phase - 2.0;
448 return x * (fabs(x) - 2.0);
449}
450
452[[nodiscard, gnu::const]]
453static inline float nec_parabolf(float phase) [[unsequenced]] {
454 assume(0.f <= phase && phase < 1.f);
455 const auto x = 4.f * phase - 2.f;
456 return x * (fabsf(x) - 2.f);
457}
458
466[[gnu::reproducible, gnu::nonnull]]
467static inline void nec_fill_paraboll(
468 size_t len,
469#ifdef __cplusplus
470 long double *const __restrict phase,
471 long double *__restrict output
472#else
473 long double phase[const restrict static len],
474 long double output[restrict static len]
475#endif
476) [[reproducible]] {
477 assume(len > 0);
478 for (size_t i = 0; i < len; ++i) {
479 output[i] = nec_paraboll(phase[i]);
480 }
481}
482
484[[gnu::reproducible, gnu::nonnull]]
485static inline void nec_fill_parabol(
486 size_t len,
487#ifdef __cplusplus
488 double *const __restrict phase,
489 double *__restrict output
490#else
491 double phase[const restrict static len],
492 double output[restrict static len]
493#endif
494) [[reproducible]] {
495 assume(len > 0);
496 #pragma omp simd
497 for (size_t i = 0; i < len; ++i) {
498 output[i] = nec_parabol(phase[i]);
499 }
500}
501
503[[gnu::reproducible, gnu::nonnull]]
504static inline void nec_fill_parabolf(
505 size_t len,
506#ifdef __cplusplus
507 float *const __restrict phase,
508 float *__restrict output
509#else
510 float phase[const restrict static len],
511 float output[restrict static len]
512#endif
513) [[reproducible]] {
514 assume(len > 0);
515 #pragma omp simd
516 for (size_t i = 0; i < len; ++i) {
517 output[i] = nec_parabolf(phase[i]);
518 }
519}
520
529[[nodiscard, gnu::const]]
530static inline long double nec_sinl(long double phase) [[unsequenced]] {
531 constexpr auto weight = (long double)(NECTARINE_SINE_ERR_CORRECTION_WEIGHT);
532 const auto p = nec_paraboll(phase);
533 return weight * p * (fabsl(p) - 1.l) + p;
534}
535
537[[nodiscard, gnu::const]]
538static inline double nec_sin(double phase) [[unsequenced]] {
539 constexpr auto weight = (double)(NECTARINE_SINE_ERR_CORRECTION_WEIGHT);
540 const auto p = nec_parabol(phase);
541 return weight * p * (fabs(p) - 1.0) + p;
542}
543
545[[nodiscard, gnu::const]]
546static inline float nec_sinf(float phase) [[unsequenced]] {
547 constexpr auto weight = (float)(NECTARINE_SINE_ERR_CORRECTION_WEIGHT);
548 const auto p = nec_parabolf(phase);
549 return weight * p * (fabsf(p) - 1.f) + p;
550}
551
559[[gnu::reproducible, gnu::nonnull]]
560static inline void nec_fill_sinl(
561 size_t len,
562#ifdef __cplusplus
563 long double *const __restrict phase,
564 long double *__restrict output
565#else
566 long double phase[const restrict static len],
567 long double output[restrict static len]
568#endif
569) [[reproducible]] {
570 assume(len > 0);
571 for (size_t i = 0; i < len; ++i) {
572 output[i] = nec_sinl(phase[i]);
573 }
574}
575
577[[gnu::reproducible, gnu::nonnull]]
578static inline void nec_fill_sin(
579 size_t len,
580#ifdef __cplusplus
581 double *const __restrict phase,
582 double *__restrict output
583#else
584 double phase[const restrict static len],
585 double output[restrict static len]
586#endif
587) [[reproducible]] {
588 assume(len > 0);
589 #pragma omp simd
590 for (size_t i = 0; i < len; ++i) {
591 output[i] = nec_sin(phase[i]);
592 }
593}
594
596[[gnu::reproducible, gnu::nonnull]]
597static inline void nec_fill_sinf(
598 size_t len,
599#ifdef __cplusplus
600 float *const __restrict phase,
601 float *__restrict output
602#else
603 float phase[const restrict static len],
604 float output[restrict static len]
605#endif
606) [[reproducible]] {
607 assume(len > 0);
608 #pragma omp simd
609 for (size_t i = 0; i < len; ++i) {
610 output[i] = nec_sinf(phase[i]);
611 }
612}
613
618[[nodiscard, gnu::const]]
619static inline long double nec_circlel(long double phase) [[unsequenced]] {
620 const auto p = nec_paraboll(phase);
621 return copysignl(sqrtl(fabsl(p)), p);
622}
623
625[[nodiscard, gnu::const]]
626static inline double nec_circle(double phase) [[unsequenced]] {
627 const auto p = nec_parabol(phase);
628 return copysign(sqrt(fabs(p)), p);
629}
630
632[[nodiscard, gnu::const]]
633static inline float nec_circlef(float phase) [[unsequenced]] {
634 const auto p = nec_parabolf(phase);
635 return copysignf(sqrtf(fabsf(p)), p);
636}
637
645[[gnu::reproducible, gnu::nonnull]]
646static inline void nec_fill_circlel(
647 size_t len,
648#ifdef __cplusplus
649 long double *const __restrict phase,
650 long double *__restrict output
651#else
652 long double phase[const restrict static len],
653 long double output[restrict static len]
654#endif
655) [[reproducible]] {
656 assume(len > 0);
657 for (size_t i = 0; i < len; ++i) {
658 output[i] = nec_circlel(phase[i]);
659 }
660}
661
663[[gnu::reproducible, gnu::nonnull]]
664static inline void nec_fill_circle(
665 size_t len,
666#ifdef __cplusplus
667 double *const __restrict phase,
668 double *__restrict output
669#else
670 double phase[const restrict static len],
671 double output[restrict static len]
672#endif
673) [[reproducible]] {
674 assume(len > 0);
675 #pragma omp simd
676 for (size_t i = 0; i < len; ++i) {
677 output[i] = nec_circle(phase[i]);
678 }
679}
680
682[[gnu::reproducible, gnu::nonnull]]
683static inline void nec_fill_circlef(
684 size_t len,
685#ifdef __cplusplus
686 float *const __restrict phase,
687 float *__restrict output
688#else
689 float phase[const restrict static len],
690 float output[restrict static len]
691#endif
692) [[reproducible]] {
693 assume(len > 0);
694 #pragma omp simd
695 for (size_t i = 0; i < len; ++i) {
696 output[i] = nec_circlef(phase[i]);
697 }
698}
699
703[[nodiscard, gnu::const]]
704static inline long double nec_sawtoothl(long double phase) [[unsequenced]] {
705 assume(0.l <= phase && phase < 1.l);
706 return -2.l * phase + 1.l;
707}
708
710[[nodiscard, gnu::const]]
711static inline double nec_sawtooth(double phase) [[unsequenced]] {
712 assume(0.0 <= phase && phase < 1.0);
713 return -2.0 * phase + 1.0;
714}
715
717[[nodiscard, gnu::const]]
718static inline float nec_sawtoothf(float phase) [[unsequenced]] {
719 assume(0.f <= phase && phase < 1.f);
720 return -2.f * phase + 1.f;
721}
722
730[[gnu::reproducible, gnu::nonnull]]
731static inline void nec_fill_sawtoothl(
732 size_t len,
733#ifdef __cplusplus
734 long double *const __restrict phase,
735 long double *__restrict output
736#else
737 long double phase[const restrict static len],
738 long double output[restrict static len]
739#endif
740) [[reproducible]] {
741 assume(len > 0);
742 for (size_t i = 0; i < len; ++i) {
743 output[i] = nec_sawtoothl(phase[i]);
744 }
745}
746
748[[gnu::reproducible, gnu::nonnull]]
749static inline void nec_fill_sawtooth(
750 size_t len,
751#ifdef __cplusplus
752 double *const __restrict phase,
753 double *__restrict output
754#else
755 double phase[const restrict static len],
756 double output[restrict static len]
757#endif
758) [[reproducible]] {
759 assume(len > 0);
760 #pragma omp simd
761 for (size_t i = 0; i < len; ++i) {
762 output[i] = nec_sawtooth(phase[i]);
763 }
764}
765
767[[gnu::reproducible, gnu::nonnull]]
768static inline void nec_fill_sawtoothf(
769 size_t len,
770#ifdef __cplusplus
771 float *const __restrict phase,
772 float *__restrict output
773#else
774 float phase[const restrict static len],
775 float output[restrict static len]
776#endif
777) [[reproducible]] {
778 assume(len > 0);
779 #pragma omp simd
780 for (size_t i = 0; i < len; ++i) {
781 output[i] = nec_sawtoothf(phase[i]);
782 }
783}
784
789[[nodiscard, gnu::const]]
790static inline long double nec_squarel(long double phase, long double duty) [[unsequenced]] {
791 assume(0.l <= phase && phase < 1.l);
792 assume(0.l <= duty && duty <= 1.l);
793 return copysignl(1.l, duty - phase);
794}
795
797[[nodiscard, gnu::const]]
798static inline double nec_square(double phase, double duty) [[unsequenced]] {
799 assume(0.0 <= phase && phase < 1.0);
800 assume(0.0 <= duty && duty <= 1.0);
801 return copysign(1.0, duty - phase);
802}
803
805[[nodiscard, gnu::const]]
806static inline float nec_squaref(float phase, float duty) [[unsequenced]] {
807 assume(0.f <= phase && phase < 1.f);
808 assume(0.f <= duty && duty <= 1.f);
809 return copysignf(1.f, duty - phase);
810}
811
820[[gnu::reproducible, gnu::nonnull]]
821static inline void nec_fill_squarel(
822 size_t len,
823#ifdef __cplusplus
824 long double *const __restrict phase,
825 long double *const __restrict duty,
826 long double *__restrict output
827#else
828 long double phase[const restrict static len],
829 long double duty[const restrict static len],
830 long double output[restrict static len]
831#endif
832) [[reproducible]] {
833 assume(len > 0);
834 for (size_t i = 0; i < len; ++i) {
835 output[i] = nec_squarel(phase[i], duty[i]);
836 }
837}
838
840[[gnu::reproducible, gnu::nonnull]]
841static inline void nec_fill_square(
842 size_t len,
843#ifdef __cplusplus
844 double *const __restrict phase,
845 double *const __restrict duty,
846 double *__restrict output
847#else
848 double phase[const restrict static len],
849 double duty[const restrict static len],
850 double output[restrict static len]
851#endif
852) [[reproducible]] {
853 assume(len > 0);
854 #pragma omp simd
855 for (size_t i = 0; i < len; ++i) {
856 output[i] = nec_square(phase[i], duty[i]);
857 }
858}
859
861[[gnu::reproducible, gnu::nonnull]]
862static inline void nec_fill_squaref(
863 size_t len,
864#ifdef __cplusplus
865 float *const __restrict phase,
866 float *const __restrict duty,
867 float *__restrict output
868#else
869 float phase[const restrict static len],
870 float duty[const restrict static len],
871 float output[restrict static len]
872#endif
873) [[reproducible]] {
874 assume(len > 0);
875 #pragma omp simd
876 for (size_t i = 0; i < len; ++i) {
877 output[i] = nec_squaref(phase[i], duty[i]);
878 }
879}
880
884[[nodiscard, gnu::const]]
885static inline long double nec_trianglel(long double phase) [[unsequenced]] {
886 assume(0.l <= phase && phase < 1.l);
887 return 2.l * fabsl(nec_sawtoothl(phase)) - 1.l;
888}
889
891[[nodiscard, gnu::const]]
892static inline double nec_triangle(double phase) [[unsequenced]] {
893 assume(0.0 <= phase && phase < 1.0);
894 return 2.0 * fabs(nec_sawtooth(phase)) - 1.0;
895}
896
898[[nodiscard, gnu::const]]
899static inline float nec_trianglef(float phase) [[unsequenced]] {
900 assume(0.f <= phase && phase < 1.f);
901 return 2.f * fabsf(nec_sawtoothf(phase)) - 1.f;
902}
903
911[[gnu::reproducible, gnu::nonnull]]
912static inline void nec_fill_trianglel(
913 size_t len,
914#ifdef __cplusplus
915 long double *const __restrict phase,
916 long double *__restrict output
917#else
918 long double phase[const restrict static len],
919 long double output[restrict static len]
920#endif
921) [[reproducible]] {
922 assume(len > 0);
923 for (size_t i = 0; i < len; ++i) {
924 output[i] = nec_trianglel(phase[i]);
925 }
926}
927
929[[gnu::reproducible, gnu::nonnull]]
930static inline void nec_fill_triangle(
931 size_t len,
932#ifdef __cplusplus
933 double *const __restrict phase,
934 double *__restrict output
935#else
936 double phase[const restrict static len],
937 double output[restrict static len]
938#endif
939) [[reproducible]] {
940 assume(len > 0);
941 #pragma omp simd
942 for (size_t i = 0; i < len; ++i) {
943 output[i] = nec_triangle(phase[i]);
944 }
945}
946
948[[gnu::reproducible, gnu::nonnull]]
949static inline void nec_fill_trianglef(
950 size_t len,
951#ifdef __cplusplus
952 float *const __restrict phase,
953 float *__restrict output
954#else
955 float phase[const restrict static len],
956 float output[restrict static len]
957#endif
958) [[reproducible]] {
959 assume(len > 0);
960 #pragma omp simd
961 for (size_t i = 0; i < len; ++i) {
962 output[i] = nec_trianglef(phase[i]);
963 }
964}
#define nec_fill_analog_square(len, phase, duty, output)
Fills a buffer with an analog-like square waveform.
Definition tgwaveforms.h:63
#define nec_analog_square(phase, duty)
Analog-like square waveform.
Definition tgwaveforms.h:56
#define nec_triangle(phase)
Basic triangle waveform.
Definition tgwaveforms.h:154
#define nec_fill_triangle(len, phase, output)
Fills a buffer with a triangle waveform.
Definition tgwaveforms.h:161
#define nec_fill_square(len, phase, duty, output)
Fills a buffer with a square waveform.
Definition tgwaveforms.h:147
#define nec_square(phase, duty)
Basic square waveform.
Definition tgwaveforms.h:140
#define nec_sawtooth(phase)
Basic sawtooth waveform.
Definition tgwaveforms.h:126
#define nec_wrap(phase)
Maps an arbitrary phase into the domain [0, 1).
Definition tgwaveforms.h:28
#define nec_circle(phase)
Circle waveform function.
Definition tgwaveforms.h:112
#define nec_fill_sawtooth(len, phase, output)
Fills a buffer with a sawtooth waveform.
Definition tgwaveforms.h:133
#define nec_analog_sawtooth(phase)
Analog-like sawtooth waveform.
Definition tgwaveforms.h:42
#define nec_fill_wrap(len, phase, output)
Maps a buffer of arbitrary phases into the domain [0, 1).
Definition tgwaveforms.h:35
#define nec_sin(phase)
Accurate sine approximation waveform.
Definition tgwaveforms.h:98
#define nec_analog_triangle(phase)
Analog-like triangle waveform.
Definition tgwaveforms.h:70
#define nec_fill_analog_triangle(len, phase, output)
Fills a buffer with an analog-like triangle waveform.
Definition tgwaveforms.h:77
#define nec_fill_circle(len, phase, output)
Fills a buffer with a circle waveform.
Definition tgwaveforms.h:119
#define nec_fill_sin(len, phase, output)
Fills a buffer with an accurate sine approximation waveform.
Definition tgwaveforms.h:105
#define nec_fill_analog_sawtooth(len, phase, output)
Fills a buffer with an analog-like sawtooth waveform.
Definition tgwaveforms.h:49
#define nec_parabol(phase)
Fast sine approximation waveform.
Definition tgwaveforms.h:84
#define nec_fill_parabol(len, phase, output)
Fills a buffer with a fast sine approximation waveform.
Definition tgwaveforms.h:91
static void nec_fill_analog_squaref(size_t len, float phase[const restrict static len], float duty[const restrict static len], float output[restrict static len])
Fills a buffer with an analog-like square waveform.
Definition waveforms.h:314
static float nec_sinf(float phase)
Accurate sine approximation waveform.
Definition waveforms.h:546
static void nec_fill_analog_sawtoothf(size_t len, float phase[const restrict static len], float output[restrict static len])
Fills a buffer with an analog-like sawtooth waveform.
Definition waveforms.h:209
static void nec_fill_trianglel(size_t len, long double phase[const restrict static len], long double output[restrict static len])
Fills a buffer with a triangle waveform.
Definition waveforms.h:912
static void nec_fill_paraboll(size_t len, long double phase[const restrict static len], long double output[restrict static len])
Fills a buffer with a fast sine approximation waveform.
Definition waveforms.h:467
static void nec_fill_wrapf(size_t len, float phase[const restrict static len], float output[restrict static len])
Maps a buffer of arbitrary phases into the domain [0, 1).
Definition waveforms.h:116
static void nec_fill_parabolf(size_t len, float phase[const restrict static len], float output[restrict static len])
Fills a buffer with a fast sine approximation waveform.
Definition waveforms.h:504
static void nec_fill_analog_sawtoothl(size_t len, long double phase[const restrict static len], long double output[restrict static len])
Fills a buffer with an analog-like sawtooth waveform.
Definition waveforms.h:172
static float nec_analog_squaref(float phase, float duty)
Analog-like square waveform.
Definition waveforms.h:257
static float nec_wrapf(float phase)
Maps an arbitrary phase into the domain [0, 1).
Definition waveforms.h:66
static void nec_fill_circlel(size_t len, long double phase[const restrict static len], long double output[restrict static len])
Fills a buffer with a circle waveform.
Definition waveforms.h:646
static void nec_fill_wrapl(size_t len, long double phase[const restrict static len], long double output[restrict static len])
Maps a buffer of arbitrary phases into the domain [0, 1).
Definition waveforms.h:79
static void nec_fill_sawtoothl(size_t len, long double phase[const restrict static len], long double output[restrict static len])
Fills a buffer with a sawtooth waveform.
Definition waveforms.h:731
static void nec_fill_sinf(size_t len, float phase[const restrict static len], float output[restrict static len])
Fills a buffer with an accurate sine approximation waveform.
Definition waveforms.h:597
static float nec_sawtoothf(float phase)
Basic sawtooth waveform.
Definition waveforms.h:718
static long double nec_analog_trianglel(long double phase)
Analog-like triangle waveform.
Definition waveforms.h:345
static void nec_fill_trianglef(size_t len, float phase[const restrict static len], float output[restrict static len])
Fills a buffer with a triangle waveform.
Definition waveforms.h:949
static float nec_trianglef(float phase)
Basic triangle waveform.
Definition waveforms.h:899
static float nec_analog_sawtoothf(float phase)
Analog-like sawtooth waveform.
Definition waveforms.h:159
static float nec_squaref(float phase, float duty)
Basic square waveform.
Definition waveforms.h:806
static float nec_parabolf(float phase)
Fast sine approximation waveform.
Definition waveforms.h:453
static long double nec_circlel(long double phase)
Circle waveform function.
Definition waveforms.h:619
static float nec_circlef(float phase)
Circle waveform function.
Definition waveforms.h:633
static float nec_analog_trianglef(float phase)
Analog-like triangle waveform.
Definition waveforms.h:359
static long double nec_squarel(long double phase, long double duty)
Basic square waveform.
Definition waveforms.h:790
static long double nec_trianglel(long double phase)
Basic triangle waveform.
Definition waveforms.h:885
static void nec_fill_analog_trianglef(size_t len, float phase[const restrict static len], float output[restrict static len])
Fills a buffer with an analog-like triangle waveform.
Definition waveforms.h:409
static void nec_fill_sawtoothf(size_t len, float phase[const restrict static len], float output[restrict static len])
Fills a buffer with a sawtooth waveform.
Definition waveforms.h:768
static constexpr long double NECTARINE_SINE_ERR_CORRECTION_WEIGHT
Error correction term used to increase the accuracy of nec_sin.
Definition waveforms.h:35
static void nec_fill_circlef(size_t len, float phase[const restrict static len], float output[restrict static len])
Fills a buffer with a circle waveform.
Definition waveforms.h:683
static long double nec_sinl(long double phase)
Accurate sine approximation waveform.
Definition waveforms.h:530
static long double nec_sawtoothl(long double phase)
Basic sawtooth waveform.
Definition waveforms.h:704
static void nec_fill_squarel(size_t len, long double phase[const restrict static len], long double duty[const restrict static len], long double output[restrict static len])
Fills a buffer with a square waveform.
Definition waveforms.h:821
static void nec_fill_analog_trianglel(size_t len, long double phase[const restrict static len], long double output[restrict static len])
Fills a buffer with an analog-like triangle waveform.
Definition waveforms.h:372
static long double nec_analog_sawtoothl(long double phase)
Analog-like sawtooth waveform.
Definition waveforms.h:145
static long double nec_analog_squarel(long double phase, long double duty)
Analog-like square waveform.
Definition waveforms.h:239
static void nec_fill_sinl(size_t len, long double phase[const restrict static len], long double output[restrict static len])
Fills a buffer with an accurate sine approximation waveform.
Definition waveforms.h:560
static long double nec_wrapl(long double phase)
Maps an arbitrary phase into the domain [0, 1).
Definition waveforms.h:52
static void nec_fill_squaref(size_t len, float phase[const restrict static len], float duty[const restrict static len], float output[restrict static len])
Fills a buffer with a square waveform.
Definition waveforms.h:862
static void nec_fill_analog_squarel(size_t len, long double phase[const restrict static len], long double duty[const restrict static len], long double output[restrict static len])
Fills a buffer with an analog-like square waveform.
Definition waveforms.h:273
static long double nec_paraboll(long double phase)
Fast sine approximation waveform.
Definition waveforms.h:437