2021-12-26 11:29:43 +00:00
|
|
|
/*
|
|
|
|
* 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 "BuildSettings.h"
|
|
|
|
|
|
|
|
#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_CONSTEXPR11_FUN output_t Convert(const input_t x)
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
// Interpolation templates
|
|
|
|
|
|
|
|
template<class Traits>
|
|
|
|
struct NoInterpolation
|
|
|
|
{
|
2022-03-14 11:35:36 +00:00
|
|
|
MPT_FORCEINLINE NoInterpolation(const ModChannel &, const CResampler &, unsigned int) { }
|
2021-12-26 11:29:43 +00:00
|
|
|
|
|
|
|
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);
|
|
|
|
|
2022-03-14 11:35:36 +00:00
|
|
|
InterpolationFunc interpolate{c, resampler, numSamples};
|
|
|
|
FilterFunc filter{c};
|
|
|
|
MixFunc mix{c};
|
2021-12-26 11:29:43 +00:00
|
|
|
|
|
|
|
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
|