#pragma once //waveform functions #include #include "ukaelTypedefC.h" static uint64_t rdtsc(){ uint32_t lo,hi; __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi)); return ((uint64_t)hi << 32) | lo; } /* static uint64_t rdrand(){ uint64_t rnum; __asm__ __volatile__ ("rdrand %0" : "=r" (rnum)); return rnum; } */ //refresh random seed 00000000000000000000000000000000 static uint32_t ENTROPY=4091831291; void reseed(){ ENTROPY^=ENTROPY<<15; ENTROPY^=ENTROPY>>13; return; } //sine approximation. static inline uint8_t ukaelSine(WaveArg *arg) { uint8_t time8 = arg->time*arg->freq.a/arg->freq.b; //n=floor(n) uint8_t secondHalf = time8 & 0b10000000; //s=floor(n%255/128) time8 <<= 1; //2*n%255 uint16_t buf = ((uint16_t)(time8)<<1) - UINT8_MAX; //(2*n-255)%65536 time8 = (uint8_t)((buf * buf) >> 9); //(floor(n^2%65536)/512)%255 time8 = secondHalf ? time8 : ~time8; //n = s ? n : 255-n return time8; } //Crunchy Sine static inline uint8_t ukaelCSine(WaveArg *arg) { uint8_t time8 = arg->time*arg->freq.a/arg->freq.b; uint8_t secondHalf = time8 & 0b10000000; time8 = !(time8 & 0b01000000) ? ~time8 : time8; //invert even quarters time8 <<= 2; //2 period saw time8 >>= 4; //square root. Crunchy precision time8*=time8; //square time8 >>= 1; //divide by 2 time8 = secondHalf ? time8 : ~time8; //invert 2nd half return time8; } //triangle static inline uint8_t ukaelTriangle(WaveArg *arg) { uint8_t time8 = arg->time*arg->freq.a/arg->freq.b; time8+=63; uint8_t secondHalf = time8&0b10000000; time8 <<= 1; time8 = secondHalf ? ~time8 : time8; //invert 2nd half return time8; } //Saw static inline uint8_t ukaelSaw(WaveArg *arg) { uint8_t time8 = arg->time*arg->freq.a/arg->freq.b; time8+=127; //add UINT_MAX/2 return time8; } //Square static inline uint8_t ukaelSquare(WaveArg *arg) { uint8_t time8 = arg->time*arg->freq.a/arg->freq.b; time8 = ( time8>>7 ) ? UINT8_MAX : 0; //hi if 0 to 0.5, low if 0.5 to 1.0 return time8 ; } //Pulse square 2 arguments static inline uint8_t ukaelPulse(WaveArg *arg) { uint8_t time8 = arg->time*arg->freq.a/arg->freq.b; time8 = (time8 >= arg->u8arg[0]) ? UINT8_MAX : 0; //same as square but dutyCycle sets treshold return time8 ; } //Time dependent noise static inline uint8_t ukaelNoise(WaveArg *arg) { uint16_t time16 = arg->time*arg->freq.a/arg->freq.b; reseed(); time16^=ENTROPY<<9; time16^=ENTROPY>>7; return time16; } //White noise static inline uint8_t ukaelWNoise(WaveArg *arg) { reseed(); return ENTROPY; } //White noise static inline uint8_t ukaelWNoiseOLD(uint16_t num) { reseed(); num*=3083*ENTROPY; return num; } //random walk static inline uint8_t ukaelRWalk(WaveArg *arg) { uint8_t prevSample = arg->u8arg[1]; uint8_t random = ukaelWNoise( &((WaveArg){ .freq=arg->freq} ) )>>(arg->u8arg[0]&6); //(0 to 255) / 3 uint8_t sign = random&1; //add=0 subtract=1 random>>=1; random=prevSample+(1-sign)*random-(sign)*random; //add or subtract random/2 and reuse random as result if(sign==1 && random>prevSample){ //underflow return 0; } if(sign==0 && randomu8arg[1]=random; return random; } #include //accurate sine very slow static inline uint8_t ukaelSinef(WaveArg *arg){ uint8_t time8 = arg->time*arg->freq.a/arg->freq.b; return (sin((float)time8/40.7436654)*128+128); } /* // Input: x (angle in radians, represented as fixed-point) // Output: sin(x) approximation (represented as uint8_t) uint8_t testing(WaveArg *arg) { uint8_t time8 = arg->time*arg->freq.a/arg->freq.b; const uint8_t lut[] = { 0, 25, 49, 74, 98, 120, 141, 160, 177, 191, 202, 210, 215, 218, 218, 215, 210, 202, 191, 177, 160, 141, 120, 98, 74, 49, 25 }; // Ensure x is within the range of one period time8 &= UINT8_MAX; // Map x to the lookup table index uint8_t index = (time8 * sizeof(lut)) >> 8; return lut[index]; } */ static const uint8_t sineLut[] = {128,131,134,137,140,143,146,149,152,156,159,162,165,168,171,174,176,179,182,185,188,191,193,196,199,201,204,206,209,211,213,216,218,220,222,224,226,228,230,232,234,236,237,239,240,242,243,245,246,247,248,249,250,251,252,252,253,254,254,255,255,255,255,255,255,255,255,255,255,255,254,254,253,252,252,251,250,249,248,247,246,245,243,242,240,239,237,236,234,232,230,228,226,224,222,220,218,216,213,211,209,206,204,201,199,196,193,191,188,185,182,179,176,174,171,168,165,162,159,156,152,149,146,143,140,137,134,131,127,124,121,118,115,112,109,106,103,99,96,93,90,87,84,81,79,76,73,70,67,64,62,59,56,54,51,49,46,44,42,39,37,35,33,31,29,27,25,23,21,19,18,16,15,13,12,10,9,8,7,6,5,4,3,3,2,1,1,0,0,0,0,0,0,0,0,0,0,0,1,1,2,3,3,4,5,6,7,8,9,10,12,13,15,16,18,19,21,23,25,27,29,31,33,35,37,39,42,44,46,49,51,54,56,59,62,64,67,70,73,76,79,81,84,87,90,93,96,99,103,107,110,113,116,119,122,125}; static inline uint8_t ukaeLSine(WaveArg *arg) { uint8_t time8 = arg->time * arg->freq.a / arg->freq.b; time8=sineLut[time8]; return time8; } static inline uint8_t testing(WaveArg *arg) { uint8_t time8 = arg->time * arg->freq.a / arg->freq.b; return time8; }