MixerInterface.h 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. /*
  2. * MixerInterface.h
  3. * ----------------
  4. * Purpose: The basic mixer interface and main mixer loop, completely agnostic of the actual sample input / output formats.
  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 "Snd_defs.h"
  12. #include "ModChannel.h"
  13. OPENMPT_NAMESPACE_BEGIN
  14. class CResampler;
  15. //////////////////////////////////////////////////////////////////////////
  16. // Sample conversion traits
  17. template<int channelsOut, int channelsIn, typename out, typename in>
  18. struct MixerTraits
  19. {
  20. enum : int { numChannelsIn = channelsIn }; // Number of channels in sample
  21. enum : int { numChannelsOut = channelsOut }; // Number of mixer output channels
  22. typedef out output_t; // Output buffer sample type
  23. typedef in input_t; // Input buffer sample type
  24. typedef out outbuf_t[channelsOut]; // Output buffer sampling point type
  25. // To perform sample conversion, add a function with the following signature to your derived classes:
  26. // static MPT_CONSTEXPRINLINE output_t Convert(const input_t x)
  27. };
  28. //////////////////////////////////////////////////////////////////////////
  29. // Interpolation templates
  30. template<class Traits>
  31. struct NoInterpolation
  32. {
  33. MPT_FORCEINLINE NoInterpolation(const ModChannel &, const CResampler &, unsigned int) { }
  34. MPT_FORCEINLINE void operator() (typename Traits::outbuf_t &outSample, const typename Traits::input_t * const inBuffer, const int32)
  35. {
  36. static_assert(static_cast<int>(Traits::numChannelsIn) <= static_cast<int>(Traits::numChannelsOut), "Too many input channels");
  37. for(int i = 0; i < Traits::numChannelsIn; i++)
  38. {
  39. outSample[i] = Traits::Convert(inBuffer[i]);
  40. }
  41. }
  42. };
  43. // Other interpolation algorithms depend on the input format type (integer / float) and can thus be found in FloatMixer.h and IntMixer.h
  44. //////////////////////////////////////////////////////////////////////////
  45. // Main sample render loop template
  46. // Template parameters:
  47. // Traits: A class derived from MixerTraits that defines the number of channels, sample buffer types, etc..
  48. // InterpolationFunc: Functor for reading the sample data and doing the SRC
  49. // FilterFunc: Functor for applying the resonant filter
  50. // MixFunc: Functor for mixing the computed sample data into the output buffer
  51. template<class Traits, class InterpolationFunc, class FilterFunc, class MixFunc>
  52. static void SampleLoop(ModChannel &chn, const CResampler &resampler, typename Traits::output_t * MPT_RESTRICT outBuffer, unsigned int numSamples)
  53. {
  54. ModChannel &c = chn;
  55. const typename Traits::input_t * MPT_RESTRICT inSample = static_cast<const typename Traits::input_t *>(c.pCurrentSample);
  56. InterpolationFunc interpolate{c, resampler, numSamples};
  57. FilterFunc filter{c};
  58. MixFunc mix{c};
  59. unsigned int samples = numSamples;
  60. SamplePosition smpPos = c.position; // Fixed-point sample position
  61. const SamplePosition increment = c.increment; // Fixed-point sample increment
  62. while(samples--)
  63. {
  64. typename Traits::outbuf_t outSample;
  65. interpolate(outSample, inSample + smpPos.GetInt() * Traits::numChannelsIn, smpPos.GetFract());
  66. filter(outSample, c);
  67. mix(outSample, c, outBuffer);
  68. outBuffer += Traits::numChannelsOut;
  69. smpPos += increment;
  70. }
  71. c.position = smpPos;
  72. }
  73. // Type of the SampleLoop function above
  74. typedef void (*MixFuncInterface)(ModChannel &, const CResampler &, mixsample_t *, unsigned int);
  75. OPENMPT_NAMESPACE_END