removed obsolete plugins

git-svn-id: https://lmms.svn.sf.net/svnroot/lmms/trunk/lmms@1168 0778d3d1-df1d-0410-868b-ea421aaaa00d
This commit is contained in:
Tobias Doerffel
2008-06-24 14:10:11 +00:00
parent 154df24102
commit 161e5265dc
11 changed files with 12 additions and 1760 deletions

View File

@@ -1,5 +1,17 @@
2008-06-24 Tobias Doerffel <tobydox/at/users/dot/sourceforge/dot/net>
* plugins/plucked_string_synth/logo.png:
* plugins/plucked_string_synth/plucked_string_synth.cpp:
* plugins/plucked_string_synth/plucked_string_synth.h:
* plugins/plucked_string_synth/Makefile.am:
* plugins/plucked_string_synth/artwork.png:
* plugins/polyb302/polyb302.h:
* plugins/polyb302/logo.png:
* plugins/polyb302/Makefile.am:
* plugins/polyb302/polyb302.cpp:
* plugins/polyb302/artwork.png:
removed obsolete plugins
* plugins/spectrum_analyzer/spectrumanalyzer_control_dialog.cpp:
* plugins/spectrum_analyzer/spectrum_analyzer.cpp:
* plugins/spectrum_analyzer/Makefile.am:

View File

@@ -1,33 +0,0 @@
AUTOMAKE_OPTIONS = foreign 1.4
INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/src/lib -I.
AM_CXXFLAGS := $(AM_CXXFLAGS) $(QT_CXXFLAGS) -DPLUGIN_NAME="pluckedstringsynth"
%.moc: ./%.h
$(MOC) -o $@ $<
MOC_FILES = ./plucked_string_synth.moc
BUILT_SOURCES = $(MOC_FILES) ./embedded_resources.h
EMBEDDED_RESOURCES = $(wildcard *png)
./embedded_resources.h: $(EMBEDDED_RESOURCES)
$(BIN2RES) $(EMBEDDED_RESOURCES) > $@
EXTRA_DIST = $(EMBEDDED_RESOURCES)
CLEANFILES = $(MOC_FILES) ./embedded_resources.h
pkglib_LTLIBRARIES= libpluckedstringsynth.la
libpluckedstringsynth_la_SOURCES = plucked_string_synth.cpp plucked_string_synth.h
$(libpluckedstringsynth_la_SOURCES): ./embedded_resources.h

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

View File

@@ -1,278 +0,0 @@
/*
* plucked_string_synth.cpp - instrument which uses the Karplus-Strong-algorithm
*
* Copyright (c) 2004-2007 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 <Qt/QtXml>
#include "plucked_string_synth.h"
#include "engine.h"
#include "instrument_track.h"
#include "knob.h"
#include "note_play_handle.h"
#include "templates.h"
#undef SINGLE_SOURCE_COMPILE
#include "embed.cpp"
extern "C"
{
plugin::descriptor pluckedstringsynth_plugin_descriptor =
{
STRINGIFY_PLUGIN_NAME( PLUGIN_NAME ),
"PluckedStringSynth",
QT_TRANSLATE_NOOP( "pluginBrowser",
"cheap synthesis of guitar/harp-like sounds" ),
"Tobias Doerffel <tobydox/at/users.sf.net>",
0x0100,
plugin::Instrument,
new QPixmap( PLUGIN_NAME::getIconPixmap( "logo" ) ),
NULL
} ;
}
// TODO: make this synth stereo for better better spacial (room) feeling and
// add distortion
pluckedStringSynth::pluckedStringSynth( instrumentTrack * _instrument_track ) :
instrument( _instrument_track, &pluckedstringsynth_plugin_descriptor ),
m_pickModel( 0.0f, 0.0f, 0.5f, 0.005f, this ),
m_pickupModel( 0.05f, 0.0f, 0.5f, 0.005f, this )
{
}
pluckedStringSynth::~pluckedStringSynth()
{
}
void pluckedStringSynth::saveSettings( QDomDocument & _doc,
QDomElement & _this )
{
m_pickModel.saveSettings( _doc, _this, "pick" );
m_pickupModel.saveSettings( _doc, _this, "pickup" );
}
void pluckedStringSynth::loadSettings( const QDomElement & _this )
{
m_pickModel.loadSettings( _this, "pick" );
m_pickupModel.loadSettings( _this, "pickup" );
}
QString pluckedStringSynth::nodeName( void ) const
{
return( pluckedstringsynth_plugin_descriptor.name );
}
void pluckedStringSynth::playNote( notePlayHandle * _n, bool )
{
if ( _n->totalFramesPlayed() == 0 )
{
_n->m_pluginData = new pluckSynth( _n->frequency(),
m_pickModel.value(),
m_pickupModel.value(),
engine::getMixer()->sampleRate() );
}
const fpp_t frames = _n->framesLeftForCurrentPeriod();
sampleFrame * buf = new sampleFrame[frames];
pluckSynth * ps = static_cast<pluckSynth *>( _n->m_pluginData );
for( fpp_t frame = 0; frame < frames; ++frame )
{
const sample_t cur = ps->nextStringSample();
for( Uint8 chnl = 0; chnl < DEFAULT_CHANNELS; ++chnl )
{
buf[frame][chnl] = cur;
}
}
getInstrumentTrack()->processAudioBuffer( buf, frames, _n );
delete[] buf;
}
void pluckedStringSynth::deleteNotePluginData( notePlayHandle * _n )
{
delete static_cast<pluckSynth *>( _n->m_pluginData );
}
pluginView * pluckedStringSynth::instantiateView( QWidget * _parent )
{
return( new pluckedStringSynthView( this, _parent ) );
}
pluckedStringSynthView::pluckedStringSynthView( instrument * _instrument,
QWidget * _parent ) :
instrumentView( _instrument, _parent )
{
m_pickKnob = new knob( knobDark_28, this, tr( "Pick position" ) );
m_pickKnob->move( 86, 134 );
m_pickKnob->setHintText( tr( "Pick position:" ) + " ", "" );
m_pickupKnob = new knob( knobDark_28, this, tr( "Pickup position" ) );
m_pickupKnob->move( 138, 134 );
m_pickupKnob->setHintText( tr( "Pickup position:" ) + " ", "" );
setAutoFillBackground( TRUE );
QPalette pal;
pal.setBrush( backgroundRole(), PLUGIN_NAME::getIconPixmap(
"artwork" ) );
setPalette( pal );
}
pluckedStringSynthView::~pluckedStringSynthView()
{
}
void pluckedStringSynthView::modelChanged( void )
{
pluckedStringSynth * p = castModel<pluckedStringSynth>();
m_pickKnob->setModel( &p->m_pickModel );
m_pickupKnob->setModel( &p->m_pickupModel );
}
pluckSynth::delayLine * FASTCALL pluckSynth::initDelayLine( int _len )
{
delayLine * dl = new pluckSynth::delayLine[_len];
dl->length = _len;
if( _len > 0 )
{
dl->data = new sample_t[_len];
}
else
{
dl->data = NULL;
}
dl->pointer = dl->data;
dl->end = dl->data + _len - 1;
return( dl );
}
void FASTCALL pluckSynth::freeDelayLine( delayLine * _dl )
{
if( _dl )
{
delete[] _dl->data;
delete[] _dl;
}
}
pluckSynth::pluckSynth( const float _pitch, const float _pick,
const float _pickup, const sample_rate_t _sample_rate )
{
const float AMP = 1.5f;
int rail_length = static_cast<int>( _sample_rate / 2 / _pitch ) + 1;
// Round pick position to nearest spatial sample.
// A pick position at x = 0 is not allowed.
int pick_sample = static_cast<int>( tMax<float>( rail_length * _pick,
1.0f ) );
float initial_shape[rail_length];
m_upperRail = pluckSynth::initDelayLine( rail_length );
m_lowerRail = pluckSynth::initDelayLine( rail_length );
//#define METALLIC_PLUCK
#ifdef METALLIC_PLUCK
for ( int i = 0; i < rail_length; i++ )
{
initial_shape[i] = rand() * AMP / RAND_MAX;
}
initial_shape[pick_sample] = 0.5;
initial_shape[pick_sample+1] = 0.5;
#else
float upslope = AMP / pick_sample;
const float downslope = AMP / ( rail_length - pick_sample - 1 );
for( int i = 0; i < pick_sample; i++ )
{
initial_shape[i] = upslope * i;
}
for( int i = pick_sample; i < rail_length; i++ )
{
initial_shape[i] = downslope * ( rail_length - 1 - i );
}
#endif
// Initial conditions for the ideal plucked string.
// "Past history" is measured backward from the end of the array.
pluckSynth::setDelayLine( m_lowerRail, initial_shape, 0.5f );
pluckSynth::setDelayLine( m_upperRail, initial_shape, 0.5f );
m_pickupLoc = static_cast<int>( _pickup * rail_length );
}
extern "C"
{
// neccessary for getting instance out of shared lib
plugin * lmms_plugin_main( model *, void * _data )
{
return( new pluckedStringSynth(
static_cast<instrumentTrack *>( _data ) ) );
}
}

View File

@@ -1,238 +0,0 @@
/*
* plucked_string_synth.h - declaration of class pluckedStringSynth which
* is a synth for plucked string-sounds
*
* Copyright (c) 2004-2006 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 _PLUCKED_STRING_SYNTH_H
#define _PLUCKED_STRING_SYNTH_H
#include "instrument.h"
#include "instrument_view.h"
#include "knob.h"
class knob;
class notePlayHandle;
// the actual synth
class pluckSynth
{
public:
pluckSynth( const float _pitch, const float _pick, const float _pickup,
const sample_rate_t _sample_rate );
inline ~pluckSynth( void )
{
pluckSynth::freeDelayLine( m_upperRail );
pluckSynth::freeDelayLine( m_lowerRail );
}
inline sample_t nextStringSample( void )
{
// Output at pickup position
sample_t outsamp = rgDlAccess( m_upperRail, m_pickupLoc );
outsamp += lgDlAccess( m_lowerRail, m_pickupLoc );
// Sample traveling into "bridge"
sample_t ym0 = lgDlAccess( m_lowerRail, 1 );
// Sample to "nut"
sample_t ypM = rgDlAccess( m_upperRail,
m_upperRail->length - 2 );
// String state update
// Decrement pointer and then update
rgDlUpdate( m_upperRail, -bridgeReflection( ym0 ) );
// Update and then increment pointer
lgDlUpdate( m_lowerRail, -ypM );
return( outsamp );
}
private:
struct delayLine
{
sample_t * data;
int length;
sample_t * pointer;
sample_t * end;
} ;
delayLine * m_upperRail;
delayLine * m_lowerRail;
int m_pickupLoc;
static delayLine * FASTCALL initDelayLine( int _len );
static void FASTCALL freeDelayLine( delayLine * _dl );
static inline void setDelayLine( delayLine * _dl, float * _values,
float _scale )
{
for( int i = 0; i < _dl->length; ++i )
{
_dl->data[i] = _scale * _values[i];
}
}
/* lgDlUpdate(dl, insamp);
* Places "nut-reflected" sample from upper delay-line into
* current lower delay-line pointer position (which represents
* x = 0 position). The pointer is then incremented (i.e. the
* wave travels one sample to the left), turning the previous
* position into an "effective" x = L position for the next
* iteration. */
static inline void lgDlUpdate( delayLine * _dl, sample_t _insamp )
{
register sample_t * ptr = _dl->pointer;
*ptr = _insamp;
++ptr;
if( ptr > _dl->end )
{
ptr = _dl->data;
}
_dl->pointer = ptr;
}
/* rgDlUpdate(dl, insamp);
* Decrements current upper delay-line pointer position (i.e.
* the wave travels one sample to the right), moving it to the
* "effective" x = 0 position for the next iteration. The
* "bridge-reflected" sample from lower delay-line is then placed
* into this position. */
static inline void rgDlUpdate( delayLine * _dl, sample_t _insamp )
{
register sample_t * ptr = _dl->pointer;
--ptr;
if( ptr < _dl->data )
{
ptr = _dl->end;
}
*ptr = _insamp;
_dl->pointer = ptr;
}
/* dlAccess(dl, position);
* Returns sample "position" samples into delay-line's past.
* Position "0" points to the most recently inserted sample. */
static inline sample_t dlAccess( delayLine * _dl, int _position )
{
sample_t * outpos = _dl->pointer + _position;
while( outpos < _dl->data )
{
outpos += _dl->length;
}
while( outpos > _dl->end )
{
outpos -= _dl->length;
}
return( *outpos );
}
/*
* Right-going delay line:
* -->---->---->---
* x=0
* (pointer)
* Left-going delay line:
* --<----<----<---
* x=0
* (pointer)
*/
/* rgDlAccess(dl, position);
* Returns spatial sample at position "position", where position zero
* is equal to the current upper delay-line pointer position (x = 0).
* In a right-going delay-line, position increases to the right, and
* delay increases to the right => left = past and right = future. */
static inline sample_t rgDlAccess( delayLine * _dl, int _position )
{
return( dlAccess( _dl, _position ) );
}
/* lgDlAccess(dl, position);
* Returns spatial sample at position "position", where position zero
* is equal to the current lower delay-line pointer position (x = 0).
* In a left-going delay-line, position increases to the right, and
* delay DEcreases to the right => left = future and right = past. */
static inline sample_t lgDlAccess( delayLine * _dl, int _position )
{
return( dlAccess( _dl, _position ) );
}
static inline sample_t bridgeReflection( sample_t _insamp )
{
static sample_t state = 0.0f; // filter memory
// Implement a one-pole lowpass with feedback coefficient = 0.5
return( state = state*0.5f + _insamp*0.5f );
}
} ;
class pluckedStringSynth : public instrument
{
public:
pluckedStringSynth( instrumentTrack * _instrument_track );
virtual ~pluckedStringSynth();
virtual void FASTCALL playNote( notePlayHandle * _n,
bool _try_parallelizing );
virtual void FASTCALL deleteNotePluginData( notePlayHandle * _n );
virtual void FASTCALL saveSettings( QDomDocument & _doc,
QDomElement & _parent );
virtual void FASTCALL loadSettings( const QDomElement & _this );
virtual QString nodeName( void ) const;
virtual pluginView * instantiateView( QWidget * _parent );
private:
knobModel m_pickModel;
knobModel m_pickupModel;
friend class pluckedStringSynthView;
} ;
class pluckedStringSynthView : public instrumentView
{
public:
pluckedStringSynthView( instrument * _instrument,
QWidget * _parent );
virtual ~pluckedStringSynthView();
private:
virtual void modelChanged( void );
knob * m_pickKnob;
knob * m_pickupKnob;
} ;
#endif

View File

@@ -1,33 +0,0 @@
AUTOMAKE_OPTIONS = foreign 1.4
INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/src/gui -I.
AM_CXXFLAGS := $(AM_CXXFLAGS) $(QT_CXXFLAGS) -DPLUGIN_NAME="polyb302"
%.moc: ./%.h
$(MOC) -o $@ $<
MOC_FILES = ./polyb302.moc
BUILT_SOURCES = $(MOC_FILES) ./embedded_resources.h
EMBEDDED_RESOURCES = $(wildcard *png)
./embedded_resources.h: $(EMBEDDED_RESOURCES)
$(BIN2RES) $(EMBEDDED_RESOURCES) > $@
EXTRA_DIST = $(EMBEDDED_RESOURCES)
CLEANFILES = $(MOC_FILES) ./embedded_resources.h
pkglib_LTLIBRARIES = libpolyb302.la
libpolyb302_la_SOURCES = polyb302.cpp polyb302.h
$(libpolyb302_la_SOURCES): ./embedded_resources.h

Binary file not shown.

Before

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.4 KiB

View File

@@ -1,926 +0,0 @@
/*
* polyb302.cpp - implementation of instrument polyb302, an attempt to emulate
* the Roland TB303 bass synth
*
* Copyright (c) 2006-2007 Paul Giblock <pgib/at/users.sourceforge.net>
*
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
*
* lb302FilterIIR2 is based on the gsyn filter code by Andy Sloane.
*
* lb302Filter3Pole is based on the TB303 instrument written by
* Josep M Comajuncosas for the CSounds library
*
* 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 "polyb302.h"
#include "engine.h"
#include "knob.h"
#include "led_checkbox.h"
#include "note_play_handle.h"
#undef SINGLE_SOURCE_COMPILE
#include "embed.cpp"
#include "polyb302.moc"
// Envelope Recalculation period
#define ENVINC 64
//
// New config
//
#define LB_24_IGNORE_ENVELOPE
#define LB_FILTERED
//#define LB_24_RES_TRICK
#define LB_DIST_RATIO 4.0
#define LB_24_VOL_ADJUST 3.0
using namespace std;
extern "C"
{
plugin::descriptor polyb302_plugin_descriptor =
{
STRINGIFY_PLUGIN_NAME( PLUGIN_NAME ),
"PoLyB302",
QT_TRANSLATE_NOOP( "pluginBrowser",
"Incomplete polyphonic immitation tb303" ),
"Javier Serrano Polo <jasp00/at/users.sourceforge.net>",
0x0100,
plugin::Instrument,
new QPixmap( PLUGIN_NAME::getIconPixmap( "logo" ) ),
NULL
} ;
// necessary for getting instance out of shared lib
plugin * lmms_plugin_main( void * _data )
{
return( new polyb302Synth( static_cast<instrumentTrack *>( _data ) ) );
}
}
//
// lb302Filter
//
lb302Filter::lb302Filter( lb302FilterState * _p_fs ) :
m_fs( _p_fs ),
m_vcf_c0( 0 ),
m_vcf_e0( 0 ),
m_vcf_e1( 0 )
{
}
void lb302Filter::recalc( void )
{
m_vcf_e1 = exp( 4.909 + 1.5876 * m_fs->envmod + 2.1553 * m_fs->cutoff
+ 1.2 * m_fs->reso );
m_vcf_e0 = exp( 4.8434 - 0.8 * m_fs->envmod + 2.1553 * m_fs->cutoff
+ 0.7696 * m_fs->reso );
m_vcf_e0 *= M_PI / engine::getMixer()->sampleRate();
m_vcf_e1 *= M_PI / engine::getMixer()->sampleRate();
m_vcf_e1 -= m_vcf_e0;
}
void lb302Filter::envRecalc( void )
{
// Filter Decay. vcf_decay is adjusted for Hz and ENVINC
m_vcf_c0 *= m_fs->envdecay;
m_vcf_rescoeff = exp( -1.20 + 3.455 * m_fs->reso );
}
void lb302Filter::playNote( void )
{
m_vcf_c0 = m_vcf_e1;
}
//
// lb302FilterIIR2
//
lb302FilterIIR2::lb302FilterIIR2( lb302FilterState * _p_fs ) :
lb302Filter( _p_fs ),
m_vcf_d1( 0 ),
m_vcf_d2( 0 ),
m_vcf_a( 0 ),
m_vcf_b( 0 ),
m_vcf_c( 1 )
{
m_dist = new effectLib::distortion<>( 1.0, 1.0f );
}
lb302FilterIIR2::~lb302FilterIIR2()
{
delete m_dist;
}
void lb302FilterIIR2::recalc( void )
{
lb302Filter::recalc();
//m_dist->setThreshold(0.5+(m_fs->dist*2.0));
m_dist->setThreshold( m_fs->dist * 75.0 );
}
void lb302FilterIIR2::envRecalc( void )
{
lb302Filter::envRecalc();
// e0 is adjusted for Hz and doesn't need ENVINC
float w = m_vcf_e0 + m_vcf_c0;
float k = exp( -w / m_vcf_rescoeff );
// Does this mean c0 is inheritantly?
m_vcf_a = 2.0 * cos( 2.0 * w ) * k;
m_vcf_b = -k * k;
m_vcf_c = 1.0 - m_vcf_a - m_vcf_b;
}
float lb302FilterIIR2::process( const float & _samp )
{
float ret = m_vcf_a * m_vcf_d1 + m_vcf_b * m_vcf_d2 + m_vcf_c * _samp;
// Delayed samples for filter
m_vcf_d2 = m_vcf_d1;
m_vcf_d1 = ret;
if( m_fs->dist > 0 )
{
ret = m_dist->nextSample( ret );
}
// output = IIR2 + dry
return( ret );
}
//
// lb302Filter3Pole
//
lb302Filter3Pole::lb302Filter3Pole( lb302FilterState * _p_fs ) :
lb302Filter( _p_fs ),
m_ay1( 0 ),
m_ay2( 0 ),
m_aout( 0 ),
m_lastin( 0 )
{
}
void lb302Filter3Pole::recalc( void )
{
// DO NOT CALL BASE CLASS
m_vcf_e0 = 0.000001;
m_vcf_e1 = 1.0;
}
// TODO: Try using k instead of vcf_reso
void lb302Filter3Pole::envRecalc( void )
{
lb302Filter::envRecalc();
// e0 is adjusted for Hz and doesn't need ENVINC
float w = m_vcf_e0 + m_vcf_c0;
float k = ( m_fs->cutoff > 0.975 ) ? 0.975 : m_fs->cutoff;
//TODO: Fix high quality
float kfco = 50.0f + k * ( 2300.0f - 1600.0f * m_fs->envmod
+ w * ( 700.0f + 1500.0f * k + ( 1500.0f + k * (
engine::getMixer()->sampleRate() / 2.0f - 6000.0f ) )
* m_fs->envmod ) );
//+iacc*(.3+.7*kfco*kenvmod)*kaccent*kaccurve*2000
#ifdef LB_24_IGNORE_ENVELOPE
// m_kfcn = m_fs->cutoff;
m_kfcn = 2.0 * kfco / engine::getMixer()->sampleRate();
#else
m_kfcn = w;
#endif
m_kp = ( ( -2.7528 * m_kfcn + 3.0429 ) * m_kfcn + 1.718 ) * m_kfcn
- 0.9984;
m_kp1 = m_kp + 1.0;
m_kp1h = 0.5 * m_kp1;
#ifdef LB_24_RES_TRICK
k = exp( -w / m_vcf_rescoeff );
m_kres = k * ( ( ( -2.7079 * m_kp1 + 10.963 ) * m_kp1 - 14.934 ) * m_kp1
+ 8.4974 );
#else
m_kres = m_fs->reso * ( ( ( -2.7079 * m_kp1 + 10.963 ) * m_kp1
- 14.934 ) * m_kp1 + 8.4974 );
#endif
// ENVMOD was DIST*/
m_value = 1.0 + ( m_fs->dist * ( 1.5 + 2.0 * m_kres
* ( 1.0 - m_kfcn ) ) );
}
float lb302Filter3Pole::process( const float & _samp )
{
float ax1 = m_lastin;
float ay11 = m_ay1;
float ay31 = m_ay2;
m_lastin = _samp - tanh( m_kres * m_aout );
m_ay1 = m_kp1h * ( m_lastin + ax1 ) - m_kp * m_ay1;
m_ay2 = m_kp1h * ( m_ay1 + ay11 ) - m_kp * m_ay2;
m_aout = m_kp1h * ( m_ay2 + ay31 ) - m_kp * m_aout;
return( tanh( m_aout * m_value ) * LB_24_VOL_ADJUST
/ ( 1.0 + m_fs->dist ) );
}
//
// PoLyBSynth
//
polyb302Synth::polyb302Synth( instrumentTrack * _track ) :
instrument( _track, &polyb302_plugin_descriptor )
{
m_vcf_cut_knob = new knob( knobBright_26, this,
tr( "VCF Cutoff Frequency" ),
_track );
m_vcf_cut_knob->setRange( 0.0f, 1.5f, 0.005f ); // Originally [0,1.0]
m_vcf_cut_knob->setInitValue( 0.75f );
m_vcf_cut_knob->move( 75, 130 );
m_vcf_cut_knob->setHintText( tr( "Cutoff Freq:" ) + " ", "" );
m_vcf_cut_knob->setLabel( tr( "CUT" ) );
m_vcf_res_knob = new knob( knobBright_26, this, tr( "VCF Resonance" ),
_track );
m_vcf_res_knob->setRange( 0.0f, 1.25f, 0.005f ); // Originally [0,1.0]
m_vcf_res_knob->setInitValue( 0.75f );
m_vcf_res_knob->move( 120, 130 );
m_vcf_res_knob->setHintText( tr( "Resonance:" ) + " ", "" );
m_vcf_res_knob->setLabel( tr( "RES" ) );
m_vcf_mod_knob = new knob( knobBright_26, this,
tr( "VCF Envelope Mod" ),
_track );
m_vcf_mod_knob->setRange( 0.0f, 1.0f, 0.005f ); // Originally [0,1.0]
m_vcf_mod_knob->setInitValue( 1.0f );
m_vcf_mod_knob->move( 165, 130 );
m_vcf_mod_knob->setHintText( tr( "Env Mod:" ) + " ", "" );
m_vcf_mod_knob->setLabel( tr( "ENV MOD" ) );
m_vcf_dec_knob = new knob( knobBright_26, this,
tr( "VCF Envelope Decay" ),
_track );
m_vcf_dec_knob->setRange( 0.0f, 1.0f, 0.005f ); // Originally [0,1.0]
m_vcf_dec_knob->setInitValue( 0.1f );
m_vcf_dec_knob->move( 210, 130 );
m_vcf_dec_knob->setHintText( tr( "Decay:" ) + " ", "" );
m_vcf_dec_knob->setLabel( tr( "DEC" ) );
// m_slideToggle = new ledCheckBox( "Slide", this, tr( "Slide" ), _track );
// m_slideToggle->move( 10, 180 );
// m_accentToggle = new ledCheckBox( "Accent", this,
// tr( "Accent" ),
// _track );
// m_accentToggle->move( 10, 200 );
// m_accentToggle->setDisabled(true);
// m_deadToggle = new ledCheckBox( "Dead", this, tr( "Dead" ), _track );
// m_deadToggle->move( 10, 220 );
m_db24Toggle = new ledCheckBox( "24dB/oct", this,
tr( "303-es-que, 24dB/octave, 3 pole filter" ),
_track );
m_db24Toggle->move( 10, 150 );
m_slide_dec_knob = new knob( knobBright_26, this, tr( "Slide Decay" ),
_track );
m_slide_dec_knob->setRange( 0.0f, 1.0f, 0.005f ); // Originally [0,1.0]
m_slide_dec_knob->setInitValue( 0.6f );
m_slide_dec_knob->move( 210, 75 );
m_slide_dec_knob->setHintText( tr( "Slide Decay:" ) + " ", "" );
m_slide_dec_knob->setLabel( tr( "SLIDE" ) );
m_vco_fine_detune_knob = new knob( knobBright_26, this,
tr( "VCO fine detuning" ),
_track );
m_vco_fine_detune_knob->setRange( -100.0f, 100.0f, 1.0f );
m_vco_fine_detune_knob->setInitValue( 0.0f );
m_vco_fine_detune_knob->move( 165, 75 );
m_vco_fine_detune_knob->setHintText( tr( "VCO Fine Detuning:" ) + " ",
"cents" );
m_vco_fine_detune_knob->setLabel( tr( "DETUNE" ) );
m_dist_knob = new knob( knobBright_26, this, tr( "Distortion" ),
_track );
m_dist_knob->setRange( 0.0f, 1.0f, 0.01f ); // Originally [0,1.0]
m_dist_knob->setInitValue( 0.0f );
m_dist_knob->move( 210, 190 );
m_dist_knob->setHintText( tr( "DIST:" ) + " ", "" );
m_dist_knob->setLabel( tr( "DIST" ) );
m_wave_knob = new knob( knobBright_26, this, tr( "Waveform" ), _track );
m_wave_knob->setRange( 0.0f, 5.0f, 1.0f ); // Originally [0,1.0]
m_wave_knob->setInitValue( 0.0f );
m_wave_knob->move( 120, 75 );
m_wave_knob->setHintText( tr( "WAVE:" ) + " ", "" );
m_wave_knob->setLabel( tr( "WAVE" ) );
setAutoFillBackground( TRUE );
QPalette pal;
pal.setBrush( backgroundRole(), PLUGIN_NAME::getIconPixmap(
"artwork" ) );
setPalette( pal );
connect( m_vcf_cut_knob, SIGNAL( valueChanged( float ) ),
this, SLOT ( filterChanged( float ) ) );
connect( m_vcf_res_knob, SIGNAL( valueChanged( float ) ),
this, SLOT ( filterChanged( float ) ) );
connect( m_vcf_mod_knob, SIGNAL( valueChanged( float ) ),
this, SLOT ( filterChanged( float ) ) );
connect( m_vcf_dec_knob, SIGNAL( valueChanged( float ) ),
this, SLOT ( filterChanged( float ) ) );
connect( m_vco_fine_detune_knob, SIGNAL( valueChanged( float ) ),
this, SLOT ( detuneChanged( float) ) );
connect( m_db24Toggle, SIGNAL( toggled( bool ) ),
this, SLOT ( db24Toggled( bool) ) );
connect( m_dist_knob, SIGNAL( valueChanged(float) ),
this, SLOT ( filterChanged( float ) ) );
connect( m_wave_knob, SIGNAL( valueChanged( float ) ),
this, SLOT ( waveChanged( float ) ) );
}
polyb302Synth::~polyb302Synth()
{
}
void polyb302Synth::saveSettings( QDomDocument & _doc, QDomElement & _this )
{
m_vcf_cut_knob->saveSettings( _doc, _this, "vcf_cut" );
m_vcf_res_knob->saveSettings( _doc, _this, "vcf_res" );
m_vcf_mod_knob->saveSettings( _doc, _this, "vcf_mod" );
m_vcf_dec_knob->saveSettings( _doc, _this, "vcf_dec" );
m_vco_fine_detune_knob->saveSettings( _doc, _this, "vco_detune" );
m_wave_knob->saveSettings( _doc, _this, "shape" );
m_dist_knob->saveSettings( _doc, _this, "dist" );
m_slide_dec_knob->saveSettings( _doc, _this, "slide_dec" );
// m_slideToggle->saveSettings( _doc, _this, "slide" );
// m_deadToggle->saveSettings( _doc, _this, "dead" );
m_db24Toggle->saveSettings( _doc, _this, "db24");
}
void polyb302Synth::loadSettings( const QDomElement & _this )
{
m_vcf_cut_knob->loadSettings( _this, "vcf_cut" );
m_vcf_res_knob->loadSettings( _this, "vcf_res" );
m_vcf_mod_knob->loadSettings( _this, "vcf_mod" );
m_vcf_dec_knob->loadSettings( _this, "vcf_dec" );
m_vco_fine_detune_knob->loadSettings( _this, "vco_detune" );
m_dist_knob->loadSettings( _this, "dist" );
m_wave_knob->loadSettings( _this, "shape" );
m_slide_dec_knob->loadSettings( _this, "slide_dec" );
// m_slideToggle->loadSettings( _this, "slide" );
// m_deadToggle->loadSettings( _this, "dead" );
m_db24Toggle->loadSettings( _this, "db24" );
}
QString polyb302Synth::nodeName( void ) const
{
return( polyb302_plugin_descriptor.name );
}
void polyb302Synth::playNote( notePlayHandle * _n, bool )
{
//int nidx = _n->index();
//if( _n->nphsOfInstrumentTrack(_n->getInstrumentTrack()).first() != _n )
//if( _n->released() && _n->nphsOfInstrumentTrack( _n->getInstrumentTrack() ).count() > 1 )
// return;
/*
if (_n->released() ) {
if( notePlayHandle::nphsOfInstrumentTrack( getInstrumentTrack() ).size() > 0
&& notePlayHandle::nphsOfInstrumentTrack( getInstrumentTrack(),
TRUE ).last() == _n )
{
return;
}
}
*/
handleState * hstate;
if( !_n->m_pluginData )
{
hstate = new handleState( this );
_n->m_pluginData = hstate;
m_handleStates.push_back( hstate );
}
else
{
hstate = (handleState *)_n->m_pluginData;
}
if( _n->totalFramesPlayed() <= hstate->m_lastFramesPlayed )
{
// TODO: Try moving to the if() below
// if( m_deadToggle->value() == 0 )
{
hstate->m_sample_cnt = 0;
hstate->m_vca_mode = 0;
hstate->m_vca_a = 0;
}
// Adjust inc on SampRate change or detuning change
hstate->m_vco_inc = hstate->m_vco_detune
/ engine::getMixer()->sampleRate();
// Initiate Slide
// TODO: Break out into function,
// should be called again on detuneChanged
if( hstate->m_vco_slideinc )
{
hstate->m_vco_slide = hstate->m_vco_inc
- hstate->m_vco_slideinc;
hstate->m_vco_slidebase = hstate->m_vco_inc;
hstate->m_vco_slideinc = 0;
}
else
{
hstate->m_vco_slide = 0;
}
// End break-out
// Slide note, save inc for next note
// if( m_slideToggle->value() )
// {
// hstate->m_vco_slideinc = hstate->m_vco_inc;
// May need to equal m_vco_slidebase+m_vco_slide if last
// note slid
// }
hstate->recalcFilter();
// if( m_deadToggle->value() == 0 )
{
// Swap next two blocks??
hstate->m_vcf->playNote();
// Ensure envelope is recalculated
hstate->m_vcf_envpos = ENVINC;
// Double Check
hstate->m_vca_mode = 0;
hstate->m_vca_a = 0.0;
}
}
const fpp_t frames = _n->framesLeftForCurrentPeriod();
sampleFrame * buf = new sampleFrame[frames];
hstate->process( buf, frames, _n->frequency() );
getInstrumentTrack()->processAudioBuffer( buf, frames, _n );
delete[] buf;
hstate->m_lastFramesPlayed = _n->totalFramesPlayed();
}
void polyb302Synth::deleteNotePluginData( notePlayHandle * _n )
{
handleState * hstate = (handleState *)_n->m_pluginData;
m_handleStates.removeAll( hstate );
delete hstate;
}
void polyb302Synth::db24Toggled( bool )
{
for( QList<handleState *>::iterator it = m_handleStates.begin();
it != m_handleStates.end(); ++it )
{
( *it )->db24Toggled();
}
}
void polyb302Synth::detuneChanged( float )
{
for( QList<handleState *>::iterator it = m_handleStates.begin();
it != m_handleStates.end(); ++it )
{
( *it )->detuneChanged();
}
}
// TODO: Split into one function per knob. envdecay doesn't require
// recalcFilter.
void polyb302Synth::filterChanged( float )
{
for( QList<handleState *>::iterator it = m_handleStates.begin();
it != m_handleStates.end(); ++it )
{
( *it )->filterChanged();
}
}
// TODO: Set m_vco_shape in here.
void polyb302Synth::waveChanged( float )
{
switch( (int)rint( m_wave_knob->value() ) )
{
case 0:
m_wave_knob->setHintText( tr( "Sawtooth " ), "" );
break;
case 1:
m_wave_knob->setHintText( tr( "Inverted Sawtooth " ),
"" );
break;
case 2:
m_wave_knob->setHintText( tr( "Triangle " ), "" );
break;
case 3:
m_wave_knob->setHintText( tr( "Square " ), "" );
break;
case 4:
m_wave_knob->setHintText( tr( "Rounded Square " ), "" );
break;
case 5:
m_wave_knob->setHintText( tr( "Moog " ), "" );
break;
}
}
polyb302Synth::handleState::handleState( const polyb302Synth * _synth )
{
m_vco_inc = 0.0;
m_vco_c = 0;
m_vco_k = 0;
m_vco_slide = 0;
m_vco_slideinc = 0;
m_fs.cutoff = 0;
m_fs.envmod = 0;
m_fs.reso = 0;
m_fs.envdecay = 0;
m_fs.dist = 0;
m_vcf_envpos = ENVINC;
m_vco_detune = 0;
// Start VCA on an attack.
m_vca_mode = 0;
m_vca_a = 0;
//m_vca_attack = 1.0 - 0.94406088;
m_vca_attack = 1.0 - 0.96406088;
m_vca_decay = 0.99897516;
m_vco_shape = SAWTOOTH;
// Experimenting between original (0.5) and 1.0
m_vca_a0 = 0.5;
if( _synth->m_db24Toggle->isChecked() )
{
m_vcf = new lb302Filter3Pole( &m_fs );
}
else
{
m_vcf = new lb302FilterIIR2( &m_fs );
}
recalcFilter();
m_lastFramesPlayed = 0;
m_synth = _synth;
filterChanged();
detuneChanged();
}
polyb302Synth::handleState::~handleState()
{
delete m_vcf;
}
void polyb302Synth::handleState::db24Toggled( void )
{
delete m_vcf;
if( m_synth->m_db24Toggle->isChecked() )
{
m_vcf = new lb302Filter3Pole( &m_fs );
}
else
{
m_vcf = new lb302FilterIIR2( &m_fs );
}
recalcFilter();
}
void polyb302Synth::handleState::detuneChanged( void )
{
m_vco_detune = powf( 2.0f,
(float)m_synth->m_vco_fine_detune_knob->value()
/ 1200.0f );
m_vco_inc = m_vco_detune / engine::getMixer()->sampleRate();
// If a slide note is pending,
if( m_vco_slideinc )
{
m_vco_slideinc = m_vco_inc;
}
// If currently sliding,
// May need to rescale m_vco_slide as well
if( m_vco_slide )
{
m_vco_slidebase = m_vco_detune
/ engine::getMixer()->sampleRate();
}
}
// TODO: Split into one function per knob. envdecay doesn't require
// recalcFilter.
void polyb302Synth::handleState::filterChanged( void )
{
m_fs.cutoff = m_synth->m_vcf_cut_knob->value();
m_fs.reso = m_synth->m_vcf_res_knob->value();
m_fs.envmod = m_synth->m_vcf_mod_knob->value();
m_fs.dist = LB_DIST_RATIO * m_synth->m_dist_knob->value();
float d = 0.2 + 2.3 * m_synth->m_vcf_dec_knob->value();
d *= engine::getMixer()->sampleRate();
// decay is 0.1 to the 1/d * ENVINC
m_fs.envdecay = pow( 0.1, ENVINC / d );
// vcf_envdecay is now adjusted for both
// sampling rate and ENVINC
recalcFilter();
}
// OBSOLETE. Break apart once we get Q_OBJECT to work. >:[
void polyb302Synth::handleState::recalcFilter( void )
{
m_vcf->recalc();
// THIS IS OLD 3pole/24dB code, I may reintegrate it. Don't need it
// right now. Should be toggled by LB_24_RES_TRICK at the moment.
/*kfcn = 2.0 * (((vcf_cutoff*3000))) / m_LB_HZ;
kp = ((-2.7528*kfcn + 3.0429)*kfcn + 1.718)*kfcn - 0.9984;
kp1 = kp+1.0;
kp1h = 0.5*kp1;
kres = (((vcf_reso))) * (((-2.7079*kp1 + 10.963)*kp1 - 14.934)*kp1 + 8.4974);
value = 1.0+( (((0))) *(1.5 + 2.0*kres*(1.0-kfcn))); // ENVMOD was DIST*/
m_vcf_envpos = ENVINC; // Trigger filter update in process()
}
void polyb302Synth::handleState::process( sampleFrame * _outbuf,
const Uint32 _size,
float _freq )
{
for( Uint32 i = 0; i < _size; i++ )
{
// update m_vcf
if( m_vcf_envpos >= ENVINC )
{
m_vcf->envRecalc();
m_vcf_envpos = 0;
if( m_vco_slide )
{
m_vco_inc = m_vco_slidebase - m_vco_slide;
// Calculate coeff from dec_knob on knob change.
// TODO: Adjust for ENVINC
m_vco_slide *= 0.9
+ ( m_synth->m_slide_dec_knob->value()
* 0.0999 );
}
}
m_sample_cnt++;
m_vcf_envpos++;
// update vco
m_vco_c += m_vco_inc * _freq;
if( m_vco_c > 0.5 )
{
m_vco_c -= 1.0;
}
switch( (int)rint( m_synth->m_wave_knob->value() ) )
{
case 0: m_vco_shape = SAWTOOTH; break;
case 1: m_vco_shape = INVERTED_SAWTOOTH; break;
case 2: m_vco_shape = TRIANGLE; break;
case 3: m_vco_shape = SQUARE; break;
case 4: m_vco_shape = ROUND_SQUARE; break;
case 5: m_vco_shape = MOOG; break;
default: m_vco_shape = SAWTOOTH; break;
}
// add m_vco_shape_param the changes the shape of each curve.
// merge sawtooths with triangle and square with round square?
switch( m_vco_shape )
{
case SAWTOOTH: // p0: curviness of line
// Is this sawtooth backwards?
m_vco_k = m_vco_c;
break;
case INVERTED_SAWTOOTH: // p0: curviness of line
// Is this sawtooth backwards?
m_vco_k = -m_vco_c;
break;
// TODO: I think TRIANGLE is broken.
// p0: duty rev.saw<->triangle<->saw p1: curviness
case TRIANGLE:
m_vco_k = m_vco_c * 2.0 + 0.5;
if( m_vco_k > 0.5 )
{
m_vco_k = 1.0 - m_vco_k;
}
break;
case SQUARE: // p0: slope of top
m_vco_k = ( m_vco_c < 0 ) ? 0.5 : -0.5;
break;
case ROUND_SQUARE: // p0: width of round
m_vco_k = ( m_vco_c < 0 ) ?
sqrtf( 1 - m_vco_c * m_vco_c * 4 )
- 0.5 :
-0.5;
break;
// Maybe the fall should be exponential/sinsoidal
// instead of quadric.
case MOOG:
// [-0.5, 0]: Rise, [0,0.25]: Slope down,
// [0.25,0.5]: Low
m_vco_k = m_vco_c * 2.0 + 0.5;
if( m_vco_k > 1.0 )
{
m_vco_k = -0.5;
}
else if( m_vco_k > 0.5 )
{
float w = 2 * ( m_vco_k - 0.5 ) - 1;
m_vco_k = 0.5 - sqrtf( 1 - w * w );
// MOOG wave gets filtered away
m_vco_k *= 2.0;
}
break;
}
// Write out samples.
#ifdef LB_FILTERED
float samp = m_vcf->process( m_vco_k ) * 2.0 * m_vca_a;
#else
float samp = m_vco_k * m_vca_a;
#endif
for( int c = 0; c < DEFAULT_CHANNELS; c++ )
{
_outbuf[i][c] = samp;
}
// Handle Envelope
// TODO: Add decay once I figure out how to extend past the end
// of a note.
if( m_vca_mode == 0 )
{
m_vca_a += ( m_vca_a0 - m_vca_a ) * m_vca_attack;
if( m_sample_cnt >= 0.5
* engine::getMixer()->sampleRate() )
{
m_vca_mode = 2;
}
}
else if( m_vca_mode == 1 )
{
m_vca_a *= m_vca_decay;
// the following line actually speeds up processing
if( m_vca_a < 1 / 65536.0 )
{
m_vca_a = 0;
m_vca_mode = 2;
}
}
}
}

View File

@@ -1,252 +0,0 @@
/*
* polyb302.h - declaration of instrument polyb302, an attempt to emulate the
* Roland TB303 bass synth
*
* Copyright (c) 2006-2007 Paul Giblock <pgib/at/users.sourceforge.net>
*
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
*
* lb302FilterIIR2 is based on the gsyn filter code by Andy Sloane.
*
* lb302Filter3Pole is based on the TB303 instrument written by
* Josep M Comajuncosas for the CSounds library
*
* 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 _POLYB302_H_
#define _POLYB302_H_
#include "effect_lib.h"
#include "instrument.h"
#include "mixer.h"
class knob;
class ledCheckBox;
class notePlayHandle;
typedef struct
{
float cutoff;
float reso;
float envmod;
float envdecay;
float dist;
} lb302FilterState;
class lb302Filter
{
public:
lb302Filter( lb302FilterState * _p_fs );
virtual ~lb302Filter() {};
virtual void recalc( void );
virtual void envRecalc( void );
virtual float process( const float & _samp ) = 0;
virtual void playNote( void );
protected:
lb302FilterState * m_fs;
// Filter Decay
float m_vcf_c0; // c0=e1 on retrigger; c0*=ed every sample; cutoff=e0+c0
float m_vcf_e0; // e0 and e1 for interpolation
float m_vcf_e1;
float m_vcf_rescoeff; // Resonance coefficient [0.30,9.54]
};
class lb302FilterIIR2 : public lb302Filter
{
public:
lb302FilterIIR2( lb302FilterState * _p_fs );
virtual ~lb302FilterIIR2();
virtual void recalc( void );
virtual void envRecalc( void );
virtual float process( const float & _samp );
protected:
float m_vcf_d1; // d1 and d2 are added back into the sample with
float m_vcf_d2; // vcf_a and b as coefficients. IIR2 resonance
// loop.
// IIR2 Coefficients for mixing dry and delay.
float m_vcf_a; // Mixing coefficients for the final sound.
float m_vcf_b;
float m_vcf_c;
effectLib::distortion<> * m_dist;
};
class lb302Filter3Pole : public lb302Filter
{
public:
lb302Filter3Pole( lb302FilterState * _p_fs );
virtual void envRecalc( void );
virtual void recalc( void );
virtual float process( const float & _samp );
protected:
float m_kfcn,
m_kp,
m_kp1,
m_kp1h,
m_kres;
float m_ay1,
m_ay2,
m_aout,
m_lastin,
m_value;
};
class polyb302Synth : public instrument
{
Q_OBJECT
public:
polyb302Synth( instrumentTrack * _track );
virtual ~polyb302Synth();
virtual void FASTCALL playNote( notePlayHandle * _n,
bool _try_parallelizing );
virtual void FASTCALL deleteNotePluginData( notePlayHandle * _n );
virtual void FASTCALL saveSettings( QDomDocument & _doc,
QDomElement & _parent );
virtual void FASTCALL loadSettings( const QDomElement & _this );
virtual QString nodeName( void ) const;
public slots:
void db24Toggled( bool );
void detuneChanged( float );
void filterChanged( float );
void waveChanged( float );
private:
class handleState
{
public:
handleState( const polyb302Synth * _synth );
virtual ~handleState();
enum vco_shape_t {
SAWTOOTH, INVERTED_SAWTOOTH, SQUARE, TRIANGLE, MOOG,
ROUND_SQUARE
};
// Oscillator
// Sample increment for the frequency. Creates Sawtooth.
float m_vco_inc;
// Raw oscillator sample [-0.5,0.5]
float m_vco_k;
// Raw oscillator sample [-0.5,0.5]
float m_vco_c;
// Current value of slide exponential curve. Nonzero=sliding
float m_vco_slide;
// Slide base to use in next node. Nonzero=slide next note
float m_vco_slideinc;
// The base vco_inc while sliding.
float m_vco_slidebase;
float m_vco_detune;
vco_shape_t m_vco_shape;
// User settings
lb302FilterState m_fs;
lb302Filter * m_vcf;
float m_lastFramesPlayed;
// More States
// Update counter. Updates when >= ENVINC
int m_vcf_envpos;
float m_vca_attack; // Amp attack
float m_vca_decay; // Amp decay
float m_vca_a0; // Initial amplifier coefficient
float m_vca_a; // Amplifier coefficient.
// Envelope State
int m_vca_mode; // 0: attack, 1: decay, 2: idle
// My hacks
int m_sample_cnt;
// TODO: split synth slots
const polyb302Synth * m_synth;
void recalcFilter( void );
void process( sampleFrame * _outbuf, const Uint32 _size,
float _freq );
void db24Toggled( void );
void detuneChanged( void );
void filterChanged( void );
} ;
knob * m_vcf_cut_knob;
knob * m_vcf_res_knob;
knob * m_vcf_dec_knob;
knob * m_vcf_mod_knob;
knob * m_vco_fine_detune_knob;
knob * m_dist_knob;
knob * m_wave_knob;
// ledCheckBox * m_slideToggle;
// ledCheckBox * m_accentToggle;
// ledCheckBox * m_deadToggle;
ledCheckBox * m_db24Toggle;
knob * m_slide_dec_knob;
QList<handleState *> m_handleStates;
} ;
#endif