generic powerful effect-framework
git-svn-id: https://lmms.svn.sf.net/svnroot/lmms/trunk/lmms@397 0778d3d1-df1d-0410-868b-ea421aaaa00d
This commit is contained in:
@@ -2,9 +2,13 @@ if VST_SUPPORT
|
||||
VESTIGE_SUBDIR=vestige
|
||||
endif
|
||||
|
||||
if LADSPA_SUPPORT
|
||||
LADSPA_DIR=ladspa_effect
|
||||
endif
|
||||
|
||||
if STK_SUPPORT
|
||||
STK_DIR=stk
|
||||
endif
|
||||
|
||||
SUBDIRS = audio_file_processor bit_invader flp_import midi_import organic plucked_string_synth $(STK_DIR) triple_oscillator $(VESTIGE_SUBDIR) vibed
|
||||
SUBDIRS = audio_file_processor bit_invader flp_import $(LADSPA_DIR) midi_import organic plucked_string_synth $(STK_DIR) triple_oscillator $(VESTIGE_SUBDIR) vibed
|
||||
|
||||
|
||||
@@ -57,10 +57,11 @@
|
||||
#include "tooltip.h"
|
||||
#include "string_pair_drag.h"
|
||||
#include "mmp.h"
|
||||
#include "volume_knob.h"
|
||||
|
||||
|
||||
#undef SINGLE_SOURCE_COMPILE
|
||||
#include "embed.cpp"
|
||||
#include "volume_knob.h"
|
||||
|
||||
|
||||
extern "C"
|
||||
@@ -76,8 +77,9 @@ plugin::descriptor audiofileprocessor_plugin_descriptor =
|
||||
"instrument-track" ),
|
||||
"Tobias Doerffel <tobydox/at/users.sf.net>",
|
||||
0x0100,
|
||||
plugin::INSTRUMENT,
|
||||
new QPixmap( PLUGIN_NAME::getIconPixmap( "logo" ) )
|
||||
plugin::Instrument,
|
||||
new QPixmap( PLUGIN_NAME::getIconPixmap( "logo" ) ),
|
||||
NULL
|
||||
} ;
|
||||
|
||||
}
|
||||
|
||||
@@ -79,8 +79,9 @@ plugin::descriptor bitinvader_plugin_descriptor =
|
||||
"Rough & Dirty Wavetable Synthesizer." ),
|
||||
"Andreas Brandmaier <andreas/at/brandmaier/dot/de>",
|
||||
0x0100,
|
||||
plugin::INSTRUMENT,
|
||||
new QPixmap( PLUGIN_NAME::getIconPixmap( "logo" ) )
|
||||
plugin::Instrument,
|
||||
new QPixmap( PLUGIN_NAME::getIconPixmap( "logo" ) ),
|
||||
NULL
|
||||
} ;
|
||||
|
||||
}
|
||||
|
||||
@@ -80,8 +80,9 @@ plugin::descriptor flpimport_plugin_descriptor =
|
||||
"Filter for importing FL Studio projects into LMMS" ),
|
||||
"Tobias Doerffel <tobydox/at/users/dot/sf/dot/net>",
|
||||
0x0100,
|
||||
plugin::IMPORT_FILTER,
|
||||
new QPixmap()
|
||||
plugin::ImportFilter,
|
||||
new QPixmap(),
|
||||
NULL
|
||||
} ;
|
||||
|
||||
|
||||
@@ -109,7 +110,7 @@ extern QString outstring;
|
||||
}
|
||||
|
||||
|
||||
void dump_mem( const void * buffer, uint n_bytes )
|
||||
static void dump_mem( const void * buffer, uint n_bytes )
|
||||
{
|
||||
uchar * cp = (uchar *) buffer;
|
||||
for( uint k = 0; k < n_bytes; ++k )
|
||||
|
||||
34
plugins/ladspa_effect/Makefile.am
Normal file
34
plugins/ladspa_effect/Makefile.am
Normal file
@@ -0,0 +1,34 @@
|
||||
AUTOMAKE_OPTIONS = foreign 1.4
|
||||
|
||||
|
||||
INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/src/lib -I.
|
||||
|
||||
|
||||
AM_CXXFLAGS := $(AM_CXXFLAGS) $(QT_CXXFLAGS) -DPLUGIN_NAME="ladspaeffect"
|
||||
|
||||
|
||||
%.moc: ./%.h
|
||||
$(MOC) -o $@ $<
|
||||
|
||||
|
||||
MOC_FILES = ./ladspa_effect.moc ./ladspa_control_dialog.moc
|
||||
|
||||
|
||||
BUILT_SOURCES = $(MOC_FILES) ./embedded_resources.h
|
||||
EMBEDDED_RESOURCES = $(wildcard *png)
|
||||
|
||||
./embedded_resources.h: $(EMBEDDED_RESOURCES)
|
||||
$(top_builddir)/buildtools/bin2res $(EMBEDDED_RESOURCES) > $@
|
||||
|
||||
EXTRA_DIST = $(EMBEDDED_RESOURCES)
|
||||
|
||||
|
||||
CLEANFILES = $(MOC_FILES) ./embedded_resources.h
|
||||
|
||||
|
||||
|
||||
pkglib_LTLIBRARIES= libladspaeffect.la
|
||||
|
||||
libladspaeffect_la_SOURCES = ladspa_effect.cpp ladspa_control_dialog.cpp ladspa_effect.h ladspa_control_dialog.h
|
||||
|
||||
$(libladspaeffect_la_SOURCES): ./embedded_resources.h
|
||||
285
plugins/ladspa_effect/ladspa_control_dialog.cpp
Normal file
285
plugins/ladspa_effect/ladspa_control_dialog.cpp
Normal file
@@ -0,0 +1,285 @@
|
||||
#ifndef SINGLE_SOURCE_COMPILE
|
||||
|
||||
/*
|
||||
* ladspa_control_dialog.cpp - dialog for displaying and editing control port
|
||||
* values for LADSPA plugins
|
||||
*
|
||||
* Copyright (c) 2006 Danny McRae <khjklujn/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.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifdef QT4
|
||||
|
||||
#include <QtGui/QMessageBox>
|
||||
|
||||
#else
|
||||
|
||||
#include <qmessagebox.h>
|
||||
|
||||
#endif
|
||||
|
||||
#include "ladspa_effect.h"
|
||||
|
||||
|
||||
ladspaControlDialog::ladspaControlDialog( QWidget * _parent,
|
||||
ladspaEffect * _eff,
|
||||
track * _track ) :
|
||||
effectControlDialog( _parent, _eff ),
|
||||
m_effect( _eff ),
|
||||
m_processors( _eff->getProcessorCount() ),
|
||||
m_track( _track ),
|
||||
m_noLink( FALSE )
|
||||
{
|
||||
m_mainLay = new QVBoxLayout( this );
|
||||
#ifdef QT3
|
||||
m_effectLay = new QHBoxLayout( m_mainLay );
|
||||
#else
|
||||
m_effectLay = new QHBoxLayout();
|
||||
m_mainLay->addLayout( m_effectLay );
|
||||
#endif
|
||||
|
||||
multi_proc_t controls = m_effect->getControls();
|
||||
m_controlCount = controls.count();
|
||||
|
||||
int rows = static_cast<int>( sqrt(
|
||||
static_cast<double>( m_controlCount ) ) );
|
||||
|
||||
for( ch_cnt_t proc = 0; proc < m_processors; proc++ )
|
||||
{
|
||||
control_list_t p;
|
||||
|
||||
bool linked_control = FALSE;
|
||||
int row_cnt = 0;
|
||||
buffer_data_t last_port = NONE;
|
||||
|
||||
QGroupBox * grouper;
|
||||
if( m_processors > 1 )
|
||||
{
|
||||
#ifdef QT3
|
||||
grouper = new QGroupBox( rows, Qt::Vertical,
|
||||
tr( "Channel " ) + QString::number( proc + 1 ),
|
||||
this );
|
||||
#else
|
||||
grouper = new QGroupBox( tr( "Channel " ) +
|
||||
QString::number( proc + 1 ),
|
||||
this );
|
||||
grouper->setAlignment( Qt::Vertical );
|
||||
#endif
|
||||
if( proc == 0 )
|
||||
{
|
||||
linked_control = TRUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef QT3
|
||||
grouper = new QGroupBox( rows, Qt::Vertical,
|
||||
"", this );
|
||||
#else
|
||||
grouper = new QGroupBox( this );
|
||||
grouper->setAlignment( Qt::Vertical );
|
||||
#endif
|
||||
}
|
||||
|
||||
for( multi_proc_t::iterator it = controls.begin();
|
||||
it != controls.end(); it++ )
|
||||
{
|
||||
if( (*it)->proc == proc )
|
||||
{
|
||||
if( last_port == NONE ||
|
||||
(*it)->data_type != TOGGLED ||
|
||||
( (*it)->data_type == TOGGLED &&
|
||||
last_port == TOGGLED ) )
|
||||
{
|
||||
(*it)->control =
|
||||
new ladspaControl(
|
||||
grouper, (*it),
|
||||
eng(), m_track,
|
||||
linked_control );
|
||||
}
|
||||
else
|
||||
{
|
||||
while( row_cnt < rows )
|
||||
{
|
||||
m_blanks.append(
|
||||
new QWidget( grouper ) );
|
||||
row_cnt++;
|
||||
}
|
||||
(*it)->control = new ladspaControl(
|
||||
grouper, (*it),
|
||||
eng(),
|
||||
m_track,
|
||||
linked_control );
|
||||
row_cnt = 0;
|
||||
}
|
||||
|
||||
row_cnt++;
|
||||
if( row_cnt == ( rows - 1 ) )
|
||||
{
|
||||
row_cnt = 0;
|
||||
}
|
||||
last_port = (*it)->data_type;
|
||||
|
||||
p.append( (*it)->control );
|
||||
|
||||
if( linked_control )
|
||||
{
|
||||
connect( (*it)->control,
|
||||
SIGNAL( linkChanged( Uint16, bool ) ),
|
||||
this,
|
||||
SLOT( linkPort( Uint16, bool ) ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_controls.append( p );
|
||||
|
||||
m_effectLay->addWidget( grouper );
|
||||
}
|
||||
if( m_processors > 1 )
|
||||
{
|
||||
m_mainLay->addSpacing( 3 );
|
||||
#ifdef QT3
|
||||
QHBoxLayout * center = new QHBoxLayout( m_mainLay );
|
||||
#else
|
||||
QHBoxLayout * center = new QHBoxLayout();
|
||||
m_mainLay->addLayout( center );
|
||||
#endif
|
||||
m_stereoLink = new ledCheckBox( tr( "Link Channels" ),
|
||||
this, "", eng(), m_track );
|
||||
connect( m_stereoLink, SIGNAL( toggled( bool ) ),
|
||||
this, SLOT( link( bool ) ) );
|
||||
m_stereoLink->setChecked( TRUE );
|
||||
center->addWidget( m_stereoLink );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
ladspaControlDialog::~ladspaControlDialog()
|
||||
{
|
||||
for( ch_cnt_t proc = 0; proc < m_processors; proc++ )
|
||||
{
|
||||
m_controls[proc].clear();
|
||||
}
|
||||
m_controls.clear();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void FASTCALL ladspaControlDialog::saveSettings( QDomDocument & _doc,
|
||||
QDomElement & _this )
|
||||
{
|
||||
if( m_processors > 1 )
|
||||
{
|
||||
_this.setAttribute( "link", m_stereoLink->isChecked() );
|
||||
}
|
||||
|
||||
multi_proc_t controls = m_effect->getControls();
|
||||
_this.setAttribute( "ports", controls.count() );
|
||||
for( multi_proc_t::iterator it = controls.begin();
|
||||
it != controls.end(); it++ )
|
||||
{
|
||||
QString n = "port" + QString::number( (*it)->proc ) +
|
||||
QString::number( (*it)->port_id );
|
||||
(*it)->control->saveSettings( _doc, _this, n );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void FASTCALL ladspaControlDialog::loadSettings( const QDomElement & _this )
|
||||
{
|
||||
if( m_processors > 1 )
|
||||
{
|
||||
m_stereoLink->setChecked( _this.attribute( "link" ).toInt() );
|
||||
}
|
||||
|
||||
multi_proc_t controls = m_effect->getControls();
|
||||
for( multi_proc_t::iterator it = controls.begin();
|
||||
it != controls.end(); it++ )
|
||||
{
|
||||
QString n = "port" + QString::number( (*it)->proc ) +
|
||||
QString::number( (*it)->port_id );
|
||||
(*it)->control->loadSettings( _this, n );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void ladspaControlDialog::linkPort( Uint16 _port, bool _state )
|
||||
{
|
||||
ladspaControl * first = m_controls[0][_port];
|
||||
if( _state )
|
||||
{
|
||||
for( ch_cnt_t proc = 1; proc < m_processors; proc++ )
|
||||
{
|
||||
first->linkControls( m_controls[proc][_port] );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for( ch_cnt_t proc = 1; proc < m_processors; proc++ )
|
||||
{
|
||||
first->unlinkControls( m_controls[proc][_port] );
|
||||
}
|
||||
m_noLink = TRUE;
|
||||
m_stereoLink->setChecked( FALSE );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ladspaControlDialog::link( bool _state )
|
||||
{
|
||||
if( _state )
|
||||
{
|
||||
for( Uint16 port = 0;
|
||||
port < m_controlCount / m_processors;
|
||||
port++ )
|
||||
{
|
||||
m_controls[0][port]->setLink( TRUE );
|
||||
}
|
||||
}
|
||||
else if( !m_noLink )
|
||||
{
|
||||
for( Uint16 port = 0;
|
||||
port < m_controlCount / m_processors;
|
||||
port++ )
|
||||
{
|
||||
m_controls[0][port]->setLink( FALSE );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_noLink = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#include "ladspa_control_dialog.moc"
|
||||
|
||||
#endif
|
||||
|
||||
103
plugins/ladspa_effect/ladspa_control_dialog.h
Normal file
103
plugins/ladspa_effect/ladspa_control_dialog.h
Normal file
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* ladspa_control_dialog.h - dialog for displaying and editing control port
|
||||
* values for LADSPA plugins
|
||||
*
|
||||
* Copyright (c) 2006 Danny McRae <khjklujn/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 _LADSPA_CONTROL_DIALOG_H
|
||||
#define _LADSPA_CONTROL_DIALOG_H
|
||||
|
||||
#include "ladspa_manager.h"
|
||||
|
||||
#ifdef LADSPA_SUPPORT
|
||||
|
||||
#ifdef QT4
|
||||
|
||||
#include <QtGui/QGroupBox>
|
||||
#include <QtGui/QLayout>
|
||||
|
||||
#else
|
||||
|
||||
#include <qgroupbox.h>
|
||||
#include <qlayout.h>
|
||||
|
||||
#endif
|
||||
|
||||
#include "qt3support.h"
|
||||
|
||||
#include "effect_control_dialog.h"
|
||||
#include "ladspa_control.h"
|
||||
#include "track.h"
|
||||
#include "led_checkbox.h"
|
||||
|
||||
|
||||
typedef vvector<ladspaControl *> control_list_t;
|
||||
|
||||
class ladspaEffect;
|
||||
|
||||
|
||||
class ladspaControlDialog : public effectControlDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ladspaControlDialog( QWidget * _parent, ladspaEffect * _eff,
|
||||
track * _track );
|
||||
virtual ~ladspaControlDialog();
|
||||
|
||||
inline ch_cnt_t getControlCount( void )
|
||||
{
|
||||
return( m_controlCount );
|
||||
}
|
||||
|
||||
virtual void FASTCALL saveSettings( QDomDocument & _doc,
|
||||
QDomElement & _parent );
|
||||
virtual void FASTCALL loadSettings( const QDomElement & _this );
|
||||
inline virtual QString nodeName( void ) const
|
||||
{
|
||||
return( "controls" );
|
||||
}
|
||||
|
||||
|
||||
protected slots:
|
||||
void link( bool _state );
|
||||
void linkPort( Uint16 _port, bool _state );
|
||||
|
||||
|
||||
private:
|
||||
ladspaEffect * m_effect;
|
||||
ch_cnt_t m_processors;
|
||||
ch_cnt_t m_controlCount;
|
||||
track * m_track;
|
||||
bool m_noLink;
|
||||
audioPort * m_port;
|
||||
ledCheckBox * m_stereoLink;
|
||||
vvector<QWidget *> m_blanks;
|
||||
vvector<control_list_t> m_controls;
|
||||
|
||||
QVBoxLayout * m_mainLay;
|
||||
QHBoxLayout * m_effectLay;
|
||||
|
||||
} ;
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
490
plugins/ladspa_effect/ladspa_effect.cpp
Normal file
490
plugins/ladspa_effect/ladspa_effect.cpp
Normal file
@@ -0,0 +1,490 @@
|
||||
/*
|
||||
* ladspa_effect.cpp - class for processing LADSPA effects
|
||||
*
|
||||
* Copyright (c) 2006 Danny McRae <khjklujn/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.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifdef QT4
|
||||
|
||||
#include <QtGui/QMessageBox>
|
||||
|
||||
#else
|
||||
|
||||
#include "qmessagebox.h"
|
||||
#define indexOf find
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#include "ladspa_effect.h"
|
||||
#include "mixer.h"
|
||||
#include "config_mgr.h"
|
||||
#include "buffer_allocator.h"
|
||||
#include "audio_device.h"
|
||||
#include "ladspa_control.h"
|
||||
#include "ladspa_subplugin_features.h"
|
||||
|
||||
|
||||
#undef SINGLE_SOURCE_COMPILE
|
||||
#include "embed.cpp"
|
||||
|
||||
|
||||
extern "C"
|
||||
{
|
||||
|
||||
plugin::descriptor ladspaeffect_plugin_descriptor =
|
||||
{
|
||||
STRINGIFY_PLUGIN_NAME( PLUGIN_NAME ),
|
||||
"LADSPA Effect",
|
||||
QT_TRANSLATE_NOOP( "pluginBrowser",
|
||||
"plugin for using arbitrary LADSPA-effects "
|
||||
"inside LMMS." ),
|
||||
"Danny McRae <khjklujn/at/users.sourceforge.net>",
|
||||
0x0100,
|
||||
plugin::Effect,
|
||||
new QPixmap( PLUGIN_NAME::getIconPixmap( "logo" ) ),
|
||||
new ladspaSubPluginFeatures( plugin::Effect )
|
||||
} ;
|
||||
|
||||
}
|
||||
|
||||
|
||||
ladspaEffect::ladspaEffect( effect::constructionData * _cdata ) :
|
||||
effect( &ladspaeffect_plugin_descriptor, _cdata ),
|
||||
m_effName( "none" ),
|
||||
m_key( subPluginKeyToLadspaKey( _cdata->key )
|
||||
/* ladspa_key_t( _cdata->settings.attribute( "label" ),
|
||||
_cdata->settings.attribute( "lib" ) )*/ ),
|
||||
m_ladspa( eng()->getLADSPAManager() )
|
||||
{
|
||||
if( m_ladspa->getDescription( m_key ) == NULL )
|
||||
{
|
||||
QMessageBox::warning( 0, "Effect",
|
||||
"Unknown LADSPA plugin requested: " + m_key.first,
|
||||
QMessageBox::Ok, QMessageBox::NoButton );
|
||||
setOkay( FALSE );
|
||||
return;
|
||||
}
|
||||
|
||||
setPublicName( m_ladspa->getShortName( m_key ) );
|
||||
|
||||
// Calculate how many processing units are needed.
|
||||
const ch_cnt_t lmms_chnls = eng()->getMixer()->audioDev()->channels();
|
||||
m_effectChannels = m_ladspa->getDescription( m_key )->inputChannels;
|
||||
setProcessorCount( lmms_chnls / m_effectChannels );
|
||||
|
||||
// Categorize the ports, and create the buffers.
|
||||
m_portCount = m_ladspa->getPortCount( m_key );
|
||||
|
||||
for( ch_cnt_t proc = 0; proc < getProcessorCount(); proc++ )
|
||||
{
|
||||
multi_proc_t ports;
|
||||
for( Uint16 port = 0; port < m_portCount; port++ )
|
||||
{
|
||||
port_desc_t * p = new portDescription;
|
||||
|
||||
p->name = m_ladspa->getPortName( m_key, port );
|
||||
p->proc = proc;
|
||||
p->port_id = port;
|
||||
|
||||
// Determine the port's category.
|
||||
if( m_ladspa->isPortAudio( m_key, port ) )
|
||||
{
|
||||
// Nasty manual memory management--was having difficulty
|
||||
// with some prepackaged plugins that were segfaulting
|
||||
// during cleanup. It was easier to troubleshoot with the
|
||||
// memory management all taking place in one file.
|
||||
p->buffer =
|
||||
new LADSPA_Data[eng()->getMixer()->framesPerAudioBuffer()];
|
||||
|
||||
if( p->name.toUpper().contains( "IN" ) &&
|
||||
m_ladspa->isPortInput( m_key, port ) )
|
||||
{
|
||||
p->rate = CHANNEL_IN;
|
||||
}
|
||||
else if( p->name.toUpper().contains( "OUT" ) &&
|
||||
m_ladspa->isPortOutput( m_key, port ) )
|
||||
{
|
||||
p->rate = CHANNEL_OUT;
|
||||
}
|
||||
else if( m_ladspa->isPortInput( m_key, port ) )
|
||||
{
|
||||
p->rate = AUDIO_RATE_INPUT;
|
||||
}
|
||||
else
|
||||
{
|
||||
p->rate = AUDIO_RATE_OUTPUT;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
p->buffer = new LADSPA_Data;
|
||||
|
||||
if( m_ladspa->isPortInput( m_key, port ) )
|
||||
{
|
||||
p->rate = CONTROL_RATE_INPUT;
|
||||
}
|
||||
else
|
||||
{
|
||||
p->rate = CONTROL_RATE_OUTPUT;
|
||||
}
|
||||
}
|
||||
|
||||
p->scale = 1.0f;
|
||||
if( m_ladspa->isPortToggled( m_key, port ) )
|
||||
{
|
||||
p->data_type = TOGGLED;
|
||||
}
|
||||
else if( m_ladspa->isInteger( m_key, port ) )
|
||||
{
|
||||
p->data_type = INTEGER;
|
||||
}
|
||||
else if( p->name.toUpper().contains( "(SECONDS)" ) )
|
||||
{
|
||||
p->data_type = TIME;
|
||||
p->scale = 1000.0f;
|
||||
int loc = p->name.toUpper().indexOf(
|
||||
"(SECONDS)" );
|
||||
p->name.replace( loc, 9, "(ms)" );
|
||||
}
|
||||
else if( p->name.toUpper().contains( "(S)" ) )
|
||||
{
|
||||
p->data_type = TIME;
|
||||
p->scale = 1000.0f;
|
||||
int loc = p->name.toUpper().indexOf( "(S)" );
|
||||
p->name.replace( loc, 3, "(ms)" );
|
||||
}
|
||||
else if( p->name.toUpper().contains( "(MS)" ) )
|
||||
{
|
||||
p->data_type = TIME;
|
||||
int loc = p->name.toUpper().indexOf( "(MS)" );
|
||||
p->name.replace( loc, 4, "(ms)" );
|
||||
}
|
||||
else
|
||||
{
|
||||
p->data_type = FLOAT;
|
||||
}
|
||||
|
||||
// Get the range and default values.
|
||||
p->max = m_ladspa->getUpperBound( m_key, port );
|
||||
if( p->max == NOHINT )
|
||||
{
|
||||
p->max = 1.0f;
|
||||
}
|
||||
|
||||
if( m_ladspa->areHintsSampleRateDependent(
|
||||
m_key, port ) )
|
||||
{
|
||||
p->max *= eng()->getMixer()->sampleRate();
|
||||
}
|
||||
|
||||
p->min = m_ladspa->getLowerBound( m_key, port );
|
||||
if( p->min == NOHINT )
|
||||
{
|
||||
p->min = 0.0f;
|
||||
}
|
||||
|
||||
if( m_ladspa->areHintsSampleRateDependent(
|
||||
m_key, port ) )
|
||||
{
|
||||
p->min *= eng()->getMixer()->sampleRate();
|
||||
}
|
||||
|
||||
p->def = m_ladspa->getDefaultSetting( m_key, port );
|
||||
if( p->def == NOHINT )
|
||||
{
|
||||
if( p->data_type != TOGGLED )
|
||||
{
|
||||
p->def = ( p->min + p->max ) / 2.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
p->def = 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
p->max *= p->scale;
|
||||
p->min *= p->scale;
|
||||
p->def *= p->scale;
|
||||
|
||||
p->value = p->def;
|
||||
|
||||
|
||||
ports.append( p );
|
||||
|
||||
// For convenience, keep a separate list of the ports that are used
|
||||
// to control the processors.
|
||||
if( p->rate == AUDIO_RATE_INPUT ||
|
||||
p->rate == CONTROL_RATE_INPUT )
|
||||
{
|
||||
p->control_id = m_controls.count();
|
||||
m_controls.append( p );
|
||||
}
|
||||
}
|
||||
m_ports.append( ports );
|
||||
}
|
||||
|
||||
// Instantiate the processing units.
|
||||
m_descriptor = m_ladspa->getDescriptor( m_key );
|
||||
if( m_descriptor == NULL )
|
||||
{
|
||||
QMessageBox::warning( 0, "Effect",
|
||||
"Can't get LADSPA descriptor function: " + m_key.first,
|
||||
QMessageBox::Ok, QMessageBox::NoButton );
|
||||
setOkay( FALSE );
|
||||
return;
|
||||
}
|
||||
if( m_descriptor->run == NULL )
|
||||
{
|
||||
QMessageBox::warning( 0, "Effect",
|
||||
"Plugin has no processor: " + m_key.first,
|
||||
QMessageBox::Ok, QMessageBox::NoButton );
|
||||
setDontRun( TRUE );
|
||||
}
|
||||
for( ch_cnt_t proc = 0; proc < getProcessorCount(); proc++ )
|
||||
{
|
||||
LADSPA_Handle effect = m_ladspa->instantiate( m_key,
|
||||
eng()->getMixer()->sampleRate() );
|
||||
if( effect == NULL )
|
||||
{
|
||||
QMessageBox::warning( 0, "Effect",
|
||||
"Can't get LADSPA instance: " + m_key.first,
|
||||
QMessageBox::Ok, QMessageBox::NoButton );
|
||||
setOkay( FALSE );
|
||||
return;
|
||||
}
|
||||
m_handles.append( effect );
|
||||
|
||||
}
|
||||
|
||||
// Connect the ports.
|
||||
for( ch_cnt_t proc = 0; proc < getProcessorCount(); proc++ )
|
||||
{
|
||||
for( Uint16 port = 0; port < m_portCount; port++ )
|
||||
{
|
||||
if( !m_ladspa->connectPort( m_key,
|
||||
m_handles[proc],
|
||||
port,
|
||||
m_ports[proc][port]->buffer ) )
|
||||
{
|
||||
QMessageBox::warning( 0, "Effect",
|
||||
"Failed to connect port: " + m_key.first,
|
||||
QMessageBox::Ok, QMessageBox::NoButton );
|
||||
setDontRun( TRUE );
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Activate the processing units.
|
||||
for( ch_cnt_t proc = 0; proc < getProcessorCount(); proc++ )
|
||||
{
|
||||
m_ladspa->activate( m_key, m_handles[proc] );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
ladspaEffect::~ladspaEffect()
|
||||
{
|
||||
if( !isOkay() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
lock();
|
||||
|
||||
for( ch_cnt_t proc = 0; proc < getProcessorCount(); proc++ )
|
||||
{
|
||||
m_ladspa->deactivate( m_key, m_handles[proc] );
|
||||
m_ladspa->cleanup( m_key, m_handles[proc] );
|
||||
for( Uint16 port = 0; port < m_portCount; port++ )
|
||||
{
|
||||
free( m_ports[proc][port]->buffer );
|
||||
free( m_ports[proc][port] );
|
||||
}
|
||||
m_ports[proc].clear();
|
||||
}
|
||||
m_ports.clear();
|
||||
m_handles.clear();
|
||||
|
||||
unlock();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
bool FASTCALL ladspaEffect::processAudioBuffer( surroundSampleFrame * _buf,
|
||||
const fpab_t _frames )
|
||||
{
|
||||
if( !isOkay() || dontRun() || !isRunning() ||
|
||||
isBypassed() || !tryLock() )
|
||||
{
|
||||
return( FALSE );
|
||||
}
|
||||
|
||||
// Copy the LMMS audio buffer to the LADSPA input buffer and initialize
|
||||
// the control ports. Need to change this to handle non-in-place-broken
|
||||
// plugins--would speed things up to use the same buffer for both
|
||||
// LMMS and LADSPA.
|
||||
ch_cnt_t channel = 0;
|
||||
for( ch_cnt_t proc = 0; proc < getProcessorCount(); proc++)
|
||||
{
|
||||
for( Uint16 port = 0; port < m_portCount; port++ )
|
||||
{
|
||||
switch( m_ports[proc][port]->rate )
|
||||
{
|
||||
case CHANNEL_IN:
|
||||
for( fpab_t frame = 0;
|
||||
frame < _frames; frame++ )
|
||||
{
|
||||
m_ports[proc][port]->buffer[frame] =
|
||||
_buf[frame][channel];
|
||||
}
|
||||
channel++;
|
||||
break;
|
||||
case AUDIO_RATE_INPUT:
|
||||
m_ports[proc][port]->value =
|
||||
static_cast<LADSPA_Data>(
|
||||
m_ports[proc][port]->control->getValue() /
|
||||
m_ports[proc][port]->scale );
|
||||
// This only supports control rate ports, so the audio rates are
|
||||
// treated as though they were control rate by setting the
|
||||
// port buffer to all the same value.
|
||||
for( fpab_t frame = 0;
|
||||
frame < _frames; frame++ )
|
||||
{
|
||||
m_ports[proc][port]->buffer[frame] =
|
||||
m_ports[proc][port]->value;
|
||||
}
|
||||
break;
|
||||
case CONTROL_RATE_INPUT:
|
||||
m_ports[proc][port]->value =
|
||||
static_cast<LADSPA_Data>(
|
||||
m_ports[proc][port]->control->getValue() /
|
||||
m_ports[proc][port]->scale );
|
||||
m_ports[proc][port]->buffer[0] =
|
||||
m_ports[proc][port]->value;
|
||||
break;
|
||||
case CHANNEL_OUT:
|
||||
case AUDIO_RATE_OUTPUT:
|
||||
case CONTROL_RATE_OUTPUT:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Process the buffers.
|
||||
for( ch_cnt_t proc = 0; proc < getProcessorCount(); proc++ )
|
||||
{
|
||||
(m_descriptor->run)(m_handles[proc], _frames);
|
||||
}
|
||||
|
||||
// Copy the LADSPA output buffers to the LMMS buffer.
|
||||
double out_sum = 0.0;
|
||||
channel = 0;
|
||||
for( ch_cnt_t proc = 0; proc < getProcessorCount(); proc++)
|
||||
{
|
||||
for( Uint16 port = 0; port < m_portCount; port++ )
|
||||
{
|
||||
switch( m_ports[proc][port]->rate )
|
||||
{
|
||||
case CHANNEL_IN:
|
||||
case AUDIO_RATE_INPUT:
|
||||
case CONTROL_RATE_INPUT:
|
||||
break;
|
||||
case CHANNEL_OUT:
|
||||
for( fpab_t frame = 0;
|
||||
frame < _frames; frame++ )
|
||||
{
|
||||
_buf[frame][channel] =
|
||||
getDryLevel() *
|
||||
_buf[frame][channel] +
|
||||
getWetLevel() *
|
||||
m_ports[proc][port]->buffer[frame];
|
||||
out_sum +=
|
||||
_buf[frame][channel] *
|
||||
_buf[frame][channel];
|
||||
}
|
||||
channel++;
|
||||
break;
|
||||
case AUDIO_RATE_OUTPUT:
|
||||
case CONTROL_RATE_OUTPUT:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check whether we need to continue processing input. Restart the
|
||||
// counter if the threshold has been exceeded.
|
||||
if( out_sum <= getGate() )
|
||||
{
|
||||
incrementBufferCount();
|
||||
if( getBufferCount() > getTimeout() )
|
||||
{
|
||||
stopRunning();
|
||||
resetBufferCount();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
resetBufferCount();
|
||||
}
|
||||
|
||||
unlock();
|
||||
return( isRunning() );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void FASTCALL ladspaEffect::setControl( Uint16 _control, LADSPA_Data _value )
|
||||
{
|
||||
if( !isOkay() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
lock();
|
||||
m_controls[_control]->value = _value;
|
||||
unlock();
|
||||
}
|
||||
|
||||
|
||||
#undef indexOf
|
||||
|
||||
extern "C"
|
||||
{
|
||||
|
||||
// neccessary for getting instance out of shared lib
|
||||
plugin * lmms_plugin_main( void * _data )
|
||||
{
|
||||
return( new ladspaEffect(
|
||||
static_cast<effect::constructionData *>( _data ) ) );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
100
plugins/ladspa_effect/ladspa_effect.h
Normal file
100
plugins/ladspa_effect/ladspa_effect.h
Normal file
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* ladspa_effect.h - class for handling LADSPA effect plugins
|
||||
*
|
||||
* Copyright (c) 2006 Danny McRae <khjklujn/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 _LADSPA_EFFECT_H
|
||||
#define _LADSPA_EFFECT_H
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include "qt3support.h"
|
||||
|
||||
#include "effect.h"
|
||||
#include "ladspa_2_lmms.h"
|
||||
#include "mixer.h"
|
||||
#include "ladspa_control.h"
|
||||
#include "ladspa_control_dialog.h"
|
||||
#include "ladspa_base.h"
|
||||
#include "main_window.h"
|
||||
|
||||
|
||||
typedef vvector<port_desc_t *> multi_proc_t;
|
||||
|
||||
class ladspaEffect : public effect
|
||||
{
|
||||
public:
|
||||
ladspaEffect( effect::constructionData * _cdata );
|
||||
virtual ~ladspaEffect();
|
||||
|
||||
virtual bool FASTCALL processAudioBuffer( surroundSampleFrame * _buf,
|
||||
const fpab_t _frames );
|
||||
|
||||
void FASTCALL setControl( Uint16 _control, LADSPA_Data _data );
|
||||
|
||||
inline const multi_proc_t & getControls( void )
|
||||
{
|
||||
return( m_controls );
|
||||
}
|
||||
|
||||
virtual inline QString publicName( void ) const
|
||||
{
|
||||
return( m_effName );
|
||||
}
|
||||
|
||||
inline void setPublicName( const QString & _name )
|
||||
{
|
||||
m_effName = _name;
|
||||
}
|
||||
|
||||
virtual inline effectControlDialog * createControlDialog(
|
||||
track * _track )
|
||||
{
|
||||
return( new ladspaControlDialog(
|
||||
eng()->getMainWindow()->workspace(),
|
||||
this, _track ) );
|
||||
}
|
||||
|
||||
inline virtual QString nodeName( void ) const
|
||||
{
|
||||
return( "ladspaeffect" );
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
QString m_effName;
|
||||
ladspa_key_t m_key;
|
||||
ladspa2LMMS * m_ladspa;
|
||||
Uint16 m_effectChannels;
|
||||
Uint16 m_portCount;
|
||||
fpab_t m_bufferSize;
|
||||
|
||||
const LADSPA_Descriptor * m_descriptor;
|
||||
vvector<LADSPA_Handle> m_handles;
|
||||
|
||||
vvector<multi_proc_t> m_ports;
|
||||
multi_proc_t m_controls;
|
||||
} ;
|
||||
|
||||
#endif
|
||||
BIN
plugins/ladspa_effect/logo.png
Normal file
BIN
plugins/ladspa_effect/logo.png
Normal file
Binary file not shown.
@@ -62,8 +62,9 @@ plugin::descriptor midiimport_plugin_descriptor =
|
||||
"Filter for importing MIDI-files into LMMS" ),
|
||||
"Tobias Doerffel <tobydox/at/users/dot/sf/dot/net>",
|
||||
0x0100,
|
||||
plugin::IMPORT_FILTER,
|
||||
new QPixmap()
|
||||
plugin::ImportFilter,
|
||||
new QPixmap(),
|
||||
NULL
|
||||
} ;
|
||||
|
||||
}
|
||||
|
||||
@@ -76,8 +76,9 @@ plugin::descriptor organic_plugin_descriptor =
|
||||
"Additive Synthesizer for organ-like sounds" ),
|
||||
"Andreas Brandmaier <andreas/at/brandmaier.de>",
|
||||
0x0100,
|
||||
plugin::INSTRUMENT,
|
||||
new QPixmap( PLUGIN_NAME::getIconPixmap( "logo" ) )
|
||||
plugin::Instrument,
|
||||
new QPixmap( PLUGIN_NAME::getIconPixmap( "logo" ) ),
|
||||
NULL
|
||||
} ;
|
||||
|
||||
}
|
||||
|
||||
@@ -58,8 +58,9 @@ plugin::descriptor pluckedstringsynth_plugin_descriptor =
|
||||
"cheap synthesis of guitar/harp-like sounds" ),
|
||||
"Tobias Doerffel <tobydox/at/users.sf.net>",
|
||||
0x0100,
|
||||
plugin::INSTRUMENT,
|
||||
new QPixmap( PLUGIN_NAME::getIconPixmap( "logo" ) )
|
||||
plugin::Instrument,
|
||||
new QPixmap( PLUGIN_NAME::getIconPixmap( "logo" ) ),
|
||||
NULL
|
||||
} ;
|
||||
|
||||
}
|
||||
|
||||
@@ -60,8 +60,9 @@ plugin::descriptor malletsstk_plugin_descriptor =
|
||||
"Tuneful things to bang on" ),
|
||||
"Danny McRae <khjklujn/at/users.sf.net>",
|
||||
0x0100,
|
||||
plugin::INSTRUMENT,
|
||||
new QPixmap( PLUGIN_NAME::getIconPixmap( "logo" ) )
|
||||
plugin::Instrument,
|
||||
new QPixmap( PLUGIN_NAME::getIconPixmap( "logo" ) ),
|
||||
NULL
|
||||
} ;
|
||||
|
||||
}
|
||||
|
||||
@@ -73,8 +73,9 @@ plugin::descriptor tripleoscillator_plugin_descriptor =
|
||||
"in several ways" ),
|
||||
"Tobias Doerffel <tobydox/at/users.sf.net>",
|
||||
0x0100,
|
||||
plugin::INSTRUMENT,
|
||||
new QPixmap( PLUGIN_NAME::getIconPixmap( "logo" ) )
|
||||
plugin::Instrument,
|
||||
new QPixmap( PLUGIN_NAME::getIconPixmap( "logo" ) ),
|
||||
NULL
|
||||
} ;
|
||||
|
||||
}
|
||||
|
||||
@@ -77,8 +77,9 @@ plugin::descriptor vestige_plugin_descriptor =
|
||||
"VST-host for using VST(i)-plugins within LMMS" ),
|
||||
"Tobias Doerffel <tobydox/at/users.sf.net>",
|
||||
0x0100,
|
||||
plugin::INSTRUMENT,
|
||||
new QPixmap( PLUGIN_NAME::getIconPixmap( "logo" ) )
|
||||
plugin::Instrument,
|
||||
new QPixmap( PLUGIN_NAME::getIconPixmap( "logo" ) ),
|
||||
NULL
|
||||
} ;
|
||||
|
||||
}
|
||||
|
||||
@@ -72,8 +72,9 @@ plugin::descriptor vibedstrings_plugin_descriptor =
|
||||
"Vibrating string modeler" ),
|
||||
"Danny McRae <khjklujn/at/yahoo/com>",
|
||||
0x0100,
|
||||
plugin::INSTRUMENT,
|
||||
new QPixmap( PLUGIN_NAME::getIconPixmap( "logo" ) )
|
||||
plugin::Instrument,
|
||||
new QPixmap( PLUGIN_NAME::getIconPixmap( "logo" ) ),
|
||||
NULL
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user