1 #pragma once 2 #include "vt_dsp.h" 3 #include "shared.h" 4 5 /* 6 ** lipol_ps is a small utility class for generating small line segments 7 ** between values 8 ** 9 ** usage would be 10 ** 11 ** ``` 12 ** lipol_ps mypol; 13 ** 14 ** ... 15 ** 16 ** mypol.set_target(13.23); 17 ** if( init ) 18 ** mypol.instantize(); 19 ** ``` 20 ** 21 ** then later in the code 22 ** 23 ** ``` 24 ** float values alignas(16)[SIZE] 25 ** mypol.store_block(values, SIZE_OVER_FOUR); 26 ** ``` 27 ** 28 ** and block would contain the linear interpolation between the 29 ** last queried value and the target. 30 */ 31 class lipol_ps 32 { 33 public: 34 __m128 target, currentval, coef, coef_m1; 35 __m128 lipol_BLOCK_SIZE; 36 __m128 m128_lipolstarter; 37 __m128 m128_bs4_inv; 38 39 lipol_ps(); 40 set_target(float t)41 inline void set_target(float t) 42 { 43 currentval = target; 44 target = _mm_set_ss(t); 45 } 46 set_target(__m128 t)47 inline void set_target(__m128 t) 48 { 49 currentval = target; 50 target = t; 51 } set_target_instantize(float t)52 inline void set_target_instantize(float t) 53 { 54 target = _mm_set_ss(t); 55 currentval = target; 56 } set_target_smoothed(float t)57 inline void set_target_smoothed(float t) 58 { 59 currentval = target; 60 __m128 p1 = _mm_mul_ss(coef, _mm_set_ss(t)); 61 __m128 p2 = _mm_mul_ss(coef_m1, target); 62 target = _mm_add_ss(p1, p2); 63 } 64 void set_blocksize(int bs); 65 66 // inline void set_target(__m128 t) { currentval = target; target = t; } instantize()67 inline void instantize() { currentval = target; } get_target()68 float get_target() 69 { 70 float f; 71 _mm_store_ss(&f, target); 72 return f; 73 } 74 void store_block(float *dst, unsigned int nquads); 75 void multiply_block(float *src, unsigned int nquads); 76 void multiply_block_sat1( 77 float *src, 78 unsigned int nquads); // saturates the interpolator each step (for amp envelopes) 79 void add_block(float *src, unsigned int nquads); 80 void fade_block_to(float *src1, float *src2, float *dst, unsigned int nquads); 81 void fade_2_blocks_to(float *src11, float *src12, float *src21, float *src22, float *dst1, 82 float *dst2, unsigned int nquads); 83 void subtract_block(float *src, unsigned int nquads); 84 void trixpan_blocks(float *L, float *R, float *dL, float *dR, 85 unsigned int nquads); // panning that always lets both channels through 86 // unattenuated (seperate hard-panning) 87 void multiply_block_to(float *src, float *dst, unsigned int nquads); 88 void multiply_2_blocks(float *src1, float *src2, unsigned int nquads); 89 void multiply_2_blocks_to(float *src1, float *src2, float *dst1, float *dst2, 90 unsigned int nquads); 91 void MAC_block_to(float *src, float *dst, unsigned int nquads); 92 void MAC_2_blocks_to(float *src1, float *src2, float *dst1, float *dst2, unsigned int nquads); 93 94 private: initblock(__m128 & y,__m128 & dy)95 inline void initblock(__m128 &y, __m128 &dy) 96 { 97 dy = _mm_sub_ss(target, currentval); 98 dy = _mm_mul_ss(dy, m128_bs4_inv); 99 dy = _mm_shuffle_ps(dy, dy, _MM_SHUFFLE(0, 0, 0, 0)); 100 y = _mm_shuffle_ps(currentval, currentval, _MM_SHUFFLE(0, 0, 0, 0)); 101 y = _mm_add_ps(y, _mm_mul_ps(dy, m128_lipolstarter)); 102 } 103 }; 104