1
0

FloatMixer.h 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. /*
  2. * FloatMixer.h
  3. * ------------
  4. * Purpose: Floating point mixer classes
  5. * Notes : (currently none)
  6. * Authors: OpenMPT Devs
  7. * The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
  8. */
  9. #pragma once
  10. #include "openmpt/all/BuildSettings.hpp"
  11. #include "MixerInterface.h"
  12. #include "Resampler.h"
  13. OPENMPT_NAMESPACE_BEGIN
  14. template<int channelsOut, int channelsIn, typename out, typename in, int int2float>
  15. struct IntToFloatTraits : public MixerTraits<channelsOut, channelsIn, out, in>
  16. {
  17. static_assert(std::numeric_limits<input_t>::is_integer, "Input must be integer");
  18. static_assert(!std::numeric_limits<output_t>::is_integer, "Output must be floating point");
  19. static MPT_CONSTEXPRINLINE output_t Convert(const input_t x)
  20. {
  21. return static_cast<output_t>(x) * (static_cast<output_t>(1) / static_cast<output_t>(int2float));
  22. }
  23. };
  24. typedef IntToFloatTraits<2, 1, mixsample_t, int8, -int8_min> Int8MToFloatS;
  25. typedef IntToFloatTraits<2, 1, mixsample_t, int16, -int16_min> Int16MToFloatS;
  26. typedef IntToFloatTraits<2, 2, mixsample_t, int8, -int8_min> Int8SToFloatS;
  27. typedef IntToFloatTraits<2, 2, mixsample_t, int16, -int16_min> Int16SToFloatS;
  28. //////////////////////////////////////////////////////////////////////////
  29. // Interpolation templates
  30. template<class Traits>
  31. struct LinearInterpolation
  32. {
  33. MPT_FORCEINLINE LinearInterpolation(const ModChannel &, const CResampler &, unsigned int) { }
  34. MPT_FORCEINLINE void operator() (typename Traits::outbuf_t &outSample, const typename Traits::input_t * const inBuffer, const uint32 posLo)
  35. {
  36. static_assert(static_cast<int>(Traits::numChannelsIn) <= static_cast<int>(Traits::numChannelsOut), "Too many input channels");
  37. const typename Traits::output_t fract = posLo / static_cast<typename Traits::output_t>(0x100000000); //CResampler::LinearTablef[posLo >> 24];
  38. for(int i = 0; i < Traits::numChannelsIn; i++)
  39. {
  40. typename Traits::output_t srcVol = Traits::Convert(inBuffer[i]);
  41. typename Traits::output_t destVol = Traits::Convert(inBuffer[i + Traits::numChannelsIn]);
  42. outSample[i] = srcVol + fract * (destVol - srcVol);
  43. }
  44. }
  45. };
  46. template<class Traits>
  47. struct FastSincInterpolation
  48. {
  49. MPT_FORCEINLINE FastSincInterpolation(const ModChannel &, const CResampler &, unsigned int) { }
  50. MPT_FORCEINLINE void operator() (typename Traits::outbuf_t &outSample, const typename Traits::input_t * const inBuffer, const uint32 posLo)
  51. {
  52. static_assert(static_cast<int>(Traits::numChannelsIn) <= static_cast<int>(Traits::numChannelsOut), "Too many input channels");
  53. const typename Traits::output_t *lut = CResampler::FastSincTablef + ((posLo >> 22) & 0x3FC);
  54. for(int i = 0; i < Traits::numChannelsIn; i++)
  55. {
  56. outSample[i] =
  57. lut[0] * Traits::Convert(inBuffer[i - Traits::numChannelsIn])
  58. + lut[1] * Traits::Convert(inBuffer[i])
  59. + lut[2] * Traits::Convert(inBuffer[i + Traits::numChannelsIn])
  60. + lut[3] * Traits::Convert(inBuffer[i + 2 * Traits::numChannelsIn]);
  61. }
  62. }
  63. };
  64. template<class Traits>
  65. struct PolyphaseInterpolation
  66. {
  67. const typename Traits::output_t *sinc;
  68. MPT_FORCEINLINE PolyphaseInterpolation(const ModChannel &chn, const CResampler &resampler, unsigned int)
  69. {
  70. sinc = (((chn.increment > SamplePosition(0x130000000ll)) || (chn.increment < -SamplePosition(-0x130000000ll))) ?
  71. (((chn.increment > SamplePosition(0x180000000ll)) || (chn.increment < SamplePosition(-0x180000000ll))) ? resampler.gDownsample2x : resampler.gDownsample13x) : resampler.gKaiserSinc);
  72. }
  73. MPT_FORCEINLINE void operator() (typename Traits::outbuf_t &outSample, const typename Traits::input_t * const inBuffer, const uint32 posLo)
  74. {
  75. static_assert(static_cast<int>(Traits::numChannelsIn) <= static_cast<int>(Traits::numChannelsOut), "Too many input channels");
  76. const typename Traits::output_t *lut = sinc + ((posLo >> (32 - SINC_PHASES_BITS)) & SINC_MASK) * SINC_WIDTH;
  77. for(int i = 0; i < Traits::numChannelsIn; i++)
  78. {
  79. outSample[i] =
  80. lut[0] * Traits::Convert(inBuffer[i - 3 * Traits::numChannelsIn])
  81. + lut[1] * Traits::Convert(inBuffer[i - 2 * Traits::numChannelsIn])
  82. + lut[2] * Traits::Convert(inBuffer[i - Traits::numChannelsIn])
  83. + lut[3] * Traits::Convert(inBuffer[i])
  84. + lut[4] * Traits::Convert(inBuffer[i + Traits::numChannelsIn])
  85. + lut[5] * Traits::Convert(inBuffer[i + 2 * Traits::numChannelsIn])
  86. + lut[6] * Traits::Convert(inBuffer[i + 3 * Traits::numChannelsIn])
  87. + lut[7] * Traits::Convert(inBuffer[i + 4 * Traits::numChannelsIn]);
  88. }
  89. }
  90. };
  91. template<class Traits>
  92. struct FIRFilterInterpolation
  93. {
  94. const typename Traits::output_t *WFIRlut;
  95. MPT_FORCEINLINE FIRFilterInterpolation(const ModChannel &, const CResampler &resampler, unsigned int)
  96. {
  97. WFIRlut = resampler.m_WindowedFIR.lut;
  98. }
  99. MPT_FORCEINLINE void operator() (typename Traits::outbuf_t &outSample, const typename Traits::input_t * const inBuffer, const uint32 posLo)
  100. {
  101. static_assert(static_cast<int>(Traits::numChannelsIn) <= static_cast<int>(Traits::numChannelsOut), "Too many input channels");
  102. const typename Traits::output_t * const lut = WFIRlut + ((((posLo >> 16) + WFIR_FRACHALVE) >> WFIR_FRACSHIFT) & WFIR_FRACMASK);
  103. for(int i = 0; i < Traits::numChannelsIn; i++)
  104. {
  105. outSample[i] =
  106. lut[0] * Traits::Convert(inBuffer[i - 3 * Traits::numChannelsIn])
  107. + lut[1] * Traits::Convert(inBuffer[i - 2 * Traits::numChannelsIn])
  108. + lut[2] * Traits::Convert(inBuffer[i - Traits::numChannelsIn])
  109. + lut[3] * Traits::Convert(inBuffer[i])
  110. + lut[4] * Traits::Convert(inBuffer[i + Traits::numChannelsIn])
  111. + lut[5] * Traits::Convert(inBuffer[i + 2 * Traits::numChannelsIn])
  112. + lut[6] * Traits::Convert(inBuffer[i + 3 * Traits::numChannelsIn])
  113. + lut[7] * Traits::Convert(inBuffer[i + 4 * Traits::numChannelsIn]);
  114. }
  115. }
  116. };
  117. //////////////////////////////////////////////////////////////////////////
  118. // Mixing templates (add sample to stereo mix)
  119. template<class Traits>
  120. struct NoRamp
  121. {
  122. typename Traits::output_t lVol, rVol;
  123. MPT_FORCEINLINE NoRamp(const ModChannel &chn)
  124. {
  125. lVol = static_cast<Traits::output_t>(chn.leftVol) * (1.0f / 4096.0f);
  126. rVol = static_cast<Traits::output_t>(chn.rightVol) * (1.0f / 4096.0f);
  127. }
  128. };
  129. struct Ramp
  130. {
  131. ModChannel &channel;
  132. int32 lRamp, rRamp;
  133. MPT_FORCEINLINE Ramp(ModChannel &chn)
  134. : channel{chn}
  135. {
  136. lRamp = chn.rampLeftVol;
  137. rRamp = chn.rampRightVol;
  138. }
  139. MPT_FORCEINLINE ~Ramp()
  140. {
  141. channel.rampLeftVol = lRamp; channel.leftVol = lRamp >> VOLUMERAMPPRECISION;
  142. channel.rampRightVol = rRamp; channel.rightVol = rRamp >> VOLUMERAMPPRECISION;
  143. }
  144. };
  145. // Legacy optimization: If chn.nLeftVol == chn.nRightVol, save one multiplication instruction
  146. template<class Traits>
  147. struct MixMonoFastNoRamp : public NoRamp<Traits>
  148. {
  149. MPT_FORCEINLINE void operator() (const typename Traits::outbuf_t &outSample, const ModChannel &chn, typename Traits::output_t * const outBuffer)
  150. {
  151. typename Traits::output_t vol = outSample[0] * lVol;
  152. for(int i = 0; i < Traits::numChannelsOut; i++)
  153. {
  154. outBuffer[i] += vol;
  155. }
  156. }
  157. };
  158. template<class Traits>
  159. struct MixMonoNoRamp : public NoRamp<Traits>
  160. {
  161. MPT_FORCEINLINE void operator() (const typename Traits::outbuf_t &outSample, const ModChannel &, typename Traits::output_t * const outBuffer)
  162. {
  163. outBuffer[0] += outSample[0] * lVol;
  164. outBuffer[1] += outSample[0] * rVol;
  165. }
  166. };
  167. template<class Traits>
  168. struct MixMonoRamp : public Ramp
  169. {
  170. MPT_FORCEINLINE void operator() (const typename Traits::outbuf_t &outSample, const ModChannel &chn, typename Traits::output_t * const outBuffer)
  171. {
  172. // TODO volume is not float, can we optimize this?
  173. lRamp += chn.leftRamp;
  174. rRamp += chn.rightRamp;
  175. outBuffer[0] += outSample[0] * (lRamp >> VOLUMERAMPPRECISION) * (1.0f / 4096.0f);
  176. outBuffer[1] += outSample[0] * (rRamp >> VOLUMERAMPPRECISION) * (1.0f / 4096.0f);
  177. }
  178. };
  179. template<class Traits>
  180. struct MixStereoNoRamp : public NoRamp<Traits>
  181. {
  182. MPT_FORCEINLINE void operator() (const typename Traits::outbuf_t &outSample, const ModChannel &, typename Traits::output_t * const outBuffer)
  183. {
  184. outBuffer[0] += outSample[0] * lVol;
  185. outBuffer[1] += outSample[1] * rVol;
  186. }
  187. };
  188. template<class Traits>
  189. struct MixStereoRamp : public Ramp
  190. {
  191. MPT_FORCEINLINE void operator() (const typename Traits::outbuf_t &outSample, const ModChannel &chn, typename Traits::output_t * const outBuffer)
  192. {
  193. // TODO volume is not float, can we optimize this?
  194. lRamp += chn.leftRamp;
  195. rRamp += chn.rightRamp;
  196. outBuffer[0] += outSample[0] * (lRamp >> VOLUMERAMPPRECISION) * (1.0f / 4096.0f);
  197. outBuffer[1] += outSample[1] * (rRamp >> VOLUMERAMPPRECISION) * (1.0f / 4096.0f);
  198. }
  199. };
  200. //////////////////////////////////////////////////////////////////////////
  201. // Filter templates
  202. template<class Traits>
  203. struct NoFilter
  204. {
  205. MPT_FORCEINLINE NoFilter(const ModChannel &) { }
  206. MPT_FORCEINLINE void operator() (const typename Traits::outbuf_t &, const ModChannel &) { }
  207. };
  208. // Resonant filter
  209. template<class Traits>
  210. struct ResonantFilter
  211. {
  212. ModChannel &channel;
  213. // Filter history
  214. typename Traits::output_t fy[Traits::numChannelsIn][2];
  215. MPT_FORCEINLINE ResonantFilter(ModChannel &chn)
  216. : channel{chn}
  217. {
  218. for(int i = 0; i < Traits::numChannelsIn; i++)
  219. {
  220. fy[i][0] = chn.nFilter_Y[i][0];
  221. fy[i][1] = chn.nFilter_Y[i][1];
  222. }
  223. }
  224. MPT_FORCEINLINE ~ResonantFilter(ModChannel &chn)
  225. {
  226. for(int i = 0; i < Traits::numChannelsIn; i++)
  227. {
  228. channel.nFilter_Y[i][0] = fy[i][0];
  229. channel.nFilter_Y[i][1] = fy[i][1];
  230. }
  231. }
  232. // Filter values are clipped to double the input range
  233. #define ClipFilter(x) Clamp(x, static_cast<Traits::output_t>(-2.0f), static_cast<Traits::output_t>(2.0f))
  234. MPT_FORCEINLINE void operator() (typename Traits::outbuf_t &outSample, const ModChannel &chn)
  235. {
  236. static_assert(static_cast<int>(Traits::numChannelsIn) <= static_cast<int>(Traits::numChannelsOut), "Too many input channels");
  237. for(int i = 0; i < Traits::numChannelsIn; i++)
  238. {
  239. typename Traits::output_t val = outSample[i] * chn.nFilter_A0 + ClipFilter(fy[i][0]) * chn.nFilter_B0 + ClipFilter(fy[i][1]) * chn.nFilter_B1;
  240. fy[i][1] = fy[i][0];
  241. fy[i][0] = val - (outSample[i] * chn.nFilter_HP);
  242. outSample[i] = val;
  243. }
  244. }
  245. #undef ClipFilter
  246. };
  247. OPENMPT_NAMESPACE_END