@@ -46,14 +46,19 @@ public:
|
||||
{
|
||||
NearestStyle,
|
||||
LinearStyle,
|
||||
LinearNonCyclicStyle,
|
||||
NumGraphStyles
|
||||
};
|
||||
|
||||
graph( QWidget * _parent, graphStyle _style = graph::LinearStyle );
|
||||
graph( QWidget * _parent, graphStyle _style = graph::LinearStyle,
|
||||
int _width = 132,
|
||||
int _height = 104
|
||||
);
|
||||
virtual ~graph();
|
||||
|
||||
void setForeground( const QPixmap & _pixmap );
|
||||
|
||||
|
||||
void setGraphColor( const QColor );
|
||||
|
||||
inline graphModel * model()
|
||||
@@ -65,6 +70,7 @@ public:
|
||||
{
|
||||
return m_graphStyle;
|
||||
}
|
||||
|
||||
|
||||
inline void setGraphStyle( graphStyle _s )
|
||||
{
|
||||
@@ -88,7 +94,8 @@ protected slots:
|
||||
private:
|
||||
virtual void modelChanged();
|
||||
|
||||
void changeSampleAt(int _x, int _y);
|
||||
void changeSampleAt( int _x, int _y );
|
||||
void drawLineAt( int _x, int _y, int _lastx );
|
||||
|
||||
|
||||
QPixmap m_foreground;
|
||||
@@ -154,6 +161,7 @@ public slots:
|
||||
QString setWaveToUser( );
|
||||
|
||||
void smooth();
|
||||
void smoothNonCyclic();
|
||||
void normalize();
|
||||
|
||||
signals:
|
||||
|
||||
@@ -25,5 +25,6 @@ ADD_SUBDIRECTORY(triple_oscillator)
|
||||
ADD_SUBDIRECTORY(vestige)
|
||||
ADD_SUBDIRECTORY(vst_base)
|
||||
ADD_SUBDIRECTORY(vst_effect)
|
||||
ADD_SUBDIRECTORY(waveshaper)
|
||||
ADD_SUBDIRECTORY(vibed)
|
||||
ADD_SUBDIRECTORY(zynaddsubfx)
|
||||
|
||||
3
plugins/waveshaper/CMakeLists.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
INCLUDE(BuildPlugin)
|
||||
|
||||
BUILD_PLUGIN(waveshaper waveshaper.cpp waveshaper_controls.cpp waveshaper_control_dialog.cpp MOCFILES waveshaper_controls.h EMBEDDED_RESOURCES "${CMAKE_CURRENT_SOURCE_DIR}/*.png")
|
||||
BIN
plugins/waveshaper/artwork.png
Normal file
|
After Width: | Height: | Size: 65 KiB |
BIN
plugins/waveshaper/logo.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
plugins/waveshaper/reset_active.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
plugins/waveshaper/reset_inactive.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
plugins/waveshaper/smooth_active.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
plugins/waveshaper/smooth_inactive.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
plugins/waveshaper/wavegraph.png
Normal file
|
After Width: | Height: | Size: 44 KiB |
154
plugins/waveshaper/waveshaper.cpp
Normal file
@@ -0,0 +1,154 @@
|
||||
/*
|
||||
* waveshaper.cpp - waveshaper effect-plugin
|
||||
*
|
||||
* * Copyright * (c) 2014 Vesa Kivimäki <contact/dot/diizy/at/nbl/dot/fi>
|
||||
* Copyright (c) 2006-2009 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 "waveshaper.h"
|
||||
#include <math.h>
|
||||
#include "embed.cpp"
|
||||
|
||||
|
||||
extern "C"
|
||||
{
|
||||
|
||||
Plugin::Descriptor PLUGIN_EXPORT waveshaper_plugin_descriptor =
|
||||
{
|
||||
STRINGIFY( PLUGIN_NAME ),
|
||||
"Waveshaper Effect",
|
||||
QT_TRANSLATE_NOOP( "pluginBrowser",
|
||||
"plugin for waveshaping" ),
|
||||
"Vesa Kivimäki <contact/dot/diizy/at/nbl/dot/fi>",
|
||||
0x0100,
|
||||
Plugin::Effect,
|
||||
new PluginPixmapLoader( "logo" ),
|
||||
NULL,
|
||||
NULL
|
||||
} ;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
waveShaperEffect::waveShaperEffect( Model * _parent,
|
||||
const Descriptor::SubPluginFeatures::Key * _key ) :
|
||||
Effect( &waveshaper_plugin_descriptor, _parent, _key ),
|
||||
m_wsControls( this )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
waveShaperEffect::~waveShaperEffect()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
bool waveShaperEffect::processAudioBuffer( sampleFrame * _buf,
|
||||
const fpp_t _frames )
|
||||
{
|
||||
if( !isEnabled() || !isRunning () )
|
||||
{
|
||||
return( false );
|
||||
}
|
||||
|
||||
// variables for effect
|
||||
int i = 0;
|
||||
float lookup;
|
||||
float frac;
|
||||
float posneg;
|
||||
|
||||
double out_sum = 0.0;
|
||||
const float d = dryLevel();
|
||||
const float w = wetLevel();
|
||||
for( fpp_t f = 0; f < _frames; ++f )
|
||||
{
|
||||
sample_t s[2] = { _buf[f][0], _buf[f][1] };
|
||||
|
||||
// apply input gain
|
||||
s[0] *= m_wsControls.m_inputModel.value();
|
||||
s[1] *= m_wsControls.m_inputModel.value();
|
||||
|
||||
// start effect
|
||||
|
||||
for ( i=0; i <= 1; ++i )
|
||||
{
|
||||
lookup = fabsf( s[i] ) * 200.0f;
|
||||
posneg = s[i] < 0 ? -1.0f : 1.0f;
|
||||
|
||||
if ( lookup < 1 )
|
||||
{
|
||||
frac = lookup - truncf(lookup);
|
||||
s[i] = frac * m_wsControls.m_wavegraphModel.samples()[0] * posneg;
|
||||
}
|
||||
else
|
||||
if ( lookup < 200 )
|
||||
{
|
||||
frac = lookup - truncf(lookup);
|
||||
s[i] =
|
||||
(( (1.0f-frac) * m_wsControls.m_wavegraphModel.samples()[ (int)truncf(lookup) - 1 ] ) +
|
||||
( frac * m_wsControls.m_wavegraphModel.samples()[ (int)truncf(lookup) ] ))
|
||||
* posneg;
|
||||
}
|
||||
else
|
||||
{
|
||||
s[i] *= m_wsControls.m_wavegraphModel.samples()[199];
|
||||
}
|
||||
}
|
||||
|
||||
// apply output gain
|
||||
s[0] *= m_wsControls.m_outputModel.value();
|
||||
s[1] *= m_wsControls.m_outputModel.value();
|
||||
|
||||
// mix wet/dry signals
|
||||
_buf[f][0] = d * _buf[f][0] + w * s[0];
|
||||
_buf[f][1] = d * _buf[f][1] + w * s[1];
|
||||
|
||||
out_sum += _buf[f][0]*_buf[f][0] + _buf[f][1]*_buf[f][1];
|
||||
}
|
||||
|
||||
checkGate( out_sum / _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 waveShaperEffect( _parent,
|
||||
static_cast<const Plugin::Descriptor::SubPluginFeatures::Key *>(
|
||||
_data ) ) );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
63
plugins/waveshaper/waveshaper.h
Normal file
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* waveshaper.h - bass-booster-effect-plugin
|
||||
*
|
||||
* * Copyright * (c) 2014 Vesa Kivimäki <contact/dot/diizy/at/nbl/dot/fi>
|
||||
* Copyright (c) 2006-2008 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 _WAVESHAPER_H
|
||||
#define _WAVESHAPER_H
|
||||
|
||||
#include "Effect.h"
|
||||
#include "effect_lib.h"
|
||||
#include "waveshaper_controls.h"
|
||||
|
||||
|
||||
|
||||
class waveShaperEffect : public Effect
|
||||
{
|
||||
public:
|
||||
waveShaperEffect( Model * _parent,
|
||||
const Descriptor::SubPluginFeatures::Key * _key );
|
||||
virtual ~waveShaperEffect();
|
||||
virtual bool processAudioBuffer( sampleFrame * _buf,
|
||||
const fpp_t _frames );
|
||||
|
||||
virtual EffectControls * controls()
|
||||
{
|
||||
return( &m_wsControls );
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
|
||||
waveShaperControls m_wsControls;
|
||||
|
||||
friend class waveShaperControls;
|
||||
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
89
plugins/waveshaper/waveshaper_control_dialog.cpp
Normal file
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* waveshaper_control_dialog.cpp - control-dialog for waveshaper-effect
|
||||
*
|
||||
* Copyright * (c) 2014 Vesa Kivimäki <contact/dot/diizy/at/nbl/dot/fi>
|
||||
* Copyright * (c) 2006-2008 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 <QtGui/QLayout>
|
||||
|
||||
#include "waveshaper_control_dialog.h"
|
||||
#include "waveshaper_controls.h"
|
||||
#include "embed.h"
|
||||
#include "graph.h"
|
||||
#include "pixmap_button.h"
|
||||
#include "tooltip.h"
|
||||
|
||||
|
||||
waveShaperControlDialog::waveShaperControlDialog(
|
||||
waveShaperControls * _controls ) :
|
||||
EffectControlDialog( _controls )
|
||||
{
|
||||
setAutoFillBackground( true );
|
||||
QPalette pal;
|
||||
pal.setBrush( backgroundRole(),
|
||||
PLUGIN_NAME::getIconPixmap( "artwork" ) );
|
||||
setPalette( pal );
|
||||
setFixedSize( 224, 300 );
|
||||
|
||||
graph * waveGraph = new graph( this, graph::LinearNonCyclicStyle, 204, 204 );
|
||||
waveGraph -> move( 10, 32 );
|
||||
waveGraph -> setModel( &_controls -> m_wavegraphModel );
|
||||
waveGraph -> setAutoFillBackground( true );
|
||||
pal = QPalette();
|
||||
pal.setBrush( backgroundRole(),
|
||||
PLUGIN_NAME::getIconPixmap("wavegraph") );
|
||||
waveGraph->setPalette( pal );
|
||||
waveGraph->setGraphColor( QColor( 170, 255, 255 ) );
|
||||
waveGraph -> setMaximumSize( 204, 204 );
|
||||
|
||||
knob * inputKnob = new knob( knobBright_26, this);
|
||||
inputKnob -> move( 14, 251 );
|
||||
inputKnob->setModel( &_controls->m_inputModel );
|
||||
inputKnob->setLabel( tr( "INPUT" ) );
|
||||
inputKnob->setHintText( tr( "Input gain:" ) + " ", "" );
|
||||
|
||||
knob * outputKnob = new knob( knobBright_26, this );
|
||||
outputKnob -> move( 54, 251 );
|
||||
outputKnob->setModel( &_controls->m_outputModel );
|
||||
outputKnob->setLabel( tr( "OUTPUT" ) );
|
||||
outputKnob->setHintText( tr( "Output gain:" ) + " ", "" );
|
||||
|
||||
pixmapButton * resetButton = new pixmapButton( this, tr("Reset waveform") );
|
||||
resetButton -> move( 164, 251 );
|
||||
resetButton -> resize( 12, 48 );
|
||||
resetButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "reset_active" ) );
|
||||
resetButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "reset_inactive" ) );
|
||||
toolTip::add( resetButton, tr( "Click here to reset the wavegraph back to default" ) );
|
||||
|
||||
pixmapButton * smoothButton = new pixmapButton( this, tr("Smooth waveform") );
|
||||
smoothButton -> move( 164, 267 );
|
||||
smoothButton -> resize( 12, 48 );
|
||||
smoothButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "smooth_active" ) );
|
||||
smoothButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "smooth_inactive" ) );
|
||||
toolTip::add( smoothButton, tr( "Click here to apply smooth to wavegraph" ) );
|
||||
|
||||
connect( resetButton, SIGNAL (clicked () ),
|
||||
_controls, SLOT ( resetClicked() ) );
|
||||
connect( smoothButton, SIGNAL (clicked () ),
|
||||
_controls, SLOT ( smoothClicked() ) );
|
||||
}
|
||||
48
plugins/waveshaper/waveshaper_control_dialog.h
Normal file
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* waveshaper_control_dialog.h - control-dialog for waveshaper-effect
|
||||
*
|
||||
* * Copyright * (c) 2014 Vesa Kivimäki <contact/dot/diizy/at/nbl/dot/fi>
|
||||
* Copyright (c) 2006-2008 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 _WAVESHAPER_CONTROL_DIALOG_H
|
||||
#define _WAVESHAPER_CONTROL_DIALOG_H
|
||||
|
||||
#include "EffectControlDialog.h"
|
||||
|
||||
|
||||
class waveShaperControls;
|
||||
|
||||
|
||||
class waveShaperControlDialog : public EffectControlDialog
|
||||
{
|
||||
public:
|
||||
waveShaperControlDialog( waveShaperControls * _controls );
|
||||
virtual ~waveShaperControlDialog()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
|
||||
} ;
|
||||
|
||||
#endif
|
||||
144
plugins/waveshaper/waveshaper_controls.cpp
Normal file
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
* waveshaper_controls.cpp - controls for waveshaper-effect
|
||||
*
|
||||
* 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 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 <QtXml/QDomElement>
|
||||
|
||||
#include "waveshaper_controls.h"
|
||||
#include "waveshaper.h"
|
||||
#include "graph.h"
|
||||
#include "engine.h"
|
||||
#include "song.h"
|
||||
|
||||
|
||||
waveShaperControls::waveShaperControls( waveShaperEffect * _eff ) :
|
||||
EffectControls( _eff ),
|
||||
m_effect( _eff ),
|
||||
m_inputModel( 1.0f, 0.0f, 5.0f, 0.01f, this, tr( "Input gain" ) ),
|
||||
m_outputModel( 1.0f, 0.0f, 5.0f, 0.01f, this, tr( "Output gain" ) ),
|
||||
m_wavegraphModel( 0.0f, 1.0f, 200, this )
|
||||
{
|
||||
connect( &m_inputModel, SIGNAL( dataChanged() ),
|
||||
this, SLOT( changeInput() ) );
|
||||
|
||||
connect( &m_outputModel, SIGNAL( dataChanged() ),
|
||||
this, SLOT( changeOutput() ) );
|
||||
|
||||
connect( &m_wavegraphModel, SIGNAL( samplesChanged( int, int ) ),
|
||||
this, SLOT( samplesChanged( int, int ) ) );
|
||||
|
||||
changeInput();
|
||||
changeOutput();
|
||||
setDefaultShape();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void waveShaperControls::changeInput()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void waveShaperControls::changeOutput()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void waveShaperControls::samplesChanged( int _begin, int _end)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void waveShaperControls::loadSettings( const QDomElement & _this )
|
||||
{
|
||||
//load input, output knobs
|
||||
m_inputModel.setValue( _this.attribute( "inputGain" ).toFloat() );
|
||||
m_outputModel.setValue( _this.attribute( "outputGain" ).toFloat() );
|
||||
|
||||
//load waveshape
|
||||
int size = 0;
|
||||
char * dst = 0;
|
||||
base64::decode( _this.attribute( "waveShape"), &dst, &size );
|
||||
|
||||
m_wavegraphModel.setSamples( (float*) dst );
|
||||
delete[] dst;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void waveShaperControls::saveSettings( QDomDocument & _doc,
|
||||
QDomElement & _this )
|
||||
{
|
||||
//save input, output knobs
|
||||
_this.setAttribute( "inputGain", m_inputModel.value() );
|
||||
_this.setAttribute( "outputGain", m_outputModel.value() );
|
||||
|
||||
//save waveshape
|
||||
QString sampleString;
|
||||
base64::encode( (const char *)m_wavegraphModel.samples(),
|
||||
m_wavegraphModel.length() * sizeof(float), sampleString );
|
||||
_this.setAttribute( "waveShape", sampleString );
|
||||
|
||||
}
|
||||
|
||||
|
||||
void waveShaperControls::setDefaultShape()
|
||||
{
|
||||
float shp [200] = { };
|
||||
for ( int i = 0; i<200; i++)
|
||||
{
|
||||
shp[i] = ((float)i + 1.0f) / 200.0f;
|
||||
}
|
||||
|
||||
m_wavegraphModel.setLength( 200 );
|
||||
m_wavegraphModel.setSamples( (float*)&shp );
|
||||
}
|
||||
|
||||
void waveShaperControls::resetClicked()
|
||||
{
|
||||
setDefaultShape();
|
||||
engine::getSong()->setModified();
|
||||
}
|
||||
|
||||
void waveShaperControls::smoothClicked()
|
||||
{
|
||||
m_wavegraphModel.smoothNonCyclic();
|
||||
engine::getSong()->setModified();
|
||||
}
|
||||
|
||||
|
||||
|
||||
#include "moc_waveshaper_controls.cxx"
|
||||
|
||||
85
plugins/waveshaper/waveshaper_controls.h
Normal file
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* waveshaper_controls.h - controls for waveshaper-effect
|
||||
*
|
||||
* 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 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 _WAVESHAPER_CONTROLS_H
|
||||
#define _WAVESHAPER_CONTROLS_H
|
||||
|
||||
#include "EffectControls.h"
|
||||
#include "waveshaper_control_dialog.h"
|
||||
#include "knob.h"
|
||||
#include "graph.h"
|
||||
|
||||
class waveShaperEffect;
|
||||
|
||||
|
||||
class waveShaperControls : public EffectControls
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
waveShaperControls( waveShaperEffect * _eff );
|
||||
virtual ~waveShaperControls()
|
||||
{
|
||||
}
|
||||
|
||||
virtual void saveSettings( QDomDocument & _doc, QDomElement & _parent );
|
||||
virtual void loadSettings( const QDomElement & _this );
|
||||
inline virtual QString nodeName() const
|
||||
{
|
||||
return( "waveshapercontrols" );
|
||||
}
|
||||
|
||||
virtual void setDefaultShape();
|
||||
|
||||
virtual int controlCount()
|
||||
{
|
||||
return( 3 );
|
||||
}
|
||||
|
||||
virtual EffectControlDialog * createView()
|
||||
{
|
||||
return( new waveShaperControlDialog( this ) );
|
||||
}
|
||||
|
||||
|
||||
private slots:
|
||||
void changeInput();
|
||||
void changeOutput();
|
||||
void samplesChanged( int, int );
|
||||
|
||||
void resetClicked();
|
||||
void smoothClicked();
|
||||
|
||||
private:
|
||||
waveShaperEffect * m_effect;
|
||||
FloatModel m_inputModel;
|
||||
FloatModel m_outputModel;
|
||||
graphModel m_wavegraphModel;
|
||||
|
||||
friend class waveShaperControlDialog;
|
||||
friend class waveShaperEffect;
|
||||
|
||||
} ;
|
||||
|
||||
#endif
|
||||
|
Before Width: | Height: | Size: 66 KiB After Width: | Height: | Size: 66 KiB |
@@ -471,7 +471,7 @@ pianoRoll::pianoRoll() :
|
||||
this, SLOT( zoomingChanged() ) );
|
||||
m_zoomingComboBox = new comboBox( m_toolBar );
|
||||
m_zoomingComboBox->setModel( &m_zoomingModel );
|
||||
m_zoomingComboBox->setFixedSize( 80, 22 );
|
||||
m_zoomingComboBox->setFixedSize( 64, 22 );
|
||||
|
||||
// setup quantize-stuff
|
||||
QLabel * quantize_lbl = new QLabel( m_toolBar );
|
||||
@@ -490,7 +490,7 @@ pianoRoll::pianoRoll() :
|
||||
m_quantizeModel.setValue( m_quantizeModel.findText( "1/16" ) );
|
||||
m_quantizeComboBox = new comboBox( m_toolBar );
|
||||
m_quantizeComboBox->setModel( &m_quantizeModel );
|
||||
m_quantizeComboBox->setFixedSize( 80, 22 );
|
||||
m_quantizeComboBox->setFixedSize( 64, 22 );
|
||||
connect( &m_quantizeModel, SIGNAL( dataChanged() ),
|
||||
this, SLOT( quantizeChanged() ) );
|
||||
|
||||
@@ -571,23 +571,23 @@ pianoRoll::pianoRoll() :
|
||||
this, SLOT( updateSemiToneMarkerMenu() ) );
|
||||
|
||||
|
||||
tb_layout->addSpacing( 5 );
|
||||
tb_layout->addSpacing( 4 );
|
||||
tb_layout->addWidget( m_playButton );
|
||||
tb_layout->addWidget( m_recordButton );
|
||||
tb_layout->addWidget( m_recordAccompanyButton );
|
||||
tb_layout->addWidget( m_stopButton );
|
||||
tb_layout->addSpacing( 10 );
|
||||
tb_layout->addSpacing( 7 );
|
||||
tb_layout->addWidget( m_drawButton );
|
||||
tb_layout->addWidget( m_eraseButton );
|
||||
tb_layout->addWidget( m_selectButton );
|
||||
tb_layout->addWidget( m_detuneButton );
|
||||
tb_layout->addSpacing( 10 );
|
||||
tb_layout->addSpacing( 7 );
|
||||
tb_layout->addWidget( m_cutButton );
|
||||
tb_layout->addWidget( m_copyButton );
|
||||
tb_layout->addWidget( m_pasteButton );
|
||||
tb_layout->addSpacing( 10 );
|
||||
tb_layout->addSpacing( 7 );
|
||||
m_timeLine->addToolButtons( m_toolBar );
|
||||
tb_layout->addSpacing( 15 );
|
||||
tb_layout->addSpacing( 7 );
|
||||
tb_layout->addWidget( zoom_lbl );
|
||||
tb_layout->addSpacing( 4 );
|
||||
tb_layout->addWidget( m_zoomingComboBox );
|
||||
|
||||
@@ -34,7 +34,8 @@
|
||||
#include "engine.h"
|
||||
|
||||
|
||||
graph::graph( QWidget * _parent, graphStyle _style ) :
|
||||
graph::graph( QWidget * _parent, graphStyle _style, int _width,
|
||||
int _height ) :
|
||||
QWidget( _parent ),
|
||||
/* TODO: size, background? */
|
||||
ModelView( new graphModel( -1.0, 1.0, 128, NULL, true ), this ),
|
||||
@@ -43,7 +44,7 @@ graph::graph( QWidget * _parent, graphStyle _style ) :
|
||||
m_mouseDown = false;
|
||||
m_graphColor = QColor( 0xFF, 0xAA, 0x00 );
|
||||
|
||||
resize( 132, 104 );
|
||||
resize( _width, _height );
|
||||
setAcceptDrops( true );
|
||||
setCursor( Qt::CrossCursor );
|
||||
|
||||
@@ -76,7 +77,7 @@ void graph::setGraphColor( QColor _graphcol )
|
||||
/*
|
||||
void graph::loadSampleFromFile( const QString & _filename )
|
||||
{
|
||||
|
||||
|
||||
int i;
|
||||
|
||||
// zero sample_shape
|
||||
@@ -84,7 +85,7 @@ void graph::loadSampleFromFile( const QString & _filename )
|
||||
{
|
||||
samplePointer[i] = 0;
|
||||
}
|
||||
|
||||
|
||||
// load user shape
|
||||
sampleBuffer buffer( _filename );
|
||||
|
||||
@@ -107,34 +108,38 @@ void graph::mouseMoveEvent ( QMouseEvent * _me )
|
||||
int x = _me->x();
|
||||
int y = _me->y();
|
||||
|
||||
static bool skip = false;
|
||||
/* static bool skip = false;
|
||||
|
||||
if( skip )
|
||||
{
|
||||
skip = false;
|
||||
return;
|
||||
}
|
||||
|
||||
*/
|
||||
// avoid mouse leaps
|
||||
int diff = x - m_lastCursorX;
|
||||
|
||||
if( diff >= 1 )
|
||||
/* if( diff >= 1 )
|
||||
{
|
||||
x = qMin( width() - 2, m_lastCursorX + 1);
|
||||
x = qMin( width() - 3, m_lastCursorX + 1 );
|
||||
}
|
||||
else if( diff <= 1 )
|
||||
else if( diff <= -1 )
|
||||
{
|
||||
x = qMax( 2, m_lastCursorX - 1 );
|
||||
}*/
|
||||
|
||||
x = qMax( 2, qMin( x, width()-3 ) );
|
||||
y = qMax( 2, qMin( y, height()-3 ) );
|
||||
|
||||
if( qAbs( diff ) > 1 )
|
||||
{
|
||||
drawLineAt( x, y, m_lastCursorX );
|
||||
}
|
||||
else
|
||||
{
|
||||
x = m_lastCursorX;
|
||||
changeSampleAt( x, y );
|
||||
}
|
||||
|
||||
y = qMax( 2, qMin( y, height()-3 ) );
|
||||
|
||||
changeSampleAt( x, y );
|
||||
|
||||
// update mouse
|
||||
if( diff != 0 )
|
||||
{
|
||||
@@ -145,7 +150,7 @@ void graph::mouseMoveEvent ( QMouseEvent * _me )
|
||||
QCursor::setPos( pt.x(), pt.y() );
|
||||
}
|
||||
|
||||
skip = true;
|
||||
// skip = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -154,25 +159,73 @@ void graph::mousePressEvent( QMouseEvent * _me )
|
||||
{
|
||||
if( _me->button() == Qt::LeftButton )
|
||||
{
|
||||
// toggle mouse state
|
||||
m_mouseDown = true;
|
||||
if ( !( _me->modifiers() & Qt::ShiftModifier ) )
|
||||
{
|
||||
// get position
|
||||
int x = _me->x();
|
||||
int y = _me->y();
|
||||
|
||||
// get position
|
||||
int x = _me->x();
|
||||
int y = _me->y();
|
||||
changeSampleAt( x, y );
|
||||
|
||||
changeSampleAt( x, y );
|
||||
// toggle mouse state
|
||||
m_mouseDown = true;
|
||||
setCursor( Qt::BlankCursor );
|
||||
m_lastCursorX = x;
|
||||
}
|
||||
else
|
||||
{
|
||||
//when shift-clicking, draw a line from last position to current
|
||||
//position
|
||||
int x = _me->x();
|
||||
int y = _me->y();
|
||||
|
||||
drawLineAt( x, y, m_lastCursorX );
|
||||
|
||||
m_mouseDown = true;
|
||||
setCursor( Qt::BlankCursor );
|
||||
m_lastCursorX = x;
|
||||
}
|
||||
|
||||
// toggle mouse state
|
||||
m_mouseDown = true;
|
||||
setCursor( Qt::BlankCursor );
|
||||
m_lastCursorX = x;
|
||||
}
|
||||
}
|
||||
|
||||
void graph::drawLineAt( int _x, int _y, int _lastx )
|
||||
{
|
||||
float minVal = model()->minValue();
|
||||
float maxVal = model()->maxValue();
|
||||
if ( width() <= 4 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
float xscale = static_cast<float>( model()->length() ) /
|
||||
( width()-4 );
|
||||
|
||||
void graph::changeSampleAt(int _x, int _y)
|
||||
//consider border
|
||||
_x -= 2;
|
||||
_y -= 2;
|
||||
_lastx -= 2;
|
||||
|
||||
_lastx = qMax( 0, qMin( _lastx, width()-5 ) );
|
||||
|
||||
float range = minVal - maxVal;
|
||||
float val = ( _y*range/( height()-4 ) ) + maxVal;
|
||||
float lastval = model() -> m_samples[ (int)( _lastx * xscale ) ];
|
||||
|
||||
// calculate line drawing variables
|
||||
int linelen = qAbs( _x - _lastx ) + 1;
|
||||
int xstep = _x > _lastx ? -1 : 1;
|
||||
float ystep = ( lastval - val ) / linelen;
|
||||
|
||||
// draw a line
|
||||
for ( int i = 0; i < linelen; i++ )
|
||||
{
|
||||
int x = (_x + (i * xstep)); // get x value
|
||||
model()->setSampleAt( (int)( x * xscale ), val + (i * ystep));
|
||||
}
|
||||
}
|
||||
|
||||
void graph::changeSampleAt( int _x, int _y )
|
||||
{
|
||||
float minVal = model()->minValue();
|
||||
float maxVal = model()->maxValue();
|
||||
@@ -208,7 +261,7 @@ void graph::mouseReleaseEvent( QMouseEvent * _me )
|
||||
setCursor( Qt::CrossCursor );
|
||||
update();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -221,7 +274,7 @@ void graph::paintEvent( QPaintEvent * )
|
||||
QVector<float> * samps = &(model()->m_samples);
|
||||
int length = model()->length();
|
||||
const float maxVal = model()->maxValue();
|
||||
|
||||
|
||||
float xscale = (float)( width()-4 ) / length;
|
||||
float yscale = (float)( height()-4 ) / ( model()->minValue() - maxVal );
|
||||
|
||||
@@ -231,23 +284,24 @@ void graph::paintEvent( QPaintEvent * )
|
||||
|
||||
switch( m_graphStyle )
|
||||
{
|
||||
case graph::LinearStyle:
|
||||
case graph::LinearStyle:
|
||||
p.setRenderHints( QPainter::Antialiasing, true );
|
||||
|
||||
for( int i=0; i < length; i++ )
|
||||
{
|
||||
// Needs to be rewritten
|
||||
p.drawLine(2+static_cast<int>(i*xscale),
|
||||
p.drawLine(
|
||||
2+static_cast<int>(i*xscale),
|
||||
2+static_cast<int>( ( (*samps)[i] - maxVal ) * yscale ),
|
||||
2+static_cast<int>((i+1)*xscale),
|
||||
2+static_cast<int>((i+1)*xscale),
|
||||
2+static_cast<int>( ( (*samps)[i+1] - maxVal ) * yscale )
|
||||
);
|
||||
}
|
||||
|
||||
// Draw last segment wrapped around
|
||||
p.drawLine(2+static_cast<int>(length*xscale),
|
||||
p.drawLine(2+static_cast<int>(length*xscale),
|
||||
2+static_cast<int>( ( (*samps)[length] - maxVal ) * yscale ),
|
||||
width()-2,
|
||||
width()-3,
|
||||
2+static_cast<int>( ( (*samps)[0] - maxVal ) * yscale ) );
|
||||
|
||||
p.setRenderHints( QPainter::Antialiasing, false );
|
||||
@@ -257,23 +311,43 @@ void graph::paintEvent( QPaintEvent * )
|
||||
case graph::NearestStyle:
|
||||
for( int i=0; i < length; i++ )
|
||||
{
|
||||
p.drawLine(2+static_cast<int>(i*xscale),
|
||||
p.drawLine(2+static_cast<int>(i*xscale),
|
||||
2+static_cast<int>( ( (*samps)[i] - maxVal ) * yscale ),
|
||||
2+static_cast<int>((i+1)*xscale),
|
||||
2+static_cast<int>((i+1)*xscale),
|
||||
2+static_cast<int>( ( (*samps)[i] - maxVal ) * yscale )
|
||||
);
|
||||
p.drawLine(2+static_cast<int>((i+1)*xscale),
|
||||
p.drawLine(2+static_cast<int>((i+1)*xscale),
|
||||
2+static_cast<int>( ( (*samps)[i] - maxVal ) * yscale ),
|
||||
2+static_cast<int>((i+1)*xscale),
|
||||
2+static_cast<int>((i+1)*xscale),
|
||||
2+static_cast<int>( ( (*samps)[i+1] - maxVal ) * yscale )
|
||||
);
|
||||
}
|
||||
|
||||
p.drawLine(2+static_cast<int>(length*xscale),
|
||||
p.drawLine(2+static_cast<int>(length*xscale),
|
||||
2+static_cast<int>( ( (*samps)[length] - maxVal ) * yscale ),
|
||||
width()-2,
|
||||
width()-3,
|
||||
2+static_cast<int>( ( (*samps)[length] - maxVal ) * yscale ) );
|
||||
break;
|
||||
|
||||
case graph::LinearNonCyclicStyle:
|
||||
p.setRenderHints( QPainter::Antialiasing, true );
|
||||
|
||||
for( int i=0; i < length; i++ )
|
||||
{
|
||||
// Needs to be rewritten
|
||||
p.drawLine(
|
||||
2+static_cast<int>(i*xscale),
|
||||
2+static_cast<int>( ( (*samps)[i] - maxVal ) * yscale ),
|
||||
2+static_cast<int>((i+1)*xscale),
|
||||
2+static_cast<int>( ( (*samps)[i+1] - maxVal ) * yscale )
|
||||
);
|
||||
}
|
||||
|
||||
// Do not draw last segment wrapped around - hence, "non-cyclic"
|
||||
|
||||
p.setRenderHints( QPainter::Antialiasing, false );
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
break;
|
||||
@@ -281,7 +355,7 @@ void graph::paintEvent( QPaintEvent * )
|
||||
|
||||
|
||||
// draw Pointer
|
||||
if( m_mouseDown )
|
||||
if( m_mouseDown )
|
||||
{
|
||||
QPoint cursor = mapFromGlobal( QCursor::pos() );
|
||||
p.setPen( QColor( 0xAA, 0xFF, 0x00, 0x70 ) );
|
||||
@@ -369,7 +443,7 @@ void graphModel::setRange( float _min, float _max )
|
||||
|
||||
if( !m_samples.isEmpty() )
|
||||
{
|
||||
// Trim existing values
|
||||
// Trim existing values
|
||||
for( int i=0; i < length(); i++ )
|
||||
{
|
||||
m_samples[i] = fmaxf( _min, fminf( m_samples[i], _max ) );
|
||||
@@ -397,15 +471,14 @@ void graphModel::setSampleAt( int _x, float _val )
|
||||
{
|
||||
//snap to the grid
|
||||
_val -= ( m_step != 0.0 ) ? fmod( _val, m_step ) * m_step : 0;
|
||||
// boundary check
|
||||
if ( _x >= 0 && _x < length() &&
|
||||
_val >= minValue() && _val < maxValue() )
|
||||
{
|
||||
|
||||
// change sample shape
|
||||
m_samples[_x] = _val;
|
||||
emit samplesChanged( _x, _x );
|
||||
}
|
||||
// boundary crop
|
||||
_x = qMax( 0, qMin( length()-1, _x ) );
|
||||
_val = qMax( minValue(), qMin( maxValue(), _val ) );
|
||||
|
||||
// change sample shape
|
||||
m_samples[_x] = _val;
|
||||
emit samplesChanged( _x, _x );
|
||||
}
|
||||
|
||||
|
||||
@@ -509,16 +582,31 @@ void graphModel::smooth()
|
||||
QVector<float> temp = m_samples;
|
||||
|
||||
// Smoothing
|
||||
m_samples[0] = ( temp[0] + temp[length()-1] ) * 0.5f;
|
||||
for ( int i=1; i < length(); i++ )
|
||||
m_samples[0] = ( temp[length()-1] + ( temp[0] * 2 ) + temp[1] ) * 0.25f;
|
||||
for ( int i=1; i < ( length()-1 ); i++ )
|
||||
{
|
||||
m_samples[i] = ( temp[i-1] + temp[i] ) * 0.5f;
|
||||
m_samples[i] = ( temp[i-1] + ( temp[i] * 2 ) + temp[i+1] ) * 0.25f;
|
||||
}
|
||||
m_samples[length()-1] = ( temp[length()-2] + ( temp[length()-1] * 2 ) + temp[0] ) * 0.25f;
|
||||
|
||||
emit samplesChanged(0, length()-1);
|
||||
}
|
||||
|
||||
void graphModel::smoothNonCyclic()
|
||||
{
|
||||
// store values in temporary array
|
||||
QVector<float> temp = m_samples;
|
||||
|
||||
// Smoothing
|
||||
m_samples[0] = ( ( temp[0] * 2 ) + temp[1] ) / 3.0f;
|
||||
for ( int i=1; i < ( length()-1 ); i++ )
|
||||
{
|
||||
m_samples[i] = ( temp[i-1] + ( temp[i] * 2 ) + temp[i+1] ) * 0.25f;
|
||||
}
|
||||
m_samples[length()-1] = ( temp[length()-2] + ( temp[length()-1] * 2 ) ) / 3.0f;
|
||||
|
||||
emit samplesChanged(0, length()-1);
|
||||
}
|
||||
|
||||
void graphModel::normalize()
|
||||
{
|
||||
@@ -539,7 +627,7 @@ void graphModel::normalize()
|
||||
if( max != 1.0f ) {
|
||||
emit samplesChanged( 0, length()-1 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||