Vital
Loading...
Searching...
No Matches
poly_utils.h
Go to the documentation of this file.
1#pragma once
2
3#include "matrix.h"
4#include "utils.h"
5
6#include <cmath>
7
8namespace vital {
17 namespace utils {
22
26 constexpr unsigned int kNotePressedMask = 0xf;
27
32 static const poly_float kStereoSplit(1.0f, -1.0f);
33
37 static const poly_float kLagrangeOne(0.0f, 1.0f, 0.0f, 0.0f);
38 static const poly_float kLagrangeTwo(-1.0f, -1.0f, 1.0f, 1.0f);
39 static const poly_float kLagrangeThree(-2.0f, -2.0f, -2.0f, -1.0f);
40 static const poly_float kLagrangeMult(-1.0f / 6.0f, 1.0f / 2.0f, -1.0f / 2.0f, 1.0f / 6.0f);
41
45 static const poly_float kOptimalOne(0.00224072707074864375f, 0.20184198969656244725f,
46 0.59244492420272312725f, 0.20345744715566445625f);
47 static const poly_float kOptimalTwo(-0.0059513775678254975f, -0.456633315206820491f,
48 -0.035736698832993691f, 0.4982319203618311775f);
49 static const poly_float kOptimalThree(0.093515484757265265f, 0.294278871937834749f,
50 -0.786648885977648931f, 0.398765058036740415f);
51 static const poly_float kOptimalFour(-0.10174985775982505f, 0.36030925263849456f,
52 -0.36030925263849456f, 0.10174985775982505f);
53
64
75
82 template<mono_float(*func)(mono_float)>
84 poly_float result;
85 for (int i = 0; i < poly_float::kSize; ++i)
86 result.set(i, func(value[i]));
87 return result;
88 }
89
98
105
112
119
126
133
140
145
150
155
160
165
170 #if VITAL_AVX2
171 return _mm256_sqrt_ps(value.value);
172 #elif VITAL_SSE2
173 return _mm_sqrt_ps(value.value);
174 #elif VITAL_NEON
175 return map<sqrtf>(value);
176 #endif
177 }
178
183 return mulAdd(from, to - from, t);
184 }
185
190 poly_float t = mono_t;
191 return kLagrangeMult * (t + kLagrangeOne) * (t + kLagrangeTwo) * (t + kLagrangeThree);
192 }
193
198 poly_float t = mono_t;
199 return ((kOptimalFour * t + kOptimalThree) * t + kOptimalTwo) * t + kOptimalOne;
200 }
201
206 static constexpr mono_float kMultPrev = -1.0f / 6.0f;
207 static constexpr mono_float kMultFrom = 1.0f / 2.0f;
208 static constexpr mono_float kMultTo = -1.0f / 2.0f;
209 static constexpr mono_float kMultNext = 1.0f / 6.0f;
210
211 poly_float t_prev = t_from + 1.0f;
212 poly_float t_to = t_from - 1.0f;
213 poly_float t_next = t_from - 2.0f;
214
215 poly_float t_prev_from = t_prev * t_from;
216 poly_float t_to_next = t_to * t_next;
217
218 return matrix(t_from * t_to_next * kMultPrev,
219 t_prev * t_to_next * kMultFrom,
220 t_prev_from * t_next * kMultTo,
221 t_prev_from * t_to * kMultNext);
222 }
223
228 poly_float half_t = t * 0.5f;
229 poly_float half_t2 = t * half_t;
230 poly_float half_t3 = half_t2 * t;
231 poly_float half_three_t3 = half_t3 * 3.0f;
232
233 return matrix(half_t2 * 2.0f - half_t3 - half_t,
234 mulSub(half_three_t3, half_t2, 5.0f) + 1.0f,
235 mulAdd(half_t, half_t2, 4.0f) - half_three_t3,
236 half_t3 - half_t2);
237 }
238
243 return matrix(0.0f, poly_float(1.0f) - t, t, 0.0f);
244 }
245
250 #if VITAL_AVX2
251 return _mm256_loadu_ps(unaligned);
252 #elif VITAL_SSE2
253 return _mm_loadu_ps(unaligned);
254 #elif VITAL_NEON
255 return vld1q_f32(unaligned);
256 #endif
257 }
258
263 return matrix(toPolyFloatFromUnaligned(buffer + indices[0]),
264 toPolyFloatFromUnaligned(buffer + indices[1]),
265 toPolyFloatFromUnaligned(buffer + indices[2]),
266 toPolyFloatFromUnaligned(buffer + indices[3]));
267 }
268
272 force_inline matrix getValueMatrix(const mono_float* const* buffers, poly_int indices) {
273 return matrix(toPolyFloatFromUnaligned(buffers[0] + indices[0]),
274 toPolyFloatFromUnaligned(buffers[1] + indices[1]),
275 toPolyFloatFromUnaligned(buffers[2] + indices[2]),
276 toPolyFloatFromUnaligned(buffers[3] + indices[3]));
277 }
278
283 return mulAdd(from, to - from, t);
284 }
285
290 return mulAdd(from, to - from, t);
291 }
292
297 poly_float interpolate_from = from * t;
298 poly_float interpolate_to = to * (t - 1.0f);
299 poly_float interpolate_t = t * t * (t * -2.0f + 3.0f);
300 return interpolate(interpolate_from, interpolate_to, interpolate_t) * 2.0f;
301 }
302
309
316
323
328 return poly_float::max(left, right);
329 }
330
335 return poly_float::min(left, right);
336 }
337
342 return poly_float::notEqual(left, right).sum() == 0;
343 }
344
351 force_inline poly_float maskLoad(poly_float zero_value, poly_float one_value, poly_mask reset_mask) {
352 poly_float old_values = zero_value & ~reset_mask;
353 poly_float new_values = one_value & reset_mask;
354
355 return old_values + new_values;
356 }
357
361 force_inline poly_int maskLoad(poly_int zero_value, poly_int one_value, poly_mask reset_mask) {
362 poly_int old_values = zero_value & ~reset_mask;
363 poly_int new_values = one_value & reset_mask;
364
365 return old_values | new_values;
366 }
367
373 poly_mask less_mask = poly_float::lessThan(value, 1.0f);
374 poly_float lower = value - 1.0f;
375 return maskLoad(lower, value, less_mask);
376 }
377
384
389 poly_float result;
390 int size = poly_float::kSize;
391 for (int i = 0; i < size; ++i)
392 result.set(i, powf(base[i], exponent[i]));
393 return result;
394 }
395
399 force_inline poly_mask getSilentMask(const poly_float* buffer, int length) {
400 poly_mask silent_mask = poly_float::equal(0.0f, 0.0f);
401 for (int i = 0; i < length; ++i) {
402 poly_mask zero_mask = closeToZeroMask(buffer[i]);
403 silent_mask &= zero_mask;
404 }
405 return silent_mask;
406 }
407
412 #if VITAL_AVX2
413 return _mm256_shuffle_ps(value.value, value.value, _MM_SHUFFLE(2, 3, 0, 1));
414 #elif VITAL_SSE2
415 return _mm_shuffle_ps(value.value, value.value, _MM_SHUFFLE(2, 3, 0, 1));
416 #elif VITAL_NEON
417 return vrev64q_f32(value.value);
418 #endif
419 }
420
425 #if VITAL_AVX2
426 return _mm256_shuffle_epi32(value.value, _MM_SHUFFLE(2, 3, 0, 1));
427 #elif VITAL_SSE2
428 return _mm_shuffle_epi32(value.value, _MM_SHUFFLE(2, 3, 0, 1));
429 #elif VITAL_NEON
430 return vrev64q_u32(value.value);
431 #endif
432 }
433
438 #if VITAL_AVX2
439 return _mm256_shuffle_ps(value.value, value.value, _MM_SHUFFLE(1, 0, 3, 2));
440 #elif VITAL_SSE2
441 return _mm_shuffle_ps(value.value, value.value, _MM_SHUFFLE(1, 0, 3, 2));
442 #elif VITAL_NEON
443 return vextq_f32(value.value, value.value, 2);
444 #endif
445 }
446
451 #if VITAL_AVX2
452 return _mm256_shuffle_epi32(value.value, value.value, _MM_SHUFFLE(1, 0, 3, 2));
453 #elif VITAL_SSE2
454 return _mm_shuffle_epi32(value.value, _MM_SHUFFLE(1, 0, 3, 2));
455 #elif VITAL_NEON
456 return vextq_u32(value.value, value.value, 2);
457 #endif
458 }
459
464 #if VITAL_AVX2
465 return _mm256_shuffle_ps(value.value, value.value, _MM_SHUFFLE(3, 1, 2, 0));
466 #elif VITAL_SSE2
467 return _mm_shuffle_ps(value.value, value.value, _MM_SHUFFLE(3, 1, 2, 0));
468 #elif VITAL_NEON
469 float32x4_t rotated = vextq_f32(value.value, value.value, 2);
470 float32x4x2_t zipped = vzipq_f32(value.value, rotated);
471 return zipped.val[0];
472 #endif
473 }
474
479 #if VITAL_AVX2
480 return _mm256_shuffle_ps(value.value, value.value, _MM_SHUFFLE(0, 1, 2, 3));
481 #elif VITAL_SSE2
482 return _mm_shuffle_ps(value.value, value.value, _MM_SHUFFLE(0, 1, 2, 3));
483 #elif VITAL_NEON
484 return swapVoices(swapStereo(value));
485 #endif
486 }
487
492 #if VITAL_AVX2
493 return _mm256_unpacklo_ps(one.value, two.value);
494 #elif VITAL_SSE2
495 return _mm_unpacklo_ps(one.value, two.value);
496 #elif VITAL_NEON
497 return vzipq_f32(one.value, two.value).val[0];
498 #endif
499 }
500
505 #if VITAL_AVX2
506 return _mm256_shuffle_ps(one.value, two.value, _MM_SHUFFLE(1, 0, 1, 0));
507 #elif VITAL_SSE2
508 return _mm_shuffle_ps(one.value, two.value, _MM_SHUFFLE(1, 0, 1, 0));
509 #elif VITAL_NEON
510 return vcombine_f32(vget_low_f32(one.value), vget_low_f32(two.value));
511 #endif
512 }
513
518 poly_float totals = sum + utils::swapStereo(sum);
519 return utils::swapInner(totals);
520 }
521
526 poly_float swap_voices = swapVoices(values);
527 poly_float max_voice = utils::max(values, swap_voices);
528 return utils::max(max_voice, utils::swapStereo(max_voice))[0];
529 }
530
535 poly_float swap_voices = swapVoices(values);
536 poly_float min_voice = utils::min(values, swap_voices);
537 return utils::min(min_voice, utils::swapStereo(min_voice))[0];
538 }
539
544 return (value + kStereoSplit * swapStereo(value)) * 0.5f;
545 }
546
551 return (value + swapStereo(kStereoSplit * value));
552 }
553
557 force_inline poly_float peak(const poly_float* buffer, int num, int skip = 1) {
558 poly_float peak = 0.0f;
559 for (int i = 0; i < num; i += skip) {
560 peak = poly_float::max(peak, buffer[i]);
561 peak = poly_float::max(peak, -buffer[i]);
562 }
563
564 return peak;
565 }
566
570 force_inline void zeroBuffer(mono_float* buffer, int size) {
571 for (int i = 0; i < size; ++i)
572 buffer[i] = 0.0f;
573 }
574
578 force_inline void zeroBuffer(poly_float* buffer, int size) {
579 for (int i = 0; i < size; ++i)
580 buffer[i] = 0.0f;
581 }
582
586 force_inline void copyBuffer(mono_float* dest, const mono_float* source, int size) {
587 for (int i = 0; i < size; ++i)
588 dest[i] = source[i];
589 }
590
594 force_inline void copyBuffer(poly_float* dest, const poly_float* source, int size) {
595 for (int i = 0; i < size; ++i)
596 dest[i] = source[i];
597 }
598
602 force_inline void addBuffers(poly_float* dest, const poly_float* b1, const poly_float* b2, int size) {
603 for (int i = 0; i < size; ++i)
604 dest[i] = b1[i] + b2[i];
605 }
606
611 for (int i = 0; i < poly_float::kSize; ++i) {
612 mono_float val = value[i];
613 if (!std::isfinite(val))
614 return false;
615 }
616 return true;
617 }
618
623 poly_mask greater_mask = poly_float::greaterThan(value, max);
624 poly_mask less_than_mask = poly_float::greaterThan(min, value);
625 return (greater_mask.sum() + less_than_mask.sum()) == 0;
626 }
627
632 static constexpr mono_float kRange = 8000.0f;
633 return isInRange(value, -kRange, kRange);
634 }
635
639 force_inline bool isFinite(const poly_float* buffer, int size) {
640 for (int i = 0; i < size; ++i) {
641 if (!isFinite(buffer[i]))
642 return false;
643 }
644 return true;
645 }
646
650 force_inline bool isInRange(const poly_float* buffer, int size, mono_float min, mono_float max) {
651 for (int i = 0; i < size; ++i) {
652 if (!isInRange(buffer[i], min, max))
653 return false;
654 }
655 return true;
656 }
657
661 force_inline bool isContained(const poly_float* buffer, int size) {
662 static constexpr mono_float kRange = 8000.0f;
663 return isInRange(buffer, size, -kRange, kRange);
664 }
665
669 force_inline bool isSilent(const poly_float* buffer, int size) {
670 const mono_float* mono_buffer = reinterpret_cast<const mono_float*>(buffer);
671 return isSilent(mono_buffer, size * poly_float::kSize);
672 }
673
677 force_inline poly_float gather(const mono_float* buffer, const poly_int& indices) {
678 poly_float result;
679 for (int i = 0; i < poly_float::kSize; ++i) {
680 int index = indices[i];
681 result.set(i, buffer[index]);
682 }
683 return result;
684 }
685
689 force_inline void adjacentGather(const mono_float* buffer, const poly_int& indices,
690 poly_float& value, poly_float& next) {
691 for (int i = 0; i < poly_float::kSize; ++i) {
692 int index = indices[i];
693 value.set(i, buffer[index]);
694 next.set(i, buffer[index + 1]);
695 }
696 }
697
701 force_inline poly_float gatherSeparate(const mono_float* const* buffers, const poly_int& indices) {
702 poly_float result;
703 for (int i = 0; i < poly_float::kSize; ++i) {
704 int index = indices[i];
705 result.set(i, buffers[i][index]);
706 }
707 return result;
708 }
709
714 const poly_int& indices,
715 poly_float& value, poly_float& next) {
716 for (int i = 0; i < poly_float::kSize; ++i) {
717 int index = indices[i];
718 value.set(i, buffers[i][index]);
719 next.set(i, buffers[i][index + 1]);
720 }
721 }
722
727 return power * value / ((power - 1.0f) * value + 1.0f);
728 }
729
734 VITAL_ASSERT(poly_float::kSize == poly_int::kSize);
735
736 #if VITAL_AVX2
737 return _mm256_cvtepi32_ps(integers.value);
738 #elif VITAL_SSE2
739 return _mm_cvtepi32_ps(integers.value);
740 #elif VITAL_NEON
741 return vcvtq_f32_s32(vreinterpretq_s32_u32(integers.value));
742 #endif
743 }
744
749 VITAL_ASSERT(poly_float::kSize == poly_int::kSize);
750
751 #if VITAL_AVX2
752 return _mm256_cvtps_epi32(floats.value);
753 #elif VITAL_SSE2
754 return _mm_cvtps_epi32(floats.value);
755 #elif VITAL_NEON
756 return vreinterpretq_u32_s32(vcvtq_s32_f32(floats.value));
757 #endif
758 }
759
764 return toInt(value);
765 }
766
771 return toFloat(truncToInt(value));
772 }
773
778 poly_float truncated = trunc(value);
779 return truncated + (poly_float(-1.0f) & poly_float::greaterThan(truncated, value));
780 }
781
786 return toInt(floor(value));
787 }
788
793 return floorToInt(value + 0.5f);
794 }
795
800 poly_float truncated = trunc(value);
801 return truncated + (poly_float(1.0f) & poly_float::lessThan(truncated, value));
802 }
803
808 return floor(value + 0.5f);
809 }
810
815 return value - floor(value);
816 }
817
822 #if VITAL_AVX2
823 return _mm256_castsi256_ps(value.value);
824 #elif VITAL_SSE2
825 return _mm_castsi128_ps(value.value);
826 #elif VITAL_NEON
827 return vreinterpretq_f32_u32(value.value);
828 #endif
829 }
830
835 #if VITAL_AVX2
836 return _mm256_castps_si256(value.value);
837 #elif VITAL_SSE2
838 return _mm_castps_si128(value.value);
839 #elif VITAL_NEON
840 return vreinterpretq_u32_f32(value.value);
841 #endif
842 }
843
844 template<size_t shift>
846 #if VITAL_AVX2
847 return _mm256_srli_epi32(integers.value, shift);
848 #elif VITAL_SSE2
849 return _mm_srli_epi32(integer.value, shift);
850 #elif VITAL_NEON
851 return vshrq_n_u32(integer.value, shift);
852 #endif
853 }
854
855 template<size_t shift>
857 #if VITAL_AVX2
858 return _mm256_slli_epi32(integers.value, shift);
859 #elif VITAL_SSE2
860 return _mm_slli_epi32(integer.value, shift);
861 #elif VITAL_NEON
862 return vshlq_n_u32(integer.value, shift);
863 #endif
864 }
865
869
874 poly_float adjust = t + 0.75f;
875 poly_float range = utils::mod(adjust);
876 return poly_float::abs(mulAdd(-1.0f, range, 2.0f));
877 }
878
886 poly_float offset;
887 for (int i = 0; i < poly_float::kSize; ++i) {
888 double freq = frequency[i];
889 double cycles = freq * seconds;
890 offset.set(i, cycles - ::floor(cycles));
891 }
892 return offset;
893 }
894
899 int sample_rate, int oversample_amount) {
900 double tick_time = (1.0 * oversample_amount) / sample_rate;
901 double seconds_passed = tick_time * samples;
902 return getCycleOffsetFromSeconds(seconds_passed, frequency);
903 }
904
909 poly_float octave_floored = utils::floor(transpose * (1.0f / kNotesPerOctave)) * kNotesPerOctave;
910 poly_float tranpose_from_octave = transpose - octave_floored;
911 poly_float min_distance = kNotesPerOctave;
912 poly_float transpose_in_octave = tranpose_from_octave;
913 for (int i = 0; i <= kNotesPerOctave; ++i) {
914 if ((quantize >> (i % kNotesPerOctave)) & 1) {
915 poly_float distance = poly_float::abs(tranpose_from_octave - i);
916 poly_mask best_mask = poly_float::lessThan(distance, min_distance);
917 min_distance = utils::maskLoad(min_distance, distance, best_mask);
918 transpose_in_octave = utils::maskLoad(transpose_in_octave, i, best_mask);
919 }
920 }
921
922 return octave_floored + transpose_in_octave;
923 }
924
928 force_inline void fillSnapBuffer(int transpose_quantize, float* snap_buffer) {
929 float min_snap = 0.0f;
930 float max_snap = 0.0f;
931 for (int i = 0; i < kNotesPerOctave; ++i) {
932 if ((transpose_quantize >> i) & 1) {
933 max_snap = i;
934 if (min_snap == 0.0f)
935 min_snap = i;
936 }
937 }
938
939 float offset = kNotesPerOctave - max_snap;
940 for (int i = 0; i <= kNotesPerOctave; ++i) {
941 if ((transpose_quantize >> (i % kNotesPerOctave)) & 1)
942 offset = 0.0f;
943
944 snap_buffer[i] = offset;
945 offset += 1.0f;
946 }
947 offset = min_snap;
948 for (int i = kNotesPerOctave; i >= 0; --i) {
949 if (offset < snap_buffer[i])
950 snap_buffer[i] = i + offset;
951 else if (snap_buffer[i] != 0.0f)
952 snap_buffer[i] = i - snap_buffer[i];
953 else {
954 snap_buffer[i] = i;
955 offset = 0.0f;
956 }
957 offset += 1.0f;
958 }
959 }
960
965 return quantize >> kNotesPerOctave;
966 }
967
972 static constexpr int kTransposeMask = (1 << kNotesPerOctave) - 1;
973 return quantize & kTransposeMask;
974 }
975
980 poly_float voice_float = toFloat((toInt(voice) & poly_int(kNotePressedMask)) + 1);
981 return voice_float + phase * kPhaseEncodingMultiplier;
982 }
983
987 force_inline std::pair<poly_float, poly_float> decodePhaseAndVoice(poly_float encoded) {
988 poly_float modulo = mod(encoded);
989 poly_float voice = encoded - modulo;
990 poly_float phase = modulo * (1.0f / kPhaseEncodingMultiplier);
991 return { phase, voice };
992 }
993 } // namespace utils
994} // namespace vital
995
#define VITAL_ASSERT(x)
Definition common.h:11
#define force_inline
Definition common.h:23
Contains a collection of utility functions and classes used throughout Vital.
const poly_float kStereoSplit
Splits stereo channels into left and right components.
Definition synth_constants.h:251
force_inline poly_float mod(poly_float value)
Returns the fractional part of each lane by subtracting the floored value.
Definition poly_utils.h:814
force_inline poly_float pow2ToFloat(poly_int value)
Definition poly_utils.h:866
force_inline poly_float cos(poly_float value)
Computes the cosine of each element (in radians).
Definition poly_utils.h:164
force_inline void addBuffers(poly_float *dest, const poly_float *b1, const poly_float *b2, int size)
Adds two poly_float buffers element-by-element, storing in dest.
Definition poly_utils.h:602
force_inline poly_int reinterpretToInt(poly_float value)
Reinterprets a poly_float as a poly_int (bitcast).
Definition poly_utils.h:834
force_inline poly_float clamp(poly_float value, mono_float min, mono_float max)
Clamps each lane of a vector to [min, max].
Definition poly_utils.h:306
force_inline bool isSilent(const poly_float *buffer, int size)
Determines if the entire buffer is silent (very close to zero).
Definition poly_utils.h:669
force_inline poly_float trunc(poly_float value)
Returns the truncated value of each lane in value.
Definition poly_utils.h:770
force_inline poly_float triangleWave(poly_float t)
Generates a simple triangle wave [0..1] from a fraction t in [0..1].
Definition poly_utils.h:873
force_inline void adjacentGatherSeparate(const mono_float *const *buffers, const poly_int &indices, poly_float &value, poly_float &next)
Similar to adjacentGather but for separate buffers.
Definition poly_utils.h:713
force_inline poly_float consolidateAudio(poly_float one, poly_float two)
Interleaves two stereo poly_floats into a single vector with left channels first, then right channels...
Definition poly_utils.h:491
force_inline bool isFinite(poly_float value)
Checks if all lanes in a poly_float are finite.
Definition poly_utils.h:610
force_inline void zeroBuffer(mono_float *buffer, int size)
Zeros a mono buffer (standard array).
Definition poly_utils.h:570
constexpr unsigned int kNotePressedMask
A bitmask used in voice encoding for note-on states.
Definition poly_utils.h:26
force_inline poly_float toFloat(poly_int integers)
Casts a poly_int to poly_float lane-by-lane.
Definition poly_utils.h:733
force_inline poly_float encodePhaseAndVoice(poly_float phase, poly_float voice)
Encodes a phase [0..1) and a voice index into a single float, storing the voice in the integer portio...
Definition poly_utils.h:979
force_inline bool isTransposeQuantizeGlobal(int quantize)
Checks if the transpose quantize mask applies globally (over multiple octaves).
Definition poly_utils.h:964
force_inline poly_float reinterpretToFloat(poly_int value)
Reinterprets a poly_int as a poly_float (bitcast).
Definition poly_utils.h:821
force_inline void fillSnapBuffer(int transpose_quantize, float *snap_buffer)
Fills a buffer with snap offsets for a given quantize mask.
Definition poly_utils.h:928
force_inline poly_float encodeMidSide(poly_float value)
Converts an L/R stereo representation into M/S (mid/side) encoding.
Definition poly_utils.h:543
force_inline poly_float peak(const poly_float *buffer, int num, int skip=1)
Returns the peak magnitude of a buffer (considering both positive and negative values).
Definition poly_utils.h:557
force_inline poly_float decodeMidSide(poly_float value)
Converts a mid/side encoded stereo value back to L/R (decodes).
Definition poly_utils.h:550
force_inline poly_float mulAdd(poly_float a, poly_float b, poly_float c)
Performs a fused multiply-add on SIMD data: (a * b) + c.
Definition poly_utils.h:61
force_inline poly_float round(poly_float value)
Rounds each lane to the nearest integer as a poly_float.
Definition poly_utils.h:807
force_inline poly_float modOnce(poly_float value)
A special mod operation that ensures the result stays below 1.0, subtracting 1.0 if needed.
Definition poly_utils.h:372
force_inline poly_int roundToInt(poly_float value)
Rounds each lane to the nearest integer.
Definition poly_utils.h:792
force_inline poly_float floor(poly_float value)
Floors each lane in value.
Definition poly_utils.h:777
force_inline poly_float swapInner(poly_float value)
Reorders internal stereo lanes.
Definition poly_utils.h:463
force_inline poly_float tan(poly_float value)
Computes the tangent of each element (in radians) in a poly_float.
Definition poly_utils.h:154
force_inline poly_float min(poly_float left, poly_float right)
Returns the minimum of two poly_floats lane-by-lane.
Definition poly_utils.h:334
constexpr mono_float kPhaseEncodingMultiplier
Used as a multiplier when encoding phase and voice data in a single float.
Definition poly_utils.h:21
force_inline poly_mask closeToZeroMask(poly_float value)
Returns a mask where lanes are true if value is close to 0.
Definition poly_utils.h:381
force_inline poly_float getCycleOffsetFromSamples(long long samples, poly_float frequency, int sample_rate, int oversample_amount)
Computes a cycle offset given a sample count, frequency, sample rate, and oversampling factor.
Definition poly_utils.h:898
force_inline poly_float getCycleOffsetFromSeconds(double seconds, poly_float frequency)
Computes a cycle offset given a time in seconds and a frequency.
Definition poly_utils.h:885
force_inline bool isInRange(poly_float value, mono_float min, mono_float max)
Checks if each lane in a poly_float is within [min, max].
Definition poly_utils.h:622
force_inline matrix getPolynomialInterpolationMatrix(poly_float t_from)
Creates a matrix for polynomial interpolation given a starting poly_float t_from.
Definition poly_utils.h:205
force_inline poly_float magnitudeToDb(poly_float value)
Converts a magnitude value to decibels (vectorized).
Definition poly_utils.h:144
force_inline poly_mask getSilentMask(const poly_float *buffer, int length)
Creates a mask indicating whether all values in the given buffer are near zero.
Definition poly_utils.h:399
force_inline bool isContained(poly_float value)
Checks if all lanes in a poly_float are within a broad range [-8000..8000].
Definition poly_utils.h:631
force_inline poly_float toPolyFloatFromUnaligned(const mono_float *unaligned)
Loads a poly_float from an unaligned float pointer.
Definition poly_utils.h:249
force_inline poly_float getOptimalInterpolationValues(mono_float mono_t)
Returns an "optimal" polynomial interpolation for a scalar mono_t.
Definition poly_utils.h:197
force_inline poly_float getCubicInterpolationValues(mono_float mono_t)
Returns the cubic Lagrange interpolation constants for a scalar mono_t.
Definition poly_utils.h:189
force_inline poly_int shiftRight(poly_int integer)
Definition poly_utils.h:845
force_inline matrix getLinearInterpolationMatrix(poly_float t)
Creates a matrix for simple linear interpolation using scalar or vector t.
Definition poly_utils.h:242
force_inline poly_float pow(poly_float base, poly_float exponent)
Raises each lane in base to the power of the corresponding lane in exponent.
Definition poly_utils.h:388
force_inline poly_float frequencyToMidiNote(poly_float value)
Converts a frequency to a MIDI note (vectorized).
Definition poly_utils.h:130
force_inline poly_int shiftLeft(poly_int integer)
Definition poly_utils.h:856
force_inline poly_float dbToMagnitude(poly_float value)
Converts a dB value to linear magnitude (vectorized).
Definition poly_utils.h:149
force_inline poly_float ratioToMidiTranspose(poly_float value)
Converts a ratio to MIDI transpose (vectorized).
Definition poly_utils.h:109
force_inline poly_float max(poly_float left, poly_float right)
Returns the maximum of two poly_floats lane-by-lane.
Definition poly_utils.h:327
force_inline bool equal(poly_float left, poly_float right)
Checks if two poly_floats are equal lane-by-lane. Returns true if all lanes match.
Definition poly_utils.h:341
force_inline mono_float minFloat(poly_float values)
Returns the minimum lane value from a poly_float.
Definition poly_utils.h:534
force_inline mono_float maxFloat(poly_float values)
Returns the maximum lane value from a poly_float.
Definition poly_utils.h:525
force_inline poly_float swapVoices(poly_float value)
Swaps the first half of the lanes with the second half.
Definition poly_utils.h:437
force_inline poly_float map(poly_float value)
Applies a scalar function to each element in a poly_float.
Definition poly_utils.h:83
force_inline matrix getCatmullInterpolationMatrix(poly_float t)
Creates a Catmull-Rom interpolation matrix from a poly_float t.
Definition poly_utils.h:227
force_inline poly_float sumSplitAudio(poly_float sum)
Adds two stereo lanes for each voice, returning a combined mono result in each lane.
Definition poly_utils.h:517
force_inline matrix getValueMatrix(const mono_float *buffer, poly_int indices)
Creates a matrix of 4 poly_float lanes from a single buffer at varying indices.
Definition poly_utils.h:262
force_inline poly_float snapTranspose(poly_float transpose, int quantize)
Snaps a MIDI transpose value to a quantization mask (e.g., scale degrees).
Definition poly_utils.h:908
force_inline poly_float gatherSeparate(const mono_float *const *buffers, const poly_int &indices)
Gathers values from different buffers, with each lane potentially reading from a different buffer ind...
Definition poly_utils.h:701
force_inline poly_float fltScale(poly_float value, poly_float power)
Performs a simple filter scaling operation (power * value) / ((power - 1)*value + 1).
Definition poly_utils.h:726
force_inline poly_int floorToInt(poly_float value)
Floors each lane and returns the result as an integer.
Definition poly_utils.h:785
force_inline void copyBuffer(mono_float *dest, const mono_float *source, int size)
Copies data from a source mono buffer to a destination mono buffer.
Definition poly_utils.h:586
force_inline poly_float maskLoad(poly_float zero_value, poly_float one_value, poly_mask reset_mask)
Selects between two values (zero_value or one_value) based on a mask in each lane.
Definition poly_utils.h:351
force_inline poly_float midiNoteToFrequency(poly_float value)
Converts a MIDI note to a frequency (vectorized).
Definition poly_utils.h:123
force_inline poly_int toInt(poly_float floats)
Casts a poly_float to poly_int by truncation.
Definition poly_utils.h:748
force_inline poly_float sqrt(poly_float value)
Computes the square root of each element in a poly_float.
Definition poly_utils.h:169
force_inline poly_float sin(poly_float value)
Computes the sine of each element (in radians).
Definition poly_utils.h:159
force_inline poly_int truncToInt(poly_float value)
Truncates a poly_float to an integer (effectively floor for positive values).
Definition poly_utils.h:763
force_inline poly_float noteOffsetToRatio(poly_float value)
Converts note offsets to frequency ratios. Similar to centsToRatio, but may differ in how offset is d...
Definition poly_utils.h:102
force_inline poly_float interpolate(poly_float from, poly_float to, mono_float t)
Performs a linear interpolation between two poly_floats using a scalar t in [0..1].
Definition poly_utils.h:182
force_inline poly_float frequencyToMidiCents(poly_float value)
Converts a frequency to MIDI cents (vectorized).
Definition poly_utils.h:137
force_inline poly_float midiCentsToFrequency(poly_float value)
Converts MIDI cents to frequency (vectorized).
Definition poly_utils.h:116
force_inline void adjacentGather(const mono_float *buffer, const poly_int &indices, poly_float &value, poly_float &next)
Gathers adjacent values for each lane, storing them in value and next.
Definition poly_utils.h:689
force_inline bool isTransposeSnapping(int quantize)
Checks if any snapping bits are set in the transpose quantize mask.
Definition poly_utils.h:971
force_inline poly_float compactFirstVoices(poly_float one, poly_float two)
Packs the first voice from two different poly_floats into a single vector.
Definition poly_utils.h:504
force_inline poly_float perlinInterpolate(poly_float from, poly_float to, poly_float t)
A specialized interpolation function used in perlin-like routines.
Definition poly_utils.h:296
force_inline poly_float reverse(poly_float value)
Reverses the order of stereo lanes from (L, R, L, R) to (R, L, R, L).
Definition poly_utils.h:478
force_inline poly_float ceil(poly_float value)
Ceils each lane in value.
Definition poly_utils.h:799
force_inline poly_float swapStereo(poly_float value)
Swaps the left and right channels of a stereo poly_float.
Definition poly_utils.h:411
force_inline std::pair< poly_float, poly_float > decodePhaseAndVoice(poly_float encoded)
Decodes a phase and voice from an encoded float, returning (phase, voice).
Definition poly_utils.h:987
force_inline poly_float gather(const mono_float *buffer, const poly_int &indices)
Gathers values from a mono float buffer into a poly_float, using per-lane indices.
Definition poly_utils.h:677
force_inline poly_float centsToRatio(poly_float value)
Converts semitone cents to a linear frequency ratio (vectorized).
Definition poly_utils.h:95
force_inline poly_float mulSub(poly_float a, poly_float b, poly_float c)
Performs a fused multiply-sub on SIMD data: (a * b) - c.
Definition poly_utils.h:72
Contains classes and functions used within the Vital synthesizer framework.
constexpr int kNotesPerOctave
Number of semitones per octave.
Definition common.h:51
constexpr mono_float kEpsilon
A small epsilon for floating comparisons.
Definition common.h:38
float mono_float
Definition common.h:33
A structure representing a 4x1 matrix of poly_float rows.
Definition matrix.h:19
Represents a vector of floating-point values using SIMD instructions.
Definition poly_values.h:600
static force_inline simd_type vector_call mulSub(simd_type one, simd_type two, simd_type three)
Fused multiply-sub operation: one = one - (two * three).
Definition poly_values.h:800
static force_inline mask_simd_type vector_call equal(simd_type one, simd_type two)
Compares two SIMD float registers for equality, element-wise.
Definition poly_values.h:954
static force_inline poly_mask vector_call lessThan(poly_float one, poly_float two)
Definition poly_values.h:1105
simd_type value
The underlying SIMD register for float.
Definition poly_values.h:1112
static force_inline simd_type vector_call min(simd_type one, simd_type two)
Returns the element-wise minimum of two SIMD float registers.
Definition poly_values.h:920
static force_inline simd_type vector_call max(simd_type one, simd_type two)
Returns the element-wise maximum of two SIMD float registers.
Definition poly_values.h:904
static force_inline simd_type vector_call abs(simd_type value)
Computes the absolute value of each element in the SIMD float register.
Definition poly_values.h:935
static force_inline mask_simd_type vector_call notEqual(simd_type one, simd_type two)
Compares two SIMD float registers for non-equality, element-wise.
Definition poly_values.h:1003
static force_inline simd_type vector_call mulAdd(simd_type one, simd_type two, simd_type three)
Fused multiply-add operation: one = one + (two * three).
Definition poly_values.h:779
force_inline void vector_call set(size_t index, float new_value) noexcept
Sets a specific element in the SIMD register.
Definition poly_values.h:1182
static force_inline mask_simd_type vector_call greaterThan(simd_type one, simd_type two)
Compares two SIMD float registers, element-wise, for greater than.
Definition poly_values.h:971
Represents a vector of integer values using SIMD instructions.
Definition poly_values.h:56
simd_type value
The underlying SIMD register.
Definition poly_values.h:385
static force_inline simd_type vector_call max(simd_type one, simd_type two)
Returns the element-wise maximum of two SIMD integer registers.
Definition poly_values.h:253
static force_inline uint32_t vector_call sum(simd_type value)
Computes the sum of all elements in a SIMD integer register.
Definition poly_values.h:326
static force_inline simd_type vector_call min(simd_type one, simd_type two)
Returns the element-wise minimum of two SIMD integer registers.
Definition poly_values.h:272
Provides various utility functions, classes, and constants for audio, math, and general-purpose opera...