1
0

classic_vis.cpp 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. #include "main.h"
  2. #include "SABuffer.h"
  3. #include <math.h>
  4. #include "WinampAttributes.h"
  5. #include "fft.h"
  6. extern int _srate;
  7. #ifdef _M_IX86
  8. __inline static int lrint(float flt)
  9. {
  10. int intgr;
  11. _asm
  12. {
  13. fld flt
  14. fistp intgr
  15. }
  16. return intgr;
  17. }
  18. #else
  19. __inline static int lrint(float flt)
  20. {
  21. return (int)flt;
  22. }
  23. #endif
  24. // quantizes to 23 bits - use appropriately
  25. inline static float fastmin(float x, const float b)
  26. {
  27. x = b - x;
  28. x += (float)fabs(x);
  29. x *= 0.5f;
  30. x = b - x;
  31. return x;
  32. }
  33. #define FASTMIN(x,b) { x = b - x; x += (float)fabs(x); x *= 0.5f; x = b - x; }
  34. inline static float fastclip(float x, const float a, const float b)
  35. {
  36. float x1 = (float)fabs(x-a);
  37. float x2 = (float)fabs(x-b);
  38. x = x1 + (a+b);
  39. x -= x2;
  40. x *= 0.5f;
  41. return (x);
  42. }
  43. void makeOscData(char *tempdata, char *data_buf, int little_block, int channels, int bits)
  44. {
  45. float dd = little_block/75.0f;
  46. int x,c;
  47. int stride=bits/8; // number of bytes between samples
  48. // we're calculating using only the most significant byte,
  49. // because we only end up with 6 bit data anyway
  50. // if you want full resolution, check out CVS tag BETA_2005_1122_182830, file: vis.c
  51. char *ptr, *sbuf = data_buf;
  52. for (x = 0; x < 75; x ++)
  53. {
  54. float val=0;
  55. int index =(int)((float)x * dd); // calculate the nearest sample for this point, interpolation is too expensive for this use
  56. ptr=&sbuf[index*stride*channels+stride-1]; // find first sample, and offset for little endian
  57. for (c=0;c<channels;c++)
  58. {
  59. val += (float)*ptr / 8.0f; // we want our final value to be -32 to 32
  60. ptr+=stride; // jump to the next sample (channels are interleaved)
  61. }
  62. tempdata[x] = (char)lrint(val / (float)channels); // average the channels
  63. }
  64. }
  65. inline double fast_exp2(const double val)
  66. {
  67. int e;
  68. double ret;
  69. if (val >= 0)
  70. {
  71. e = int (val);
  72. ret = val - (e - 1);
  73. ((*(1 + (int *) &ret)) &= ~(2047 << 20)) += (e + 1023) << 20;
  74. }
  75. else
  76. {
  77. e = int (val + 1023);
  78. ret = val - (e - 1024);
  79. ((*(1 + (int *) &ret)) &= ~(2047 << 20)) += e << 20;
  80. }
  81. return (ret);
  82. }
  83. // ~6 clocks on Pentium M vs. ~24 for single precision sqrtf
  84. #if !defined(_WIN64)
  85. static inline float squareroot_sse_11bits(float x)
  86. {
  87. float z;
  88. _asm
  89. {
  90. rsqrtss xmm0, x
  91. rcpss xmm0, xmm0
  92. movss z, xmm0 // z ~= sqrt(x) to 0.038%
  93. }
  94. return z;
  95. }
  96. static inline int floor_int(double x)
  97. {
  98. int i;
  99. static const float round_toward_m_i = -0.5f;
  100. __asm
  101. {
  102. fld x
  103. fadd st, st(0)
  104. fadd round_toward_m_i
  105. fistp i
  106. sar i, 1
  107. }
  108. return (i);
  109. }
  110. #endif
  111. /*
  112. static inline float hermite(float x, float y0, float y1, float y2, float y3)
  113. {
  114. // 4-point, 3rd-order Hermite (x-form)
  115. float c0 = y1;
  116. float c1 = 0.5f * (y2 - y0);
  117. float c2 = y0 - 2.5f * y1 + 2.f * y2 - 0.5f * y3;
  118. float c3 = 1.5f * (y1 - y2) + 0.5f * (y3 - y0);
  119. return ((c3 * x + c2) * x + c1) * x + c0;
  120. }
  121. */
  122. /*
  123. static const float c_half = 0.5f;
  124. __declspec(naked) static float hermite(float frac_pos, const float* pntr)
  125. {
  126. __asm
  127. {
  128. push ecx;
  129. mov ecx, dword ptr[esp + 12]; //////////////////////////////////////////////////////////////////////////////////////////////////
  130. add ecx, 0x04; // ST(0) ST(1) ST(2) ST(3) ST(4) ST(5) ST(6) ST(7)
  131. fld dword ptr [ecx+4]; // x1
  132. fsub dword ptr [ecx-4]; // x1-xm1
  133. fld dword ptr [ecx]; // x0 x1-xm1
  134. fsub dword ptr [ecx+4]; // v x1-xm1
  135. fld dword ptr [ecx+8]; // x2 v x1-xm1
  136. fsub dword ptr [ecx]; // x2-x0 v x1-xm1
  137. fxch st(2); // x1-m1 v x2-x0
  138. fmul c_half; // c v x2-x0
  139. fxch st(2); // x2-x0 v c
  140. fmul c_half; // 0.5*(x2-x0) v c
  141. fxch st(2); // c v 0.5*(x2-x0)
  142. fst st(3); // c v 0.5*(x2-x0) c
  143. fadd st(0), st(1); // w v 0.5*(x2-x0) c
  144. fxch st(2); // 0.5*(x2-x0) v w c
  145. faddp st(1), st(0); // v+.5(x2-x0) w c
  146. fadd st(0), st(1); // a w c
  147. fadd st(1), st(0); // a b_neg c
  148. fmul dword ptr [esp+8]; // a*frac b_neg c
  149. fsubrp st(1), st(0); // a*f-b c
  150. fmul dword ptr [esp+8]; // (a*f-b)*f c
  151. faddp st(1), st(0); // res-x0/f
  152. fmul dword ptr [esp+8]; // res-x0
  153. fadd dword ptr [ecx]; // res
  154. pop ecx;
  155. ret;
  156. }
  157. }
  158. */
  159. inline float hermite(float x, float y0, float y1, float y2, float y3)
  160. {
  161. // 4-point, 3rd-order Hermite (x-form)
  162. float c0 = y1;
  163. float c1 = 0.5f * (y2 - y0);
  164. float c3 = 1.5f * (y1 - y2) + 0.5f * (y3 - y0);
  165. float c2 = y0 - y1 + c1 - c3;
  166. return ((c3 * x + c2) * x + c1) * x + c0;
  167. }
  168. static inline float fpow2(const float y)
  169. {
  170. union
  171. {
  172. float f;
  173. int i;
  174. } c;
  175. int integer = lrint(floor(y));
  176. /* cut: because we guarantee y>=0
  177. if(y < 0)
  178. integer = integer-1;
  179. */
  180. float frac = y - (float)integer;
  181. c.i = (integer+127) << 23;
  182. c.f *= 0.33977f*frac*frac + (1.0f-0.33977f)*frac + 1.0f;
  183. return c.f;
  184. }
  185. //#define SAPOW(x) (powf(2.f, (float)(x)/12.f))
  186. #define SAPOW(x) (fpow2((float)(x)/12.f))
  187. //#define WARP(x) ((powf(1.1f, (float)(x)/12.f) - 1.) * bla)
  188. #define WARP(x) ((SAPOW(x) - 1.f) * bla)
  189. void makeSpecData(unsigned char *tempdata, float *wavetrum)
  190. {
  191. //WARP(75);
  192. float bla = (255.f/SAPOW(75.f));
  193. fft_9(wavetrum);
  194. float spec_scale=0.5;
  195. if (config_replaygain)
  196. { // benski> i'm sure there's some math identity we can use to optimize this.
  197. spec_scale/=pow(10.0f, config_replaygain_non_rg_gain.GetFloat() / 20.0f);
  198. }
  199. for (int i=0;i<256;i++)
  200. {
  201. //int lookup=2*i;
  202. float sinT = wavetrum[2*i];
  203. float cosT = wavetrum[2*i+1];
  204. wavetrum[i] = sqrt(sinT*sinT+cosT*cosT)*spec_scale;
  205. }
  206. float next = WARP(0)+1 ;
  207. for (int x = 0; x < 75; x ++)
  208. {
  209. //float prev = 1.+(pow(2.,(float)x/12.) -1.) * bla;
  210. float binF = next;
  211. next = WARP(x+1) +1;
  212. float thisValue = 0;
  213. int bin = lrint(floor(binF));
  214. int end = lrint(floor(next));
  215. end = min(end, 255);
  216. float mult = ((float)(bin+1))-binF;
  217. bool herm=true;
  218. do
  219. {
  220. if (bin == end)
  221. {
  222. mult = (next-binF);
  223. herm=true;
  224. }
  225. if (herm)
  226. {
  227. float C=0, D=0;
  228. if (bin<255)
  229. {
  230. C=wavetrum[bin+1];
  231. if (bin<254)
  232. D=wavetrum[bin+2];
  233. }
  234. //float samples[4] = { wavetrum[lookupA], wavetrum[lookupB], wavetrum[lookupC], wavetrum[lookupD] };
  235. //thisValue += hermite(binF-bin, samples) * mult;
  236. thisValue += hermite(binF-bin, wavetrum[bin-1], wavetrum[bin], C, D) * mult;
  237. }
  238. else
  239. {
  240. thisValue += wavetrum[bin];
  241. }
  242. herm=false;
  243. bin++;
  244. binF=(float)bin;
  245. }
  246. while (bin <= end);
  247. tempdata[x]=lrint(fastmin(thisValue, 255.f));
  248. }
  249. }
  250. ////////////////////////////////
  251. SABuffer saBuffer;
  252. void sa_addpcmdata(void *_data_buf, int numChannels, int numBits, int ts)
  253. {
  254. char *data_buf = reinterpret_cast<char *>(_data_buf);
  255. char tempdata[75*2] = {0};
  256. __declspec(align(16)) float wavetrum[512];
  257. //extern int sa_curmode;
  258. int vis_Csa=sa_override ? 3 : sa_curmode;
  259. switch (vis_Csa)
  260. {
  261. case 4:
  262. tempdata[0] = 0;
  263. tempdata[1] = 0;
  264. sa_add(tempdata,ts,4);
  265. return;
  266. case 2:
  267. makeOscData(tempdata,data_buf,576,numChannels, numBits);
  268. sa_add(tempdata,ts,2);
  269. return ;
  270. case 3:
  271. makeOscData(tempdata+75,data_buf,576,numChannels, numBits);
  272. // fall through!
  273. case 1:
  274. calcVuData((unsigned char*)tempdata, data_buf, numChannels, numBits);
  275. vu_add(tempdata, ts);
  276. break;
  277. }
  278. bool done=false;
  279. size_t samples=576;
  280. while (samples)
  281. {
  282. unsigned int copied = saBuffer.AddToBuffer(data_buf, numChannels, numBits, ts, (unsigned int) samples);
  283. samples-=copied;
  284. data_buf+=(copied*(numBits/8)*numChannels);
  285. if (saBuffer.Full())
  286. {
  287. saBuffer.WindowToFFTBuffer(wavetrum);
  288. if (!done)
  289. {
  290. if (vis_Csa == 3)
  291. {
  292. makeSpecData((unsigned char*)tempdata, wavetrum);
  293. sa_add(tempdata, ts, 0x80000003);
  294. }
  295. else if (vis_Csa == 1)
  296. {
  297. makeSpecData((unsigned char*)tempdata, wavetrum);
  298. sa_add(tempdata, ts, 1);
  299. }
  300. }
  301. //done=true;
  302. saBuffer.CopyHalf();
  303. ts+=MulDiv(SABUFFER_WINDOW_INCREMENT,1000,_srate);
  304. }
  305. }
  306. }