1
0

MixerLoops.cpp 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. /*
  2. * MixerLoops.cpp
  3. * --------------
  4. * Purpose: Utility inner loops for mixer-related functionality.
  5. * Notes : This file contains performance-critical loops.
  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 "MixerLoops.h"
  12. #include "Snd_defs.h"
  13. #include "ModChannel.h"
  14. OPENMPT_NAMESPACE_BEGIN
  15. void FloatToStereoMix(const float *pIn1, const float *pIn2, int32 *pOut, uint32 nCount, const float _f2ic)
  16. {
  17. for(uint32 i=0; i<nCount; ++i)
  18. {
  19. *pOut++ = (int)(*pIn1++ * _f2ic);
  20. *pOut++ = (int)(*pIn2++ * _f2ic);
  21. }
  22. }
  23. void StereoMixToFloat(const int32 *pSrc, float *pOut1, float *pOut2, uint32 nCount, const float _i2fc)
  24. {
  25. for(uint32 i=0; i<nCount; ++i)
  26. {
  27. *pOut1++ = *pSrc++ * _i2fc;
  28. *pOut2++ = *pSrc++ * _i2fc;
  29. }
  30. }
  31. void FloatToMonoMix(const float *pIn, int32 *pOut, uint32 nCount, const float _f2ic)
  32. {
  33. for(uint32 i=0; i<nCount; ++i)
  34. {
  35. *pOut++ = (int)(*pIn++ * _f2ic);
  36. }
  37. }
  38. void MonoMixToFloat(const int32 *pSrc, float *pOut, uint32 nCount, const float _i2fc)
  39. {
  40. for(uint32 i=0; i<nCount; ++i)
  41. {
  42. *pOut++ = *pSrc++ * _i2fc;
  43. }
  44. }
  45. void InitMixBuffer(mixsample_t *pBuffer, uint32 nSamples)
  46. {
  47. std::memset(pBuffer, 0, nSamples * sizeof(mixsample_t));
  48. }
  49. void InterleaveFrontRear(mixsample_t *pFrontBuf, mixsample_t *pRearBuf, uint32 nFrames)
  50. {
  51. // copy backwards as we are writing back into FrontBuf
  52. for(int i=nFrames-1; i>=0; i--)
  53. {
  54. pFrontBuf[i*4+3] = pRearBuf[i*2+1];
  55. pFrontBuf[i*4+2] = pRearBuf[i*2+0];
  56. pFrontBuf[i*4+1] = pFrontBuf[i*2+1];
  57. pFrontBuf[i*4+0] = pFrontBuf[i*2+0];
  58. }
  59. }
  60. void MonoFromStereo(mixsample_t *pMixBuf, uint32 nSamples)
  61. {
  62. for(uint32 i=0; i<nSamples; ++i)
  63. {
  64. pMixBuf[i] = (pMixBuf[i*2] + pMixBuf[i*2+1]) / 2;
  65. }
  66. }
  67. #define OFSDECAYSHIFT 8
  68. #define OFSDECAYMASK 0xFF
  69. #define OFSTHRESHOLD static_cast<mixsample_t>(1.0 / (1 << 20)) // Decay threshold for floating point mixer
  70. void StereoFill(mixsample_t *pBuffer, uint32 nSamples, mixsample_t &rofs, mixsample_t &lofs)
  71. {
  72. if((!rofs) && (!lofs))
  73. {
  74. InitMixBuffer(pBuffer, nSamples*2);
  75. return;
  76. }
  77. for(uint32 i=0; i<nSamples; i++)
  78. {
  79. #ifdef MPT_INTMIXER
  80. // Equivalent to int x_r = (rofs + (rofs > 0 ? 255 : -255)) / 256;
  81. const mixsample_t x_r = mpt::rshift_signed(rofs + (mpt::rshift_signed(-rofs, sizeof(mixsample_t) * 8 - 1) & OFSDECAYMASK), OFSDECAYSHIFT);
  82. const mixsample_t x_l = mpt::rshift_signed(lofs + (mpt::rshift_signed(-lofs, sizeof(mixsample_t) * 8 - 1) & OFSDECAYMASK), OFSDECAYSHIFT);
  83. #else
  84. const mixsample_t x_r = rofs * (1.0f / (1 << OFSDECAYSHIFT));
  85. const mixsample_t x_l = lofs * (1.0f / (1 << OFSDECAYSHIFT));
  86. #endif
  87. rofs -= x_r;
  88. lofs -= x_l;
  89. pBuffer[i*2] = rofs;
  90. pBuffer[i*2+1] = lofs;
  91. }
  92. #ifndef MPT_INTMIXER
  93. if(fabs(rofs) < OFSTHRESHOLD) rofs = 0;
  94. if(fabs(lofs) < OFSTHRESHOLD) lofs = 0;
  95. #endif
  96. }
  97. void EndChannelOfs(ModChannel &chn, mixsample_t *pBuffer, uint32 nSamples)
  98. {
  99. mixsample_t rofs = chn.nROfs;
  100. mixsample_t lofs = chn.nLOfs;
  101. if((!rofs) && (!lofs))
  102. {
  103. return;
  104. }
  105. for(uint32 i=0; i<nSamples; i++)
  106. {
  107. #ifdef MPT_INTMIXER
  108. const mixsample_t x_r = mpt::rshift_signed(rofs + (mpt::rshift_signed(-rofs, sizeof(mixsample_t) * 8 - 1) & OFSDECAYMASK), OFSDECAYSHIFT);
  109. const mixsample_t x_l = mpt::rshift_signed(lofs + (mpt::rshift_signed(-lofs, sizeof(mixsample_t) * 8 - 1) & OFSDECAYMASK), OFSDECAYSHIFT);
  110. #else
  111. const mixsample_t x_r = rofs * (1.0f / (1 << OFSDECAYSHIFT));
  112. const mixsample_t x_l = lofs * (1.0f / (1 << OFSDECAYSHIFT));
  113. #endif
  114. rofs -= x_r;
  115. lofs -= x_l;
  116. pBuffer[i*2] += rofs;
  117. pBuffer[i*2+1] += lofs;
  118. }
  119. #ifndef MPT_INTMIXER
  120. if(std::abs(rofs) < OFSTHRESHOLD) rofs = 0;
  121. if(std::abs(lofs) < OFSTHRESHOLD) lofs = 0;
  122. #endif
  123. chn.nROfs = rofs;
  124. chn.nLOfs = lofs;
  125. }
  126. void InterleaveStereo(const mixsample_t * MPT_RESTRICT inputL, const mixsample_t * MPT_RESTRICT inputR, mixsample_t * MPT_RESTRICT output, size_t numSamples)
  127. {
  128. while(numSamples--)
  129. {
  130. *(output++) = *(inputL++);
  131. *(output++) = *(inputR++);
  132. }
  133. }
  134. void DeinterleaveStereo(const mixsample_t * MPT_RESTRICT input, mixsample_t * MPT_RESTRICT outputL, mixsample_t * MPT_RESTRICT outputR, size_t numSamples)
  135. {
  136. while(numSamples--)
  137. {
  138. *(outputL++) = *(input++);
  139. *(outputR++) = *(input++);
  140. }
  141. }
  142. OPENMPT_NAMESPACE_END