Merge pull request #1315 from diizy/stable-1.1

Add class RmsHelper to help with RMS
This commit is contained in:
Vesa V
2014-11-17 12:59:57 +02:00
3 changed files with 123 additions and 11 deletions

94
include/RmsHelper.h Normal file
View File

@@ -0,0 +1,94 @@
/*
* RmsHelper.h - helper class for calculating RMS
*
* Copyright (c) 2014 Vesa Kivimäki <contact/dot/diizy/at/nbl/dot/fi>
* Copyright (c) 2008 Tobias Doerffel <tobydox/at/users.sourceforge.net>
*
* This file is part of LMMS - http://lmms.io
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program (see COPYING); if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
*/
#ifndef RMS_HELPER_H
#define RMS_HELPER_H
#include "lmms_math.h"
class RmsHelper
{
public:
RmsHelper( int size ) :
m_buffer( NULL )
{
setSize( size );
}
virtual ~RmsHelper()
{
if( m_buffer ) delete m_buffer;
}
inline void setSize( int size )
{
if( m_buffer )
{
if( m_size < size )
{
delete m_buffer;
m_buffer = new float[ size ];
m_size = size;
reset();
}
else
{
m_size = size;
reset();
}
}
else
{
m_buffer = new float[ size ];
m_size = size;
reset();
}
}
inline void reset()
{
m_sizef = 1.0f / (float) m_size;
m_pos = 0;
m_sum = 0.0f;
memset( m_buffer, 0, m_size * sizeof( float ) );
}
inline float update( const float in )
{
m_sum -= m_buffer[ m_pos ];
m_sum += m_buffer[ m_pos ] = in * in;
++m_pos %= m_size;
return sqrtf( m_sum * m_sizef );
}
private:
float * m_buffer;
float m_sum;
unsigned int m_pos;
unsigned int m_size;
float m_sizef;
};
#endif

View File

@@ -58,7 +58,10 @@ dynProcEffect::dynProcEffect( Model * _parent,
m_dpControls( this )
{
m_currentPeak[0] = m_currentPeak[1] = DYN_NOISE_FLOOR;
m_needsUpdate = true;
m_rms[0] = new RmsHelper( 64 * engine::mixer()->processingSampleRate() / 44100 );
m_rms[1] = new RmsHelper( 64 * engine::mixer()->processingSampleRate() / 44100 );
calcAttack();
calcRelease();
}
@@ -66,6 +69,8 @@ dynProcEffect::dynProcEffect( Model * _parent,
dynProcEffect::~dynProcEffect()
{
delete m_rms[0];
delete m_rms[1];
}
@@ -110,15 +115,25 @@ bool dynProcEffect::processAudioBuffer( sampleFrame * _buf,
// debug code
// qDebug( "peaks %f %f", m_currentPeak[0], m_currentPeak[1] );
if( m_dpControls.m_attackModel.isValueChanged() || m_needsUpdate )
if( m_needsUpdate )
{
m_rms[0]->setSize( 64 * engine::mixer()->processingSampleRate() / 44100 );
m_rms[1]->setSize( 64 * engine::mixer()->processingSampleRate() / 44100 );
calcAttack();
}
if( m_dpControls.m_releaseModel.isValueChanged() || m_needsUpdate )
{
calcRelease();
m_needsUpdate = false;
}
else
{
if( m_dpControls.m_attackModel.isValueChanged() )
{
calcAttack();
}
if( m_dpControls.m_releaseModel.isValueChanged() )
{
calcRelease();
}
}
m_needsUpdate = false;
for( fpp_t f = 0; f < _frames; ++f )
{
@@ -131,14 +146,15 @@ bool dynProcEffect::processAudioBuffer( sampleFrame * _buf,
// update peak values
for ( i=0; i <= 1; i++ )
{
if( qAbs( s[i] ) > m_currentPeak[i] )
const double t = m_rms[i]->update( s[i] );
if( t > m_currentPeak[i] )
{
m_currentPeak[i] = qMin( m_currentPeak[i] * m_attCoeff, qAbs( s[i] ) );
m_currentPeak[i] = qMin( m_currentPeak[i] * m_attCoeff, t );
}
else
if( qAbs( s[i] ) < m_currentPeak[i] )
if( t < m_currentPeak[i] )
{
m_currentPeak[i] = qMax( m_currentPeak[i] * m_relCoeff, qAbs( s[i] ) );
m_currentPeak[i] = qMax( m_currentPeak[i] * m_relCoeff, t );
}
m_currentPeak[i] = qBound( DYN_NOISE_FLOOR, m_currentPeak[i], 10.0f );

View File

@@ -29,7 +29,7 @@
#include "Effect.h"
#include "dynamics_processor_controls.h"
#include "RmsHelper.h"
class dynProcEffect : public Effect
@@ -59,6 +59,8 @@ private:
double m_relCoeff;
bool m_needsUpdate;
RmsHelper * m_rms [2];
friend class dynProcControls;