Multitap initial

This commit is contained in:
Vesa
2014-11-28 00:29:55 +02:00
parent fb349ea386
commit 13393900d2
16 changed files with 731 additions and 3 deletions

View File

@@ -137,7 +137,7 @@ public:
inline int length() const
{
return( m_samples.count() );
return m_length;
}
inline const float * samples() const
@@ -175,6 +175,7 @@ private:
void drawSampleAt( int x, float val );
QVector<float> m_samples;
int m_length;
float m_minValue;
float m_maxValue;
float m_step;

View File

@@ -42,6 +42,9 @@ void add( sampleFrame* dst, const sampleFrame* src, int frames );
/*! \brief Add samples from src multiplied by coeffSrc to dst */
void addMultiplied( sampleFrame* dst, const sampleFrame* src, float coeffSrc, int frames );
/*! \brief Add samples from src multiplied by coeffSrc to dst, swap inputs */
void addSwappedMultiplied( sampleFrame* dst, const sampleFrame* src, float coeffSrc, int frames );
/*! \brief Add samples from src multiplied by coeffSrc and coeffSrcBuf to dst */
void addMultipliedByBuffer( sampleFrame* dst, const sampleFrame* src, float coeffSrc, ValueBuffer * coeffSrcBuf, int frames );

View File

@@ -179,6 +179,24 @@ public:
*/
void writeAddingMultiplied( sampleFrame * src, float offset, f_cnt_t length, float level );
/** \brief Mixes a buffer of sampleframes additively to the ringbuffer at specified position, with
* a specified multiplier applied to the frames, with swapped channels
* \param src Pointer to the source buffer
* \param offset Offset in frames against current position, may *NOT* be negative
* \param length Length of the source buffer, if zero, period size is used - must not be higher than the size of the ringbuffer!
* \param level Multiplier applied to the frames before they're written to the ringbuffer
*/
void writeSwappedAddingMultiplied( sampleFrame * src, f_cnt_t offset, f_cnt_t length, float level );
/** \brief Mixes a buffer of sampleframes additively to the ringbuffer at specified position, with
* a specified multiplier applied to the frames, with swapped channels
* \param src Pointer to the source buffer
* \param offset Offset in milliseconds against current position, may *NOT* be negative
* \param length Length of the source buffer, if zero, period size is used
* \param level Multiplier applied to the frames before they're written to the ringbuffer
*/
void writeSwappedAddingMultiplied( sampleFrame * src, float offset, f_cnt_t length, float level );
protected slots:
void updateSamplerate();

View File

@@ -16,6 +16,7 @@ ADD_SUBDIRECTORY(LadspaEffect)
ADD_SUBDIRECTORY(lb302)
#ADD_SUBDIRECTORY(lb303)
ADD_SUBDIRECTORY(MidiImport)
ADD_SUBDIRECTORY(MultitapEcho)
ADD_SUBDIRECTORY(monstro)
ADD_SUBDIRECTORY(nes)
ADD_SUBDIRECTORY(opl2)

View File

@@ -0,0 +1,3 @@
INCLUDE(BuildPlugin)
BUILD_PLUGIN(multitapecho MultitapEcho.cpp MultitapEchoControls.cpp MultitapEchoControlDialog.cpp MOCFILES MultitapEchoControls.h MultitapEchoControlDialog.h EMBEDDED_RESOURCES "${CMAKE_CURRENT_SOURCE_DIR}/*.png")

View File

@@ -0,0 +1,155 @@
/*
* MultitapEcho.cpp - a multitap echo delay plugin
*
* Copyright (c) 2014 Vesa Kivimäki <contact/dot/diizy/at/nbl/dot/fi>
* Copyright (c) 2008-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
*
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
*
* 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.
*
*/
#include "MultitapEcho.h"
#include "embed.cpp"
extern "C"
{
Plugin::Descriptor PLUGIN_EXPORT multitapecho_plugin_descriptor =
{
STRINGIFY( PLUGIN_NAME ),
"Multitap Echo",
QT_TRANSLATE_NOOP( "pluginBrowser", "A multitap echo delay plugin" ),
"Vesa Kivimäki <contact/dot/diizy/at/nbl/dot/fi>",
0x0100,
Plugin::Effect,
new PluginPixmapLoader( "logo" ),
NULL,
NULL
} ;
}
MultitapEchoEffect::MultitapEchoEffect( Model* parent, const Descriptor::SubPluginFeatures::Key* key ) :
Effect( &multitapecho_plugin_descriptor, parent, key ),
m_controls( this ),
m_buffer( 20000.0f ),
m_sampleRate( Engine::mixer()->processingSampleRate() ),
m_sampleRatio( 1.0f / m_sampleRate )
{
updateFilters( 0, 19 );
}
MultitapEchoEffect::~MultitapEchoEffect()
{
}
void MultitapEchoEffect::updateFilters( int begin, int end )
{
for( int i = begin; i <= end; ++i )
{
m_filter[i][0].setFc( m_lpFreq[i] * m_sampleRatio );
m_filter[i][1].setFc( m_lpFreq[i] * m_sampleRatio );
}
}
void MultitapEchoEffect::runFilter( sampleFrame * dst, sampleFrame * src, StereoOnePole & filter, const fpp_t frames )
{
for( int f = 0; f < frames; ++f )
{
dst[f][0] = filter[0].update( src[f][0] );
dst[f][1] = filter[1].update( src[f][1] );
}
}
bool MultitapEchoEffect::processAudioBuffer( sampleFrame * buf, const fpp_t frames )
{
if( !isEnabled() || !isRunning () )
{
return( false );
}
double outSum = 0.0;
const float d = dryLevel();
const float w = wetLevel();
// get processing vars
const int steps = m_controls.m_steps.value();
const float stepLength = m_controls.m_stepLength.value();
const float dryGain = dbvToAmp( m_controls.m_dryGain.value() );
const bool swapInputs = m_controls.m_swapInputs.value();
// temp processing stackbuffer for lp-filtering
sampleFrame work [frames];
// add dry buffer - never swap inputs for dry
m_buffer.writeAddingMultiplied( buf, 0, frames, dryGain );
// swapped inputs?
if( swapInputs )
{
float offset = stepLength;
for( int i = 0; i < steps; ++i ) // add all steps swapped
{
runFilter( &work[0], buf, m_filter[i], frames );
m_buffer.writeSwappedAddingMultiplied( &work[0], offset, frames, m_amp[i] );
offset += stepLength;
}
}
else
{
float offset = stepLength;
for( int i = 0; i < steps; ++i ) // add all steps swapped
{
runFilter( &work[0], buf, m_filter[i], frames );
m_buffer.writeAddingMultiplied( &work[0], offset, frames, m_amp[i] );
offset += stepLength;
}
}
// pop the buffer and mix it into output
m_buffer.pop( &work[0] );
for( int f = 0; f < frames; ++f )
{
buf[f][0] = d * buf[f][0] + w * work[f][0];
buf[f][1] = d * buf[f][1] + w * work[f][1];
outSum += buf[f][0]*buf[f][0] + buf[f][1]*buf[f][1];
}
checkGate( outSum / frames );
return isRunning();
}
extern "C"
{
// necessary for getting instance out of shared lib
Plugin * PLUGIN_EXPORT lmms_plugin_main( Model* parent, void* data )
{
return new MultitapEchoEffect( parent, static_cast<const Plugin::Descriptor::SubPluginFeatures::Key *>( data ) );
}
}

View File

@@ -0,0 +1,95 @@
/*
* MultitapEcho.h - a multitap echo delay plugin
*
* Copyright (c) 2014 Vesa Kivimäki <contact/dot/diizy/at/nbl/dot/fi>
* Copyright (c) 2008-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
*
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
*
* 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 MULTITAP_ECHO_H
#define MULTITAP_ECHO_H
#include "Effect.h"
#include "MultitapEchoControls.h"
#include "ValueBuffer.h"
#include "RingBuffer.h"
#include "lmms_math.h"
class OnePole
{
public:
OnePole()
{
m_a0 = 1.0;
m_b1 = 0.0;
m_z1 = 0.0;
}
virtual ~OnePole() {}
inline void setFc( float fc )
{
m_b1 = expf( -2.0f * F_PI * fc );
m_a0 = 1.0f - m_b1;
}
inline float update( float s )
{
return m_z1 = s * m_a0 + m_z1 * m_b1;
}
private:
float m_a0, m_b1, m_z1;
};
typedef OnePole StereoOnePole [2];
class MultitapEchoEffect : public Effect
{
public:
MultitapEchoEffect( Model* parent, const Descriptor::SubPluginFeatures::Key* key );
virtual ~MultitapEchoEffect();
virtual bool processAudioBuffer( sampleFrame* buf, const fpp_t frames );
virtual EffectControls* controls()
{
return &m_controls;
}
private:
void updateFilters( int begin, int end );
void runFilter( sampleFrame * dst, sampleFrame * src, StereoOnePole & filter, const fpp_t frames );
MultitapEchoControls m_controls;
float m_amp [20];
float m_lpFreq [20];
RingBuffer m_buffer;
StereoOnePole m_filter [20];
float m_sampleRate;
float m_sampleRatio;
friend class MultitapEchoControls;
};
#endif

View File

@@ -0,0 +1,99 @@
/*
* MultitapEchoControlDialog.cpp - a multitap echo delay plugin
*
* Copyright (c) 2014 Vesa Kivimäki <contact/dot/diizy/at/nbl/dot/fi>
* Copyright (c) 2008-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
*
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
*
* 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.
*
*/
#include <QLayout>
#include "MultitapEchoControlDialog.h"
#include "MultitapEchoControls.h"
#include "embed.h"
#include "Graph.h"
#include "PixmapButton.h"
#include "ToolTip.h"
#include "LedCheckbox.h"
#include "Knob.h"
#include "TempoSyncKnob.h"
#include "LcdSpinBox.h"
MultitapEchoControlDialog::MultitapEchoControlDialog( MultitapEchoControls * controls ) :
EffectControlDialog( controls )
{
setAutoFillBackground( true );
QPalette pal;
pal.setBrush( backgroundRole(), PLUGIN_NAME::getIconPixmap( "artwork" ) );
setPalette( pal );
setFixedSize( 245, 300 );
// graph widgets
Graph * ampGraph = new Graph( this, Graph::BarStyle, 204, 105 );
Graph * lpGraph = new Graph( this, Graph::BarStyle, 204, 105 );
ampGraph->move( 30, 10 );
lpGraph->move( 30, 125 );
ampGraph->setModel( & controls->m_ampGraph );
lpGraph->setModel( & controls->m_lpGraph );
pal = QPalette();
pal.setBrush( backgroundRole(), PLUGIN_NAME::getIconPixmap("graph_bg") );
ampGraph->setAutoFillBackground( true );
ampGraph->setPalette( pal );
ampGraph->setGraphColor( QColor( 48, 255, 117 ) );
ampGraph -> setMaximumSize( 204, 105 );
lpGraph->setAutoFillBackground( true );
lpGraph->setPalette( pal );
lpGraph->setGraphColor( QColor( 48, 255, 117 ) );
lpGraph -> setMaximumSize( 204, 105 );
// steps spinbox
LcdSpinBox * steps = new LcdSpinBox( 2, this, "Steps" );
steps->move( 20, 240 );
steps->setModel( & controls->m_steps );
// knobs
TempoSyncKnob * stepLength = new TempoSyncKnob( knobBright_26, this );
stepLength->move( 80, 240 );
stepLength->setModel( & controls->m_stepLength );
stepLength->setLabel( tr( "Length" ) );
stepLength->setHintText( tr( "Step length:" ) + " ", "ms" );
Knob * dryGain = new Knob( knobBright_26, this );
dryGain->move( 130, 240 );
dryGain->setModel( & controls->m_dryGain );
dryGain->setLabel( tr( "Dry" ) );
dryGain->setHintText( tr( "Dry Gain:" ) + " ", "dBV" );
// switch led
LedCheckBox * swapInputs = new LedCheckBox( "Swap inputs", this, tr( "Swap in" ), LedCheckBox::Green );
swapInputs->move( 180, 240 );
swapInputs->setModel( & controls-> m_swapInputs );
ToolTip::add( swapInputs, tr( "Swap left and right channel for reflections" ) );
}

View File

@@ -0,0 +1,44 @@
/*
* MultitapEchoControlDialog.h - a multitap echo delay plugin
*
* Copyright (c) 2014 Vesa Kivimäki <contact/dot/diizy/at/nbl/dot/fi>
* Copyright (c) 2008-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
*
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
*
* 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 MULTITAP_ECHO_CONTROL_DIALOG_H
#define MULTITAP_ECHO_CONTROL_DIALOG_H
#include "EffectControlDialog.h"
class MultitapEchoControls;
class MultitapEchoControlDialog : public EffectControlDialog
{
Q_OBJECT
public:
MultitapEchoControlDialog( MultitapEchoControls * controls );
virtual ~MultitapEchoControlDialog()
{
}
};
#endif

View File

@@ -0,0 +1,168 @@
/*
* MultitapEchoControls.cpp - a multitap echo delay plugin
*
* Copyright (c) 2014 Vesa Kivimäki <contact/dot/diizy/at/nbl/dot/fi>
* Copyright (c) 2008-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
*
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
*
* 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.
*
*/
#include <QDomElement>
#include "MultitapEchoControls.h"
#include "MultitapEcho.h"
#include "lmms_math.h"
#include "base64.h"
MultitapEchoControls::MultitapEchoControls( MultitapEchoEffect * eff ) :
EffectControls( eff ),
m_effect( eff ),
m_steps( 16, 4, 20, this, "Steps" ),
m_stepLength( 100.0f, 1.0f, 1000.0f, 0.1f, 1000.0f, this, "Step length" ),
m_dryGain( 0.0f, -80.0f, 20.0f, 0.1f, this, "Dry gain" ),
m_swapInputs( false, this, "Swap inputs" ),
m_ampGraph( -100.0f, 0.0f, 16, this ),
m_lpGraph( 0.0f, 3.0f, 16, this )
{
connect( &m_ampGraph, SIGNAL( samplesChanged( int, int ) ), this, SLOT( ampSamplesChanged( int, int ) ) );
connect( &m_lpGraph, SIGNAL( samplesChanged( int, int ) ), this, SLOT( lpSamplesChanged( int, int ) ) );
connect( &m_steps, SIGNAL( dataChanged() ), this, SLOT( lengthChanged() ) );
connect( Engine::mixer(), SIGNAL( sampleRateChanged() ), this, SLOT( sampleRateChanged() ) );
setDefaultAmpShape();
setDefaultLpShape();
}
MultitapEchoControls::~MultitapEchoControls()
{
}
void MultitapEchoControls::saveSettings( QDomDocument & doc, QDomElement & parent )
{
m_steps.saveSettings( doc, parent, "steps" );
m_stepLength.saveSettings( doc, parent, "steplength" );
m_dryGain.saveSettings( doc, parent, "drygain" );
m_swapInputs.saveSettings( doc, parent, "swapinputs" );
QString ampString;
base64::encode( (const char *) m_ampGraph.samples(), m_ampGraph.length() * sizeof(float), ampString );
parent.setAttribute( "ampsteps", ampString );
QString lpString;
base64::encode( (const char *) m_lpGraph.samples(), m_lpGraph.length() * sizeof(float), lpString );
parent.setAttribute( "lpsteps", lpString );
}
void MultitapEchoControls::loadSettings( const QDomElement & elem )
{
m_steps.loadSettings( elem, "steps" );
m_stepLength.loadSettings( elem, "steplength" );
m_dryGain.loadSettings( elem, "drygain" );
m_swapInputs.loadSettings( elem, "swapinputs" );
int size = 0;
char * dst = 0;
base64::decode( elem.attribute( "ampsteps"), &dst, &size );
m_ampGraph.setSamples( (float*) dst );
base64::decode( elem.attribute( "lpsteps"), &dst, &size );
m_lpGraph.setSamples( (float*) dst );
delete[] dst;
}
void MultitapEchoControls::setDefaultAmpShape()
{
const int length = m_steps.value();
float samples [length];
for( int i = 0; i < length; ++i )
{
samples[i] = 0.0f;
}
m_ampGraph.setSamples( &samples[0] );
}
void MultitapEchoControls::setDefaultLpShape()
{
const int length = m_steps.value();
float samples [length];
for( int i = 0; i < length; ++i )
{
samples[i] = 3.0f;
}
m_lpGraph.setSamples( &samples[0] );
}
void MultitapEchoControls::ampSamplesChanged( int begin, int end )
{
const float * samples = m_ampGraph.samples();
for( int i = begin; i <= end; ++i )
{
m_effect->m_amp[i] = dbvToAmp( samples[i] );
}
}
void MultitapEchoControls::ampResetClicked()
{
setDefaultAmpShape();
}
void MultitapEchoControls::lpSamplesChanged( int begin, int end )
{
const float * samples = m_lpGraph.samples();
for( int i = begin; i <= end; ++i )
{
m_effect->m_lpFreq[i] = 20.0f * exp10f( samples[i] );
}
m_effect->updateFilters( begin, end );
}
void MultitapEchoControls::lpResetClicked()
{
setDefaultLpShape();
}
void MultitapEchoControls::lengthChanged()
{
m_ampGraph.setLength( m_steps.value() );
m_lpGraph.setLength( m_steps.value() );
}
void MultitapEchoControls::sampleRateChanged()
{
m_effect->updateFilters( 0, 19 );
}

View File

@@ -0,0 +1,90 @@
/*
* MultitapEchoControls.h - a multitap echo delay plugin
*
* Copyright (c) 2014 Vesa Kivimäki <contact/dot/diizy/at/nbl/dot/fi>
* Copyright (c) 2008-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
*
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
*
* 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 MULTITAP_ECHO_CONTROLS_H
#define MULTITAP_ECHO_CONTROLS_H
#include "EffectControls.h"
#include "MultitapEchoControlDialog.h"
#include "Knob.h"
#include "Graph.h"
class MultitapEchoEffect;
class MultitapEchoControls : public EffectControls
{
Q_OBJECT
public:
MultitapEchoControls( MultitapEchoEffect * eff );
virtual ~MultitapEchoControls();
virtual void saveSettings( QDomDocument & doc, QDomElement & parent );
virtual void loadSettings( const QDomElement & elem );
inline virtual QString nodeName() const
{
return( "multitapechocontrols" );
}
void setDefaultAmpShape();
void setDefaultLpShape();
virtual int controlCount()
{
return( 4 );
}
virtual EffectControlDialog * createView()
{
return( new MultitapEchoControlDialog( this ) );
}
private slots:
void ampSamplesChanged( int, int );
void ampResetClicked();
void lpSamplesChanged( int, int );
void lpResetClicked();
void lengthChanged();
void sampleRateChanged();
private:
MultitapEchoEffect * m_effect;
IntModel m_steps;
TempoSyncKnobModel m_stepLength;
FloatModel m_dryGain;
BoolModel m_swapInputs;
graphModel m_ampGraph;
graphModel m_lpGraph;
friend class MultitapEchoEffect;
friend class MultitapEchoControlDialog;
};
#endif

Binary file not shown.

After

Width:  |  Height:  |  Size: 118 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

View File

@@ -124,6 +124,25 @@ void addMultiplied( sampleFrame* dst, const sampleFrame* src, float coeffSrc, in
}
struct AddSwappedMultipliedOp
{
AddSwappedMultipliedOp( float coeff ) : m_coeff( coeff ) { }
void operator()( sampleFrame& dst, const sampleFrame& src ) const
{
dst[0] += src[1] * m_coeff;
dst[1] += src[0] * m_coeff;
}
const float m_coeff;
};
void addSwappedMultiplied( sampleFrame* dst, const sampleFrame* src, float coeffSrc, int frames )
{
run<>( dst, src, frames, AddSwappedMultipliedOp(coeffSrc) );
}
void addMultipliedByBuffer( sampleFrame* dst, const sampleFrame* src, float coeffSrc, ValueBuffer * coeffSrcBuf, int frames )
{
for( int f = 0; f < frames; ++f )

View File

@@ -272,6 +272,33 @@ void RingBuffer::writeAddingMultiplied( sampleFrame * src, float offset, f_cnt_t
}
void RingBuffer::writeSwappedAddingMultiplied( sampleFrame * src, f_cnt_t offset, f_cnt_t length, float level )
{
const f_cnt_t pos = ( m_position + offset ) % m_size;
if( length == 0 ) { length = m_fpp; }
if( pos + length <= m_size ) // we won't go over the edge so we can just memcpy here
{
MixHelpers::addSwappedMultiplied( m_buffer + ( pos * sizeof( sampleFrame ) ), src, level, length );
}
else
{
f_cnt_t first = m_size - pos;
f_cnt_t second = length - first;
MixHelpers::addSwappedMultiplied( m_buffer + ( pos * sizeof( sampleFrame ) ), src, level, first );
MixHelpers::addSwappedMultiplied( m_buffer, src + ( first * sizeof( sampleFrame ) ), level, second );
}
}
void RingBuffer::writeSwappedAddingMultiplied( sampleFrame * src, float offset, f_cnt_t length, float level )
{
writeSwappedAddingMultiplied( src, msToFrames( offset ), length, level );
}
void RingBuffer::updateSamplerate()
{
float newsize = static_cast<float>( ( m_size - m_fpp ) * Engine::mixer()->processingSampleRate() ) / m_samplerate;

View File

@@ -444,6 +444,7 @@ graphModel::graphModel( float _min, float _max, int _length,
::Model * _parent, bool _default_constructed, float _step ) :
Model( _parent, tr( "Graph" ), _default_constructed ),
m_samples( _length ),
m_length( _length ),
m_minValue( _min ),
m_maxValue( _max ),
m_step( _step )
@@ -482,9 +483,13 @@ void graphModel::setRange( float _min, float _max )
void graphModel::setLength( int _length )
{
if( _length != length() )
if( _length != m_length )
{
m_samples.resize( _length );
m_length = _length;
if( m_samples.size() < m_length )
{
m_samples.resize( m_length );
}
emit lengthChanged();
}
}