ValueBuffer related cleanups

* Move implementation to a new cpp file
* Use std::vector as base class instead of doing our own memory management
* Remove unused dangerous functions
* Make more use of std algorithms
* Some cleanups in code using ValueBuffer
This commit is contained in:
Lukas W
2017-03-08 17:08:51 +01:00
parent 1b6a9f4885
commit 85ed63be85
12 changed files with 89 additions and 176 deletions

View File

@@ -25,12 +25,10 @@
#ifndef EDITOR_COMMON_H
#define EDITOR_COMMON_H
#include <QAction>
#include <QMainWindow>
#include <QToolBar>
#include "TimeLineWidget.h"
#include "ToolButton.h"
class QAction;
class DropToolBar;

View File

@@ -31,133 +31,23 @@
#include <string.h>
#include "MemoryManager.h"
class ValueBuffer
class ValueBuffer : public std::vector<float>
{
MM_OPERATORS
public:
ValueBuffer()
{
m_values = NULL;
m_length = 0;
}
ValueBuffer();
ValueBuffer(int length);
void fill(float value);
float value(int offset ) const;
const float * values() const;
float * values();
ValueBuffer( int length )
{
m_values = new float[length];
m_length = length;
}
int length() const;
ValueBuffer( float * values, int length )
{
m_values = new float[length];
m_length = length;
memcpy( m_values, values, sizeof(float) * length );
}
ValueBuffer( float value, int length )
{
m_values = new float[length];
m_length = length;
for( int i = 0; i < length; i++ )
{
m_values[i] = value;
}
}
virtual ~ValueBuffer()
{
delete[] m_values;
}
void clear()
{
delete[] m_values;
m_values = NULL;
m_length = 0;
}
void fill( float value )
{
for( int i = 0; i < m_length; i++ )
{
m_values[i] = value;
}
}
float value( int offset ) const
{
return m_values[ offset % m_length ];
}
void setValue( int offset, float value )
{
m_values[ offset % m_length ] = value;
}
float * values() const
{
return m_values;
}
void setValues( float * values )
{
m_values = values;
}
int length() const
{
return m_length;
}
void setLength( const int length )
{
m_length = length;
}
void interpolate( float start, float end )
{
float f = 0.0f;
const float fstep = 1.0f / static_cast<float>( m_length );
for( int i = 0; i < m_length; i++ )
{
f += fstep;
m_values[i] = linearInterpolate( start, end, f );
}
}
void multiply( float f )
{
for( int i = 0; i < m_length; i++ )
{
m_values[i] *= f;
}
}
ValueBuffer & operator*=( const float & f )
{
multiply( f );
return *this;
}
ValueBuffer & operator+=( const ValueBuffer & v )
{
for( int i = 0; i < qMin( m_length, v.length() ); i++ )
{
m_values[i] += v.values()[i];
}
return *this;
}
static ValueBuffer interpolatedBuffer( float start, float end, int length )
{
ValueBuffer vb = ValueBuffer( length );
vb.interpolate( start, end );
return vb;
}
private:
float * m_values;
int m_length;
void interpolate(float start, float end);
};
#endif

View File

@@ -75,10 +75,10 @@ bool AmplifierEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames )
const float d = dryLevel();
const float w = wetLevel();
ValueBuffer * volBuf = m_ampControls.m_volumeModel.valueBuffer();
ValueBuffer * panBuf = m_ampControls.m_panModel.valueBuffer();
ValueBuffer * leftBuf = m_ampControls.m_leftModel.valueBuffer();
ValueBuffer * rightBuf = m_ampControls.m_rightModel.valueBuffer();
const ValueBuffer * volBuf = m_ampControls.m_volumeModel.valueBuffer();
const ValueBuffer * panBuf = m_ampControls.m_panModel.valueBuffer();
const ValueBuffer * leftBuf = m_ampControls.m_leftModel.valueBuffer();
const ValueBuffer * rightBuf = m_ampControls.m_rightModel.valueBuffer();
for( fpp_t f = 0; f < frames; ++f )
{
@@ -90,8 +90,8 @@ bool AmplifierEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames )
// vol knob
if( volBuf )
{
s[0] *= volBuf->values()[ f ] * 0.01f;
s[1] *= volBuf->values()[ f ] * 0.01f;
s[0] *= volBuf->value( f ) * 0.01f;
s[1] *= volBuf->value( f ) * 0.01f;
}
else
{
@@ -101,7 +101,7 @@ bool AmplifierEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames )
// convert pan values to left/right values
const float pan = panBuf
? panBuf->values()[ f ]
? panBuf->value( f )
: m_ampControls.m_panModel.value();
const float left1 = pan <= 0
? 1.0
@@ -112,10 +112,10 @@ bool AmplifierEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames )
// second stage amplification
const float left2 = leftBuf
? leftBuf->values()[ f ]
? leftBuf->value( f )
: m_ampControls.m_leftModel.value();
const float right2 = rightBuf
? rightBuf->values()[ f ]
? rightBuf->value( f )
: m_ampControls.m_rightModel.value();
s[0] *= left1 * left2 * 0.01;

View File

@@ -83,45 +83,30 @@ bool BassBoosterEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames
if( m_bbControls.m_gainModel.isValueChanged() ) { changeGain(); }
if( m_bbControls.m_ratioModel.isValueChanged() ) { changeRatio(); }
float gain = m_bbControls.m_gainModel.value();
ValueBuffer *gainBuffer = m_bbControls.m_gainModel.valueBuffer();
int gainInc = gainBuffer ? 1 : 0;
float *gainPtr = gainBuffer ? &( gainBuffer->values()[ 0 ] ) : &gain;
const float const_gain = m_bbControls.m_gainModel.value();
const ValueBuffer *gainBuffer = m_bbControls.m_gainModel.valueBuffer();
double outSum = 0.0;
const float d = dryLevel();
const float w = wetLevel();
if( gainBuffer )
for( fpp_t f = 0; f < frames; ++f )
{
//process period using sample exact data
for( fpp_t f = 0; f < frames; ++f )
{
m_bbFX.leftFX().setGain( *gainPtr );
m_bbFX.rightFX().setGain( *gainPtr );
outSum += buf[f][0]*buf[f][0] + buf[f][1]*buf[f][1];
sample_t s[2] = { buf[f][0], buf[f][1] };
m_bbFX.nextSample( s[0], s[1] );
buf[f][0] = d * buf[f][0] + w * s[0];
buf[f][1] = d * buf[f][1] + w * s[1];
gainPtr += gainInc;
float gain = const_gain;
if (gainBuffer) {
//process period using sample exact data
gain = gainBuffer->value( f );
}
} else
{
//process period without sample exact data
m_bbFX.leftFX().setGain( *gainPtr );
m_bbFX.rightFX().setGain( *gainPtr );
for( fpp_t f = 0; f < frames; ++f )
{
outSum += buf[f][0]*buf[f][0] + buf[f][1]*buf[f][1];
//float gain = gainBuffer ? gainBuffer[f] : gain;
m_bbFX.leftFX().setGain( const_gain );
m_bbFX.rightFX().setGain( const_gain);
outSum += buf[f][0]*buf[f][0] + buf[f][1]*buf[f][1];
sample_t s[2] = { buf[f][0], buf[f][1] };
m_bbFX.nextSample( s[0], s[1] );
sample_t s[2] = { buf[f][0], buf[f][1] };
m_bbFX.nextSample( s[0], s[1] );
buf[f][0] = d * buf[f][0] + w * s[0];
buf[f][1] = d * buf[f][1] + w * s[1];
}
buf[f][0] = d * buf[f][0] + w * s[0];
buf[f][1] = d * buf[f][1] + w * s[1];
}
checkGate( outSum / frames );

View File

@@ -93,8 +93,8 @@ bool waveShaperEffect::processAudioBuffer( sampleFrame * _buf,
int inputInc = inputBuffer ? 1 : 0;
int outputInc = outputBufer ? 1 : 0;
float *inputPtr = inputBuffer ? &( inputBuffer->values()[ 0 ] ) : &input;
float *outputPtr = outputBufer ? &( outputBufer->values()[ 0 ] ) : &output;
const float *inputPtr = inputBuffer ? &( inputBuffer->values()[ 0 ] ) : &input;
const float *outputPtr = outputBufer ? &( outputBufer->values()[ 0 ] ) : &output;
for( fpp_t f = 0; f < _frames; ++f )
{

View File

@@ -63,6 +63,7 @@ set(LMMS_SRCS
core/ToolPlugin.cpp
core/Track.cpp
core/TrackContainer.cpp
core/ValueBuffer.cpp
core/VstSyncController.cpp
core/audio/AudioAlsa.cpp

View File

@@ -136,11 +136,7 @@ ValueBuffer * Controller::valueBuffer()
void Controller::updateValueBuffer()
{
float * values = m_valueBuffer.values();
for( int i = 0; i < m_valueBuffer.length(); i++ )
{
values[i] = 0.5f;
}
m_valueBuffer.fill(0.5f);
m_bufferLastUpdated = s_periods;
}

View File

@@ -86,7 +86,6 @@ LfoController::~LfoController()
void LfoController::updateValueBuffer()
{
m_phaseOffset = m_phaseModel.value() / 360.0;
float * values = m_valueBuffer.values();
float phase = m_currentPhase + m_phaseOffset;
// roll phase up until we're in sync with period counter
@@ -103,13 +102,13 @@ void LfoController::updateValueBuffer()
int amountInc = amountBuffer ? 1 : 0;
float *amountPtr = amountBuffer ? &(amountBuffer->values()[ 0 ] ) : &amount;
for( int i = 0; i < m_valueBuffer.length(); i++ )
for( float& f : m_valueBuffer )
{
const float currentSample = m_sampleFunction != NULL
? m_sampleFunction( phase )
: m_userDefSampleBuffer->userWaveSample( phase );
values[i] = qBound( 0.0f, m_baseModel.value() + ( *amountPtr * currentSample / 2.0f ), 1.0f );
f = qBound( 0.0f, m_baseModel.value() + ( *amountPtr * currentSample / 2.0f ), 1.0f );
phase += 1.0 / m_duration;
amountPtr += amountInc;

41
src/core/ValueBuffer.cpp Normal file
View File

@@ -0,0 +1,41 @@
#include "ValueBuffer.h"
ValueBuffer::ValueBuffer()
{}
ValueBuffer::ValueBuffer(int length)
: std::vector<float>(length)
{}
void ValueBuffer::fill(float value)
{
std::fill(begin(), end(), value);
}
float ValueBuffer::value(int offset) const
{
return at(offset % length());
}
const float *ValueBuffer::values() const
{
return data();
}
float *ValueBuffer::values()
{
return data();
}
int ValueBuffer::length() const
{
return size();
}
void ValueBuffer::interpolate(float start, float end_)
{
float i = 0;
std::generate(begin(), end(), [&]() {
return linearInterpolate( start, end_, i++ / length());
});
}

View File

@@ -38,6 +38,8 @@
#include "TextFloat.h"
#include "ToolTip.h"
#include "Engine.h"
QPixmap * AutomationPatternView::s_pat_rec = NULL;

View File

@@ -24,6 +24,8 @@
#include "Editor.h"
#include "Song.h"
#include "MainWindow.h"
#include "embed.h"

View File

@@ -64,7 +64,6 @@
#include "Pattern.h"
#include "Piano.h"
#include "PixmapButton.h"
#include "Song.h"
#include "SongEditor.h"
#include "templates.h"
#include "TextFloat.h"