This commit is contained in:
Vesa
2014-11-28 03:19:21 +02:00
parent 13393900d2
commit 7410174c8b
8 changed files with 98 additions and 82 deletions

View File

@@ -543,7 +543,7 @@ BBTCOView {
/* Plugins */
TripleOscillatorView knob {
TripleOscillatorView Knob {
color: rgb(1, 32, 64);
qproperty-outerColor: rgb(0, 0, 0);
qproperty-innerRadius: 2;
@@ -554,7 +554,7 @@ TripleOscillatorView knob {
}
kickerInstrumentView knob#smallKnob {
kickerInstrumentView Knob#smallKnob {
color: #595959;
qproperty-outerColor: black;
qproperty-innerRadius: 3;
@@ -565,7 +565,7 @@ kickerInstrumentView knob#smallKnob {
}
kickerInstrumentView knob#largeKnob {
kickerInstrumentView Knob#largeKnob {
color: #0c3b89;
qproperty-outerColor: #519fff;
qproperty-innerRadius: 12.0;
@@ -576,7 +576,7 @@ kickerInstrumentView knob#largeKnob {
}
AudioFileProcessorView knob {
AudioFileProcessorView Knob {
color: rgb(240, 147, 14);
qproperty-outerColor: rgb(30, 35, 37);
qproperty-innerRadius: 4;
@@ -586,7 +586,7 @@ AudioFileProcessorView knob {
qproperty-lineWidth: 3;
}
organicInstrumentView knob {
organicInstrumentView Knob {
color: rgb(124, 207, 98);
qproperty-outerColor: rgb(13, 42, 4);
qproperty-innerRadius: 2;
@@ -596,13 +596,13 @@ organicInstrumentView knob {
qproperty-lineWidth: 1.5;
}
organicInstrumentView knob#harmKnob {
organicInstrumentView Knob#harmKnob {
color: rgb(205, 98, 216);
qproperty-outerColor: rgb(18, 4, 18);
}
organicInstrumentView knob#fx1Knob,
organicInstrumentView knob#volKnob {
organicInstrumentView Knob#fx1Knob,
organicInstrumentView Knob#volKnob {
color: rgb(157, 157, 157);
qproperty-outerColor: rgb(37, 37, 37);
qproperty-innerRadius: 4;
@@ -612,7 +612,7 @@ organicInstrumentView knob#volKnob {
qproperty-lineWidth: 2;
}
sf2InstrumentView knob {
sf2InstrumentView Knob {
color: #ff00ea;
qproperty-outerColor: rgb(20, 5, 18);
qproperty-innerRadius: 2;
@@ -622,7 +622,7 @@ sf2InstrumentView knob {
qproperty-lineWidth: 2;
}
sfxrInstrumentView knob {
sfxrInstrumentView Knob {
color: #000;
qproperty-outerColor: rgb(194, 177, 145);
qproperty-innerRadius: 2;
@@ -630,42 +630,42 @@ sfxrInstrumentView knob {
qproperty-lineWidth: 2;
}
sfxrInstrumentView knob#envKnob {
sfxrInstrumentView Knob#envKnob {
color: #263352;
qproperty-outerColor: #4b66a4;
}
sfxrInstrumentView knob#freqKnob {
sfxrInstrumentView Knob#freqKnob {
color: #1e4a22;
qproperty-outerColor: #3c9544;
}
sfxrInstrumentView knob#changeKnob {
sfxrInstrumentView Knob#changeKnob {
color: #591c1c;
qproperty-outerColor: #b23737;
}
sfxrInstrumentView knob#sqrKnob {
sfxrInstrumentView Knob#sqrKnob {
color: #3b2714;
qproperty-outerColor: #724c27;
}
sfxrInstrumentView knob#repeatKnob {
sfxrInstrumentView Knob#repeatKnob {
color: #292929;
qproperty-outerColor: #515151;
}
sfxrInstrumentView knob#phaserKnob {
sfxrInstrumentView Knob#phaserKnob {
color: #144c4d;
qproperty-outerColor: #299899;
}
sfxrInstrumentView knob#filterKnob {
sfxrInstrumentView Knob#filterKnob {
color: #47224c;
qproperty-outerColor: #8e4397;
}
opl2instrumentView knob {
opl2instrumentView Knob {
color: rgb(128,128,128);
qproperty-outerColor: rgb(255,255,255);
qproperty-innerRadius: 2;
@@ -673,7 +673,7 @@ opl2instrumentView knob {
qproperty-lineWidth: 2;
}
sidInstrumentView knob {
sidInstrumentView Knob {
color: rgb(113,95,80);
qproperty-outerColor: rgb( 255,255,255 );
qproperty-innerRadius: 2;
@@ -681,7 +681,7 @@ sidInstrumentView knob {
qproperty-lineWidth: 2;
}
WatsynView knob {
WatsynView Knob {
qproperty-innerRadius: 1;
qproperty-outerRadius: 7;
qproperty-centerPointX: 9.5;
@@ -689,17 +689,17 @@ WatsynView knob {
qproperty-lineWidth: 2;
}
WatsynView knob#aKnob {
WatsynView Knob#aKnob {
color: #43b2ff;
qproperty-outerColor: #43b2ff;
}
WatsynView knob#bKnob {
WatsynView Knob#bKnob {
color: #fc5431;
qproperty-outerColor: #fc5431;
}
WatsynView knob#mixKnob {
WatsynView Knob#mixKnob {
color: #43ff82;
qproperty-outerColor: #43ff82;
qproperty-outerRadius: 13;
@@ -707,17 +707,17 @@ WatsynView knob#mixKnob {
qproperty-centerPointY: 15.5;
}
WatsynView knob#mixenvKnob {
WatsynView Knob#mixenvKnob {
color: #43ff82;
qproperty-outerColor: #43ff82;
}
WatsynView knob#xtalkKnob {
WatsynView Knob#xtalkKnob {
color: #fb50fb;
qproperty-outerColor: #fb50fb;
}
MonstroView knob {
MonstroView Knob {
color: #ffffff;
qproperty-outerColor: #aaaaaa;
qproperty-outerRadius: 9;
@@ -727,7 +727,7 @@ MonstroView knob {
qproperty-lineWidth: 2.5;
}
NesInstrumentView knob {
NesInstrumentView Knob {
color: #e7231b;
qproperty-outerColor: #fff;
qproperty-outerRadius: 11.0;

View File

@@ -1,5 +1,5 @@
/*
* RingBuffer.h - an effective, thread-safe and flexible implementation of a ringbuffer for LMMS
* RingBuffer.h - an effective and flexible implementation of a ringbuffer for LMMS
*
* Copyright (c) 2014 Vesa Kivimäki
* Copyright (c) 2005-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
@@ -32,7 +32,7 @@
#include "lmms_math.h"
#include "MemoryManager.h"
class RingBuffer : public QObject
class EXPORT RingBuffer : public QObject
{
Q_OBJECT
MM_OPERATORS
@@ -204,14 +204,14 @@ protected slots:
private:
inline f_cnt_t msToFrames( float ms )
{
return static_cast<f_cnt_t>( ceilf( ms * m_samplerate / 1000 ) );
return static_cast<f_cnt_t>( ceilf( ms * (float)m_samplerate * 0.001f ) );
}
const fpp_t m_fpp;
sample_rate_t m_samplerate;
f_cnt_t m_size;
size_t m_size;
sampleFrame * m_buffer;
f_cnt_t m_position;
volatile unsigned int m_position;
};
#endif

View File

@@ -49,16 +49,19 @@ Plugin::Descriptor PLUGIN_EXPORT multitapecho_plugin_descriptor =
MultitapEchoEffect::MultitapEchoEffect( Model* parent, const Descriptor::SubPluginFeatures::Key* key ) :
Effect( &multitapecho_plugin_descriptor, parent, key ),
m_controls( this ),
m_buffer( 20000.0f ),
m_buffer( 20100.0f ),
m_sampleRate( Engine::mixer()->processingSampleRate() ),
m_sampleRatio( 1.0f / m_sampleRate )
{
m_work = new sampleFrame[ Engine::mixer()->framesPerPeriod() ];
m_buffer.reset();
updateFilters( 0, 19 );
}
MultitapEchoEffect::~MultitapEchoEffect()
{
delete m_work;
}
@@ -99,9 +102,6 @@ bool MultitapEchoEffect::processAudioBuffer( sampleFrame * buf, const fpp_t fram
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 );
@@ -111,8 +111,8 @@ bool MultitapEchoEffect::processAudioBuffer( sampleFrame * buf, const fpp_t fram
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] );
runFilter( m_work, buf, m_filter[i], frames );
m_buffer.writeSwappedAddingMultiplied( m_work, offset, frames, m_amp[i] );
offset += stepLength;
}
}
@@ -121,19 +121,19 @@ bool MultitapEchoEffect::processAudioBuffer( sampleFrame * buf, const fpp_t fram
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] );
runFilter( m_work, buf, m_filter[i], frames );
m_buffer.writeAddingMultiplied( m_work, offset, frames, m_amp[i] );
offset += stepLength;
}
}
// pop the buffer and mix it into output
m_buffer.pop( &work[0] );
m_buffer.pop( m_work );
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];
buf[f][0] = d * buf[f][0] + w * m_work[f][0];
buf[f][1] = d * buf[f][1] + w * m_work[f][1];
outSum += buf[f][0]*buf[f][0] + buf[f][1]*buf[f][1];
}

View File

@@ -86,6 +86,8 @@ private:
float m_sampleRate;
float m_sampleRatio;
sampleFrame * m_work;
friend class MultitapEchoControls;

View File

@@ -92,8 +92,8 @@ MultitapEchoControlDialog::MultitapEchoControlDialog( MultitapEchoControls * con
// 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" ) );
LedCheckBox * swapInputs = new LedCheckBox( "Swap inputs", this, tr( "Swap inputs" ), LedCheckBox::Green );
swapInputs->move( 20, 280 );
swapInputs->setModel( & controls->m_swapInputs );
ToolTip::add( swapInputs, tr( "Swap left and right input channel for reflections" ) );
}

View File

@@ -38,7 +38,7 @@ MultitapEchoControls::MultitapEchoControls( MultitapEchoEffect * eff ) :
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_ampGraph( -60.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 ) ) );
@@ -140,6 +140,7 @@ void MultitapEchoControls::ampResetClicked()
void MultitapEchoControls::lpSamplesChanged( int begin, int end )
{
//qDebug( "b/e %d - %d", begin, end );
const float * samples = m_lpGraph.samples();
for( int i = begin; i <= end; ++i )
{
@@ -157,12 +158,18 @@ void MultitapEchoControls::lpResetClicked()
void MultitapEchoControls::lengthChanged()
{
m_ampGraph.setLength( m_steps.value() );
m_lpGraph.setLength( m_steps.value() );
const int len = m_steps.value();
m_ampGraph.setLength( len );
ampSamplesChanged( 0, len - 1 );
m_lpGraph.setLength( len );
lpSamplesChanged( 0, len - 1 );
m_effect->updateFilters( 0, len - 1 );
}
void MultitapEchoControls::sampleRateChanged()
{
m_effect->m_sampleRate = Engine::mixer()->processingSampleRate();
m_effect->m_sampleRatio = 1.0f / m_effect->m_sampleRate;
m_effect->updateFilters( 0, 19 );
}

View File

@@ -1,5 +1,5 @@
/*
* RingBuffer.cpp - an effective, thread-safe and flexible implementation of a ringbuffer for LMMS
* RingBuffer.cpp - an effective and flexible implementation of a ringbuffer for LMMS
*
* Copyright (c) 2014 Vesa Kivimäki
* Copyright (c) 2005-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
@@ -36,6 +36,7 @@ RingBuffer::RingBuffer( f_cnt_t size ) :
m_size( size + m_fpp )
{
m_buffer = new sampleFrame[ m_size ];
memset( m_buffer, 0, m_size * sizeof( sampleFrame ) );
m_position = 0;
}
@@ -49,6 +50,7 @@ RingBuffer::RingBuffer( float size ) :
memset( m_buffer, 0, m_size * sizeof( sampleFrame ) );
m_position = 0;
setSamplerateAware( true );
//qDebug( "m_size %d, m_position %d", m_size, m_position );
}
@@ -87,11 +89,11 @@ void RingBuffer::setSamplerateAware( bool b )
{
if( b )
{
connect( Engine::mixer(), SIGNAL( sampleRateChanged() ), this, SLOT( updateSampleRate() ), Qt::UniqueConnection );
connect( Engine::mixer(), SIGNAL( sampleRateChanged() ), this, SLOT( updateSamplerate() ), Qt::UniqueConnection );
}
else
{
disconnect( Engine::mixer(), SIGNAL( sampleRateChanged() ), this, SLOT( updateSampleRate() ) );
disconnect( Engine::mixer(), SIGNAL( sampleRateChanged() ), this, SLOT( updateSamplerate() ) );
}
}
@@ -118,18 +120,18 @@ void RingBuffer::pop( sampleFrame * dst )
{
if( m_position + m_fpp <= m_size ) // we won't go over the edge so we can just memcpy here
{
memcpy( dst, m_buffer + ( m_position * sizeof( sampleFrame ) ), m_fpp * sizeof( sampleFrame ) );
memset( m_buffer + ( m_position * sizeof( sampleFrame ) ), 0, m_fpp * sizeof( sampleFrame ) );
memcpy( dst, & m_buffer [ m_position ], m_fpp * sizeof( sampleFrame ) );
memset( & m_buffer[m_position], 0, m_fpp * sizeof( sampleFrame ) );
}
else
{
f_cnt_t first = m_size - m_position;
f_cnt_t second = m_fpp - first;
memcpy( dst, m_buffer + ( m_position * sizeof( sampleFrame ) ), first * sizeof( sampleFrame ) );
memset( m_buffer + ( m_position * sizeof( sampleFrame ) ), 0, first * sizeof( sampleFrame ) );
memcpy( dst, & m_buffer [ m_position ], first * sizeof( sampleFrame ) );
memset( & m_buffer [m_position], 0, first * sizeof( sampleFrame ) );
memcpy( dst + ( first * sizeof( sampleFrame ) ), m_buffer, second * sizeof( sampleFrame ) );
memcpy( & dst [first], m_buffer, second * sizeof( sampleFrame ) );
memset( m_buffer, 0, second * sizeof( sampleFrame ) );
}
@@ -144,16 +146,16 @@ void RingBuffer::read( sampleFrame * dst, f_cnt_t offset )
if( pos + m_fpp <= m_size ) // we won't go over the edge so we can just memcpy here
{
memcpy( dst, m_buffer + ( pos * sizeof( sampleFrame ) ), m_fpp * sizeof( sampleFrame ) );
memcpy( dst, & m_buffer [pos], m_fpp * sizeof( sampleFrame ) );
}
else
{
f_cnt_t first = m_size - pos;
f_cnt_t second = m_fpp - first;
memcpy( dst, m_buffer + ( pos * sizeof( sampleFrame ) ), first * sizeof( sampleFrame ) );
memcpy( dst, & m_buffer [pos], first * sizeof( sampleFrame ) );
memcpy( dst + ( first * sizeof( sampleFrame ) ), m_buffer, second * sizeof( sampleFrame ) );
memcpy( & dst [first], m_buffer, second * sizeof( sampleFrame ) );
}
}
@@ -171,16 +173,16 @@ void RingBuffer::read( sampleFrame * dst, f_cnt_t offset, f_cnt_t length )
if( pos + length <= m_size ) // we won't go over the edge so we can just memcpy here
{
memcpy( dst, m_buffer + ( pos * sizeof( sampleFrame ) ), length * sizeof( sampleFrame ) );
memcpy( dst, & m_buffer [pos], length * sizeof( sampleFrame ) );
}
else
{
f_cnt_t first = m_size - pos;
f_cnt_t second = length - first;
memcpy( dst, m_buffer + ( pos * sizeof( sampleFrame ) ), first * sizeof( sampleFrame ) );
memcpy( dst, & m_buffer [pos], first * sizeof( sampleFrame ) );
memcpy( dst + ( first * sizeof( sampleFrame ) ), m_buffer, second * sizeof( sampleFrame ) );
memcpy( & dst [first], m_buffer, second * sizeof( sampleFrame ) );
}
}
@@ -198,16 +200,16 @@ void RingBuffer::write( sampleFrame * src, f_cnt_t offset, f_cnt_t length )
if( pos + length <= m_size ) // we won't go over the edge so we can just memcpy here
{
memcpy( m_buffer + ( pos * sizeof( sampleFrame ) ), src, length * sizeof( sampleFrame ) );
memcpy( & m_buffer [pos], src, length * sizeof( sampleFrame ) );
}
else
{
f_cnt_t first = m_size - pos;
f_cnt_t second = length - first;
memcpy( m_buffer + ( pos * sizeof( sampleFrame ) ), src, first * sizeof( sampleFrame ) );
memcpy( & m_buffer [pos], src, first * sizeof( sampleFrame ) );
memcpy( m_buffer, src + ( first * sizeof( sampleFrame ) ), second * sizeof( sampleFrame ) );
memcpy( m_buffer, & src [first], second * sizeof( sampleFrame ) );
}
}
@@ -225,16 +227,16 @@ void RingBuffer::writeAdding( sampleFrame * src, f_cnt_t offset, f_cnt_t length
if( pos + length <= m_size ) // we won't go over the edge so we can just memcpy here
{
MixHelpers::add( m_buffer + ( pos * sizeof( sampleFrame ) ), src, length );
MixHelpers::add( & m_buffer [pos], src, length );
}
else
{
f_cnt_t first = m_size - pos;
f_cnt_t second = length - first;
MixHelpers::add( m_buffer + ( pos * sizeof( sampleFrame ) ), src, first );
MixHelpers::add( & m_buffer[pos], src, first );
MixHelpers::add( m_buffer, src + ( first * sizeof( sampleFrame ) ), second );
MixHelpers::add( m_buffer, & src[first], second );
}
}
@@ -248,27 +250,29 @@ void RingBuffer::writeAdding( sampleFrame * src, float offset, f_cnt_t length )
void RingBuffer::writeAddingMultiplied( sampleFrame * src, f_cnt_t offset, f_cnt_t length, float level )
{
const f_cnt_t pos = ( m_position + offset ) % m_size;
//qDebug( "pos %d m_pos %d ofs %d siz %d", 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::addMultiplied( m_buffer + ( pos * sizeof( sampleFrame ) ), src, level, length );
MixHelpers::addMultiplied( & m_buffer[pos], src, level, length );
}
else
{
f_cnt_t first = m_size - pos;
f_cnt_t second = length - first;
MixHelpers::addMultiplied( m_buffer + ( pos * sizeof( sampleFrame ) ), src, level, first );
MixHelpers::addMultiplied( & m_buffer[pos], src, level, first );
MixHelpers::addMultiplied( m_buffer, src + ( first * sizeof( sampleFrame ) ), level, second );
MixHelpers::addMultiplied( m_buffer, & src [first], level, second );
}
}
void RingBuffer::writeAddingMultiplied( sampleFrame * src, float offset, f_cnt_t length, float level )
{
writeAddingMultiplied( src, msToFrames( offset ), length, level );
f_cnt_t ofs = msToFrames( offset );
writeAddingMultiplied( src, ofs, length, level );
}
@@ -279,16 +283,16 @@ void RingBuffer::writeSwappedAddingMultiplied( sampleFrame * src, f_cnt_t offset
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 );
MixHelpers::addSwappedMultiplied( & m_buffer [pos], 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 [pos], src, level, first );
MixHelpers::addSwappedMultiplied( m_buffer, src + ( first * sizeof( sampleFrame ) ), level, second );
MixHelpers::addSwappedMultiplied( m_buffer, & src [first], level, second );
}
}

View File

@@ -217,14 +217,17 @@ void Graph::drawLineAt( int _x, int _y, int _lastx )
int xstep = _x > _lastx ? -1 : 1;
float ystep = ( lastval - val ) / linelen;
int start = INT_MAX;
int end = 0;
// draw a line
for ( int i = 0; i < linelen; i++ )
{
int x = (_x + (i * xstep)); // get x value
model()->drawSampleAt( (int)( x * xscale ), val + (i * ystep));
int x = (_x + (i * xstep)) * xscale; // get x value
model()->drawSampleAt( x, val + (i * ystep));
start = qMin( start, x );
end = qMax( end, x );
}
int start = qMin( _x, _x + ( ( linelen - 1 ) * xstep ) );
int end = qMax( _x, _x + ( ( linelen - 1 ) * xstep ) );
model()->samplesChanged( start, end );
}
@@ -362,7 +365,7 @@ void Graph::paintEvent( QPaintEvent * )
qMax( static_cast<int>( ( minVal - maxVal ) * yscale ) - static_cast<int>( ( (*samps)[i] - maxVal ) * yscale ), 1 ),
gcol );
p.setPen( QPen( m_graphColor, 1 ) );
p.setPen( QPen( m_graphColor, 1.0 ) );
p.drawLine( 2+static_cast<int>(i*xscale),
2+static_cast<int>( ( (*samps)[i] - maxVal ) * yscale ),