Initial implementation of sample-exact models and controllers

Also featuring a very efficient buffer-based system for transporting sample-exact control data
Also interpolation for automations
The native Amplifier is a reference implementation for taking advantage of sample-exact data and is currently
the only one that does so, it can be used to test things out, and as documentation/example for implementing the
same elsewhere
This commit is contained in:
Vesa
2014-05-20 01:43:23 +03:00
parent 3a833d2ad8
commit 44f1d3df85
16 changed files with 485 additions and 127 deletions

View File

@@ -74,29 +74,62 @@ bool AmplifierEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames )
double outSum = 0.0;
const float d = dryLevel();
const float w = wetLevel();
ValueBuffer * volBuf = m_ampControls.m_volumeModel.hasSampleExactData()
? m_ampControls.m_volumeModel.valueBuffer()
: NULL;
ValueBuffer * panBuf = m_ampControls.m_panModel.hasSampleExactData()
? m_ampControls.m_panModel.valueBuffer()
: NULL;
ValueBuffer * leftBuf = m_ampControls.m_leftModel.hasSampleExactData()
? m_ampControls.m_leftModel.valueBuffer()
: NULL;
ValueBuffer * rightBuf = m_ampControls.m_rightModel.hasSampleExactData()
? m_ampControls.m_rightModel.valueBuffer()
: NULL;
for( fpp_t f = 0; f < frames; ++f )
{
// qDebug( "offset %d, value %f", f, m_ampControls.m_volumeModel.value( f ) );
sample_t s[2] = { buf[f][0], buf[f][1] };
// convert vol/pan values to left/right values
const float left1 = m_ampControls.m_volumeModel.value( f ) *
( m_ampControls.m_panModel.value( f ) <= 0
? 1.0
: 1.0 - m_ampControls.m_panModel.value( f ) / 100.0 );
const float right1 = m_ampControls.m_volumeModel.value( f ) *
( m_ampControls.m_panModel.value( f ) >= 0
? 1.0
: 1.0 + m_ampControls.m_panModel.value( f ) / 100.0 );
// vol knob
if( volBuf )
{
s[0] *= volBuf->values()[ f ] * 0.01f;
s[1] *= volBuf->values()[ f ] * 0.01f;
}
else
{
s[0] *= m_ampControls.m_volumeModel.value() * 0.01f;
s[1] *= m_ampControls.m_volumeModel.value() * 0.01f;
}
// first stage amplification
s[0] *= ( left1 / 100.0 );
s[1] *= ( right1 / 100.0 );
// convert pan values to left/right values
const float pan = panBuf
? panBuf->values()[ f ]
: m_ampControls.m_panModel.value();
const float left1 = pan <= 0
? 1.0
: 1.0 - m_ampControls.m_panModel.value( f ) * 0.01f;
const float right1 = pan >= 0
? 1.0
: 1.0 + m_ampControls.m_panModel.value( ) * 0.01f;
// second stage amplification
s[0] *= ( m_ampControls.m_leftModel.value( f ) / 100.0 );
s[1] *= ( m_ampControls.m_rightModel.value( f ) / 100.0 );
const float left2 = leftBuf
? leftBuf->values()[ f ]
: m_ampControls.m_leftModel.value();
const float right2 = rightBuf
? rightBuf->values()[ f ]
: m_ampControls.m_rightModel.value();
s[0] *= left1 * left2 * 0.01;
s[1] *= right1 * right2 * 0.01;
buf[f][0] = d * buf[f][0] + w * s[0];
buf[f][1] = d * buf[f][1] + w * s[1];

View File

@@ -29,7 +29,7 @@
#include "Effect.h"
#include "AmplifierControls.h"
#include "ValueBuffer.h"
class AmplifierEffect : public Effect
{

View File

@@ -63,6 +63,7 @@ PeakControllerEffect::PeakControllerEffect(
m_effectId( rand() ),
m_peakControls( this ),
m_lastSample( 0 ),
m_previousSample( 0 ),
m_lastRMS( -1 ),
m_lastRMSavail(false),
m_autoController( NULL )
@@ -89,11 +90,15 @@ namespace helpers
{
//! returns 1.0f if val > 0.0f, -1.0 else
inline float sign(float val) { return -1.0f + 2.0f * (val > 0.0f); }
inline float sign( float val )
{
return -1.0f + 2.0f * ( val > 0.0f );
}
//! if val >= 0.0f, returns sqrtf(val), else: -sqrtf(-val)
inline float sqrt_neg(float val) {
return sqrtf(fabs(val)) * helpers::sign(val);
inline float sqrt_neg( float val )
{
return sqrtf( fabs( val ) ) * helpers::sign( val );
}
}
@@ -113,7 +118,7 @@ bool PeakControllerEffect::processAudioBuffer( sampleFrame * _buf,
// RMS:
double sum = 0;
if(c.m_absModel.value())
if( c.m_absModel.value() )
{
for( int i = 0; i < _frames; ++i )
{
@@ -127,8 +132,8 @@ bool PeakControllerEffect::processAudioBuffer( sampleFrame * _buf,
{
// the value is absolute because of squaring,
// so we need to correct it
sum += _buf[i][0]*_buf[i][0]*helpers::sign(_buf[i][0])
+ _buf[i][1]*_buf[i][1]*helpers::sign(_buf[i][1]);
sum += _buf[i][0] * _buf[i][0] * helpers::sign( _buf[i][0] )
+ _buf[i][1] * _buf[i][1] * helpers::sign( _buf[i][1] );
}
}
@@ -157,6 +162,7 @@ bool PeakControllerEffect::processAudioBuffer( sampleFrame * _buf,
curRMS = (1-a)*curRMS + a*m_lastRMS;
const float amount = c.m_amountModel.value() * c.m_amountMultModel.value();
m_previousSample = m_lastSample;
m_lastSample = c.m_baseModel.value() + amount*curRMS;
m_lastRMS = curRMS;

View File

@@ -23,8 +23,8 @@
*/
#ifndef _PEAK_CONTROLLER_EFFECT_H
#define _PEAK_CONTROLLER_EFFECT_H
#ifndef PEAK_CONTROLLER_EFFECT_H
#define PEAK_CONTROLLER_EFFECT_H
#include "Effect.h"
#include "peak_controller_effect_controls.h"
@@ -48,6 +48,11 @@ public:
return m_lastSample;
}
float previousSample()
{
return m_previousSample;
}
PeakController * controller()
{
return m_autoController;
@@ -59,6 +64,7 @@ private:
PeakControllerEffectControls m_peakControls;
float m_lastSample;
float m_previousSample;
float m_lastRMS;
bool m_lastRMSavail;