A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
at master 528 lines 14 kB view raw
1/* 2** Algorithm: complex multiplication 3** 4** Performance: Bad accuracy, great speed. 5** 6** The simplest, way of generating trig values. Note, this method is 7** not stable, and errors accumulate rapidly. 8** 9** Computation: 2 *, 1 + per value. 10*/ 11 12#include "m_pd.h" 13 14#include "m_fixed.h" 15 16 17#define TRIG_FAST 18 19#ifdef TRIG_FAST 20char mtrig_algorithm[] = "Simple"; 21#define TRIG_VARS \ 22 t_fixed t_c,t_s; 23#define TRIG_INIT(k,c,s) \ 24 { \ 25 t_c = fcostab[k]; \ 26 t_s = fsintab[k]; \ 27 c = itofix(1); \ 28 s = 0; \ 29 } 30#define TRIG_NEXT(k,c,s) \ 31 { \ 32 t_fixed t = c; \ 33 c = mult(t,t_c) - mult(s,t_s); \ 34 s = mult(t,t_s) + mult(s,t_c); \ 35 } 36#define TRIG_23(k,c1,s1,c2,s2,c3,s3) \ 37 { \ 38 c2 = mult(c1,c1) - mult(s1,s1); \ 39 s2 = (mult(c1,s1)<<2); \ 40 c3 = mult(c2,c1) - mult(s2,s1); \ 41 s3 = mult(c2,s1) + mult(s2,c1); \ 42 } 43#endif 44#define TRIG_RESET(k,c,s) 45 46/* 47** Algorithm: O. Buneman's trig generator. 48** 49** Performance: Good accuracy, mediocre speed. 50** 51** Manipulates a log(n) table to stably create n evenly spaced trig 52** values. The newly generated values lay halfway between two 53** known values, and are calculated by appropriatelly scaling the 54** average of the known trig values appropriatelly according to the 55** angle between them. This process is inherently stable; and is 56** about as accurate as most trig library functions. The errors 57** caused by this code segment are primarily due to the less stable 58** method to calculate values for 2t and s 3t. Note: I believe this 59** algorithm is patented(!), see readme file for more details. 60** 61** Computation: 1 +, 1 *, much integer math, per trig value 62** 63*/ 64 65#ifdef TRIG_GOOD 66#define TRIG_VARS \ 67 int t_lam=0; \ 68 double coswrk[TRIG_TABLE_SIZE],sinwrk[TRIG_TABLE_SIZE]; 69#define TRIG_INIT(k,c,s) \ 70 { \ 71 int i; \ 72 for (i=0 ; i<=k ; i++) \ 73 {coswrk[i]=fcostab[i];sinwrk[i]=fsintab[i];} \ 74 t_lam = 0; \ 75 c = 1; \ 76 s = 0; \ 77 } 78#define TRIG_NEXT(k,c,s) \ 79 { \ 80 int i,j; \ 81 (t_lam)++; \ 82 for (i=0 ; !((1<<i)&t_lam) ; i++); \ 83 i = k-i; \ 84 s = sinwrk[i]; \ 85 c = coswrk[i]; \ 86 if (i>1) \ 87 { \ 88 for (j=k-i+2 ; (1<<j)&t_lam ; j++); \ 89 j = k - j; \ 90 sinwrk[i] = halsec[i] * (sinwrk[i-1] + sinwrk[j]); \ 91 coswrk[i] = halsec[i] * (coswrk[i-1] + coswrk[j]); \ 92 } \ 93 } 94#endif 95 96 97#define TRIG_TAB_SIZE 22 98 99#ifndef ROCKBOX 100static long long halsec[TRIG_TAB_SIZE]= {1,2,3}; 101#endif 102 103#define FFTmult(x,y) mult(x,y) 104 105 106 107 108#include "d_imayer_tables.h" 109 110#define SQRT2 ftofix(1.414213562373095048801688724209698) 111 112 113static void imayer_fht(t_fixed *fz, int n) 114{ 115 int k,k1,k2,k3,k4,kx; 116 t_fixed *fi,*fn,*gi; 117 TRIG_VARS; 118 119 for (k1=1,k2=0;k1<n;k1++) 120 { 121 t_fixed aa; 122 for (k=n>>1; (!((k2^=k)&k)); k>>=1); 123 if (k1>k2) 124 { 125 aa=fz[k1];fz[k1]=fz[k2];fz[k2]=aa; 126 } 127 } 128 for ( k=0 ; (1<<k)<n ; k++ ); 129 k &= 1; 130 if (k==0) 131 { 132 for (fi=fz,fn=fz+n;fi<fn;fi+=4) 133 { 134 t_fixed f0,f1,f2,f3; 135 f1 = fi[0 ]-fi[1 ]; 136 f0 = fi[0 ]+fi[1 ]; 137 f3 = fi[2 ]-fi[3 ]; 138 f2 = fi[2 ]+fi[3 ]; 139 fi[2 ] = (f0-f2); 140 fi[0 ] = (f0+f2); 141 fi[3 ] = (f1-f3); 142 fi[1 ] = (f1+f3); 143 } 144 } 145 else 146 { 147 for (fi=fz,fn=fz+n,gi=fi+1;fi<fn;fi+=8,gi+=8) 148 { 149 t_fixed bs1,bc1,bs2,bc2,bs3,bc3,bs4,bc4, 150 bg0,bf0,bf1,bg1,bf2,bg2,bf3,bg3; 151 bc1 = fi[0 ] - gi[0 ]; 152 bs1 = fi[0 ] + gi[0 ]; 153 bc2 = fi[2 ] - gi[2 ]; 154 bs2 = fi[2 ] + gi[2 ]; 155 bc3 = fi[4 ] - gi[4 ]; 156 bs3 = fi[4 ] + gi[4 ]; 157 bc4 = fi[6 ] - gi[6 ]; 158 bs4 = fi[6 ] + gi[6 ]; 159 bf1 = (bs1 - bs2); 160 bf0 = (bs1 + bs2); 161 bg1 = (bc1 - bc2); 162 bg0 = (bc1 + bc2); 163 bf3 = (bs3 - bs4); 164 bf2 = (bs3 + bs4); 165 bg3 = FFTmult(SQRT2,bc4); 166 bg2 = FFTmult(SQRT2,bc3); 167 fi[4 ] = bf0 - bf2; 168 fi[0 ] = bf0 + bf2; 169 fi[6 ] = bf1 - bf3; 170 fi[2 ] = bf1 + bf3; 171 gi[4 ] = bg0 - bg2; 172 gi[0 ] = bg0 + bg2; 173 gi[6 ] = bg1 - bg3; 174 gi[2 ] = bg1 + bg3; 175 } 176 } 177 if (n<16) return; 178 179 do 180 { 181 t_fixed s1,c1; 182 int ii; 183 k += 2; 184 k1 = 1 << k; 185 k2 = k1 << 1; 186 k4 = k2 << 1; 187 k3 = k2 + k1; 188 kx = k1 >> 1; 189 fi = fz; 190 gi = fi + kx; 191 fn = fz + n; 192 do 193 { 194 t_fixed g0,f0,f1,g1,f2,g2,f3,g3; 195 f1 = fi[0 ] - fi[k1]; 196 f0 = fi[0 ] + fi[k1]; 197 f3 = fi[k2] - fi[k3]; 198 f2 = fi[k2] + fi[k3]; 199 fi[k2] = f0 - f2; 200 fi[0 ] = f0 + f2; 201 fi[k3] = f1 - f3; 202 fi[k1] = f1 + f3; 203 g1 = gi[0 ] - gi[k1]; 204 g0 = gi[0 ] + gi[k1]; 205 g3 = FFTmult(SQRT2, gi[k3]); 206 g2 = FFTmult(SQRT2, gi[k2]); 207 gi[k2] = g0 - g2; 208 gi[0 ] = g0 + g2; 209 gi[k3] = g1 - g3; 210 gi[k1] = g1 + g3; 211 gi += k4; 212 fi += k4; 213 } while (fi<fn); 214 TRIG_INIT(k,c1,s1); 215 for (ii=1;ii<kx;ii++) 216 { 217 t_fixed c2,s2; 218 TRIG_NEXT(k,c1,s1); 219 c2 = FFTmult(c1,c1) - FFTmult(s1,s1); 220 s2 = 2*FFTmult(c1,s1); 221 fn = fz + n; 222 fi = fz +ii; 223 gi = fz +k1-ii; 224 do 225 { 226 t_fixed a,b,g0,f0,f1,g1,f2,g2,f3,g3; 227 b = FFTmult(s2,fi[k1]) - FFTmult(c2,gi[k1]); 228 a = FFTmult(c2,fi[k1]) + FFTmult(s2,gi[k1]); 229 f1 = fi[0 ] - a; 230 f0 = fi[0 ] + a; 231 g1 = gi[0 ] - b; 232 g0 = gi[0 ] + b; 233 b = FFTmult(s2,fi[k3]) - FFTmult(c2,gi[k3]); 234 a = FFTmult(c2,fi[k3]) + FFTmult(s2,gi[k3]); 235 f3 = fi[k2] - a; 236 f2 = fi[k2] + a; 237 g3 = gi[k2] - b; 238 g2 = gi[k2] + b; 239 b = FFTmult(s1,f2) - FFTmult(c1,g3); 240 a = FFTmult(c1,f2) + FFTmult(s1,g3); 241 fi[k2] = f0 - a; 242 fi[0 ] = f0 + a; 243 gi[k3] = g1 - b; 244 gi[k1] = g1 + b; 245 b = FFTmult(c1,g2) - FFTmult(s1,f3); 246 a = FFTmult(s1,g2) + FFTmult(c1,f3); 247 gi[k2] = g0 - a; 248 gi[0 ] = g0 + a; 249 fi[k3] = f1 - b; 250 fi[k1] = f1 + b; 251 gi += k4; 252 fi += k4; 253 } while (fi<fn); 254 } 255 TRIG_RESET(k,c1,s1); 256 } while (k4<n); 257} 258 259 260void imayer_fft(int n, t_fixed *real, t_fixed *imag) 261{ 262 t_fixed a,b,c,d; 263 t_fixed q,r,s,t; 264 int i,j,k; 265 for (i=1,j=n-1,k=n/2;i<k;i++,j--) { 266 a = real[i]; b = real[j]; q=a+b; r=a-b; 267 c = imag[i]; d = imag[j]; s=c+d; t=c-d; 268 real[i] = (q+t)>>1; real[j] = (q-t)>>1; 269 imag[i] = (s-r)>>1; imag[j] = (s+r)>>1; 270 } 271 imayer_fht(real,n); 272 imayer_fht(imag,n); 273} 274 275void imayer_ifft(int n, t_fixed *real, t_fixed *imag) 276{ 277 t_fixed a,b,c,d; 278 t_fixed q,r,s,t; 279 int i,j,k; 280 imayer_fht(real,n); 281 imayer_fht(imag,n); 282 for (i=1,j=n-1,k=n/2;i<k;i++,j--) { 283 a = real[i]; b = real[j]; q=a+b; r=a-b; 284 c = imag[i]; d = imag[j]; s=c+d; t=c-d; 285 imag[i] = (s+r)>>1; imag[j] = (s-r)>>1; 286 real[i] = (q-t)>>1; real[j] = (q+t)>>1; 287 } 288} 289 290void imayer_realfft(int n, t_fixed *real) 291{ 292#ifdef ROCKBOX 293 t_fixed a,b; 294#else 295 t_fixed a,b,c,d; 296#endif 297 int i,j,k; 298 imayer_fht(real,n); 299 for (i=1,j=n-1,k=n/2;i<k;i++,j--) { 300 a = real[i]; 301 b = real[j]; 302 real[j] = (a-b)>>1; 303 real[i] = (a+b)>>1; 304 } 305} 306 307void imayer_realifft(int n, t_fixed *real) 308{ 309#ifdef ROCKBOX 310 t_fixed a,b; 311#else 312 t_fixed a,b,c,d; 313#endif 314 int i,j,k; 315 for (i=1,j=n-1,k=n/2;i<k;i++,j--) { 316 a = real[i]; 317 b = real[j]; 318 real[j] = (a-b); 319 real[i] = (a+b); 320 } 321 imayer_fht(real,n); 322} 323 324 325 326#ifdef TEST 327 328static double dfcostab[TRIG_TAB_SIZE]= 329 { 330 .00000000000000000000000000000000000000000000000000, 331 .70710678118654752440084436210484903928483593768847, 332 .92387953251128675612818318939678828682241662586364, 333 .98078528040323044912618223613423903697393373089333, 334 .99518472667219688624483695310947992157547486872985, 335 .99879545620517239271477160475910069444320361470461, 336 .99969881869620422011576564966617219685006108125772, 337 .99992470183914454092164649119638322435060646880221, 338 .99998117528260114265699043772856771617391725094433, 339 .99999529380957617151158012570011989955298763362218, 340 .99999882345170190992902571017152601904826792288976, 341 .99999970586288221916022821773876567711626389934930, 342 .99999992646571785114473148070738785694820115568892, 343 .99999998161642929380834691540290971450507605124278, 344 .99999999540410731289097193313960614895889430318945, 345 .99999999885102682756267330779455410840053741619428, 346 .99999999971275670684941397221864177608908945791828, 347 .99999999992818917670977509588385049026048033310951 348 }; 349static double dfsintab[TRIG_TAB_SIZE]= 350 { 351 1.0000000000000000000000000000000000000000000000000, 352 .70710678118654752440084436210484903928483593768846, 353 .38268343236508977172845998403039886676134456248561, 354 .19509032201612826784828486847702224092769161775195, 355 .09801714032956060199419556388864184586113667316749, 356 .04906767432741801425495497694268265831474536302574, 357 .02454122852291228803173452945928292506546611923944, 358 .01227153828571992607940826195100321214037231959176, 359 .00613588464915447535964023459037258091705788631738, 360 .00306795676296597627014536549091984251894461021344, 361 .00153398018628476561230369715026407907995486457522, 362 .00076699031874270452693856835794857664314091945205, 363 .00038349518757139558907246168118138126339502603495, 364 .00019174759731070330743990956198900093346887403385, 365 .00009587379909597734587051721097647635118706561284, 366 .00004793689960306688454900399049465887274686668768, 367 .00002396844980841821872918657716502182009476147489, 368 .00001198422490506970642152156159698898480473197753 369 }; 370 371static double dhalsec[TRIG_TAB_SIZE]= 372 { 373 0, 374 0, 375 .54119610014619698439972320536638942006107206337801, 376 .50979557910415916894193980398784391368261849190893, 377 .50241928618815570551167011928012092247859337193963, 378 .50060299823519630134550410676638239611758632599591, 379 .50015063602065098821477101271097658495974913010340, 380 .50003765191554772296778139077905492847503165398345, 381 .50000941253588775676512870469186533538523133757983, 382 .50000235310628608051401267171204408939326297376426, 383 .50000058827484117879868526730916804925780637276181, 384 .50000014706860214875463798283871198206179118093251, 385 .50000003676714377807315864400643020315103490883972, 386 .50000000919178552207366560348853455333939112569380, 387 .50000000229794635411562887767906868558991922348920, 388 .50000000057448658687873302235147272458812263401372, 389 .50000000014362164661654736863252589967935073278768, 390 .50000000003590541164769084922906986545517021050714 391 }; 392 393 394#include <stdio.h> 395 396 397int writetables() 398{ 399 int i; 400 401 printf("/* Tables for fixed point lookup with %d bit precision*/\n\n",fix1); 402 403 printf("static int fsintab[TRIG_TAB_SIZE]= {\n"); 404 405 for (i=0;i<TRIG_TAB_SIZE-1;i++) 406 printf("%ld, \n",ftofix(dfsintab[i])); 407 printf("%ld }; \n",ftofix(dfsintab[i])); 408 409 410 printf("\n\nstatic int fcostab[TRIG_TAB_SIZE]= {\n"); 411 412 for (i=0;i<TRIG_TAB_SIZE-1;i++) 413 printf("%ld, \n",ftofix(dfcostab[i])); 414 printf("%ld }; \n",ftofix(dfcostab[i])); 415 416} 417 418 419#define OUTPUT \ 420 fprintf(stderr,"Integer - Float\n");\ 421 for (i=0;i<NP;i++)\ 422 fprintf(stderr,"%f %f --> %f %f\n",fixtof(r[i]),fixtof(im[i]),\ 423 fr[i],fim[i]);\ 424 fprintf(stderr,"\n\n"); 425 426 427 428int main() 429{ 430 int i; 431 t_fixed r[256]; 432 t_fixed im[256]; 433 float fr[256]; 434 float fim[256]; 435 436 437#if 1 438 writetables(); 439 exit(0); 440#endif 441 442 443#if 0 444 t_fixed c1,s1,c2,s2,c3,s3; 445 int k; 446 int i; 447 448 TRIG_VARS; 449 450 for (k=2;k<10;k+=2) { 451 TRIG_INIT(k,c1,s1); 452 for (i=0;i<8;i++) { 453 TRIG_NEXT(k,c1,s1); 454 TRIG_23(k,c1,s1,c2,s2,c3,s3); 455 printf("TRIG value k=%d,%d val1 = %f %f\n",k,i,fixtof(c1),fixtof(s1)); 456 } 457 } 458#endif 459 460 461 462#if 1 463 464 #define NP 16 465 466 for (i=0;i<NP;i++) { 467 fr[i] = 0.; 468 r[i] = 0.; 469 fim[i] = 0.; 470 im[i] = 0; 471 } 472 473#if 0 474 for (i=0;i<NP;i++) { 475 if (i&1) { 476 fr[i] = 0.1*i; 477 r[i] = ftofix(0.1*i); 478 } 479 else { 480 fr[i] = 0.; 481 r[i] = 0.; 482 } 483 } 484#endif 485#if 0 486 for (i=0;i<NP;i++) { 487 fr[i] = 0.1; 488 r[i] = ftofix(0.1); 489 } 490#endif 491 492 r[1] = ftofix(0.1); 493 fr[1] = 0.1; 494 495 496 497 /* TEST RUN */ 498 499 OUTPUT 500 501 imayer_fft(NP,r,im); 502 mayer_fft(NP,fr,fim); 503// imayer_fht(r,NP); 504// mayer_fht(fr,NP); 505 506#if 1 507 for (i=0;i<NP;i++) { 508 r[i] = mult(ftofix(0.01),r[i]); 509 fr[i] = 0.01*fr[i]; 510 } 511#endif 512 513 OUTPUT 514 515 516 imayer_fft(NP,r,im); 517 mayer_fft(NP,fr,fim); 518 519 OUTPUT 520 521 522#endif 523 524 525} 526 527#endif 528