diff --git a/ChangeLog b/ChangeLog index 486de7229..6bdd9366e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,27 @@ +2006-12-20 Tobias Doerffel + + * plugins/kicker/kicker.h: + * plugins/kicker/kicker.cpp: + * plugins/kicker/logo.png: + * plugins/kicker/artwork.png: + * plugins/kicker/Makefile.am: + * plugins/Makefile.am: + * configure.in: + added Kicker-plugin, a versatile kick- & bassdrum-synthesizer + + * include/sweep_oscillator.h: + added simple sweep-oscillator-class + + * include/effect_lib.h: + - added foldbackDistortion-class + - added process()-methods to monoBase- and stereoBase-class + - added bypass-classes for mono and stereo + - added effect-chaining-class + + * configure.in: + fail if -fomit-frame-pointer is found in compiler-flags and + VST-support is not disabled + 2006-12-19 Javier Serrano Polo * include/tool.h: diff --git a/Makefile.am b/Makefile.am index 8a3494938..4317c60b4 100644 --- a/Makefile.am +++ b/Makefile.am @@ -350,7 +350,8 @@ lmms_SOURCES = \ $(srcdir)/include/rack_view.h \ $(srcdir)/include/effect_select_dialog.h \ $(srcdir)/include/dummy_effect.h \ - $(srcdir)/include/ladspa-1.1.h \ + $(srcdir)/include/ladspa-1.1.h \ + $(srcdir)/include/sweep_oscillator.h \ $(srcdir)/include/meter_dialog.h \ $(srcdir)/include/qxembed.h \ $(srcdir)/include/xqmap.h diff --git a/configure.in b/configure.in index a37f87b66..cec09fe78 100644 --- a/configure.in +++ b/configure.in @@ -2,8 +2,8 @@ # Process this file with autoconf to produce a configure script. AC_PREREQ(2.50) -AC_INIT(lmms, 0.2.1-svn20061219, lmms-devel/at/lists/dot/sf/dot/net) -AM_INIT_AUTOMAKE(lmms, 0.2.1-svn20061219) +AC_INIT(lmms, 0.2.1-svn20061220, lmms-devel/at/lists/dot/sf/dot/net) +AM_INIT_AUTOMAKE(lmms, 0.2.1-svn20061220) AM_CONFIG_HEADER(config.h) @@ -32,8 +32,6 @@ if test "x$build_win32" = "xtrue" ; then AC_MSG_RESULT([Win32, will enable support for it]) AC_DEFINE(BUILD_WIN32) AC_DEFINE(WIN32) - #WIN32_DEFINES="-D_WIN32_WINNT=Windows2000" - #AC_SUBST(WIN32_DEFINES) build_linux="false" build_win32="true" else @@ -211,10 +209,13 @@ AM_CONDITIONAL(HAVE_LIBJACK, test ! -z "$HAVE_JACK_JACK_H") # check for proper WINE-installation and existing Steinberg headers AC_ARG_WITH(vst, AS_HELP_STRING([--without-vst], - [enable support for builtin VST-plugin-hosting]), , [ with_vst=yes ]) + [disable support for builtin VST-plugin-hosting]), , [ with_vst=yes ]) AH_TEMPLATE(HAVE_VST_AEFFECTX_H, [Define to 1 if you have the header file.]) if test "x$with_vst" = "xyes" ; then + if echo $CFLAGS $CXXFLAGS | grep "fomit-frame-pointer" > /dev/null ; then + AC_MSG_ERROR([*** passing -fomit-frame-pointer as compiler-flag will break LMMS' VST-support so either disable VST-support using --without-vst or remove it from compiler-flags]) + fi ORIG_CFLAGS=$CFLAGS ORIG_CPPFLAGS=$CPPFLAGS CFLAGS="$CFLAGS -I./include" @@ -557,6 +558,7 @@ AC_CONFIG_FILES([Makefile plugins/bass_booster/Makefile plugins/bit_invader/Makefile plugins/flp_import/Makefile + plugins/kicker/Makefile plugins/ladspa_base/Makefile plugins/ladspa_effect/Makefile plugins/ladspa_effect/caps/Makefile diff --git a/include/effect_lib.h b/include/effect_lib.h index a2895b5aa..56d0bdce2 100644 --- a/include/effect_lib.h +++ b/include/effect_lib.h @@ -29,31 +29,58 @@ #include "templates.h" #include "types.h" + namespace effectLib { + + template class monoBypass; + template class stereoBypass; + + template class monoBase { public: typedef SAMPLE sampleType; + typedef monoBypass bypassType; + virtual ~monoBase() { } virtual SAMPLE nextSample( const SAMPLE _in ) const = 0; + virtual void process( SAMPLE * * _buf, + const f_cnt_t _frames ) const + { + for( f_cnt_t f = 0; f < _frames; ++f ) + { + _buf[f][0] = nextSample( _buf[f][0] ); + } + } } ; template class stereoBase { public: + typedef SAMPLE sampleType; + typedef stereoBypass bypassType; + virtual ~stereoBase() { } - typedef SAMPLE sampleType; virtual void nextSample( SAMPLE & _in_left, SAMPLE & _in_right ) const = 0; + virtual void process( SAMPLE * * _buf, + const f_cnt_t _frames ) const + { + for( f_cnt_t f = 0; f < _frames; ++f ) + { + nextSample( _buf[f][0], _buf[f][1] ); + } + } } ; + template class monoToStereoAdaptor : public stereoBase { @@ -119,6 +146,69 @@ namespace effectLib } ; + template + class monoBypass : public monoBase + { + public: + virtual SAMPLE nextSample( const SAMPLE _in ) const + { + return( _in ); + } + } ; + + + template + class stereoBypass : public stereoBase + { + public: + virtual void nextSample( SAMPLE &, SAMPLE & ) const + { + } + } ; + + + /* convenient class to build up static FX-chains, for example + + using namespace effectLib; + chain >, + chain, + monoToStereoAdaptor > > > + fxchain( bassBoost<>( 60.0, 1.0, 4.0f ), + chain, + monoToStereoAdaptor > >( + stereoEnhancer<>( 1.0 ), + foldbackDistortion<>( 1.0f, 1.0f ) ) ); + + // now you can do simple calls such as which will process a bass-boost-, + // stereo-enhancer- and foldback-distortion-effect on your buffer + fx_chain.process( (sample_t * *) buf, frames ); +*/ + + template + class chain : public FX0::bypassType + { + public: + typedef typename FX0::sampleType sampleType; + chain( const FX0 & _fx0, const FX1 & _fx1 = FX1() ) : + m_FX0( _fx0 ), + m_FX1( _fx1 ) + { + } + + virtual void process( sampleType * * _buf, + const f_cnt_t _frames ) const + { + m_FX0.process( _buf, _frames ); + m_FX1.process( _buf, _frames ); + } + + private: + FX0 m_FX0; + FX1 m_FX1; + } ; + + + template inline SAMPLE saturate( const SAMPLE _x ) { @@ -184,6 +274,49 @@ namespace effectLib } ; + template + class foldbackDistortion : public monoBase + { + public: + foldbackDistortion( const float _threshold, + const float _gain ) : + m_threshold( _threshold ), + m_gain( _gain ) + { + } + + virtual SAMPLE nextSample( const SAMPLE _in ) const + { + if( _in >= m_threshold || _in < -m_threshold ) + { + return( ( fabsf( fabsf( + fmodf( _in - m_threshold, + m_threshold*4 ) ) - + m_threshold*2 ) - + m_threshold ) * + m_gain ); + } + return( _in * m_gain ); + } + + void setThreshold( const float _threshold ) + { + m_threshold = _threshold; + } + + void setGain( const float _gain ) + { + m_gain = _gain; + } + + + private: + float m_threshold; + float m_gain; + + } ; + + template class stereoEnhancer : public stereoBase { diff --git a/include/sweep_oscillator.h b/include/sweep_oscillator.h new file mode 100644 index 000000000..db128bbce --- /dev/null +++ b/include/sweep_oscillator.h @@ -0,0 +1,80 @@ +/* + * sweep_oscillator.h - sweep-oscillator + * + * Copyright (c) 2006 Tobias Doerffel + * + * 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 _SWEEP_OSCILLATOR_H +#define _SWEEP_OSCILLATOR_H + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "oscillator.h" +#include "effect_lib.h" + + +template > +class sweepOscillator +{ +public: + sweepOscillator( const FX & _fx = FX() ) : + m_phase( 0.0f ), + m_FX( _fx ) + { + } + + virtual ~sweepOscillator() + { + } + + void update( sampleFrame * _ab, const fpab_t _frames, + const float _freq1, const float _freq2, + const float _sample_rate ) + { + const float df = _freq2 - _freq1; + for( fpab_t frame = 0; frame < _frames; ++frame ) + { + sample_t s = oscillator::sinSample( m_phase ); + for( ch_cnt_t ch = 0; ch < DEFAULT_CHANNELS; ++ch ) + { + _ab[frame][ch] = s; + } + m_FX.nextSample( _ab[frame][0], _ab[frame][1] ); + m_phase += ( _freq1 + ( frame * df / _frames ) ) / + _sample_rate; + } + } + + +private: + float m_phase; + FX m_FX; + + inline sample_t getSample( const float _sample ); + inline void FASTCALL recalcPhase( void ); + +} ; + + +#endif diff --git a/plugins/Makefile.am b/plugins/Makefile.am index e6a050dc9..9d45b8285 100644 --- a/plugins/Makefile.am +++ b/plugins/Makefile.am @@ -15,6 +15,7 @@ SUBDIRS = \ bass_booster \ bit_invader \ flp_import \ + kicker \ $(LADSPA_DIRS) \ live_tool \ midi_import \ diff --git a/plugins/kicker/Makefile.am b/plugins/kicker/Makefile.am new file mode 100644 index 000000000..99d0d53c7 --- /dev/null +++ b/plugins/kicker/Makefile.am @@ -0,0 +1,33 @@ +AUTOMAKE_OPTIONS = foreign 1.4 + + +INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/src/lib -I. + + +AM_CXXFLAGS := $(AM_CXXFLAGS) $(QT_CXXFLAGS) -DPLUGIN_NAME="kicker" + + +%.moc: ./%.h + $(MOC) -o $@ $< + + +MOC_FILES = ./kicker.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= libkicker.la + +libkicker_la_SOURCES = kicker.cpp kicker.h + +$(libkicker_la_SOURCES): ./embedded_resources.h diff --git a/plugins/kicker/artwork.png b/plugins/kicker/artwork.png new file mode 100644 index 000000000..17087a79e Binary files /dev/null and b/plugins/kicker/artwork.png differ diff --git a/plugins/kicker/kicker.cpp b/plugins/kicker/kicker.cpp new file mode 100644 index 000000000..7f415b4c4 --- /dev/null +++ b/plugins/kicker/kicker.cpp @@ -0,0 +1,253 @@ +/* + * kicker.cpp - bassdrum-synthesizer + * + * Copyright (c) 2006 Tobias Doerffel + * + * 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 "qt3support.h" + +#ifdef QT4 + +#include +#include + +#else + +#include +#include + +#endif + + +#include "kicker.h" +#include "instrument_track.h" +#include "note_play_handle.h" +#include "sweep_oscillator.h" +#include "buffer_allocator.h" +#include "knob.h" + +#undef SINGLE_SOURCE_COMPILE +#include "embed.cpp" + + +extern "C" +{ + +plugin::descriptor kicker_plugin_descriptor = +{ + STRINGIFY_PLUGIN_NAME( PLUGIN_NAME ), + "Kicker", + QT_TRANSLATE_NOOP( "pluginBrowser", + "versatile kick- & bassdrum-synthesizer" ), + "Tobias Doerffel ", + 0x0100, + plugin::Instrument, + new QPixmap( PLUGIN_NAME::getIconPixmap( "logo" ) ), + NULL +} ; + +} + + +kickerInstrument::kickerInstrument( instrumentTrack * _instrument_track ) : + instrument( _instrument_track, &kicker_plugin_descriptor ) +{ + QVBoxLayout * vl = new QVBoxLayout( this ); + QHBoxLayout * hl = new QHBoxLayout; + m_startFreqKnob = new knob( knobDark_28, this, tr( "Start frequency" ), + eng(), _instrument_track ); + m_startFreqKnob->setRange( 40.0f, 1000.0f, 1.0f ); + m_startFreqKnob->setInitValue( 150.0f ); + m_startFreqKnob->setLabel( tr( "START" ) ); + m_startFreqKnob->setHintText( tr( "Start frequency:" ) + " ", "Hz" ); + + m_endFreqKnob = new knob( knobDark_28, this, tr( "End frequency" ), + eng(), _instrument_track ); + m_endFreqKnob->setRange( 40.0f, 1000.0f, 1.0f ); + m_endFreqKnob->setInitValue( 40.0f ); + m_endFreqKnob->setLabel( tr( "END" ) ); + m_endFreqKnob->setHintText( tr( "End frequency:" ) + " ", "Hz" ); + + m_decayKnob = new knob( knobDark_28, this, tr( "Decay" ), + eng(), _instrument_track ); + m_decayKnob->setRange( 5.0f, 1000.0f, 1.0f ); + m_decayKnob->setInitValue( 120.0f ); + m_decayKnob->setLabel( tr( "DECAY" ) ); + m_decayKnob->setHintText( tr( "Decay:" ) + " ", "ms" ); + + m_distKnob = new knob( knobDark_28, this, tr( "Distortion" ), + eng(), _instrument_track ); + m_distKnob->setRange( 0.00f, 0.99f, 0.01f ); + m_distKnob->setInitValue( 0.1f ); + m_distKnob->setLabel( tr( "DIST" ) ); + m_distKnob->setHintText( tr( "Distortion:" ) + " ", "" ); + + m_gainKnob = new knob( knobDark_28, this, tr( "Gain" ), + eng(), _instrument_track ); + m_gainKnob->setRange( 0.1f, 5.0f, 0.05f ); + m_gainKnob->setInitValue( 1.0f ); + m_gainKnob->setLabel( tr( "GAIN" ) ); + m_gainKnob->setHintText( tr( "Gain:" ) + " ", "" ); + + hl->addWidget( m_startFreqKnob ); + hl->addWidget( m_endFreqKnob ); + hl->addWidget( m_decayKnob ); + hl->addWidget( m_distKnob ); + hl->addWidget( m_gainKnob ); + + vl->addLayout( hl ); +#ifdef QT4 + setAutoFillBackground( TRUE ); + QPalette pal; + pal.setBrush( backgroundRole(), PLUGIN_NAME::getIconPixmap( + "artwork" ) ); + setPalette( pal ); +#else + setErasePixmap( PLUGIN_NAME::getIconPixmap( "artwork" ) ); +#endif +} + + + + +kickerInstrument::~kickerInstrument() +{ +} + + + + +void kickerInstrument::saveSettings( QDomDocument & _doc, + QDomElement & _this ) +{ + m_startFreqKnob->saveSettings( _doc, _this, "startfreq" ); + m_endFreqKnob->saveSettings( _doc, _this, "endfreq" ); + m_decayKnob->saveSettings( _doc, _this, "decay" ); + m_distKnob->saveSettings( _doc, _this, "dist" ); + m_gainKnob->saveSettings( _doc, _this, "gain" ); +} + + + + +void kickerInstrument::loadSettings( const QDomElement & _this ) +{ + m_startFreqKnob->loadSettings( _this, "startfreq" ); + m_endFreqKnob->loadSettings( _this, "endfreq" ); + m_decayKnob->loadSettings( _this, "decay" ); + m_distKnob->loadSettings( _this, "dist" ); + m_gainKnob->loadSettings( _this, "gain" ); +} + + + + +QString kickerInstrument::nodeName( void ) const +{ + return( kicker_plugin_descriptor.name ); +} + + + +typedef effectLib::foldbackDistortion<> distFX; +typedef sweepOscillator > sweepOsc; + + +void kickerInstrument::playNote( notePlayHandle * _n, bool ) +{ + const float decfr = m_decayKnob->value() * + eng()->getMixer()->sampleRate() / 1000.0f; + const f_cnt_t tfp = _n->totalFramesPlayed(); + + if ( tfp == 0 ) + { + _n->m_pluginData = new sweepOsc( + distFX( 1.0f-m_distKnob->value(), + m_gainKnob->value() ) ); + } + else if( tfp > decfr && !_n->released() ) + { + _n->noteOff(); + } + + //const float freq = getInstrumentTrack()->frequency( _n ) / 2; + const float fdiff = m_endFreqKnob->value() - m_startFreqKnob->value(); + const fpab_t frames = _n->released() ? + tMin( desiredReleaseFrames()-_n->releaseFramesDone(), + eng()->getMixer()->framesPerAudioBuffer() ) + : + eng()->getMixer()->framesPerAudioBuffer(); + const float f1 = m_startFreqKnob->value() + tfp * fdiff / decfr; + const float f2 = m_startFreqKnob->value() + (frames+tfp-1)*fdiff/decfr; + + sampleFrame * buf = bufferAllocator::alloc( frames ); + + + sweepOsc * so = static_cast( _n->m_pluginData ); + so->update( buf, frames, f1, f2, eng()->getMixer()->sampleRate() ); + + if( _n->released() ) + { + for( fpab_t f = 0; f < frames; ++f ) + { + const float fac = 1.0f - + (float)( _n->releaseFramesDone()+f ) / + desiredReleaseFrames(); + for( ch_cnt_t ch = 0; ch < DEFAULT_CHANNELS; ++ch ) + { + buf[f][ch] *= fac; + } + } + } + + getInstrumentTrack()->processAudioBuffer( buf, frames, _n ); + + bufferAllocator::free( buf ); +} + + + +void kickerInstrument::deleteNotePluginData( notePlayHandle * _n ) +{ + delete static_cast( _n->m_pluginData ); +} + + + + + + + +extern "C" +{ + +// neccessary for getting instance out of shared lib +plugin * lmms_plugin_main( void * _data ) +{ + return( new kickerInstrument( + static_cast( _data ) ) ); +} + + +} + + diff --git a/plugins/kicker/kicker.h b/plugins/kicker/kicker.h new file mode 100644 index 000000000..2d9782f2d --- /dev/null +++ b/plugins/kicker/kicker.h @@ -0,0 +1,67 @@ +/* + * kicker.h - bassdrum-synthesizer + * + * Copyright (c) 2006 Tobias Doerffel + * + * 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 _KICKER_H +#define _KICKER_H + +#include "instrument.h" + + +class notePlayHandle; +class knob; + + +class kickerInstrument : public instrument +{ +public: + kickerInstrument( instrumentTrack * _instrument_track ); + virtual ~kickerInstrument(); + + 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 f_cnt_t desiredReleaseFrames( void ) const + { + return( 512 ); + } + +private: + knob * m_startFreqKnob; + knob * m_endFreqKnob; + knob * m_decayKnob; + knob * m_distKnob; + knob * m_gainKnob; +} ; + + +#endif diff --git a/plugins/kicker/logo.png b/plugins/kicker/logo.png new file mode 100644 index 000000000..8cb2718f4 Binary files /dev/null and b/plugins/kicker/logo.png differ diff --git a/plugins/plucked_string_synth/plucked_string_synth.cpp b/plugins/plucked_string_synth/plucked_string_synth.cpp index 8b8b4db16..1791bba5d 100644 --- a/plugins/plucked_string_synth/plucked_string_synth.cpp +++ b/plugins/plucked_string_synth/plucked_string_synth.cpp @@ -69,18 +69,18 @@ plugin::descriptor pluckedstringsynth_plugin_descriptor = // TODO: make this synth stereo for better better spacial (room) feeling and // add distortion -pluckedStringSynth::pluckedStringSynth( instrumentTrack * _channel_track ) : - instrument( _channel_track, &pluckedstringsynth_plugin_descriptor ) +pluckedStringSynth::pluckedStringSynth( instrumentTrack * _instrument_track ) : + instrument( _instrument_track, &pluckedstringsynth_plugin_descriptor ) { m_pickKnob = new knob( knobDark_28, this, tr( "Pick position" ), - eng(), _channel_track ); + eng(), _instrument_track ); m_pickKnob->setRange( 0.0f, 0.5f, 0.005f ); m_pickKnob->setInitValue( 0.0f ); m_pickKnob->move( 86, 134 ); m_pickKnob->setHintText( tr( "Pick position:" ) + " ", "" ); m_pickupKnob = new knob( knobDark_28, this, tr( "Pickup position" ), - eng(), _channel_track ); + eng(), _instrument_track ); m_pickupKnob->setRange( 0.0f, 0.5f, 0.005f ); m_pickupKnob->setInitValue( 0.05f ); m_pickupKnob->move( 138, 134 ); diff --git a/plugins/plucked_string_synth/plucked_string_synth.h b/plugins/plucked_string_synth/plucked_string_synth.h index 51c27b31e..a88a0f08c 100644 --- a/plugins/plucked_string_synth/plucked_string_synth.h +++ b/plugins/plucked_string_synth/plucked_string_synth.h @@ -194,7 +194,7 @@ private: class pluckedStringSynth : public instrument { public: - pluckedStringSynth( instrumentTrack * _channel_track ); + pluckedStringSynth( instrumentTrack * _instrument_track ); virtual ~pluckedStringSynth(); virtual void FASTCALL playNote( notePlayHandle * _n,