Advertisement
Kaelygon

Sine approximations

Jul 5th, 2024 (edited)
967
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 1.59 KB | None | 0 0
  1.  
  2. #include <stdint.h>
  3. #include <stdio.h>
  4.  
  5. /*
  6.     Sine approximation of 127.5*sin(pi*x/2^7)+127.5
  7.     Based on quadratic (3x-x^3)/2 [0,0.25]
  8.     Detailed functions: https://desmos.com/calculator/sqllbjao14
  9.     Max error = ~1.8%. Identical to sine at 0,64,128,192,255
  10. */
  11. uint8_t kaelAudio_sine(uint8_t n){
  12.         uint8_t q = n>>6; //quarter phase 0b00=1st 0b01=2nd 0b10=3rd 0b11=4th  
  13.         n = n&0b00111111; //repeat quarters
  14.         n = q&0b01 ? 64-n : n; //mirror 2nd and 4th quarters by x-axis
  15.         uint16_t p = (((uint16_t)n*n)>>6)+1; //calculate 6x-n^3/2^11 cube in two parts to prevent overflow //+1 compensates flooring
  16.         p = 6*n - (((uint16_t)n*p)>>5);
  17.         uint8_t o = (p>>1)+128; //scale and offset to match sine wave
  18.         o = q&0b10 ? ~o : o; //mirror 3rd and 4th quarters by y-axis
  19.         return o;
  20. }
  21.  
  22. /*
  23.     Sine approximation of sin(2pi*x/128)*128
  24.     Based on parabola 2x-x^2 [0,0.5]
  25.     Detailed functions: https://desmos.com/calculator/fuhb4xzejt
  26.     max error 3.6%. Identical to sine at 0,64,128,192,255
  27. */
  28. uint8_t kaelAudio_sineParabola(uint8_t phase){
  29.     uint8_t secondHalf = phase & 0b10000000;
  30.     phase <<= 1;
  31.     uint16_t buf = ((uint16_t)(phase) << 1) - UINT8_MAX;
  32.     phase = (uint8_t)((buf * buf) >> 9);
  33.     phase = secondHalf ? phase : ~phase;
  34.     return phase;
  35. }
  36.  
  37. int main() {
  38.     //printf("print raw PCM unsigned 8-bit little endian");
  39.     //printf("(3x-x^3)/2\n");
  40.     for(uint16_t i=0;i!=65535;i++){
  41.         uint8_t o = kaelAudio_sine(i);
  42.         fwrite(&o, sizeof(uint8_t), 1, stdout);
  43.     }
  44.     for(uint16_t i=0;i!=65535;i++){
  45.         uint8_t o = kaelAudio_sineParabola(i);
  46.         fwrite(&o, sizeof(uint8_t), 1, stdout);
  47.     }
  48.     //printf("\n");
  49.     return 0;
  50. }
  51.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement