123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899 |
- /*
- * MixerInterface.h
- * ----------------
- * Purpose: The basic mixer interface and main mixer loop, completely agnostic of the actual sample input / output formats.
- * Notes : (currently none)
- * Authors: OpenMPT Devs
- * The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
- */
- #pragma once
- #include "openmpt/all/BuildSettings.hpp"
- #include "Snd_defs.h"
- #include "ModChannel.h"
- OPENMPT_NAMESPACE_BEGIN
- class CResampler;
- //////////////////////////////////////////////////////////////////////////
- // Sample conversion traits
- template<int channelsOut, int channelsIn, typename out, typename in>
- struct MixerTraits
- {
- enum : int { numChannelsIn = channelsIn }; // Number of channels in sample
- enum : int { numChannelsOut = channelsOut }; // Number of mixer output channels
- typedef out output_t; // Output buffer sample type
- typedef in input_t; // Input buffer sample type
- typedef out outbuf_t[channelsOut]; // Output buffer sampling point type
- // To perform sample conversion, add a function with the following signature to your derived classes:
- // static MPT_CONSTEXPRINLINE output_t Convert(const input_t x)
- };
- //////////////////////////////////////////////////////////////////////////
- // Interpolation templates
- template<class Traits>
- struct NoInterpolation
- {
- MPT_FORCEINLINE NoInterpolation(const ModChannel &, const CResampler &, unsigned int) { }
- MPT_FORCEINLINE void operator() (typename Traits::outbuf_t &outSample, const typename Traits::input_t * const inBuffer, const int32)
- {
- static_assert(static_cast<int>(Traits::numChannelsIn) <= static_cast<int>(Traits::numChannelsOut), "Too many input channels");
- for(int i = 0; i < Traits::numChannelsIn; i++)
- {
- outSample[i] = Traits::Convert(inBuffer[i]);
- }
- }
- };
- // Other interpolation algorithms depend on the input format type (integer / float) and can thus be found in FloatMixer.h and IntMixer.h
- //////////////////////////////////////////////////////////////////////////
- // Main sample render loop template
- // Template parameters:
- // Traits: A class derived from MixerTraits that defines the number of channels, sample buffer types, etc..
- // InterpolationFunc: Functor for reading the sample data and doing the SRC
- // FilterFunc: Functor for applying the resonant filter
- // MixFunc: Functor for mixing the computed sample data into the output buffer
- template<class Traits, class InterpolationFunc, class FilterFunc, class MixFunc>
- static void SampleLoop(ModChannel &chn, const CResampler &resampler, typename Traits::output_t * MPT_RESTRICT outBuffer, unsigned int numSamples)
- {
- ModChannel &c = chn;
- const typename Traits::input_t * MPT_RESTRICT inSample = static_cast<const typename Traits::input_t *>(c.pCurrentSample);
- InterpolationFunc interpolate{c, resampler, numSamples};
- FilterFunc filter{c};
- MixFunc mix{c};
- unsigned int samples = numSamples;
- SamplePosition smpPos = c.position; // Fixed-point sample position
- const SamplePosition increment = c.increment; // Fixed-point sample increment
- while(samples--)
- {
- typename Traits::outbuf_t outSample;
- interpolate(outSample, inSample + smpPos.GetInt() * Traits::numChannelsIn, smpPos.GetFract());
- filter(outSample, c);
- mix(outSample, c, outBuffer);
- outBuffer += Traits::numChannelsOut;
- smpPos += increment;
- }
- c.position = smpPos;
- }
- // Type of the SampleLoop function above
- typedef void (*MixFuncInterface)(ModChannel &, const CResampler &, mixsample_t *, unsigned int);
- OPENMPT_NAMESPACE_END
|