From c6529888fd1c476842d9985cfd54cdf33271f9ef Mon Sep 17 00:00:00 2001 From: Chris Moeller Date: Thu, 31 Oct 2013 18:20:58 -0700 Subject: [PATCH] Hard limit only if output would clip, and use a table for up to 2x volume level --- Frameworks/GME/gme/Spc_Filter.cpp | 35 +++++++++++++++++++++++-------- Frameworks/GME/gme/Spc_Filter.h | 4 ++++ 2 files changed, 30 insertions(+), 9 deletions(-) diff --git a/Frameworks/GME/gme/Spc_Filter.cpp b/Frameworks/GME/gme/Spc_Filter.cpp index c4e56a19b..87b38fae6 100644 --- a/Frameworks/GME/gme/Spc_Filter.cpp +++ b/Frameworks/GME/gme/Spc_Filter.cpp @@ -22,15 +22,31 @@ static const float limiter_max_05 = (float)(limiter_max - 0.5); static short hard_limit_sample( int sample ) { - double val = (double)sample * (1.0 / 32768.0); - if (val < -0.5) - val = (tanh((val + 0.5) / limiter_max_05) * limiter_max_05 - 0.5); - else if (val > 0.5) - val = (tanh((val - 0.5) / limiter_max_05) * limiter_max_05 + 0.5); - return val * 32768.0; + double val = (double)sample * (1.0 / 32768.0); + if (val < -0.5) + val = (tanh((val + 0.5) / limiter_max_05) * limiter_max_05 - 0.5); + else if (val > 0.5) + val = (tanh((val - 0.5) / limiter_max_05) * limiter_max_05 + 0.5); + return val * 32768.0; } -void Spc_Filter::clear() { memset( ch, 0, sizeof ch ); } +void Spc_Filter::build_limit_table() +{ + for (int i = -65536; i < 65536; ++i) + { + hard_limit_table[ i + 65536 ] = hard_limit_sample( i ); + } +} + +inline short Spc_Filter::limit_sample(int sample) +{ + if (!limiting && ((unsigned)sample + 32768) < 65536) return sample; + limiting = true; + if (((unsigned)sample + 65536) < 131072) return hard_limit_table[ sample + 65536 ]; + return hard_limit_sample( sample ); +} + +void Spc_Filter::clear() { limiting = false; memset( ch, 0, sizeof ch ); } Spc_Filter::Spc_Filter() { @@ -38,6 +54,7 @@ Spc_Filter::Spc_Filter() gain = gain_unit; bass = bass_norm; clear(); + build_limit_table(); } void Spc_Filter::run( short io [], int count ) @@ -68,7 +85,7 @@ void Spc_Filter::run( short io [], int count ) int s = sum >> (gain_bits + 2); sum += (delta * gain) - (sum >> bass); - io [i] = hard_limit_sample( s ); + io [i] = limit_sample( s ); } c->p1 = p1; @@ -84,7 +101,7 @@ void Spc_Filter::run( short io [], int count ) while ( io < end ) { int s = (*io * gain) >> gain_bits; - *io++ = hard_limit_sample( s ); + *io++ = limit_sample( s ); } } } diff --git a/Frameworks/GME/gme/Spc_Filter.h b/Frameworks/GME/gme/Spc_Filter.h index 06758c971..26653de10 100644 --- a/Frameworks/GME/gme/Spc_Filter.h +++ b/Frameworks/GME/gme/Spc_Filter.h @@ -40,8 +40,12 @@ private: int gain; int bass; bool enabled; + bool limiting; struct chan_t { int p1, pp1, sum; }; chan_t ch [2]; + short hard_limit_table[131072]; + void build_limit_table(); + inline short limit_sample(int sample); }; inline void Spc_Filter::enable( bool b ) { enabled = b; }