Advertisement
Kaelygon

kaelWaveforms.h

Jul 1st, 2023 (edited)
933
0
Never
2
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 3.02 KB | None | 0 0
  1. #include <cstdint>
  2. #include <type_traits>
  3.  
  4. #include <type_traits>
  5.  
  6. template<typename T>
  7. struct uiChecks {
  8.     static constexpr bool isUnsigned = std::is_unsigned<T>::value || std::is_same<T, __uint128_t>::value;
  9.     static constexpr bool isIntegral = std::is_integral<T>::value || std::is_same<T, __uint128_t>::value;
  10.     static constexpr bool isBig = std::endian::native == std::endian::big;
  11. };
  12.  
  13.  
  14. template <typename T>
  15. void uiRequired() {
  16.     static_assert(uiChecks<T>::isUnsigned, "Type must be unsigned integer type");
  17.     static_assert(uiChecks<T>::isIntegral, "Type must be an integer");
  18. }
  19.  
  20. //select uint type that is double of T width
  21. template <typename T>
  22. struct twiceWide {
  23.     using type = typename std::conditional<(sizeof(T) == 1), uint16_t,
  24.                    typename std::conditional<(sizeof(T) == 2), uint32_t,
  25.                    typename std::conditional<(sizeof(T) == 4), uint64_t,
  26.                    typename std::conditional<(sizeof(T) == 8), __uint128_t,
  27.                                                 void>::type>::type>::type>::type;
  28. };
  29.  
  30. //Fast sine approximation.
  31. template <typename T>
  32. T ukaelSine(T num) {
  33.     uiRequired<T>(); //check uint compatibility
  34.     using T2 = typename twiceWide<T>::type; //requires twice T bit width for squaring
  35.     bool secondHalf = (num >> ((sizeof(T)<<3) - 1));    //sizeof(T)*8-1. values that're more than 0.5*UINT_MAX
  36.     num <<= 1;  //get 2 periods of saw wave
  37.     T2 buf = (static_cast<T2>(num)<<1) - ((T)~0);   //store to twiceWide to prevent overflow
  38.     num = static_cast<T>((buf * buf) >> ((sizeof(T)<<3) + 1));  //square and revert back to T scale
  39.     num = secondHalf ? num : ~num;  //invert 2nd half
  40.     return num;
  41. }
  42.  
  43. //Crunchy Sine
  44. template <typename T>
  45. T ukaelCSine(T num) {
  46.     uiRequired<T>();
  47.     bool secondHalf = (num >> ((sizeof(T)<<3) - 1));
  48.     bool evenQuarter = (num >> ((sizeof(T)<<3) - 2))==0 || (num >> ((sizeof(T)<<3) - 2))==2;
  49.     num = evenQuarter ? ~num : num; //invert even quarters
  50.     num <<= 2;  //2 period saw
  51.     num >>= sizeof(T)<<2;   //square root. Crunchy precision
  52.     num*=num;   //square
  53.     num >>= 1;  //divide by 2
  54.     num = secondHalf ? num : ~num;  //invert 2nd half
  55.     return num;
  56. }
  57.  
  58. //triangle
  59. template <typename T>
  60. T ukaelTriangle(T num) {
  61.     uiRequired<T>();
  62.     num+=((T)~0)>>2;    //add UINT_MAX/4
  63.     bool secondHalf = (num >> ((sizeof(T)<<3) - 1));
  64.     num <<= 1;  //*2
  65.     num = secondHalf ? ~num : num;  //invert 2nd half
  66.     return num;
  67. }
  68.  
  69. //Saw
  70. template <typename T>
  71. T ukaelSaw(T num){
  72.     num+=((T)~0)>>1;    //add UINT_MAX/2
  73.     return num;
  74. }
  75.  
  76. //Square
  77. template <typename T>
  78. T ukaelSquare(T num){
  79.     uiRequired<T>();
  80.     return ( num>>((sizeof(T)<<3)-1) ) ? T(0) : ~0; //hi if 0 to 0.5, low if 0.5 to 1.0
  81. }
  82.  
  83. //Pulse square 2 arguments
  84. template <typename T>
  85. T ukaelPulse(T num, T dutyCycle) {
  86.     uiRequired<T>();
  87.     return (num >= dutyCycle) ? T(0) : ~0 ; //same as square but dutyCycle sets treshold
  88. }
  89.  
  90. //pseudo random noise generator, 2 optionally different types
  91. template <typename T>
  92. T ukaelNoise(T num) {
  93.     uiRequired<T>();
  94.     constexpr size_t sz = sizeof(T)*2;
  95.     num^=num<<((num&sz)+2);
  96.     num*=3083;
  97.     num^=num>>((num&sz)+2);
  98.     return num;
  99. }
  100.  
Advertisement
Comments
Add Comment
Please, Sign In to add comment
Advertisement