DSP.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487
  1. /*
  2. * DSP.cpp
  3. * -----------
  4. * Purpose: Mixing code for various DSPs (EQ, Mega-Bass, ...)
  5. * Notes : Ugh... This should really be removed at some point.
  6. * Authors: Olivier Lapicque
  7. * OpenMPT Devs
  8. * The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
  9. */
  10. #include "stdafx.h"
  11. #include "DSP.h"
  12. #include "openmpt/soundbase/MixSample.hpp"
  13. #include <math.h>
  14. OPENMPT_NAMESPACE_BEGIN
  15. #ifndef NO_DSP
  16. // Bass Expansion
  17. #define DEFAULT_XBASS_RANGE 14 // (x+2)*20 Hz (320Hz)
  18. #define DEFAULT_XBASS_DEPTH 6 // 1+(3>>(x-4)) (+6dB)
  19. ////////////////////////////////////////////////////////////////////
  20. // DSP Effects internal state
  21. static void X86_StereoDCRemoval(int *, uint32 count, int32 &nDCRFlt_Y1l, int32 &nDCRFlt_X1l, int32 &nDCRFlt_Y1r, int32 &nDCRFlt_X1r);
  22. static void X86_MonoDCRemoval(int *, uint32 count, int32 &nDCRFlt_Y1l, int32 &nDCRFlt_X1l);
  23. ///////////////////////////////////////////////////////////////////////////////////
  24. //
  25. // Biquad setup
  26. //
  27. #define PI 3.14159265358979323f
  28. static inline float Sgn(float x) { return (x >= 0) ? 1.0f : -1.0f; }
  29. static void ShelfEQ(int32 scale,
  30. int32 &outA1, int32 &outB0, int32 &outB1,
  31. int32 F_c, int32 F_s, float gainDC, float gainFT, float gainPI)
  32. {
  33. float a1, b0, b1;
  34. float gainFT2, gainDC2, gainPI2;
  35. float alpha, beta0, beta1, rho;
  36. float wT, quad;
  37. wT = PI * F_c / F_s;
  38. gainPI2 = gainPI * gainPI;
  39. gainFT2 = gainFT * gainFT;
  40. gainDC2 = gainDC * gainDC;
  41. quad = gainPI2 + gainDC2 - (gainFT2*2);
  42. alpha = 0;
  43. if (quad != 0)
  44. {
  45. float lambda = (gainPI2 - gainDC2) / quad;
  46. alpha = (float)(lambda - Sgn(lambda)*sqrt(lambda*lambda - 1.0f));
  47. }
  48. beta0 = 0.5f * ((gainDC + gainPI) + (gainDC - gainPI) * alpha);
  49. beta1 = 0.5f * ((gainDC - gainPI) + (gainDC + gainPI) * alpha);
  50. rho = (float)((sin((wT*0.5f) - (PI/4.0f))) / (sin((wT*0.5f) + (PI/4.0f))));
  51. quad = 1.0f / (1.0f + rho*alpha);
  52. b0 = ((beta0 + rho*beta1) * quad);
  53. b1 = ((beta1 + rho*beta0) * quad);
  54. a1 = - ((rho + alpha) * quad);
  55. outA1 = mpt::saturate_round<int32>(a1 * scale);
  56. outB0 = mpt::saturate_round<int32>(b0 * scale);
  57. outB1 = mpt::saturate_round<int32>(b1 * scale);
  58. }
  59. CSurroundSettings::CSurroundSettings() : m_nProLogicDepth(12), m_nProLogicDelay(20)
  60. {
  61. }
  62. CMegaBassSettings::CMegaBassSettings() : m_nXBassDepth(DEFAULT_XBASS_DEPTH), m_nXBassRange(DEFAULT_XBASS_RANGE)
  63. {
  64. }
  65. CSurround::CSurround()
  66. {
  67. // Surround Encoding: 1 delay line + low-pass filter + high-pass filter
  68. nSurroundSize = 0;
  69. nSurroundPos = 0;
  70. nDolbyDepth = 0;
  71. // Surround Biquads
  72. nDolbyHP_Y1 = 0;
  73. nDolbyHP_X1 = 0;
  74. nDolbyLP_Y1 = 0;
  75. nDolbyHP_B0 = 0;
  76. nDolbyHP_B1 = 0;
  77. nDolbyHP_A1 = 0;
  78. nDolbyLP_B0 = 0;
  79. nDolbyLP_B1 = 0;
  80. nDolbyLP_A1 = 0;
  81. MemsetZero(SurroundBuffer);
  82. }
  83. CMegaBass::CMegaBass()
  84. {
  85. // Bass Expansion: low-pass filter
  86. nXBassFlt_Y1 = 0;
  87. nXBassFlt_X1 = 0;
  88. nXBassFlt_B0 = 0;
  89. nXBassFlt_B1 = 0;
  90. nXBassFlt_A1 = 0;
  91. // DC Removal Biquad
  92. nDCRFlt_Y1lf = 0;
  93. nDCRFlt_X1lf = 0;
  94. nDCRFlt_Y1rf = 0;
  95. nDCRFlt_X1rf = 0;
  96. nDCRFlt_Y1lb = 0;
  97. nDCRFlt_X1lb = 0;
  98. nDCRFlt_Y1rb = 0;
  99. nDCRFlt_X1rb = 0;
  100. }
  101. void CSurround::Initialize(bool bReset, DWORD MixingFreq)
  102. {
  103. MPT_UNREFERENCED_PARAMETER(bReset);
  104. if (!m_Settings.m_nProLogicDelay) m_Settings.m_nProLogicDelay = 20;
  105. // Pro-Logic Surround
  106. nSurroundPos = nSurroundSize = 0;
  107. {
  108. memset(SurroundBuffer, 0, sizeof(SurroundBuffer));
  109. nSurroundSize = (MixingFreq * m_Settings.m_nProLogicDelay) / 1000;
  110. if (nSurroundSize > SURROUNDBUFFERSIZE) nSurroundSize = SURROUNDBUFFERSIZE;
  111. nDolbyDepth = m_Settings.m_nProLogicDepth;
  112. if (nDolbyDepth < 1) nDolbyDepth = 1;
  113. if (nDolbyDepth > 16) nDolbyDepth = 16;
  114. // Setup biquad filters
  115. ShelfEQ(1024, nDolbyHP_A1, nDolbyHP_B0, nDolbyHP_B1, 200, MixingFreq, 0, 0.5f, 1);
  116. ShelfEQ(1024, nDolbyLP_A1, nDolbyLP_B0, nDolbyLP_B1, 7000, MixingFreq, 1, 0.75f, 0);
  117. nDolbyHP_X1 = nDolbyHP_Y1 = 0;
  118. nDolbyLP_Y1 = 0;
  119. // Surround Level
  120. nDolbyHP_B0 = (nDolbyHP_B0 * nDolbyDepth) >> 5;
  121. nDolbyHP_B1 = (nDolbyHP_B1 * nDolbyDepth) >> 5;
  122. // +6dB
  123. nDolbyLP_B0 *= 2;
  124. nDolbyLP_B1 *= 2;
  125. }
  126. }
  127. void CMegaBass::Initialize(bool bReset, DWORD MixingFreq)
  128. {
  129. // Bass Expansion Reset
  130. {
  131. int32 a1 = 0, b0 = 1024, b1 = 0;
  132. int nXBassCutOff = 50 + (m_Settings.m_nXBassRange+2) * 20;
  133. int nXBassGain = m_Settings.m_nXBassDepth;
  134. nXBassGain = std::clamp(nXBassGain, 2, 8);
  135. nXBassCutOff = std::clamp(nXBassCutOff, 60, 600);
  136. ShelfEQ(1024, a1, b0, b1, nXBassCutOff, MixingFreq,
  137. 1.0f + (1.0f/16.0f) * (0x300 >> nXBassGain),
  138. 1.0f,
  139. 0.0000001f);
  140. if (nXBassGain > 5)
  141. {
  142. b0 >>= (nXBassGain-5);
  143. b1 >>= (nXBassGain-5);
  144. }
  145. nXBassFlt_A1 = a1;
  146. nXBassFlt_B0 = b0;
  147. nXBassFlt_B1 = b1;
  148. //Log("b0=%d b1=%d a1=%d\n", b0, b1, a1);
  149. }
  150. if (bReset)
  151. {
  152. nXBassFlt_X1 = 0;
  153. nXBassFlt_Y1 = 0;
  154. nDCRFlt_X1lf = 0;
  155. nDCRFlt_X1rf = 0;
  156. nDCRFlt_Y1lf = 0;
  157. nDCRFlt_Y1rf = 0;
  158. nDCRFlt_X1lb = 0;
  159. nDCRFlt_X1rb = 0;
  160. nDCRFlt_Y1lb = 0;
  161. nDCRFlt_Y1rb = 0;
  162. }
  163. }
  164. // 2-channel surround
  165. void CSurround::ProcessStereoSurround(int * MixSoundBuffer, int count)
  166. {
  167. int *pr = MixSoundBuffer, hy1 = nDolbyHP_Y1;
  168. for (int r=count; r; r--)
  169. {
  170. // Delay
  171. int secho = SurroundBuffer[nSurroundPos];
  172. SurroundBuffer[nSurroundPos] = (pr[0]+pr[1]+256) >> 9;
  173. // High-pass
  174. int v0 = (nDolbyHP_B0 * secho + nDolbyHP_B1 * nDolbyHP_X1 + nDolbyHP_A1 * hy1) >> 10;
  175. nDolbyHP_X1 = secho;
  176. // Low-pass
  177. int v = (nDolbyLP_B0 * v0 + nDolbyLP_B1 * hy1 + nDolbyLP_A1 * nDolbyLP_Y1) >> (10-8);
  178. hy1 = v0;
  179. nDolbyLP_Y1 = v >> 8;
  180. // Add echo
  181. pr[0] += v;
  182. pr[1] -= v;
  183. if (++nSurroundPos >= nSurroundSize) nSurroundPos = 0;
  184. pr += 2;
  185. }
  186. nDolbyHP_Y1 = hy1;
  187. }
  188. // 4-channels surround
  189. void CSurround::ProcessQuadSurround(int * MixSoundBuffer, int * MixRearBuffer, int count)
  190. {
  191. int *pr = MixSoundBuffer, hy1 = nDolbyHP_Y1;
  192. for (int r=count; r; r--)
  193. {
  194. int vl = pr[0] >> 1;
  195. int vr = pr[1] >> 1;
  196. pr[(uint32)(MixRearBuffer-MixSoundBuffer)] += vl;
  197. pr[((uint32)(MixRearBuffer-MixSoundBuffer))+1] += vr;
  198. // Delay
  199. int secho = SurroundBuffer[nSurroundPos];
  200. SurroundBuffer[nSurroundPos] = (vr+vl+256) >> 9;
  201. // High-pass
  202. int v0 = (nDolbyHP_B0 * secho + nDolbyHP_B1 * nDolbyHP_X1 + nDolbyHP_A1 * hy1) >> 10;
  203. nDolbyHP_X1 = secho;
  204. // Low-pass
  205. int v = (nDolbyLP_B0 * v0 + nDolbyLP_B1 * hy1 + nDolbyLP_A1 * nDolbyLP_Y1) >> (10-8);
  206. hy1 = v0;
  207. nDolbyLP_Y1 = v >> 8;
  208. // Add echo
  209. pr[(uint32)(MixRearBuffer-MixSoundBuffer)] += v;
  210. pr[((uint32)(MixRearBuffer-MixSoundBuffer))+1] += v;
  211. if (++nSurroundPos >= nSurroundSize) nSurroundPos = 0;
  212. pr += 2;
  213. }
  214. nDolbyHP_Y1 = hy1;
  215. }
  216. void CSurround::Process(int * MixSoundBuffer, int * MixRearBuffer, int count, uint32 nChannels)
  217. {
  218. if(nChannels >= 2)
  219. // Dolby Pro-Logic Surround
  220. {
  221. if (nChannels > 2) ProcessQuadSurround(MixSoundBuffer, MixRearBuffer, count); else
  222. ProcessStereoSurround(MixSoundBuffer, count);
  223. }
  224. }
  225. void CMegaBass::Process(int * MixSoundBuffer, int * MixRearBuffer, int count, uint32 nChannels)
  226. {
  227. if(nChannels >= 2)
  228. {
  229. X86_StereoDCRemoval(MixSoundBuffer, count, nDCRFlt_Y1lf, nDCRFlt_X1lf, nDCRFlt_Y1rf, nDCRFlt_X1rf);
  230. if(nChannels > 2) X86_StereoDCRemoval(MixRearBuffer, count, nDCRFlt_Y1lb, nDCRFlt_X1lb, nDCRFlt_Y1rb, nDCRFlt_X1rb);
  231. int *px = MixSoundBuffer;
  232. int *py = MixRearBuffer;
  233. int x1 = nXBassFlt_X1;
  234. int y1 = nXBassFlt_Y1;
  235. if(nChannels > 2) for (int x=count; x; x--)
  236. {
  237. int x_m = (px[0]+px[1]+py[0]+py[1]+0x100)>>9;
  238. y1 = (nXBassFlt_B0 * x_m + nXBassFlt_B1 * x1 + nXBassFlt_A1 * y1) >> (10-8);
  239. x1 = x_m;
  240. px[0] += y1;
  241. px[1] += y1;
  242. py[0] += y1;
  243. py[1] += y1;
  244. y1 = (y1+0x80) >> 8;
  245. px += 2;
  246. py += 2;
  247. } else for (int x=count; x; x--)
  248. {
  249. int x_m = (px[0]+px[1]+0x100)>>9;
  250. y1 = (nXBassFlt_B0 * x_m + nXBassFlt_B1 * x1 + nXBassFlt_A1 * y1) >> (10-8);
  251. x1 = x_m;
  252. px[0] += y1;
  253. px[1] += y1;
  254. y1 = (y1+0x80) >> 8;
  255. px += 2;
  256. }
  257. nXBassFlt_X1 = x1;
  258. nXBassFlt_Y1 = y1;
  259. } else
  260. {
  261. X86_MonoDCRemoval(MixSoundBuffer, count, nDCRFlt_Y1lf, nDCRFlt_X1lf);
  262. int *px = MixSoundBuffer;
  263. int x1 = nXBassFlt_X1;
  264. int y1 = nXBassFlt_Y1;
  265. for (int x=count; x; x--)
  266. {
  267. int x_m = (px[0]+0x80)>>8;
  268. y1 = (nXBassFlt_B0 * x_m + nXBassFlt_B1 * x1 + nXBassFlt_A1 * y1) >> (10-8);
  269. x1 = x_m;
  270. px[0] += y1;
  271. y1 = (y1+0x40) >> 8;
  272. px++;
  273. }
  274. nXBassFlt_X1 = x1;
  275. nXBassFlt_Y1 = y1;
  276. }
  277. }
  278. //////////////////////////////////////////////////////////////////////////
  279. //
  280. // DC Removal
  281. //
  282. #define DCR_AMOUNT 9
  283. static void X86_StereoDCRemoval(int *pBuffer, uint32 nSamples, int32 &nDCRFlt_Y1l, int32 &nDCRFlt_X1l, int32 &nDCRFlt_Y1r, int32 &nDCRFlt_X1r)
  284. {
  285. int y1l = nDCRFlt_Y1l, x1l = nDCRFlt_X1l;
  286. int y1r = nDCRFlt_Y1r, x1r = nDCRFlt_X1r;
  287. while(nSamples--)
  288. {
  289. int inL = pBuffer[0];
  290. int inR = pBuffer[1];
  291. int diffL = x1l - inL;
  292. int diffR = x1r - inR;
  293. x1l = inL;
  294. x1r = inR;
  295. int outL = diffL / (1 << (DCR_AMOUNT + 1)) - diffL + y1l;
  296. int outR = diffR / (1 << (DCR_AMOUNT + 1)) - diffR + y1r;
  297. pBuffer[0] = outL;
  298. pBuffer[1] = outR;
  299. pBuffer += 2;
  300. y1l = outL - outL / (1 << DCR_AMOUNT);
  301. y1r = outR - outR / (1 << DCR_AMOUNT);
  302. }
  303. nDCRFlt_Y1l = y1l;
  304. nDCRFlt_X1l = x1l;
  305. nDCRFlt_Y1r = y1r;
  306. nDCRFlt_X1r = x1r;
  307. }
  308. static void X86_MonoDCRemoval(int *pBuffer, uint32 nSamples, int32 &nDCRFlt_Y1l, int32 &nDCRFlt_X1l)
  309. {
  310. int y1l = nDCRFlt_Y1l, x1l = nDCRFlt_X1l;
  311. while(nSamples--)
  312. {
  313. int inM = pBuffer[0];
  314. int diff = x1l - inM;
  315. x1l = inM;
  316. pBuffer[0] = inM = diff / (1 << (DCR_AMOUNT + 1)) - diff + y1l;
  317. pBuffer++;
  318. y1l = inM - inM / (1 << DCR_AMOUNT);
  319. }
  320. nDCRFlt_Y1l = y1l;
  321. nDCRFlt_X1l = x1l;
  322. }
  323. /////////////////////////////////////////////////////////////////
  324. // Clean DSP Effects interface
  325. // [XBass level 0(quiet)-100(loud)], [cutoff in Hz 20-100]
  326. void CMegaBass::SetXBassParameters(uint32 nDepth, uint32 nRange)
  327. {
  328. if (nDepth > 100) nDepth = 100;
  329. uint32 gain = nDepth / 20;
  330. if (gain > 4) gain = 4;
  331. m_Settings.m_nXBassDepth = 8 - gain; // filter attenuation 1/256 .. 1/16
  332. uint32 range = nRange / 5;
  333. if (range > 5) range -= 5; else range = 0;
  334. if (nRange > 16) nRange = 16;
  335. m_Settings.m_nXBassRange = 21 - range; // filter average on 0.5-1.6ms
  336. }
  337. // [Surround level 0(quiet)-100(heavy)] [delay in ms, usually 5-50ms]
  338. void CSurround::SetSurroundParameters(uint32 nDepth, uint32 nDelay)
  339. {
  340. uint32 gain = (nDepth * 16) / 100;
  341. if (gain > 16) gain = 16;
  342. if (gain < 1) gain = 1;
  343. m_Settings.m_nProLogicDepth = gain;
  344. if (nDelay < 4) nDelay = 4;
  345. if (nDelay > 50) nDelay = 50;
  346. m_Settings.m_nProLogicDelay = nDelay;
  347. }
  348. BitCrushSettings::BitCrushSettings()
  349. : m_Bits(8)
  350. {
  351. return;
  352. }
  353. BitCrush::BitCrush()
  354. {
  355. }
  356. void BitCrush::Initialize(bool bReset, DWORD MixingFreq)
  357. {
  358. MPT_UNREFERENCED_PARAMETER(bReset);
  359. MPT_UNREFERENCED_PARAMETER(MixingFreq);
  360. }
  361. void BitCrush::Process(int * MixSoundBuffer, int * MixRearBuffer, int count, uint32 nChannels)
  362. {
  363. if(m_Settings.m_Bits <= 0)
  364. {
  365. return;
  366. }
  367. if(m_Settings.m_Bits > MixSampleIntTraits::mix_precision_bits)
  368. {
  369. return;
  370. }
  371. unsigned int mask = ~((1u << (MixSampleIntTraits::mix_precision_bits - m_Settings.m_Bits)) - 1u);
  372. if(nChannels == 4)
  373. {
  374. for(int frame = 0; frame < count; ++frame)
  375. {
  376. MixSoundBuffer[frame*2 + 0] &= mask;
  377. MixSoundBuffer[frame*2 + 1] &= mask;
  378. MixRearBuffer[frame*2 + 0] &= mask;
  379. MixRearBuffer[frame*2 + 1] &= mask;
  380. }
  381. } else if(nChannels == 2)
  382. {
  383. for(int frame = 0; frame < count; ++frame)
  384. {
  385. MixSoundBuffer[frame*2 + 0] &= mask;
  386. MixSoundBuffer[frame*2 + 1] &= mask;
  387. }
  388. } else if(nChannels == 1)
  389. {
  390. for(int frame = 0; frame < count; ++frame)
  391. {
  392. MixSoundBuffer[frame] &= mask;
  393. }
  394. }
  395. }
  396. #else
  397. MPT_MSVC_WORKAROUND_LNK4221(DSP)
  398. #endif // NO_DSP
  399. OPENMPT_NAMESPACE_END