DLL: [attachment=7024:foo_dsp_...ardlimit.zip]
Code:
#include "../SDK/foobar2000.h"
#include <boost\math\special_functions\atanh.hpp>
DECLARE_COMPONENT_VERSION("Hard Limiter Inversion", "0.0.1", "");
class dsp_invlimiter : public dsp_impl_base
{
public:
dsp_invlimiter() {}
static GUID g_get_guid() { // {C4688FBC-CCB3-4F35-8F13-E8F1760FBD32}
static const GUID guid = { 0xc4688fbc, 0xccb3, 0x4f35, { 0x8f, 0x13, 0xe8, 0xf1, 0x76, 0xf, 0xbd, 0x32 } };
return guid;
}
static void g_get_name(pfc::string_base & p_out) { p_out = "Invert HardLimiter"; }
static bool g_have_config_popup() { return false; }
virtual void on_endoftrack(abort_callback & p_abort) { }
virtual void on_endofplayback(abort_callback & p_abort) { }
virtual void flush() {}
virtual double get_latency() { return 0.0; }
virtual bool need_track_change_mark() { return false; }
virtual bool on_chunk(audio_chunk * chunk, abort_callback & p_abort)
{
static const float limiter_max = 0.9999f;
static const float limiter_max_05 = limiter_max - 0.5f;
audio_sample * ptr = chunk->get_data();
t_size n;
for(n = chunk->get_data_length(); n; --n)
{
double val = *ptr;
if (val < -0.5)
{
if (val < -limiter_max + DBL_EPSILON) val = -limiter_max + DBL_EPSILON;
val = (boost::math::atanh((val + 0.5) / limiter_max_05) * limiter_max_05 - 0.5);
}
else if (val > 0.5)
{
if (val > limiter_max - DBL_EPSILON) val = limiter_max - DBL_EPSILON;
val = (boost::math::atanh((val - 0.5) / limiter_max_05) * limiter_max_05 + 0.5);
}
*ptr = (audio_sample) val;
ptr++;
}
return true;
}
};
static dsp_factory_nopreset_t<dsp_invlimiter> foo_dsp_invlimiter;
The idea is to cancel the effect of a limiter in foo_dsp_winamp.