SA.cpp 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. /*
  2. Spectrum Analyzer
  3. */
  4. #include "Main.h"
  5. #include <math.h>
  6. #include "../nu/threadname.h"
  7. static int last_pos;
  8. typedef struct sa_l
  9. {
  10. int timestamp;
  11. unsigned char data[2*75];
  12. char which;
  13. } sa_l;
  14. static int sa_fps = 76;
  15. static sa_l *sa_bufs;
  16. static int sa_position;
  17. static int sa_length, sa_size;
  18. static CRITICAL_SECTION cs;
  19. void sa_init(int numframes)
  20. {
  21. EnterCriticalSection(&cs);
  22. sa_length=0;
  23. if (numframes < 1) numframes = 1;
  24. if (numframes > sa_size)
  25. {
  26. free(sa_bufs);
  27. sa_bufs = (sa_l *)calloc(numframes, sizeof(sa_l));
  28. sa_size=numframes;
  29. }
  30. sa_position = 0;
  31. sa_length = numframes;
  32. last_pos = 0;
  33. LeaveCriticalSection(&cs);
  34. }
  35. void sa_deinit(void)
  36. {
  37. EnterCriticalSection(&cs);
  38. //if (sa_bufs)
  39. // {
  40. // free(sa_bufs);
  41. // sa_bufs = 0;
  42. sa_length = 0;
  43. //}
  44. LeaveCriticalSection(&cs);
  45. }
  46. int sa_add(char *values, int timestamp, int csa)
  47. {
  48. EnterCriticalSection(&cs);
  49. if (!sa_bufs || sa_length == 0)
  50. {
  51. LeaveCriticalSection(&cs);
  52. return 1;
  53. }
  54. if (sa_length == 1)
  55. {
  56. sa_position = 0;
  57. }
  58. if (csa == 3) csa = 1; // dont let it happen unless it has a high bit set
  59. csa &= 0x7fffffff;
  60. sa_bufs[sa_position].timestamp = timestamp;
  61. sa_bufs[sa_position].which = (char)csa;
  62. if (csa & 1)
  63. {
  64. memcpy(sa_bufs[sa_position].data, values, 75);
  65. values += 75;
  66. }
  67. else
  68. memset(sa_bufs[sa_position].data, 0, 75);
  69. if (csa & 2)
  70. memcpy(sa_bufs[sa_position].data + 75, values, 75);
  71. else
  72. memset(sa_bufs[sa_position].data + 75, 0, 75);
  73. sa_position++;
  74. if (sa_position >= sa_length) sa_position -= sa_length;
  75. LeaveCriticalSection(&cs);
  76. return 0;
  77. }
  78. char *sa_get(int timestamp, int csa, char data[75*2+8])
  79. {
  80. static int sa_pos;
  81. int closest = 1000000, closest_v = -1;
  82. EnterCriticalSection(&cs);
  83. if (!sa_bufs || sa_length==0)
  84. {
  85. LeaveCriticalSection(&cs);
  86. return 0;
  87. }
  88. if (sa_length == 1)
  89. {
  90. memcpy(data, sa_bufs[0].data, 75*2);
  91. LeaveCriticalSection(&cs);
  92. return (data);
  93. }
  94. int i = last_pos;
  95. for (int x = 0; x < sa_length; x ++)
  96. {
  97. if (i >= sa_length) i = 0;
  98. int d = timestamp - sa_bufs[i].timestamp;
  99. if (d < 0) d = -d;
  100. if (d < closest)
  101. {
  102. closest = d;
  103. closest_v = i;
  104. }
  105. else if (closest <= 6) break;
  106. i++;
  107. }
  108. if (closest < 400 && closest_v >= 0 && sa_bufs[closest_v].which & csa)
  109. {
  110. sa_pos = 0;
  111. last_pos = closest_v;
  112. memcpy(data, sa_bufs[closest_v].data, 75*2);
  113. LeaveCriticalSection(&cs);
  114. return data;
  115. }
  116. if (closest_v < 0 || !(sa_bufs[closest_v].which & csa) || closest > 400)
  117. {
  118. memset(data, 0, 75);
  119. data[(sa_pos % 150) >= 75 ? 149 - (sa_pos % 150) : (sa_pos % 150)] = 15;
  120. for (int x = 0; x < 75; x ++)
  121. data[x + 75] = (char) (int) (7.0 * sin((sa_pos + x) * 0.1));
  122. sa_pos++;
  123. LeaveCriticalSection(&cs);
  124. return data;
  125. }
  126. LeaveCriticalSection(&cs);
  127. return 0;
  128. }
  129. volatile int sa_override;
  130. void export_sa_setreq(int want)
  131. {
  132. EnterCriticalSection(&cs);
  133. sa_override = want;
  134. LeaveCriticalSection(&cs);
  135. }
  136. char *export_sa_get_deprecated()
  137. {
  138. static char data[75*2 + 8];
  139. int now = in_getouttime();
  140. char *p = sa_get(now, 3, data);
  141. if (!p) memset(data, 0, 75*2);
  142. return data;
  143. }
  144. char *export_sa_get(char data[75*2 + 8])
  145. {
  146. try
  147. {
  148. int now = in_getouttime();
  149. char *p = sa_get(now, 3, data);
  150. if (!p) memset(data, 0, 75*2);
  151. }
  152. catch(...) {}
  153. return data;
  154. }
  155. #pragma optimize("", off) // for some reason, optimizations are breaking the case statement in bivis_thread
  156. #define KILL_EVENT 0
  157. #define BLANK_EVENT 1
  158. #define ON_EVENT 2
  159. #define NUM_EVENTS 3
  160. #define saKillEvent saEvents[0]
  161. #define saBlankEvent saEvents[1]
  162. #define saOnEvent saEvents[2]
  163. HANDLE saEvents[NUM_EVENTS] = {0};
  164. static int SA_Wait()
  165. {
  166. if (WaitForSingleObject(saKillEvent, 16) == WAIT_OBJECT_0)
  167. return KILL_EVENT;
  168. if (WaitForSingleObject(saBlankEvent, 0) == WAIT_OBJECT_0)
  169. return BLANK_EVENT;
  170. return WaitForMultipleObjects(NUM_EVENTS, saEvents, FALSE, INFINITE)-WAIT_OBJECT_0;
  171. }
  172. static DWORD WINAPI bivis_thread(void *none)
  173. {
  174. int cycleCount=0;
  175. __int8 data[75*2 + 8] = {0};
  176. SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
  177. SetThreadName((DWORD)-1, "Classic Viz");
  178. while (1)
  179. {
  180. switch(SA_Wait())
  181. {
  182. case KILL_EVENT:
  183. return 0;
  184. case BLANK_EVENT:
  185. draw_sa(NULL, 1);
  186. break;
  187. case ON_EVENT:
  188. {
  189. int draw=0;
  190. if (++cycleCount < config_saref)
  191. draw=0;
  192. else
  193. {
  194. cycleCount=0;
  195. draw=1;
  196. }
  197. if (config_sa
  198. && !paused
  199. && playing
  200. && !config_minimized
  201. && (config_mw_open || (config_pe_open && config_pe_width >= 350 && config_pe_height != 14))
  202. && (!config_disvis || !vis_running()))
  203. {
  204. int a = in_getouttime();
  205. int t = config_sa;
  206. //if ((config_windowshade&&config_mw_open) && t == 1) t=4;
  207. char *c = sa_get(a, t, data);
  208. if (c)
  209. {
  210. if (t == 2) c += 75;
  211. else memset(c + 75, 0, 4);
  212. draw_sa((unsigned char*)c, draw);
  213. }
  214. }
  215. }
  216. break;
  217. }
  218. }
  219. return 0;
  220. }
  221. #pragma optimize("", on)
  222. HANDLE saThread=0;
  223. void SpectralAnalyzer_Create()
  224. {
  225. DWORD threadId = 0;
  226. InitializeCriticalSection(&cs);
  227. saKillEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
  228. saBlankEvent= CreateEvent(NULL, FALSE, FALSE, NULL);
  229. saOnEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
  230. saThread = (HANDLE) CreateThread(NULL, 256*1024, (LPTHREAD_START_ROUTINE) bivis_thread, 0, 0, &threadId);
  231. //cut: done on thread - SetThreadPriority(saThread, THREAD_PRIORITY_HIGHEST);
  232. sa_length=sa_size=0;
  233. VU_Create();
  234. }
  235. void SpectralAnalyzer_Destroy()
  236. {
  237. VU_Destroy();
  238. SetEvent(saKillEvent);
  239. WaitForSingleObject(saThread, INFINITE);
  240. CloseHandle(saThread);
  241. saThread = 0;
  242. CloseHandle(saKillEvent);
  243. CloseHandle(saBlankEvent);
  244. CloseHandle(saOnEvent);
  245. DeleteCriticalSection(&cs);
  246. free(sa_bufs);
  247. sa_bufs=0;
  248. sa_size=0;
  249. }
  250. volatile int sa_curmode;
  251. /*
  252. @param mode -1==shutdown 0==none, 1==spectral analyzer, 2==oscilloscope
  253. */
  254. void sa_setthread(int mode)
  255. {
  256. if (mode == -1)
  257. mode=0;
  258. sa_curmode = mode;
  259. if (mode)
  260. {
  261. SetEvent(saOnEvent);
  262. }
  263. else
  264. {
  265. ResetEvent(saOnEvent);
  266. SetEvent(saBlankEvent);
  267. }
  268. }