winamp/Src/external_dependencies/openmpt-trunk/soundlib/MixerInterface.h
2024-09-24 14:54:57 +02:00

99 lines
3.4 KiB
C++

/*
* 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