Collection of DPF-based plugins for packaging
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

558 lines
15KB

  1. /**
  2. * projectM -- Milkdrop-esque visualisation SDK
  3. * Copyright (C)2003-2004 projectM Team
  4. *
  5. * This library is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU Lesser General Public
  7. * License as published by the Free Software Foundation; either
  8. * version 2.1 of the License, or (at your option) any later version.
  9. *
  10. * This library is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  13. * Lesser General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU Lesser General Public
  16. * License along with this library; if not, write to the Free Software
  17. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  18. * See 'LICENSE.txt' included within this release
  19. *
  20. */
  21. /**
  22. * $Id: PCM.c,v 1.3 2006/03/13 20:35:26 psperl Exp $
  23. *
  24. * Takes sound data from wherever and hands it back out.
  25. * Returns PCM Data or spectrum data, or the derivative of the PCM data
  26. */
  27. #include <stdlib.h>
  28. #include <stdio.h>
  29. #include <math.h>
  30. #include "Common.hpp"
  31. #include "wipemalloc.h"
  32. #include "fftsg.h"
  33. #include "PCM.hpp"
  34. #include <cassert>
  35. // see https://github.com/projectM-visualizer/projectm/issues/161
  36. class AutoLevel
  37. {
  38. private:
  39. double level;
  40. // accumulate sample data
  41. size_t level_samples;
  42. double level_sum;
  43. double level_max;
  44. double l0,l1,l2;
  45. public:
  46. AutoLevel() : level(0.01),level_samples(0),level_sum(0),level_max(0),l0(-1),l1(-1),l2(-1)
  47. {
  48. }
  49. /*
  50. * Here is where we try to do auto volume setting. Doing this here
  51. * means that none of the code downstream (waveforms, beatdetect, etc) needs
  52. * to worry about it.
  53. *
  54. * 1) Don't over react to level changes within a song
  55. * 2) Ignore silence/gaps
  56. *
  57. * I don't know if it's necessary to have both sum and max, but that makes
  58. * it easier to experiment...
  59. */
  60. // This is an arbitrary number that helps control
  61. // a) how quickly the level can change and
  62. // b) keeps code from being affected by how the caller provides data (lot of short buffers, or fewer long buffers)
  63. #define AUTOLEVEL_SEGMENT 4096
  64. double updateLevel(size_t samples, double sum, double max)
  65. {
  66. if (sum/samples < 0.00001)
  67. return level;
  68. level_sum += sum;
  69. level_max = fmax(level_max,max*1.02);
  70. level_samples += samples;
  71. if (level_samples >= AUTOLEVEL_SEGMENT || l0 <= 0)
  72. {
  73. double max_recent = fmax(fmax(l0, l1), fmax(l2, level_max));
  74. l0 = l1; l1 = l2; l2 = level_max; level_max *= 0.95;
  75. level_sum = level_samples = 0;
  76. level = (l0 <= 0) ? max_recent : level * 0.96 + max_recent * 0.04;
  77. level = fmax(level,0.0001);
  78. }
  79. return level;
  80. }
  81. };
  82. PCM::PCM() : start(0), newsamples(0)
  83. {
  84. leveler = new AutoLevel();
  85. //Allocate FFT workspace
  86. // per rdft() documentation
  87. // length of ip >= 2+sqrt(n) and length of w == n/2
  88. #if FFT_LENGTH > 1024
  89. #error update this code
  90. #endif
  91. w = (double *)wipemalloc(FFT_LENGTH*sizeof(double));
  92. // see fftsg.cpp length of ip >= 2+sqrt(n/2)
  93. // in this case n=2*FFT_LENGTH, so 34 is big enough to handle FFT_LENGTH=1024
  94. ip = (int *)wipemalloc(34 * sizeof(int));
  95. ip[0]=0;
  96. memset(pcmL, 0, sizeof(pcmL));
  97. memset(pcmR, 0, sizeof(pcmR));
  98. memset(freqL, 0, sizeof(freqL));
  99. memset(freqR, 0, sizeof(freqR));
  100. memset(spectrumL, 0, sizeof(spectrumL));
  101. memset(spectrumR, 0, sizeof(spectrumR));
  102. }
  103. PCM::~PCM()
  104. {
  105. delete leveler;
  106. free(w);
  107. free(ip);
  108. }
  109. #include <iostream>
  110. void PCM::addPCMfloat(const float *PCMdata, size_t samples)
  111. {
  112. float a,sum=0,max=0;
  113. for (size_t i=0; i<samples; i++)
  114. {
  115. size_t j=(i+start)%maxsamples;
  116. a=pcmL[j] = PCMdata[i];
  117. pcmR[j] = PCMdata[i];
  118. sum += fabs(a);
  119. max = fmax(max,a);
  120. }
  121. start = (start+samples)%maxsamples;
  122. newsamples += samples;
  123. level = leveler->updateLevel(samples, sum, max);
  124. }
  125. /* NOTE: this method expects total samples, not samples per channel */
  126. void PCM::addPCMfloat_2ch(const float *PCMdata, size_t count)
  127. {
  128. size_t samples = count/2;
  129. float a,b,sum=0,max=0;
  130. for (size_t i=0; i<samples; i++)
  131. {
  132. size_t j=(start+i)%maxsamples;
  133. a = pcmL[j] = PCMdata[i*2];
  134. b = pcmR[j] = PCMdata[i*2+1];
  135. sum += fabs(a) + fabs(b);
  136. max = fmax(fmax(max,fabs(a)),fabs(b));
  137. }
  138. start = (start + samples) % maxsamples;
  139. newsamples += samples;
  140. level = leveler->updateLevel(samples, sum/2, max);
  141. }
  142. void PCM::addPCM16Data(const short* pcm_data, size_t samples)
  143. {
  144. float a, b, sum = 0, max = 0;
  145. for (size_t i = 0; i < samples; ++i)
  146. {
  147. size_t j = (i + start) % maxsamples;
  148. a = pcmL[j] = (pcm_data[i * 2 + 0] / 16384.0);
  149. b = pcmR[j] = (pcm_data[i * 2 + 1] / 16384.0);
  150. sum += fabs(a) + fabs(b);
  151. max = fmax(fmax(max, a), b);
  152. }
  153. start = (start + samples) % maxsamples;
  154. newsamples += samples;
  155. level = leveler->updateLevel(samples, sum/2, max);
  156. }
  157. void PCM::addPCM16(const short PCMdata[2][512])
  158. {
  159. const int samples=512;
  160. float a,b,sum=0,max=0;
  161. for (size_t i=0;i<samples;i++)
  162. {
  163. size_t j=(i+start) % maxsamples;
  164. a=pcmL[j]=(PCMdata[0][i]/16384.0);
  165. b=pcmR[j]=(PCMdata[1][i]/16384.0);
  166. sum += fabs(a) + fabs(b);
  167. max = fmax(fmax(max,a),b);
  168. }
  169. start = (start+samples) % maxsamples;
  170. newsamples += samples;
  171. level = leveler->updateLevel(samples, sum/2, max);
  172. }
  173. void PCM::addPCM8(const unsigned char PCMdata[2][1024])
  174. {
  175. const int samples=1024;
  176. float a,b,sum=0,max=0;
  177. for (size_t i=0; i<samples; i++)
  178. {
  179. size_t j= (i+start) % maxsamples;
  180. a=pcmL[j]=(((float)PCMdata[0][i] - 128.0) / 64 );
  181. b=pcmR[j]=(((float)PCMdata[1][i] - 128.0) / 64 );
  182. sum += fabs(a) + fabs(b);
  183. max = fmax(fmax(max,a),b);
  184. }
  185. start = (start + samples) % maxsamples;
  186. newsamples += samples;
  187. level = leveler->updateLevel(samples, sum/2, max);
  188. }
  189. void PCM::addPCM8_512(const unsigned char PCMdata[2][512])
  190. {
  191. const size_t samples=512;
  192. float a,b,sum=0,max=0;
  193. for (size_t i=0; i<samples; i++)
  194. {
  195. size_t j = (i+start) % maxsamples;
  196. a=pcmL[j]=(((float)PCMdata[0][i] - 128.0 ) / 64 );
  197. b=pcmR[j]=(((float)PCMdata[1][i] - 128.0 ) / 64 );
  198. sum += fabs(a) + fabs(b);
  199. max = fmax(fmax(max,a),b);
  200. }
  201. start = (start + samples) % maxsamples;
  202. newsamples += samples;
  203. level = leveler->updateLevel(samples, sum/2, max);
  204. }
  205. // puts sound data requested at provided pointer
  206. //
  207. // samples is number of PCM samples to return
  208. // smoothing is the smoothing coefficient
  209. // returned values are normalized from -1 to 1
  210. void PCM::getPCM(float *data, CHANNEL channel, size_t samples, float smoothing)
  211. {
  212. assert(channel == 0 || channel == 1);
  213. if (0==smoothing)
  214. {
  215. _copyPCM(data, channel, samples);
  216. return;
  217. }
  218. // since we've already got the freq data laying around, let's use that for smoothing
  219. _updateFFT();
  220. // copy
  221. double freq[FFT_LENGTH*2];
  222. double *from = channel==0 ? freqL : freqR;
  223. for (int i=0 ; i<FFT_LENGTH*2 ; i++)
  224. freq[i] = from[i];
  225. // The visible effects ramp up as you smoothing value gets close to 1.0 (consistent with milkdrop2)
  226. if (1==0) // gaussian
  227. {
  228. // precompute constant:
  229. double k = -1.0 / ((1 - smoothing) * (1 - smoothing) * FFT_LENGTH * FFT_LENGTH);
  230. for (int i = 1; i < FFT_LENGTH; i++)
  231. {
  232. float g = pow(2.718281828459045, i * i * k);
  233. freq[i * 2] *= g;
  234. freq[i * 2 + 1] *= g;
  235. }
  236. freq[1] *= pow(2.718281828459045, FFT_LENGTH*FFT_LENGTH*k);
  237. }
  238. else
  239. {
  240. // butterworth
  241. // this might be slightly faster to compute. pow() is expensive
  242. double k = 1.0 / ((1 - smoothing) * (1 - smoothing) * FFT_LENGTH * FFT_LENGTH);
  243. for (int i = 1; i < FFT_LENGTH; i++)
  244. {
  245. float b = 1.0 / (1.0 + (i * i * k));
  246. freq[i * 2] *= b;
  247. freq[i * 2 + 1] *= b;
  248. }
  249. freq[1] *= 1.0 / (1.0 + (FFT_LENGTH*FFT_LENGTH*k));
  250. }
  251. // inverse fft
  252. rdft(FFT_LENGTH*2, -1, freq, ip, w);
  253. for (size_t j = 0; j < FFT_LENGTH*2; j++)
  254. freq[j] *= 1.0 / FFT_LENGTH;
  255. // copy out with zero-padding if necessary
  256. size_t count = samples<FFT_LENGTH ? samples : FFT_LENGTH;
  257. for (size_t i=0 ; i<count ; i++)
  258. data[i] = freq[i%(FFT_LENGTH*2)];
  259. for (size_t i=count ; i<samples ; i++)
  260. data[i] = 0;
  261. }
  262. /* NOTE: Still don't have real support for smoothing parameter, but this gets close to the milkdrop2 default look */
  263. void PCM::getSpectrum(float *data, CHANNEL channel, size_t samples, float smoothing)
  264. {
  265. assert(channel == 0 || channel == 1);
  266. _updateFFT();
  267. float *spectrum = channel == 0 ? spectrumL : spectrumR;
  268. if (smoothing == 0)
  269. {
  270. size_t count = samples <= FFT_LENGTH ? samples : FFT_LENGTH;
  271. for (size_t i = 0; i < count; i++)
  272. data[i] = spectrum[i];
  273. for (size_t i = count; i < samples; i++)
  274. data[0] = 0;
  275. }
  276. else
  277. {
  278. float l2 = 0, l1 =0 , c = 0, r1, r2;
  279. r1 = spectrum[0]; r2 = spectrum[0+1];
  280. for (size_t i = 0; i < samples; i++)
  281. {
  282. l2 = l1;
  283. l1 = c;
  284. c = r1;
  285. r1 = r2;
  286. r2 = (i + 2) >= samples ? 0 : spectrum[i + 2];
  287. data[i] = (l2 + 4 * l1 + 6 * c + 4 * r1 + r2) / 16.0;
  288. }
  289. }
  290. }
  291. void PCM::_updateFFT()
  292. {
  293. if (newsamples > 0)
  294. {
  295. _updateFFT(0);
  296. _updateFFT(1);
  297. newsamples = 0;
  298. }
  299. }
  300. void PCM::_updateFFT(size_t channel)
  301. {
  302. assert(channel == 0 || channel == 1);
  303. double *freq = channel==0 ? freqL : freqR;
  304. _copyPCM(freq, channel, FFT_LENGTH*2);
  305. rdft(FFT_LENGTH*2, 1, freq, ip, w);
  306. // compute magnitude data (m^2 actually)
  307. float *spectrum = channel==0 ? spectrumL : spectrumR;
  308. for (size_t i=1 ; i<FFT_LENGTH ; i++)
  309. {
  310. double m2 = (freq[i * 2] * freq[i * 2] + freq[i * 2 + 1] * freq[i * 2 + 1]);
  311. spectrum[i-1] = m2 * ((double)i)/FFT_LENGTH;
  312. }
  313. spectrum[FFT_LENGTH-1] = freq[1] * freq[1];
  314. }
  315. inline double constrain(double a, double mn, double mx)
  316. {
  317. return a>mx ? mx : a<mn ? mn : a;
  318. }
  319. // pull data from circular buffer
  320. void PCM::_copyPCM(float *to, int channel, size_t count)
  321. {
  322. assert(channel == 0 || channel == 1);
  323. assert(count < maxsamples);
  324. const float *from = channel==0 ? pcmL : pcmR;
  325. const double volume = 1.0 / level;
  326. for (size_t i=0, pos=start ; i<count ; i++)
  327. {
  328. if (pos==0)
  329. pos = maxsamples;
  330. to[i] = from[--pos] * volume;
  331. }
  332. }
  333. void PCM::_copyPCM(double *to, int channel, size_t count)
  334. {
  335. assert(channel == 0 || channel == 1);
  336. const float *from = channel==0 ? pcmL : pcmR;
  337. const double volume = 1.0 / level;
  338. for (size_t i=0, pos=start ; i<count ; i++)
  339. {
  340. if (pos==0)
  341. pos = maxsamples;
  342. to[i] = from[--pos] * volume;
  343. }
  344. }
  345. //Free stuff
  346. void PCM::freePCM()
  347. {
  348. free(ip);
  349. free(w);
  350. ip = NULL;
  351. w = NULL;
  352. }
  353. // TESTS
  354. #include "TestRunner.hpp"
  355. #ifndef NDEBUG
  356. #define TEST(cond) if (!verify(__FILE__ ": " #cond,cond)) return false
  357. #define TEST2(str,cond) if (!verify(str,cond)) return false
  358. struct PCMTest : public Test
  359. {
  360. PCMTest() : Test("PCMTest")
  361. {}
  362. bool eq(float a, float b)
  363. {
  364. return fabs(a-b) < (fabs(a)+fabs(b) + 1)/1000.0f;
  365. }
  366. public:
  367. /* smoke test for each addPCM method */
  368. bool test_addpcm()
  369. {
  370. PCM pcm;
  371. // mono float
  372. {
  373. const size_t samples = 301;
  374. float *data = new float[samples];
  375. for (size_t i = 0; i < samples; i++)
  376. data[i] = ((float) i) / (samples - 1);
  377. for (size_t i = 0; i < 10; i++)
  378. pcm.addPCMfloat(data, samples);
  379. float *copy = new float[samples];
  380. pcm.level = 1.0;
  381. pcm._copyPCM(copy, 0, samples);
  382. for (size_t i = 0; i < samples; i++)
  383. TEST(eq(copy[i],((float)samples - 1 - i) / (samples - 1)));
  384. pcm._copyPCM(copy, 1, samples);
  385. for (size_t i = 0; i < samples; i++)
  386. TEST(eq(copy[i], ((float)samples - 1 - i) / (samples - 1)));
  387. free(data);
  388. free(copy);
  389. }
  390. // float_2ch
  391. {
  392. const size_t samples = 301;
  393. float *data = new float[samples*2];
  394. for (size_t i = 0; i < samples; i++)
  395. {
  396. data[i*2] = ((float) i) / (samples - 1);
  397. data[i*2+1] = 1.0-data[i*2] ;
  398. }
  399. for (size_t i = 0; i < 10; i++)
  400. pcm.addPCMfloat_2ch(data, samples*2);
  401. float *copy0 = new float[samples];
  402. float *copy1 = new float[samples];
  403. pcm.level = 1;
  404. pcm._copyPCM(copy0, 0, samples);
  405. pcm._copyPCM(copy1, 1, samples);
  406. for (size_t i = 0; i < samples; i++)
  407. TEST(eq(1.0,copy0[i]+copy1[i]));
  408. free(data);
  409. free(copy0);
  410. free(copy1);
  411. }
  412. // void PCM::addPCM16Data(const short* pcm_data, size_t samples)
  413. // void PCM::addPCM16(const short PCMdata[2][512])
  414. // void PCM::addPCM8(const unsigned char PCMdata[2][1024])
  415. // void PCM::addPCM8_512(const unsigned char PCMdata[2][512])
  416. return true;
  417. }
  418. bool test_fft()
  419. {
  420. PCM pcm;
  421. // low frequency
  422. {
  423. const size_t samples = 1024;
  424. float *data = new float[samples * 2];
  425. for (size_t i = 0; i < samples; i++)
  426. {
  427. float f = 2 * 3.141592653589793 * ((double) i) / (samples - 1);
  428. data[i * 2] = sin(f);
  429. data[i * 2 + 1] = sin(f + 1.0); // out of phase
  430. }
  431. pcm.addPCMfloat_2ch(data, samples * 2);
  432. pcm.addPCMfloat_2ch(data, samples * 2);
  433. float *freq0 = new float[FFT_LENGTH];
  434. float *freq1 = new float[FFT_LENGTH];
  435. pcm.level = 1.0;
  436. pcm.getSpectrum(freq0, CHANNEL_0, FFT_LENGTH, 0.0);
  437. pcm.getSpectrum(freq1, CHANNEL_1, FFT_LENGTH, 0.0);
  438. // freq0 and freq1 should be equal
  439. for (size_t i = 0; i < FFT_LENGTH; i++)
  440. TEST(eq(freq0[i], freq1[i]));
  441. TEST(freq0[0] > 500);
  442. for (size_t i = 1; i < FFT_LENGTH; i++)
  443. TEST(freq0[i] < 0.1);
  444. free(data);
  445. free(freq0);
  446. free(freq1);
  447. }
  448. // high frequency
  449. {
  450. const size_t samples = 2;
  451. float data[4] = {1.0,0.0,0.0,1.0};
  452. for (size_t i = 0; i < 1024; i++)
  453. pcm.addPCMfloat_2ch(data, samples * 2);
  454. float *freq0 = new float[FFT_LENGTH];
  455. float *freq1 = new float[FFT_LENGTH];
  456. pcm.level = 1.0;
  457. pcm.getSpectrum(freq0, CHANNEL_0, FFT_LENGTH, 0.0);
  458. pcm.getSpectrum(freq1, CHANNEL_1, FFT_LENGTH, 0.0);
  459. // freq0 and freq1 should be equal
  460. for (size_t i = 0; i < FFT_LENGTH; i++)
  461. TEST(eq(freq0[i], freq1[i]));
  462. for (size_t i=0 ; i<FFT_LENGTH-1 ; i++)
  463. TEST(0==freq0[i]);
  464. TEST(freq0[FFT_LENGTH-1] > 100000);
  465. free(freq0);
  466. free(freq1);
  467. }
  468. return true;
  469. }
  470. bool test() override
  471. {
  472. TEST(test_addpcm());
  473. TEST(test_fft());
  474. return true;
  475. }
  476. };
  477. Test* PCM::test()
  478. {
  479. return new PCMTest();
  480. }
  481. #else
  482. Test* PCM::test()
  483. {
  484. return nullptr;
  485. }
  486. #endif