Advertisement
Kaelygon

fast uint waveforms

Jun 30th, 2023
923
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 3.77 KB | None | 0 0
  1. #include<cstdint>
  2. //compiled with gcc flag -O3
  3. //approx -UIMAX/2*sin((2*x*pi)/UIMAX)+UIMAX/2       https://www.desmos.com/calculator/lyyy678gdw
  4. //sine both input [0.0,2pi] and output [-1.0,1.0] are mapped to [0,4294967295]
  5. //Convert VALUE[0,4294967295] to range[-1.0,1.0] using (-1.0)*((float)VALUE/(UIMAX/2)-1)
  6. //2.8% error, 3-6x faster than sin() with num=rand()%(1+i++), up to ~20x faster with num=i++
  7. //Fast sine approximation.
  8. uint32_t u32kaelSin(uint32_t num) {
  9.     bool secondHalf = (num>>31); //second half of uint
  10.     num<<=1; //2x input for 2 parabola period
  11.     uint64_t buf = (static_cast<uint64_t>(num)<<1)-UINT32_MAX; //<cast>64b-32b and flip vertically
  12.     num = (buf * buf) >> 33; //compute parabola
  13.     num = secondHalf ? ~num : num; //flip horizontally if past mid point
  14.     return num;
  15. }
  16. uint16_t u16kaelSin(uint16_t num) {
  17.     bool secondHalf = (num>>15);
  18.     num<<=1;
  19.     uint32_t buf = (static_cast<uint32_t>(num)<<1)-UINT16_MAX;
  20.     num = (buf * buf) >> 17;
  21.     num = secondHalf ? ~num : num;
  22.     return num;
  23. }
  24. uint8_t u8kaelSin(uint8_t num) {
  25.     bool secondHalf = (num>>7);
  26.     num<<=1;
  27.     uint16_t buf = (static_cast<uint16_t>(num)<<1)-UINT8_MAX;
  28.     num = (buf * buf) >> 9;
  29.     num = secondHalf ? ~num : num;
  30.     return num;
  31. }
  32.  
  33. //Triangle wave
  34. template <typename T>
  35. T ukaelTriangle(T num) {
  36.     bool flip = num>>(sizeof(num)<<3-2)==0 | num>>(sizeof(num)<<3-2)==3;    //first and last quarters
  37.     num<<=1;
  38.     num+=~T(0)>>1;
  39.     return flip ? ~num : num;
  40. }
  41.  
  42. //Saw wave
  43. template <typename T>
  44. T ukaelSaw(T num){
  45.     return num<<=1;
  46. }
  47.  
  48. //Square wave
  49. template <typename T>
  50. T ukaelSquare(T num){
  51.     return ( num>>(sizeof(num)<<3-1) ) ? 0 : ~T(0);
  52. }
  53.  
  54. //Pulse square wave
  55. template <typename T>
  56. T ukaelPulse(T num, T dutyCycle) {
  57.     return (num > dutyCycle) ? 0 : ~T(0);
  58. }
  59.  
  60. //noise function
  61. template <typename T>
  62. T ukaelNoise(T num) {
  63.     uint sz=sizeof(num)<<1;
  64.     num^=num>>(num&sz)+4;
  65.     num*=4763;
  66.     num^=num<<(num&sz)+4;
  67.     return num;
  68. }
  69.  
  70. //helps making 8bit noise less repetitive when input is linear. Small as 32 wroks
  71. const uint8_t u8randomTable[]{
  72. 33, 138,142,237,100,84, 241,4,  139,149,159,233,64, 201,75, 235,
  73. 116,248,10, 116,247,112,214,245,221,58, 158,124,196,227,255,39,
  74. 51, 238,5,  253,76, 6,  65, 104,106,81, 230,171,55, 245,21, 244,
  75. 99, 162,98, 34, 78, 28, 195,184,229,205,14, 154,57, 224,249,45,
  76. 226,233,77, 124,10, 50, 81, 103,26, 30, 18, 18, 185,98, 214,48,
  77. 244,118,214,17, 67, 215,209,34, 134,100,177,206,190,70, 133,219,
  78. 194,66, 123,57, 26, 129,5,  64, 36, 59, 237,122,207,87, 22, 164,
  79. 133,200,191,47, 15, 54, 194,223,129,166,52, 8,  49, 193,235,254,
  80. 62, 122,55, 93, 190,241,171,91, 25, 101,233,151,224,113,69, 71,
  81. 235,253,55, 247,143,240,205,52, 229,223,229,229,211,244,252,2,  
  82. 159,141,91, 4,  46, 233,78, 127,236,237,167,248,37, 253,140,89,
  83. 155,138,185,162,65, 115,117,196,57, 195,107,39, 205,189,216,73,
  84. 57, 243,10, 107,193,226,182,204,200,165,234,253,208,185,137,151,
  85. 238,49, 18, 189,98, 185,169,67, 94, 77, 73, 165,127,121,65, 202,
  86. 148,165,101,186,131,207,252,86, 204,225,108,82, 129,133,184,179,
  87. 236,17, 223,163,11, 1,  60, 251,118,243,105,190,74, 52, 200,235
  88. };
  89.  
  90. //8-bit noise function. actually slower than ukaelNoise()
  91. uint8_t u8kaelNoise(uint16_t num) {
  92.     num^=num<<7;
  93.     num*=17;
  94.     num^=num>>7;
  95.     num^=u8randomTable[(num>>8)]; //num>>8 for 256 table
  96.     return num;
  97. }
  98.  
  99. /* too slow for random generation, seeding maybe
  100. uint64_t rdtsc(){
  101.     unsigned int lo,hi;
  102.     __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
  103.     return ((uint64_t)hi << 32) | lo;
  104. }
  105. */
  106.  
  107. /*
  108. Time warmup()           0.67921 seconds
  109. For loop overhead       0.10994 seconds
  110. Time ukaelNoi()         2.45002 seconds
  111. Time u32kaelSin()       1.62207 seconds
  112. Time ukaelTri()         0.61627 seconds
  113. Time ukaelSqu()         1.02044 seconds
  114. Time ukaelSaw()         0.41214 seconds
  115. Time ukaelPul()         0.61336 seconds
  116. Time math.h sin()       13.2384 seconds
  117. */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement