summaryrefslogtreecommitdiffstats
path: root/arts/modules/synth
diff options
context:
space:
mode:
authortoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
committertoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
commite2de64d6f1beb9e492daf5b886e19933c1fa41dd (patch)
tree9047cf9e6b5c43878d5bf82660adae77ceee097a /arts/modules/synth
downloadtdemultimedia-e2de64d6f1beb9e492daf5b886e19933c1fa41dd.tar.gz
tdemultimedia-e2de64d6f1beb9e492daf5b886e19933c1fa41dd.zip
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923 git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdemultimedia@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'arts/modules/synth')
-rw-r--r--arts/modules/synth/Makefile.am64
-rw-r--r--arts/modules/synth/artsmodulessynth.idl301
-rw-r--r--arts/modules/synth/c_filter_stuff.c984
-rw-r--r--arts/modules/synth/c_filter_stuff.h246
-rw-r--r--arts/modules/synth/mcopclass/Synth_ATAN_SATURATE.mcopclass4
-rw-r--r--arts/modules/synth/mcopclass/Synth_AUTOPANNER.mcopclass4
-rw-r--r--arts/modules/synth/mcopclass/Synth_BRICKWALL_LIMITER.mcopclass4
-rw-r--r--arts/modules/synth/mcopclass/Synth_CAPTURE_WAV.mcopclass4
-rw-r--r--arts/modules/synth/mcopclass/Synth_CDELAY.mcopclass4
-rw-r--r--arts/modules/synth/mcopclass/Synth_COMPRESSOR.mcopclass4
-rw-r--r--arts/modules/synth/mcopclass/Synth_DATA.mcopclass4
-rw-r--r--arts/modules/synth/mcopclass/Synth_DEBUG.mcopclass4
-rw-r--r--arts/modules/synth/mcopclass/Synth_DELAY.mcopclass4
-rw-r--r--arts/modules/synth/mcopclass/Synth_DIV.mcopclass4
-rw-r--r--arts/modules/synth/mcopclass/Synth_ENVELOPE_ADSR.mcopclass4
-rw-r--r--arts/modules/synth/mcopclass/Synth_FM_SOURCE.mcopclass4
-rw-r--r--arts/modules/synth/mcopclass/Synth_FX_CFLANGER.mcopclass4
-rw-r--r--arts/modules/synth/mcopclass/Synth_MIDI_DEBUG.mcopclass4
-rw-r--r--arts/modules/synth/mcopclass/Synth_MIDI_TEST.mcopclass4
-rw-r--r--arts/modules/synth/mcopclass/Synth_MOOG_VCF.mcopclass4
-rw-r--r--arts/modules/synth/mcopclass/Synth_NIL.mcopclass4
-rw-r--r--arts/modules/synth/mcopclass/Synth_NOISE.mcopclass4
-rw-r--r--arts/modules/synth/mcopclass/Synth_OSC.mcopclass4
-rw-r--r--arts/modules/synth/mcopclass/Synth_PITCH_SHIFT.mcopclass4
-rw-r--r--arts/modules/synth/mcopclass/Synth_PITCH_SHIFT_FFT.mcopclass4
-rw-r--r--arts/modules/synth/mcopclass/Synth_PLAY_PAT.mcopclass4
-rw-r--r--arts/modules/synth/mcopclass/Synth_PSCALE.mcopclass4
-rw-r--r--arts/modules/synth/mcopclass/Synth_RC.mcopclass4
-rw-r--r--arts/modules/synth/mcopclass/Synth_SEQUENCE.mcopclass4
-rw-r--r--arts/modules/synth/mcopclass/Synth_SEQUENCE_FREQ.mcopclass4
-rw-r--r--arts/modules/synth/mcopclass/Synth_SHELVE_CUTOFF.mcopclass4
-rw-r--r--arts/modules/synth/mcopclass/Synth_STD_EQUALIZER.mcopclass4
-rw-r--r--arts/modules/synth/mcopclass/Synth_TREMOLO.mcopclass4
-rw-r--r--arts/modules/synth/mcopclass/Synth_WAVE_PULSE.mcopclass4
-rw-r--r--arts/modules/synth/mcopclass/Synth_WAVE_SOFTSAW.mcopclass4
-rw-r--r--arts/modules/synth/mcopclass/Synth_WAVE_SQUARE.mcopclass4
-rw-r--r--arts/modules/synth/mcopclass/Synth_WAVE_TRI.mcopclass4
-rw-r--r--arts/modules/synth/mcopclass/Synth_XFADE.mcopclass4
-rw-r--r--arts/modules/synth/objectcache_impl.cc73
-rw-r--r--arts/modules/synth/synth_atan_saturate_impl.cc54
-rw-r--r--arts/modules/synth/synth_autopanner_impl.cc50
-rw-r--r--arts/modules/synth/synth_brickwall_limiter_impl.cc51
-rw-r--r--arts/modules/synth/synth_capture_wav_impl.cc169
-rw-r--r--arts/modules/synth/synth_cdelay_impl.cc125
-rw-r--r--arts/modules/synth/synth_compressor_impl.cc139
-rw-r--r--arts/modules/synth/synth_data_impl.cc50
-rw-r--r--arts/modules/synth/synth_debug_impl.cc60
-rw-r--r--arts/modules/synth/synth_delay_impl.cc138
-rw-r--r--arts/modules/synth/synth_div_impl.cc45
-rw-r--r--arts/modules/synth/synth_envelope_adsr_impl.cc121
-rw-r--r--arts/modules/synth/synth_fm_source_impl.cc61
-rw-r--r--arts/modules/synth/synth_fx_cflanger_impl.cc96
-rw-r--r--arts/modules/synth/synth_midi_debug_impl.cc88
-rw-r--r--arts/modules/synth/synth_midi_test_impl.cc692
-rw-r--r--arts/modules/synth/synth_moog_vcf_impl.cc91
-rw-r--r--arts/modules/synth/synth_nil_impl.cc36
-rw-r--r--arts/modules/synth/synth_noise_impl.cc63
-rw-r--r--arts/modules/synth/synth_osc_impl.cc253
-rw-r--r--arts/modules/synth/synth_pitch_shift_fft_impl.cc431
-rw-r--r--arts/modules/synth/synth_pitch_shift_impl.cc196
-rw-r--r--arts/modules/synth/synth_play_pat_impl.cc529
-rw-r--r--arts/modules/synth/synth_pscale_impl.cc53
-rw-r--r--arts/modules/synth/synth_rc_impl.cc110
-rw-r--r--arts/modules/synth/synth_sequence_freq_impl.cc131
-rw-r--r--arts/modules/synth/synth_sequence_impl.cc132
-rw-r--r--arts/modules/synth/synth_shelve_cutoff_impl.cc71
-rw-r--r--arts/modules/synth/synth_std_equalizer_impl.cc207
-rw-r--r--arts/modules/synth/synth_tremolo_impl.cc51
-rw-r--r--arts/modules/synth/synth_wave_pulse_impl.cc52
-rw-r--r--arts/modules/synth/synth_wave_softsaw_impl.cc50
-rw-r--r--arts/modules/synth/synth_wave_square_impl.cc39
-rw-r--r--arts/modules/synth/synth_wave_tri_impl.cc39
-rw-r--r--arts/modules/synth/synth_xfade_impl.cc45
73 files changed, 6322 insertions, 0 deletions
diff --git a/arts/modules/synth/Makefile.am b/arts/modules/synth/Makefile.am
new file mode 100644
index 00000000..3995f402
--- /dev/null
+++ b/arts/modules/synth/Makefile.am
@@ -0,0 +1,64 @@
+
+INCLUDES = \
+ -I$(top_builddir)/arts/modules \
+ -I$(top_srcdir)/arts/modules \
+ -I$(top_builddir)/arts/gui/common \
+ -I$(top_builddir)/arts/midi \
+ -I$(top_builddir)/arts/runtime \
+ -I$(arts_includes) \
+ $(ARTSC_INCLUDE) $(all_includes)
+
+MCOP_INCLUDES= \
+ -I$(top_srcdir)/arts/gui/common \
+ -I$(top_srcdir)/arts/midi \
+ -I$(arts_includes)
+
+lib_LTLIBRARIES = libartsmodulessynth.la
+
+libartsmodulessynth_la_SOURCES = artsmodulessynth.cc \
+ synth_xfade_impl.cc synth_autopanner_impl.cc synth_delay_impl.cc synth_cdelay_impl.cc \
+ synth_envelope_adsr_impl.cc synth_pscale_impl.cc \
+ synth_tremolo_impl.cc synth_fx_cflanger_impl.cc synth_compressor_impl.cc \
+ synth_pitch_shift_impl.cc synth_pitch_shift_fft_impl.cc c_filter_stuff.c synth_shelve_cutoff_impl.cc synth_brickwall_limiter_impl.cc synth_std_equalizer_impl.cc synth_rc_impl.cc synth_moog_vcf_impl.cc synth_atan_saturate_impl.cc \
+ synth_fm_source_impl.cc \
+ synth_wave_tri_impl.cc synth_noise_impl.cc synth_wave_softsaw_impl.cc synth_wave_square_impl.cc synth_wave_pulse_impl.cc synth_osc_impl.cc synth_play_pat_impl.cc \
+ synth_capture_wav_impl.cc \
+ synth_midi_test_impl.cc synth_sequence_impl.cc synth_sequence_freq_impl.cc \
+ synth_midi_debug_impl.cc objectcache_impl.cc synth_nil_impl.cc synth_debug_impl.cc synth_data_impl.cc \
+ synth_div_impl.cc
+libartsmodulessynth_la_COMPILE_FIRST = artsmodulessynth.h ../../midi/artsmidi.h
+
+libartsmodulessynth_la_LIBADD = \
+ $(top_builddir)/arts/runtime/libartsbuilder.la \
+ $(top_builddir)/arts/midi/libartsmidi_idl.la \
+ -lartsflow -lartsflow_idl -lmcop
+
+#libartsmodulessynth_la_LIBADD = $(top_builddir)/arts/gui/common/libartsgui_idl.la $(top_builddir)/arts/midi/libartsmidi_idl.la -lartsflow -lartsflow_idl -lmcop $(LIBDL) $(LIB_KDEUI) $(LIB_KDECORE)
+libartsmodulessynth_la_LDFLAGS = $(all_libraries) -L$(arts_libraries) -no-undefined
+
+artsmodulessynth.cc artsmodulessynth.h artsmodulessynth.mcoptype artsmodulessynth.mcopclass: $(srcdir)/artsmodulessynth.idl $(MCOPIDL)
+ $(MCOPIDL) -t $(MCOP_INCLUDES) $(srcdir)/artsmodulessynth.idl
+
+DISTCLEANFILES= artsmodulessynth.cc artsmodulessynth.h artsmodulessynth.mcop*
+
+artsincludedir = $(includedir)/arts
+artsinclude_HEADERS = artsmodulessynth.h artsmodulessynth.idl
+
+mcoptypedir = $(libdir)/mcop
+mcoptype_DATA = artsmodulessynth.mcoptype artsmodulessynth.mcopclass
+
+mcopclassdir = $(libdir)/mcop/Arts
+mcopclass_DATA = \
+ mcopclass/Synth_XFADE.mcopclass mcopclass/Synth_AUTOPANNER.mcopclass mcopclass/Synth_DELAY.mcopclass mcopclass/Synth_CDELAY.mcopclass \
+ mcopclass/Synth_ENVELOPE_ADSR.mcopclass mcopclass/Synth_PSCALE.mcopclass \
+ mcopclass/Synth_TREMOLO.mcopclass mcopclass/Synth_FX_CFLANGER.mcopclass mcopclass/Synth_COMPRESSOR.mcopclass \
+ mcopclass/Synth_PITCH_SHIFT.mcopclass mcopclass/Synth_PITCH_SHIFT_FFT.mcopclass mcopclass/Synth_SHELVE_CUTOFF.mcopclass mcopclass/Synth_BRICKWALL_LIMITER.mcopclass mcopclass/Synth_STD_EQUALIZER.mcopclass mcopclass/Synth_RC.mcopclass mcopclass/Synth_MOOG_VCF.mcopclass mcopclass/Synth_ATAN_SATURATE.mcopclass \
+ mcopclass/Synth_FM_SOURCE.mcopclass \
+ mcopclass/Synth_WAVE_TRI.mcopclass mcopclass/Synth_NOISE.mcopclass mcopclass/Synth_WAVE_SOFTSAW.mcopclass mcopclass/Synth_WAVE_SQUARE.mcopclass mcopclass/Synth_WAVE_PULSE.mcopclass mcopclass/Synth_OSC.mcopclass mcopclass/Synth_PLAY_PAT.mcopclass \
+ mcopclass/Synth_CAPTURE_WAV.mcopclass mcopclass/Synth_DIV.mcopclass \
+ mcopclass/Synth_MIDI_TEST.mcopclass mcopclass/Synth_SEQUENCE.mcopclass \
+ mcopclass/Synth_SEQUENCE_FREQ.mcopclass \
+ mcopclass/Synth_MIDI_DEBUG.mcopclass mcopclass/Synth_DATA.mcopclass mcopclass/Synth_DEBUG.mcopclass mcopclass/Synth_NIL.mcopclass
+
+synth_midi_test_impl.lo: ../../runtime/artsbuilder.h
+
diff --git a/arts/modules/synth/artsmodulessynth.idl b/arts/modules/synth/artsmodulessynth.idl
new file mode 100644
index 00000000..5e80f3e4
--- /dev/null
+++ b/arts/modules/synth/artsmodulessynth.idl
@@ -0,0 +1,301 @@
+/*
+
+ Copyright (C) 2000-2001 Stefan Westerfeld
+ stefan@space.twc.de
+ 2001-2003 Matthias Kretz
+ kretz@kde.org
+ 2002-2003 Arnold Krille
+ arnold@arnoldarts.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+*/
+
+/*
+* DISCLAIMER: The interfaces in artsmodules.idl (and the derived .cc/.h files)
+* DO NOT GUARANTEE BINARY COMPATIBILITY YET.
+*
+* They are intended for developers. You shouldn't expect that applications in
+* binary form will be fully compatibile with further releases of these
+* interfaces.
+*/
+
+#include <artsflow.idl>
+#include <artsmidi.idl>
+
+module Arts {
+
+// Arithmetic & Mixing
+
+/**
+ * Divides two audio streams
+ */
+interface Synth_DIV : SynthModule {
+ in audio stream invalue1,invalue2;
+ out audio stream outvalue;
+ default invalue1, invalue2;
+};
+
+interface Synth_XFADE : SynthModule {
+ in audio stream invalue1,invalue2,percentage;
+ out audio stream outvalue;
+};
+
+interface Synth_AUTOPANNER : SynthModule {
+ in audio stream invalue, inlfo;
+ out audio stream outvalue1, outvalue2;
+};
+
+// Delays
+
+interface Synth_DELAY : SynthModule {
+ attribute float maxdelay;
+ in audio stream invalue, time;
+ out audio stream outvalue;
+};
+
+interface Synth_CDELAY : SynthModule {
+ attribute float time;
+ in audio stream invalue;
+ out audio stream outvalue;
+};
+
+// Envelopes
+
+interface Synth_ENVELOPE_ADSR : SynthModule {
+ in audio stream active,invalue,attack,decay,sustain,release;
+ out audio stream outvalue,done;
+};
+
+interface Synth_PSCALE : SynthModule {
+ attribute float top;
+ in audio stream invalue, pos;
+ out audio stream outvalue;
+};
+
+// Effects
+
+interface Synth_TREMOLO : SynthModule {
+ in audio stream invalue, inlfo;
+ out audio stream outvalue;
+};
+
+interface Synth_FX_CFLANGER : SynthModule {
+ attribute float mintime, maxtime;
+ in audio stream invalue, lfo;
+ out audio stream outvalue;
+};
+
+interface Synth_COMPRESSOR : SynthModule {
+ attribute float attack, release, threshold, ratio, output;
+ in audio stream invalue;
+ out audio stream outvalue;
+};
+
+// Filters
+
+interface Synth_PITCH_SHIFT : SynthModule {
+ attribute float speed, frequency;
+ in audio stream invalue;
+ out audio stream outvalue;
+};
+
+interface Synth_PITCH_SHIFT_FFT : SynthModule {
+ attribute float speed, scaleFactor;
+ attribute long frameSize, oversample;
+ in audio stream inStream;
+ out audio stream outStream;
+};
+
+interface Synth_SHELVE_CUTOFF : SynthModule {
+ in audio stream invalue,frequency;
+ out audio stream outvalue;
+};
+
+interface Synth_BRICKWALL_LIMITER : SynthModule {
+ in audio stream invalue;
+ out audio stream outvalue;
+};
+
+interface Synth_STD_EQUALIZER : SynthModule {
+ attribute float low, mid, high, frequency, q;
+ in audio stream invalue;
+ out audio stream outvalue;
+};
+
+interface Synth_RC : SynthModule {
+ attribute float b, f;
+ in audio stream invalue;
+ out audio stream outvalue;
+};
+
+interface Synth_MOOG_VCF : SynthModule {
+ attribute float frequency, resonance;
+ in audio stream invalue;
+ out audio stream outvalue;
+};
+
+interface Synth_ATAN_SATURATE : SynthModule {
+ attribute float inscale;
+ in audio stream invalue;
+ out audio stream outvalue;
+};
+
+// Midi + Sequencing
+
+interface Synth_MIDI_TEST : SynthModule, MidiPort {
+ attribute string filename;
+ attribute string busname;
+};
+
+interface Synth_SEQUENCE : SynthModule {
+ attribute float speed;
+ attribute string seq;
+ out audio stream frequency, pos;
+};
+
+interface Synth_SEQUENCE_FREQ : SynthModule {
+ attribute float speed;
+ attribute string seq;
+ out audio stream frequency, pos;
+};
+
+// Oscillation & Modulation
+
+interface Synth_FM_SOURCE : SynthModule {
+ in audio stream frequency, modulator, modlevel;
+ out audio stream pos;
+};
+
+// Waveforms
+
+interface Synth_WAVE_TRI : SynthModule {
+ in audio stream pos;
+ out audio stream outvalue;
+};
+
+interface Synth_NOISE : SynthModule {
+ out audio stream outvalue;
+};
+
+interface Synth_WAVE_SQUARE : SynthModule {
+ in audio stream pos;
+ out audio stream outvalue;
+};
+
+interface Synth_WAVE_SOFTSAW : SynthModule {
+ in audio stream pos;
+ out audio stream outvalue;
+};
+
+interface Synth_WAVE_PULSE : SynthModule {
+ attribute float dutycycle;
+ in audio stream pos;
+ out audio stream outvalue;
+};
+
+enum SynthOscWaveForm {
+ soWaveSine,
+ soWaveTriangle,
+ soWaveSawRise,
+ soWaveSawFall,
+ soWavePeakRise,
+ soWavePeakFall,
+ soWaveMoogSaw,
+ soWaveSquare,
+ soWavePulseSaw
+};
+
+interface Synth_OSC : SynthModule {
+ /* streams */
+ in audio stream infrequency, modulation, inpwm, insync;
+ out audio stream outvalue, outsync;
+
+ attribute SynthOscWaveForm waveForm;
+
+ /* FM */
+ attribute boolean fmExponential;
+ attribute float fmStrength;
+ attribute float fmSelfStrength;
+
+ /* phase, frequency, fineTune */
+ attribute float phase;
+ attribute float frequency;
+ attribute long fineTune;
+
+ /* pulse width */
+ attribute float pulseWidth;
+ attribute float pulseModStrength;
+};
+
+interface Synth_PLAY_PAT : SynthModule {
+ attribute string filename;
+ in audio stream frequency;
+ out audio stream outvalue;
+};
+
+// Others
+
+/**
+ * this interface currently has probably a problem - usually, if you are
+ * using such a module, you would expect that you can specify the filename
+ * with it - BUT, if you allow this, then any instrument definition file
+ * (.arts) and similar might overwrite every file the user can access, which
+ * might not be what you want, so I currently save it to a file in
+ * /tmp/mcop-<username>/<filename>.wav (which might be unlucky since the user
+ * might not have too much space there)
+ */
+interface Synth_CAPTURE_WAV : SynthModule {
+ attribute string filename;
+ default in audio stream left, right;
+};
+
+// Tests
+
+interface Synth_NIL : SynthModule {
+};
+
+interface Synth_DEBUG : SynthModule {
+ attribute string comment;
+ in audio stream invalue;
+};
+
+interface Synth_DATA : SynthModule {
+ attribute float value;
+ out audio stream outvalue;
+};
+
+interface Synth_MIDI_DEBUG : SynthModule, MidiPort {
+};
+
+// EXPERIMENTAL MIDI
+interface ObjectCache {
+ void put(object obj, string name);
+ object get(string name);
+};
+
+interface MidiReleaseHelper : SynthModule {
+ attribute SynthModule voice;
+ attribute string name;
+ attribute ObjectCache cache;
+
+ boolean terminate();
+ in audio stream done;
+};
+// END EXPERIMENTAL MIDI
+
+};
+
diff --git a/arts/modules/synth/c_filter_stuff.c b/arts/modules/synth/c_filter_stuff.c
new file mode 100644
index 00000000..29b0d4bb
--- /dev/null
+++ b/arts/modules/synth/c_filter_stuff.c
@@ -0,0 +1,984 @@
+ /*
+
+ Copyright (C) 1998 Juhana Sadeharju
+ kouhia at nic.funet.fi
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ */
+
+#include "c_filter_stuff.h"
+#include <math.h>
+
+
+/*-- double tan(),pow(),atan2(),sqrt(),asin(); --*/
+
+#define C_MIN16 -32768
+#define C_MAX16 32767
+
+#define SR 44100
+#define PI M_PI
+
+/*
+ * Presence and Shelve filters as given in
+ * James A. Moorer
+ * The manifold joys of conformal mapping:
+ * applications to digital filtering in the studio
+ * JAES, Vol. 31, No. 11, 1983 November
+ */
+
+/*#define SPN MINDOUBLE*/
+#define SPN 0.00001
+
+double bw2angle(a,bw)
+double a,bw;
+{
+ double T,d,sn,cs,mag,delta,theta,tmp,a2,a4,asnd;
+
+ T = tan(2.0*PI*bw);
+ a2 = a*a;
+ a4 = a2*a2;
+ d = 2.0*a2*T;
+ sn = (1.0 + a4)*T;
+ cs = (1.0 - a4);
+ mag = sqrt(sn*sn + cs*cs);
+ d /= mag;
+ delta = atan2(sn,cs);
+ asnd = asin(d);
+ theta = 0.5*(PI - asnd - delta);
+ tmp = 0.5*(asnd-delta);
+ if ((tmp > 0.0) && (tmp < theta)) theta = tmp;
+ return(theta/(2.0*PI));
+}
+
+void presence(cf,boost,bw,a0,a1,a2,b1,b2)
+double cf,boost,bw,*a0,*a1,*a2,*b1,*b2;
+{
+ double a,A,F,xfmbw,C,tmp,alphan,alphad,b0,recipb0,asq,F2,a2plus1,ma2plus1;
+
+ a = tan(PI*(cf-0.25));
+ asq = a*a;
+ A = pow(10.0,boost/20.0);
+ if ((boost < 6.0) && (boost > -6.0)) F = sqrt(A);
+ else if (A > 1.0) F = A/sqrt(2.0);
+ else F = A*sqrt(2.0);
+ xfmbw = bw2angle(a,bw);
+
+ C = 1.0/tan(2.0*PI*xfmbw);
+ F2 = F*F;
+ tmp = A*A - F2;
+ if (fabs(tmp) <= SPN) alphad = C;
+ else alphad = sqrt(C*C*(F2-1.0)/tmp);
+ alphan = A*alphad;
+
+ a2plus1 = 1.0 + asq;
+ ma2plus1 = 1.0 - asq;
+ *a0 = a2plus1 + alphan*ma2plus1;
+ *a1 = 4.0*a;
+ *a2 = a2plus1 - alphan*ma2plus1;
+
+ b0 = a2plus1 + alphad*ma2plus1;
+ *b2 = a2plus1 - alphad*ma2plus1;
+
+ recipb0 = 1.0/b0;
+ *a0 *= recipb0;
+ *a1 *= recipb0;
+ *a2 *= recipb0;
+ *b1 = *a1;
+ *b2 *= recipb0;
+}
+
+void shelve(cf,boost,a0,a1,a2,b1,b2)
+double cf,boost,*a0,*a1,*a2,*b1,*b2;
+{
+ double a,A,F,tmp,b0,recipb0,asq,F2,gamma2,siggam2,gam2p1;
+ double gamman,gammad,ta0,ta1,ta2,tb0,tb1,tb2,aa1,ab1;
+
+ a = tan(PI*(cf-0.25));
+ asq = a*a;
+ A = pow(10.0,boost/20.0);
+ if ((boost < 6.0) && (boost > -6.0)) F = sqrt(A);
+ else if (A > 1.0) F = A/sqrt(2.0);
+ else F = A*sqrt(2.0);
+
+ F2 = F*F;
+ tmp = A*A - F2;
+ if (fabs(tmp) <= SPN) gammad = 1.0;
+ else gammad = pow((F2-1.0)/tmp,0.25);
+ gamman = sqrt(A)*gammad;
+
+ gamma2 = gamman*gamman;
+ gam2p1 = 1.0 + gamma2;
+ siggam2 = 2.0*sqrt(2.0)/2.0*gamman;
+ ta0 = gam2p1 + siggam2;
+ ta1 = -2.0*(1.0 - gamma2);
+ ta2 = gam2p1 - siggam2;
+
+ gamma2 = gammad*gammad;
+ gam2p1 = 1.0 + gamma2;
+ siggam2 = 2.0*sqrt(2.0)/2.0*gammad;
+ tb0 = gam2p1 + siggam2;
+ tb1 = -2.0*(1.0 - gamma2);
+ tb2 = gam2p1 - siggam2;
+
+ aa1 = a*ta1;
+ *a0 = ta0 + aa1 + asq*ta2;
+ *a1 = 2.0*a*(ta0+ta2)+(1.0+asq)*ta1;
+ *a2 = asq*ta0 + aa1 + ta2;
+
+ ab1 = a*tb1;
+ b0 = tb0 + ab1 + asq*tb2;
+ *b1 = 2.0*a*(tb0+tb2)+(1.0+asq)*tb1;
+ *b2 = asq*tb0 + ab1 + tb2;
+
+ recipb0 = 1.0/b0;
+ *a0 *= recipb0;
+ *a1 *= recipb0;
+ *a2 *= recipb0;
+ *b1 *= recipb0;
+ *b2 *= recipb0;
+}
+
+void initfilter(filter *f)
+{
+ f->x1 = 0.0;
+ f->x2 = 0.0;
+ f->y1 = 0.0;
+ f->y2 = 0.0;
+ f->y = 0.0;
+}
+
+void setfilter_presence(f,freq,boost,bw)
+filter *f;
+double freq,boost,bw;
+{
+ presence(freq/(double)SR,boost,bw/(double)SR,
+ &f->cx,&f->cx1,&f->cx2,&f->cy1,&f->cy2);
+ f->cy1 = -f->cy1;
+ f->cy2 = -f->cy2;
+}
+
+void setfilter_shelve(filter *f, double freq, double boost)
+{
+ shelve(freq/(double)SR,boost,
+ &f->cx,&f->cx1,&f->cx2,&f->cy1,&f->cy2);
+ f->cy1 = -f->cy1;
+ f->cy2 = -f->cy2;
+}
+
+void setfilter_shelvelowpass(filter *f, double freq, double boost)
+{
+ double gain;
+
+ gain = pow(10.0,boost/20.0);
+ shelve(freq/(double)SR,boost,
+ &f->cx,&f->cx1,&f->cx2,&f->cy1,&f->cy2);
+ f->cx /= gain;
+ f->cx1 /= gain;
+ f->cx2 /= gain;
+ f->cy1 = -f->cy1;
+ f->cy2 = -f->cy2;
+}
+
+/*
+ * As in ''An introduction to digital filter theory'' by Julius O. Smith
+ * and in Moore's book; I use the normalized version in Moore's book.
+ */
+void setfilter_2polebp(f,freq,R)
+filter *f;
+double freq,R;
+{
+ double theta;
+
+ theta = 2.0*PI*freq/(double)SR;
+ f->cx = 1.0-R;
+ f->cx1 = 0.0;
+ f->cx2 = -(1.0-R)*R;
+ f->cy1 = 2.0*R*cos(theta);
+ f->cy2 = -R*R;
+}
+
+/*
+ * As in
+ * Stanley A. White
+ * Design of a digital biquadratic peaking or notch filter
+ * for digital audio equalization
+ * JAES, Vol. 34, No. 6, 1986 June
+ */
+void setfilter_peaknotch(f,freq,M,bw)
+filter *f;
+double freq,M,bw;
+{
+ double w0,om,ta,d, p=0.0 /* prevents compiler warning */;
+
+ w0 = 2.0*PI*freq;
+ if ((1.0/sqrt(2.0) < M) && (M < sqrt(2.0))) {
+ fprintf(stderr,"peaknotch filter: 1/sqrt(2) < M < sqrt(2)\n");
+ exit(-1);
+ }
+ if (M <= 1.0/sqrt(2.0)) p = sqrt(1.0-2.0*M*M);
+ if (sqrt(2.0) <= M) p = sqrt(M*M-2.0);
+ om = 2.0*PI*bw;
+ ta = tan(om/((double)SR*2.0));
+ d = p+ta;
+ f->cx = (p+M*ta)/d;
+ f->cx1 = -2.0*p*cos(w0/(double)SR)/d;
+ f->cx2 = (p-M*ta)/d;
+ f->cy1 = 2.0*p*cos(w0/(double)SR)/d;
+ f->cy2 = -(p-ta)/d;
+}
+
+/*
+ * Some JAES's article on ladder filter.
+ * freq (Hz), gdb (dB), bw (Hz)
+ */
+void setfilter_peaknotch2(f,freq,gdb,bw)
+filter *f;
+double freq,gdb,bw;
+{
+ double k,w,bwr,abw,gain;
+
+ k = pow(10.0,gdb/20.0);
+ w = 2.0*PI*freq/(double)SR;
+ bwr = 2.0*PI*bw/(double)SR;
+ abw = (1.0-tan(bwr/2.0))/(1.0+tan(bwr/2.0));
+ gain = 0.5*(1.0+k+abw-k*abw);
+ f->cx = 1.0*gain;
+ f->cx1 = gain*(-2.0*cos(w)*(1.0+abw))/(1.0+k+abw-k*abw);
+ f->cx2 = gain*(abw+k*abw+1.0-k)/(abw-k*abw+1.0+k);
+ f->cy1 = 2.0*cos(w)/(1.0+tan(bwr/2.0));
+ f->cy2 = -abw;
+}
+
+double applyfilter(f,x)
+filter *f;
+double x;
+{
+ f->x = x;
+ f->y = f->cx * f->x + f->cx1 * f->x1 + f->cx2 * f->x2
+ + f->cy1 * f->y1 + f->cy2 * f->y2;
+ f->x2 = f->x1;
+ f->x1 = f->x;
+ f->y2 = f->y1;
+ f->y1 = f->y;
+ return(f->y);
+}
+
+/*
+ * aRts doesn't need the functions below this line
+ */
+
+#if 0
+int saturate16(x)
+double x;
+{
+ if (x > 32765.0) {
+ return(32765);
+ } else if (x < -32765.0) {
+ return(-32765);
+ } else return((int)x);
+}
+
+void initdelay(d,n)
+delay *d;
+int n;
+{
+ int i;
+
+ d->len = n;
+ d->wloc = n-1;
+ d->rloc = 0;
+ d->buf = (double *)malloc(n*sizeof(double));
+ for(i = 0; i < n; i++) d->buf[i] = 0.0;
+}
+
+double readdelay(d)
+delay *d;
+{
+ double y;
+
+ y = d->buf[d->rloc];
+ d->rloc++;
+ if (d->rloc == d->len) d->rloc = 0;
+ return(y);
+}
+
+void writedelay(d,x)
+delay *d;
+double x;
+{
+ d->buf[d->wloc] = x;
+ d->wloc++;
+ if (d->wloc == d->len) d->wloc = 0;
+}
+
+void initringbufferd(rb,n)
+ringbufferd *rb;
+int n;
+{
+ int i;
+
+ rb->len = n;
+ rb->wloc = n-1;
+ rb->buf = (double *)malloc(n*sizeof(double));
+ for(i = 0; i < n; i++) rb->buf[i] = 0.0;
+}
+
+double readringbufferd(rb,n)
+ringbufferd *rb;
+int n;
+{
+ int i;
+
+ if (n >= rb->len) return(0.0);
+ i = rb->wloc - n;
+ if (i < 0) i += rb->len;
+ return(rb->buf[i]);
+}
+
+void writeringbufferd(rb,x)
+ringbufferd *rb;
+double x;
+{
+ rb->buf[rb->wloc] = x;
+ rb->wloc++;
+ if (rb->wloc == rb->len) rb->wloc = 0;
+}
+
+void initringbufferi(rb,n)
+ringbufferi *rb;
+int n;
+{
+ int i;
+
+ rb->len = n;
+ rb->wloc = n-1;
+ rb->buf = (int *)malloc(n*sizeof(int));
+ for(i = 0; i < n; i++) rb->buf[i] = 0;
+}
+
+int readringbufferi(rb,n)
+ringbufferi *rb;
+int n;
+{
+ int i;
+
+ if (n >= rb->len) return(0);
+ i = rb->wloc - n;
+ if (i < 0) i += rb->len;
+ return(rb->buf[i]);
+}
+
+void writeringbufferi(rb,x)
+ringbufferi *rb;
+int x;
+{
+ rb->buf[rb->wloc] = x;
+ rb->wloc++;
+ if (rb->wloc == rb->len) rb->wloc = 0;
+}
+
+unsigned char buffc[BUFFSIZE];
+int buffi[BUFFSIZE];
+/* int buffs[C_MAXCHANNELS][BUFFSIZE]; */
+int **buffs;
+
+
+int makenodes(n)
+int n;
+{
+ int *p;
+ int i;
+
+ p = (int *)malloc(n*sizeof(int *));
+ for(i = 0; i < n; i++) p[i] = (int)(int *)0;
+ return((int)p);
+}
+
+int makeints(n)
+int n;
+{
+ int *p;
+ int i;
+
+ p = (int *)malloc(n*sizeof(int));
+ for(i = 0; i < n; i++) p[i] = 0;
+ return((int)p);
+}
+
+/*
+
+constant memory size:
+ (i) one big malloc
+ (ii) many mallocs, upper limit in doing mallocs
+
+
+
+ */
+
+
+
+/* new routines:
+ *
+ * readbufb(n) -- read n bytes (8 bits) from stream
+ * readbufs(n) -- read n shorts (16 bits) from stream
+ * readbufi(n) -- read n ints (32 bits) from stream
+ * readbuff(n) -- read n floats (32 bits) from stream
+ *
+ * bufb2bufs() -- convert byte buffer to short buffer
+ * bufb2bufi() -- convert byte buffer to int buffer
+ * bufb2buff() -- convert byte buffer to float buffer
+ * bufs2bufb() -- convert short buffer to byte buffer
+ * bufi2bufb() -- convert int buffer to byte buffer
+ * buff2bufb() -- convert float buffer to byte buffer
+ *
+ * copychannelb() -- copy one channel from buffer to buffer
+ * copychannels() -- copy one channel from buffer to buffer
+ * copychanneli() -- copy one channel from buffer to buffer
+ * copychannelf() -- copy one channel from buffer to buffer
+ *
+ * multichannel buffers:
+ * buf[sample][channel]
+ * buf[channel][sample]
+ *
+ * multi to uni buffer
+ *
+ * reading and writing:
+ * uni buffer to sample[channel]
+ * multi buffer to sample[channel]
+ *
+ */
+/*
+int newfreadbufs(buf,n,p)
+short **buf;
+int n;
+ty_audiofile *p;
+{
+ if (n*p->afsc > BUFFSIZE) {
+ fprintf(stderr,"freadbufi: reading too many samples\n");
+ exit(-1);
+ }
+ l = readbufs(tmpbufs,n*p->afsc);
+ m = uni2multis(tmpbufs,l,p->afsc,buf);
+ return(m);
+}
+
+int newfreadbufi(buf,n,p)
+int **buf;
+int n;
+ty_audiofile *p;
+{
+ if (n*p->afsc > BUFFSIZE) {
+ fprintf(stderr,"freadbufi: reading too many samples\n");
+ exit(-1);
+ }
+ l = readbufi(tmpbufi,n*p->afsc);
+ m = uni2multii(tmpbufi,l,p->afsc,buf);
+ return(m);
+}
+
+int newfreadbuff(buf,n,p)
+float **buf;
+int n;
+ty_audiofile *p;
+{
+ if (n*p->afsc > BUFFSIZE) {
+ fprintf(stderr,"freadbufi: reading too many samples\n");
+ exit(-1);
+ }
+ l = readbuf(tmpbuff,n*p->afsc);
+ m = uni2multif(tmpbuff,l,p->afsc,buf);
+ return(m);
+}
+
+
+int newfreadbuf(buf,p)
+ty_buffer *buf;
+ty_audiofile *p;
+{
+
+}
+
+*/
+
+/*
+ * freadbuf() reads next n samples from the file; one sample may have
+ * several channels.
+ * Return value is the number of the samples read.
+ */
+
+int freadbuf(buf,n,p)
+int **buf;
+int n;
+ty_audiofile *p;
+{
+ int h,i,j,k,l,s;
+ unsigned int us;
+
+ if (n > BUFFSIZE) {
+ fprintf(stderr,"freadbuf reading too many samples\n");
+ exit(-1);
+ }
+ if (p->afstype == C_INTTYPE) {
+ h = 0;
+ for(j = 0; j < p->afsc; j++) {
+ l = fread(buffi,sizeof(int),n,p->affp);
+ for(i = 0; i < l; i += p->afsc) {
+ for(k = 0; k < p->afsc; k++) buf[k][h] = buffi[i+k];
+ h++;
+ }
+ }
+ } else if (p->afstype == C_FLOATTYPE) {
+ h = 0;
+ for(j = 0; j < p->afsc; j++) {
+ l = fread((float *)buffi,sizeof(float),n,p->affp);
+ for(i = 0; i < l; i += p->afsc) {
+ for(k = 0; k < p->afsc; k++) buf[k][h] = buffi[i+k];
+ h++;
+ }
+ }
+ } else {
+ h = 0;
+ for(j = 0; j < 2*p->afsc; j++) {
+ l = fread(buffc,sizeof(unsigned char),n,p->affp);
+ for(i = 0; i < l; i += 2*p->afsc) {
+ for(k = 0; k < p->afsc; k++) {
+ if (p->afstype == C_CDASBTYPE)
+ us = buffc[i+1+2*k] + (buffc[i+2*k]<<8);
+ else
+ us = buffc[i+2*k] + (buffc[i+1+2*k]<<8);
+ us = us<<16;
+ s = ((signed int)us)>>16;
+ buf[k][h] = s;
+ }
+ h++;
+ }
+ }
+ }
+ return(h);
+}
+
+
+int fwritebuf(buf,n,p)
+int **buf;
+int n;
+ty_audiofile *p;
+{
+ int h,i,j,k,l,s;
+ unsigned int us1,us2;
+
+ if (p->afstype == C_INTTYPE) {
+ h = 0;
+ for(i = 0; i < n; i++) {
+ for(k = 0; k < p->afsc; k++) {
+ buffi[h] = buf[k][i];
+ h++;
+ }
+ if (h == BUFFSIZE) {
+ l = fwrite(buffi,sizeof(int),h,p->affp);
+ if (l != h) {
+ fprintf(stderr,"fwritebuf() error\n");
+ exit(-1);
+ }
+ h = 0;
+ }
+ }
+ l = fwrite(buffi,sizeof(int),h,p->affp);
+ if (l != h) {
+ fprintf(stderr,"fwritebuf() error\n");
+ exit(-1);
+ }
+ } else {
+ h = 0;
+ for(i = 0; i < n; i++) {
+ for(k = 0; k < p->afsc; k++) {
+ s = buf[k][i];
+ if (s > C_MAX16) s = C_MAX16;
+ else if (s < C_MIN16) s = C_MIN16;
+ us1 = ((unsigned int)s)&0x000000ff;
+ us2 = (((unsigned int)s)&0x0000ff00)>>8;
+ if (p->afstype == C_CDASBTYPE) {
+ buffc[h] = (unsigned char)us2;
+ h++;
+ buffc[h] = (unsigned char)us1;
+ h++;
+ } else {
+ buffc[h] = (unsigned char)us1;
+ h++;
+ buffc[h] = (unsigned char)us2;
+ h++;
+ }
+ }
+ if (h == BUFFSIZE) {
+ l = fwrite(buffc,sizeof(unsigned char),h,p->affp);
+ if (l != h) {
+ fprintf(stderr,"fwritebuf() error\n");
+ exit(-1);
+ }
+ h = 0;
+ }
+ }
+ l = fwrite(buffc,sizeof(unsigned char),h,p->affp);
+ if (l != h) {
+ fprintf(stderr,"fwritebuf() error\n");
+ exit(-1);
+ }
+ }
+ return(n);
+}
+
+
+ty_audiofile *initaf(afm,afn,aft)
+ty_afmethod *afm;
+ty_afname *afn;
+ty_aftype *aft;
+{
+ ty_audiofile *p;
+ int i,j,k,n,s;
+ unsigned int us;
+ FILE *fp;
+
+ p = (ty_audiofile *)malloc(sizeof(ty_audiofile));
+ p->afmethod = afm->method;
+ p->afname = afn->filename;
+ p->affd = afn->fd;
+ p->afsr = aft->sr;
+ p->afsc = aft->sc;
+ p->afstype = aft->stype;
+ p->buflen = afm->buflen;
+
+ switch(p->afmethod) {
+ case C_FLOWOUTMETHOD:
+ if (p->affd == STDOUT_FILENO) {
+ fp = stdout;
+ p->afname = "stdout";
+ } else {
+ if ((fp = fopen(p->afname,"w")) == (FILE *)NULL) {
+ fprintf(stderr,"could not open file %s\n",p->afname);
+ exit(-1);
+ }
+ }
+ p->affp = fp;
+ p->buflen = BUFFSIZE;
+ p->buf = (int **)malloc(p->afsc*sizeof(int *));
+ for(i = 0; i < p->afsc; i++)
+ p->buf[i] = (int *)malloc(p->buflen*sizeof(int));
+ p->bloc = 0;
+ break;
+ case C_RBMETHOD:
+ if (p->affd == STDIN_FILENO) {
+ fp = stdin;
+ p->afname = "stdin";
+ } else {
+ if ((fp = fopen(p->afname,"r")) == (FILE *)NULL) {
+ fprintf(stderr,"could not open file %s\n",p->afname);
+ exit(-1);
+ }
+ }
+ p->affp = fp;
+ p->buf = (int **)malloc(p->afsc*sizeof(int *));
+ for(i = 0; i < p->afsc; i++)
+ p->buf[i] = (int *)malloc(p->buflen*sizeof(int));
+ n = freadbuf(p->buf,MINBUFFSIZE,p);
+ if (n != MINBUFFSIZE) {
+ fprintf(stderr,"could not read file %s\n",p->afname);
+ fprintf(stderr,"%i\n",n);
+ exit(-1);
+ }
+ p->bloc = 0;
+ p->eloc = n-1;
+ p->rbbtime = 0;
+ p->rbetime = n-1;
+ break;
+ case C_AIMROMETHOD:
+ p->buf = (int **)malloc(p->afsc*sizeof(int *));
+ if ((fp = fopen(p->afname,"r")) == (FILE *)NULL) {
+ fprintf(stderr,"could not open file %s\n",p->afname);
+ exit(-1);
+ }
+ (void)fseek(fp,(long)0,SEEK_END);
+ p->buflen = ftell(fp)/p->afsc;
+ fclose(fp);
+ switch(p->afstype) {
+ case C_CDATYPE:
+ p->buflen /= 2;
+ break;
+ case C_CDASBTYPE:
+ p->buflen /= 2;
+ break;
+ case C_INTTYPE:
+ p->buflen /= sizeof(int);
+ break;
+ }
+ for(i = 0; i < p->afsc; i++)
+ p->buf[i] = (int *)malloc(p->buflen*sizeof(int));
+
+ if ((fp = fopen(p->afname,"r")) == (FILE *)NULL) {
+ fprintf(stderr,"could not open file %s\n",p->afname);
+ exit(-1);
+ }
+ p->affp = fp;
+ j = 0;
+ while ((n = freadbuf(buffs,BUFFSIZE,p)) != 0) {
+ for(i = 0; i < n; i++,j++) {
+ for(k = 0; k < p->afsc; k++) p->buf[k][j] = buffs[k][i];
+ }
+ }
+ fclose(fp);
+ break;
+ }
+ return(p);
+}
+
+
+void bye()
+{
+ ty_audiofile *p;
+ int i,l;
+
+ for(i = 0; i < C_MAXAUDIOFILES; i++) {
+ p = gaf[i];
+ if (p != (ty_audiofile *)0) {
+ switch(p->afmethod) {
+ case C_FLOWOUTMETHOD:
+ l = fwritebuf(p->buf,p->bloc,p);
+ if (l != p->bloc) {
+ fprintf(stderr,"could not write to %s\n",p->afname);
+ exit(-1);
+ }
+ fclose(p->affp);
+ break;
+ case C_RBMETHOD:
+ fclose(p->affp);
+ break;
+ }
+ }
+ }
+}
+
+
+ty_sample *makesample(sc)
+int sc;
+{
+ ty_sample *p;
+
+ p = (ty_sample *)malloc(sizeof(ty_sample));
+ p->sc = sc;
+ return(p);
+}
+
+
+int readsample(p,n,s)
+ty_audiofile *p;
+int n;
+ty_sample *s;
+{
+ int i,j,k,dt,l;
+ FILE *fp;
+ ty_sample *out;
+
+ /*
+ out = makesample(p->afsc);
+ / * out->time = n; * /
+ */
+
+ out = s;
+
+ switch(p->afmethod) {
+ case C_RBMETHOD:
+ for(;;) {
+ if ((p->rbbtime <= n) && (n <= p->rbetime)) {
+ dt = n - p->rbbtime;
+ l = p->bloc + dt;
+ if (l >= p->buflen) l -= p->buflen;
+ for(i = 0; i < p->afsc; i++) out->buf[i] = p->buf[i][l];
+ return(TRUE);
+ } else {
+ if (n < p->rbbtime) {
+ fprintf(stderr,"n = %i\n",n);
+ fprintf(stderr,"ring buffer has dropped this sample already\n");
+ exit(-1);
+ }
+ l = freadbuf(buffs,BUFFSIZE,p);
+ if (l == 0) return(FALSE);
+ for(i = 0; i < l; i++) {
+ p->eloc++;
+ if (p->eloc >= p->buflen) p->eloc -= p->buflen;
+ p->rbetime++;
+ if (p->eloc == p->bloc) {
+ p->bloc++;
+ if (p->bloc >= p->buflen) p->bloc -= p->buflen;
+ p->rbbtime++;
+ }
+ for(j = 0; j < p->afsc; j++) {
+ p->buf[j][p->eloc] = buffs[j][i];
+ }
+ }
+ }
+ }
+ break;
+ case C_AIMROMETHOD:
+ if ((n < 0) || (n >= p->buflen)) return(FALSE);
+ for(i = 0; i < p->afsc; i++) out->buf[i] = p->buf[i][n];
+ return(TRUE);
+ break;
+ }
+
+}
+
+
+int writesample(p,n,s)
+ty_audiofile *p;
+int n;
+ty_sample *s;
+{
+ int i,j,k,dt,l;
+ FILE *fp;
+ ty_sample *out;
+
+ switch(p->afmethod) {
+ case C_FLOWOUTMETHOD:
+ for(i = 0; i < p->afsc; i++) p->buf[i][p->bloc] = s->buf[i];
+ p->bloc++;
+ if (p->bloc == p->buflen) {
+ p->bloc = 0;
+ l = fwritebuf(p->buf,p->buflen,p);
+ if (l != p->buflen) {
+ fprintf(stderr,"could not write to %s\n",p->afname);
+ exit(-1);
+ }
+ }
+ break;
+ case C_AIMRWMETHOD:
+ if ((n < 0) || (n >= p->buflen)) return(FALSE);
+ for(i = 0; i < p->afsc; i++) p->buf[i][n] = s->buf[i];
+ break;
+ }
+ return(TRUE);
+}
+
+ty_afmethod *afmethod_flowout()
+{
+ ty_afmethod *p;
+
+ p = (ty_afmethod *)malloc(sizeof(ty_afmethod));
+ p->method = C_FLOWOUTMETHOD;
+ return(p);
+}
+
+ty_afmethod *afmethod_rb(n)
+int n;
+{
+ ty_afmethod *p;
+
+ if (n <= BUFFSIZE) {
+ fprintf(stderr,"RB buffer size should be greater than BUFFSIZE\n");
+ exit(-1);
+ }
+ p = (ty_afmethod *)malloc(sizeof(ty_afmethod));
+ p->method = C_RBMETHOD;
+ p->buflen = n;
+ return(p);
+}
+
+ty_afmethod *afmethod_aimro()
+{
+ ty_afmethod *p;
+
+ p = (ty_afmethod *)malloc(sizeof(ty_afmethod));
+ p->method = C_AIMROMETHOD;
+ return(p);
+}
+
+ty_afname *afname(s)
+char *s;
+{
+ ty_afname *p;
+
+ p = (ty_afname *)malloc(sizeof(ty_afname));
+ p->filename = strdup(s);
+ p->fd = -1;
+ return(p);
+}
+
+/* stdin and stdout could have their own read and write routines
+ * but this could be a second solution
+ */
+ty_afname *afname_stdin()
+{
+ ty_afname *p;
+
+ p = (ty_afname *)malloc(sizeof(ty_afname));
+ p->filename = (char *)0;
+ p->fd = STDIN_FILENO;
+ return(p);
+}
+
+ty_afname *afname_stdout()
+{
+ ty_afname *p;
+
+ p = (ty_afname *)malloc(sizeof(ty_afname));
+ p->filename = (char *)0;
+ p->fd = STDOUT_FILENO;
+ return(p);
+}
+
+ty_aftype *aftype(sr,sc,stype)
+int sr,sc,stype;
+{
+ ty_aftype *p;
+
+ p = (ty_aftype *)malloc(sizeof(ty_aftype));
+ p->sr = sr;
+ p->sc = sc;
+ p->stype = stype;
+ return(p);
+}
+
+ty_aftype *aftype_defstereo()
+{
+ return(aftype(44100,2,C_CDATYPE));
+}
+
+
+ty_audiofile *initaf_aimdefstereo(filename)
+char *filename;
+{
+ return(initaf(afmethod_aimro(),afname(filename),aftype_defstereo()));
+}
+
+
+ty_audiofile *initaf_stdin()
+{
+ return(initaf(afmethod_rb(C_RBBUFSIZE),afname_stdin(),aftype_defstereo()));
+}
+
+void init()
+{
+ int i;
+
+ for(i = 0; i < C_MAXAUDIOFILES; i++) {
+ gaf[i] = (ty_audiofile *)0;
+ }
+
+ buffs = (int **)malloc(C_MAXCHANNELS*sizeof(int *));
+ for(i = 0; i < C_MAXCHANNELS; i++)
+ buffs[i] = (int *)malloc(BUFFSIZE*sizeof(int));
+
+}
+
+
+#endif
diff --git a/arts/modules/synth/c_filter_stuff.h b/arts/modules/synth/c_filter_stuff.h
new file mode 100644
index 00000000..ca7ef385
--- /dev/null
+++ b/arts/modules/synth/c_filter_stuff.h
@@ -0,0 +1,246 @@
+ /*
+
+ Copyright (C) 1998 Juhana Sadeharju
+ kouhia at nic.funet.fi
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ */
+
+#ifndef C_FILTER_STUFF_H
+#define C_FILTER_STUFF_H
+
+#include <stdio.h>
+#include <math.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct {
+ double cx,cx1,cx2,cy1,cy2;
+ double x,x1,x2,y,y1,y2;
+} filter;
+
+void presence();
+void shelve();
+void initfilter(filter *f);
+void setfilter_presence();
+void setfilter_shelve(filter *f, double freq, double boost);
+void setfilter_shelvelowpass(filter *f, double freq, double boost);
+void setfilter_2polebp();
+void setfilter_peaknotch();
+void setfilter_peaknotch2();
+double applyfilter();
+
+#ifdef __cplusplus
+}
+#endif
+
+/*
+ * aRts doesn't need the flow stuff that's in music_orig.c - just the filters
+ */
+#if 0
+
+#define STRBUFSIZE 200
+#define TRUE 1
+#define FALSE 0
+
+/* must be divisible by 6 and 8
+ * max 2 items (ints or bytes) per sample value, 3 or 4 channels */
+#define MINBUFFSIZE 2*3*4
+#define BUFFSIZE 512*MINBUFFSIZE
+
+#define C_RBBUFSIZE 10*44100
+#define C_MAXCHANNELS 4
+
+/*
+ * afmethod = 0, ring buffer
+ * 1, swap ro bufs
+ * 2, swap rw bufs
+ * 3, all in memory ro
+ * 4, all in memory rw
+ * afname = filename for the audio file;
+ * in case of multipart file, the filenames are <filename>.aa, etc.
+ * affd = file descriptor number, if it is preset to be STDIN_FILENO or
+ * STDOUT_FILENO, then the filename has no effect, otherwise affd
+ * is set at the init time if afmethod == 0
+ * afsr = samplerate
+ * afsc = samplechannels
+ * afstype = 0, 16 bit (standard CDA format)
+ * 1, direct copy of int variable
+ * noofbufs = number of swap buffers
+ * buflen = length of swap buffers
+ * realbuflen = length of swap buffers with respect to the data;
+ * different from buflen only if content is load from
+ * the end of audiofile
+ * btime = time of the first sample in buffers
+ * etime = time of the last sample in buffers
+ *
+ * **buf and ***bufs since one array is for one channel
+ */
+
+typedef struct {
+ int afmethod;
+ char *afname;
+ FILE *affp;
+ int affd;
+ int afsr;
+ int afsc;
+ int afstype;
+ int buflen;
+ /* ring buffer
+ * int buflen;
+ */
+ int **buf;
+ int bloc;
+ int eloc;
+ int rbbtime;
+ int rbetime;
+ /* swap buffers
+ * int buflen;
+ */
+ int ***bufs;
+ int noofbufs;
+ int *realbuflen;
+ int *btime;
+ int *etime;
+ int bufupdatemethod;
+ /* all in memory
+ * int buflen;
+ * int *buf;
+ */
+ /* buffer updating method info */
+ int *modifiedbuf;
+ int *bufpri;
+ int npri;
+ int cpri;
+} ty_audiofile;
+
+/*
+ * Priority entries are numbered 0,1,2,... no two same number
+ * in two buffers. The buffer which will be swapped is the buffer
+ * with highest priority (i.e. nobufs-1). When a buffer is swapped,
+ * the priority is set to 1 and priorities of all other buffers are
+ * lowered down by one.
+ * When a sample is read, the priorities are set for each Nth read.
+ */
+
+typedef struct {
+ int method;
+ int noofbufs;
+ int buflen;
+} ty_afmethod;
+
+#define C_FLOWOUTMETHOD 0
+#define C_RBMETHOD 1
+#define C_SWAPROMETHOD 2
+#define C_SWAPRWMETHOD 3
+#define C_AIMROMETHOD 4
+#define C_AIMRWMETHOD 5
+
+typedef struct {
+ char *filename;
+ int fd;
+} ty_afname;
+
+typedef struct {
+ int sr;
+ int sc;
+ int stype;
+} ty_aftype;
+
+#define C_CDATYPE 0
+#define C_CDASBTYPE 1 /* swap bytes */
+#define C_INTTYPE 2
+#define C_FLOATTYPE 3
+
+typedef struct {
+ int sc;
+ int time;
+ int buf[C_MAXCHANNELS];
+} ty_sample;
+
+#define C_MAXAUDIOFILES 20
+
+typedef struct {
+ int len;
+ int rloc,wloc;
+ double *buf;
+} delay;
+
+typedef struct {
+ int len;
+ int wloc;
+ double *buf;
+} ringbufferd;
+
+typedef struct {
+ int len;
+ int wloc;
+ int *buf;
+} ringbufferi;
+
+typedef struct {
+ int n;
+ double gain;
+ filter f;
+} rbreaddev;
+
+
+ty_audiofile *gaf[C_MAXAUDIOFILES];
+
+int makenodes();
+int makeints();
+/*
+int freadbuf();
+int fwritebuf();
+*/
+ty_audiofile *initaf();
+void bye();
+ty_sample *makesample();
+int readsample();
+int writesample();
+ty_afmethod *afmethod_flowout();
+ty_afmethod *afmethod_rb();
+ty_afmethod *afmethod_aimro();
+ty_afname *afname();
+ty_afname *afname_stdin();
+ty_afname *afname_stdout();
+ty_aftype *aftype();
+ty_aftype *aftype_defstereo();
+ty_audiofile *initaf_aimdefstereo();
+ty_audiofile *initaf_stdin();
+void init();
+int saturate16();
+void initdelay();
+double readdelay();
+void writedelay();
+void initringbufferd();
+double readringbufferd();
+void writeringbufferd();
+void initringbufferi();
+int readringbufferi();
+void writeringbufferi();
+#endif
+
+#endif // C_FILTER_STUFF_H
+
diff --git a/arts/modules/synth/mcopclass/Synth_ATAN_SATURATE.mcopclass b/arts/modules/synth/mcopclass/Synth_ATAN_SATURATE.mcopclass
new file mode 100644
index 00000000..d714659a
--- /dev/null
+++ b/arts/modules/synth/mcopclass/Synth_ATAN_SATURATE.mcopclass
@@ -0,0 +1,4 @@
+Buildable=true
+Interface=Arts::Synth_ATAN_SATURATE,Arts::SynthModule,Arts::Object
+Language=C++
+Library=libartsmodulessynth.la
diff --git a/arts/modules/synth/mcopclass/Synth_AUTOPANNER.mcopclass b/arts/modules/synth/mcopclass/Synth_AUTOPANNER.mcopclass
new file mode 100644
index 00000000..a4af2832
--- /dev/null
+++ b/arts/modules/synth/mcopclass/Synth_AUTOPANNER.mcopclass
@@ -0,0 +1,4 @@
+Buildable=true
+Interface=Arts::Synth_AUTOPANNER,Arts::SynthModule,Arts::Object
+Language=C++
+Library=libartsmodulessynth.la
diff --git a/arts/modules/synth/mcopclass/Synth_BRICKWALL_LIMITER.mcopclass b/arts/modules/synth/mcopclass/Synth_BRICKWALL_LIMITER.mcopclass
new file mode 100644
index 00000000..a1204038
--- /dev/null
+++ b/arts/modules/synth/mcopclass/Synth_BRICKWALL_LIMITER.mcopclass
@@ -0,0 +1,4 @@
+Buildable=true
+Interface=Arts::Synth_BRICKWALL_LIMITER,Arts::SynthModule,Arts::Object
+Language=C++
+Library=libartsmodulessynth.la
diff --git a/arts/modules/synth/mcopclass/Synth_CAPTURE_WAV.mcopclass b/arts/modules/synth/mcopclass/Synth_CAPTURE_WAV.mcopclass
new file mode 100644
index 00000000..b2e6a6aa
--- /dev/null
+++ b/arts/modules/synth/mcopclass/Synth_CAPTURE_WAV.mcopclass
@@ -0,0 +1,4 @@
+Buildable=true
+Interface=Arts::Synth_CAPTURE_WAV,Arts::SynthModule,Arts::Object
+Language=C++
+Library=libartsmodulessynth.la
diff --git a/arts/modules/synth/mcopclass/Synth_CDELAY.mcopclass b/arts/modules/synth/mcopclass/Synth_CDELAY.mcopclass
new file mode 100644
index 00000000..da344bb5
--- /dev/null
+++ b/arts/modules/synth/mcopclass/Synth_CDELAY.mcopclass
@@ -0,0 +1,4 @@
+Buildable=true
+Interface=Arts::Synth_CDELAY,Arts::SynthModule,Arts::Object
+Language=C++
+Library=libartsmodulessynth.la
diff --git a/arts/modules/synth/mcopclass/Synth_COMPRESSOR.mcopclass b/arts/modules/synth/mcopclass/Synth_COMPRESSOR.mcopclass
new file mode 100644
index 00000000..7611908a
--- /dev/null
+++ b/arts/modules/synth/mcopclass/Synth_COMPRESSOR.mcopclass
@@ -0,0 +1,4 @@
+Buildable=true
+Interface=Arts::Synth_COMPRESSOR,Arts::SynthModule,Arts::Object
+Language=C++
+Library=libartsmodulessynth.la
diff --git a/arts/modules/synth/mcopclass/Synth_DATA.mcopclass b/arts/modules/synth/mcopclass/Synth_DATA.mcopclass
new file mode 100644
index 00000000..bbff2ac1
--- /dev/null
+++ b/arts/modules/synth/mcopclass/Synth_DATA.mcopclass
@@ -0,0 +1,4 @@
+Buildable=true
+Interface=Arts::Synth_DATA,Arts::SynthModule,Arts::Object
+Language=C++
+Library=libartsmodulessynth.la
diff --git a/arts/modules/synth/mcopclass/Synth_DEBUG.mcopclass b/arts/modules/synth/mcopclass/Synth_DEBUG.mcopclass
new file mode 100644
index 00000000..52615982
--- /dev/null
+++ b/arts/modules/synth/mcopclass/Synth_DEBUG.mcopclass
@@ -0,0 +1,4 @@
+Buildable=true
+Interface=Arts::Synth_DEBUG,Arts::SynthModule,Arts::Object
+Language=C++
+Library=libartsmodulessynth.la
diff --git a/arts/modules/synth/mcopclass/Synth_DELAY.mcopclass b/arts/modules/synth/mcopclass/Synth_DELAY.mcopclass
new file mode 100644
index 00000000..0651df87
--- /dev/null
+++ b/arts/modules/synth/mcopclass/Synth_DELAY.mcopclass
@@ -0,0 +1,4 @@
+Buildable=true
+Interface=Arts::Synth_DELAY,Arts::SynthModule,Arts::Object
+Language=C++
+Library=libartsmodulessynth.la
diff --git a/arts/modules/synth/mcopclass/Synth_DIV.mcopclass b/arts/modules/synth/mcopclass/Synth_DIV.mcopclass
new file mode 100644
index 00000000..0a2a3eec
--- /dev/null
+++ b/arts/modules/synth/mcopclass/Synth_DIV.mcopclass
@@ -0,0 +1,4 @@
+Buildable=true
+Interface=Arts::Synth_DIV,Arts::SynthModule,Arts::Object
+Language=C++
+Library=libartsmodulessynth.la
diff --git a/arts/modules/synth/mcopclass/Synth_ENVELOPE_ADSR.mcopclass b/arts/modules/synth/mcopclass/Synth_ENVELOPE_ADSR.mcopclass
new file mode 100644
index 00000000..eab45052
--- /dev/null
+++ b/arts/modules/synth/mcopclass/Synth_ENVELOPE_ADSR.mcopclass
@@ -0,0 +1,4 @@
+Buildable=true
+Interface=Arts::Synth_ENVELOPE_ADSR,Arts::SynthModule,Arts::Object
+Language=C++
+Library=libartsmodulessynth.la
diff --git a/arts/modules/synth/mcopclass/Synth_FM_SOURCE.mcopclass b/arts/modules/synth/mcopclass/Synth_FM_SOURCE.mcopclass
new file mode 100644
index 00000000..49fce727
--- /dev/null
+++ b/arts/modules/synth/mcopclass/Synth_FM_SOURCE.mcopclass
@@ -0,0 +1,4 @@
+Buildable=true
+Interface=Arts::Synth_FM_SOURCE,Arts::SynthModule,Arts::Object
+Language=C++
+Library=libartsmodulessynth.la
diff --git a/arts/modules/synth/mcopclass/Synth_FX_CFLANGER.mcopclass b/arts/modules/synth/mcopclass/Synth_FX_CFLANGER.mcopclass
new file mode 100644
index 00000000..cf7519c8
--- /dev/null
+++ b/arts/modules/synth/mcopclass/Synth_FX_CFLANGER.mcopclass
@@ -0,0 +1,4 @@
+Buildable=true
+Interface=Arts::Synth_FX_CFLANGER,Arts::SynthModule,Arts::Object
+Language=C++
+Library=libartsmodulessynth.la
diff --git a/arts/modules/synth/mcopclass/Synth_MIDI_DEBUG.mcopclass b/arts/modules/synth/mcopclass/Synth_MIDI_DEBUG.mcopclass
new file mode 100644
index 00000000..b9f03597
--- /dev/null
+++ b/arts/modules/synth/mcopclass/Synth_MIDI_DEBUG.mcopclass
@@ -0,0 +1,4 @@
+Buildable=true
+Interface=Arts::Synth_MIDI_DEBUG,Arts::MidiPort,Arts::SynthModule,Arts::Object
+Language=C++
+Library=libartsmodulessynth.la
diff --git a/arts/modules/synth/mcopclass/Synth_MIDI_TEST.mcopclass b/arts/modules/synth/mcopclass/Synth_MIDI_TEST.mcopclass
new file mode 100644
index 00000000..80ea8661
--- /dev/null
+++ b/arts/modules/synth/mcopclass/Synth_MIDI_TEST.mcopclass
@@ -0,0 +1,4 @@
+Buildable=true
+Interface=Arts::Synth_MIDI_TEST,Arts::MidiPort,Arts::SynthModule,Arts::Object
+Language=C++
+Library=libartsmodulessynth.la
diff --git a/arts/modules/synth/mcopclass/Synth_MOOG_VCF.mcopclass b/arts/modules/synth/mcopclass/Synth_MOOG_VCF.mcopclass
new file mode 100644
index 00000000..92e572b5
--- /dev/null
+++ b/arts/modules/synth/mcopclass/Synth_MOOG_VCF.mcopclass
@@ -0,0 +1,4 @@
+Buildable=true
+Interface=Arts::Synth_MOOG_VCF,Arts::SynthModule,Arts::Object
+Language=C++
+Library=libartsmodulessynth.la
diff --git a/arts/modules/synth/mcopclass/Synth_NIL.mcopclass b/arts/modules/synth/mcopclass/Synth_NIL.mcopclass
new file mode 100644
index 00000000..f11a7fb6
--- /dev/null
+++ b/arts/modules/synth/mcopclass/Synth_NIL.mcopclass
@@ -0,0 +1,4 @@
+Buildable=true
+Interface=Arts::Synth_NIL,Arts::SynthModule,Arts::Object
+Language=C++
+Library=libartsmodulessynth.la
diff --git a/arts/modules/synth/mcopclass/Synth_NOISE.mcopclass b/arts/modules/synth/mcopclass/Synth_NOISE.mcopclass
new file mode 100644
index 00000000..bf37079d
--- /dev/null
+++ b/arts/modules/synth/mcopclass/Synth_NOISE.mcopclass
@@ -0,0 +1,4 @@
+Buildable=true
+Interface=Arts::Synth_NOISE,Arts::SynthModule,Arts::Object
+Language=C++
+Library=libartsmodulessynth.la
diff --git a/arts/modules/synth/mcopclass/Synth_OSC.mcopclass b/arts/modules/synth/mcopclass/Synth_OSC.mcopclass
new file mode 100644
index 00000000..5cd19123
--- /dev/null
+++ b/arts/modules/synth/mcopclass/Synth_OSC.mcopclass
@@ -0,0 +1,4 @@
+Buildable=true
+Interface=Arts::Synth_OSC,Arts::SynthModule,Arts::Object
+Language=C++
+Library=libartsmodulessynth.la
diff --git a/arts/modules/synth/mcopclass/Synth_PITCH_SHIFT.mcopclass b/arts/modules/synth/mcopclass/Synth_PITCH_SHIFT.mcopclass
new file mode 100644
index 00000000..962b4a75
--- /dev/null
+++ b/arts/modules/synth/mcopclass/Synth_PITCH_SHIFT.mcopclass
@@ -0,0 +1,4 @@
+Buildable=true
+Interface=Arts::Synth_PITCH_SHIFT,Arts::SynthModule,Arts::Object
+Language=C++
+Library=libartsmodulessynth.la
diff --git a/arts/modules/synth/mcopclass/Synth_PITCH_SHIFT_FFT.mcopclass b/arts/modules/synth/mcopclass/Synth_PITCH_SHIFT_FFT.mcopclass
new file mode 100644
index 00000000..d37b3190
--- /dev/null
+++ b/arts/modules/synth/mcopclass/Synth_PITCH_SHIFT_FFT.mcopclass
@@ -0,0 +1,4 @@
+Buildable=true
+Interface=Arts::Synth_PITCH_SHIFT_FFT,Arts::SynthModule,Arts::Object
+Language=C++
+Library=libartsmodulessynth.la
diff --git a/arts/modules/synth/mcopclass/Synth_PLAY_PAT.mcopclass b/arts/modules/synth/mcopclass/Synth_PLAY_PAT.mcopclass
new file mode 100644
index 00000000..578f6222
--- /dev/null
+++ b/arts/modules/synth/mcopclass/Synth_PLAY_PAT.mcopclass
@@ -0,0 +1,4 @@
+Buildable=true
+Interface=Arts::Synth_PLAY_PAT,Arts::SynthModule,Arts::Object
+Language=C++
+Library=libartsmodulessynth.la
diff --git a/arts/modules/synth/mcopclass/Synth_PSCALE.mcopclass b/arts/modules/synth/mcopclass/Synth_PSCALE.mcopclass
new file mode 100644
index 00000000..52d076b3
--- /dev/null
+++ b/arts/modules/synth/mcopclass/Synth_PSCALE.mcopclass
@@ -0,0 +1,4 @@
+Buildable=true
+Interface=Arts::Synth_PSCALE,Arts::SynthModule,Arts::Object
+Language=C++
+Library=libartsmodulessynth.la
diff --git a/arts/modules/synth/mcopclass/Synth_RC.mcopclass b/arts/modules/synth/mcopclass/Synth_RC.mcopclass
new file mode 100644
index 00000000..5d40d363
--- /dev/null
+++ b/arts/modules/synth/mcopclass/Synth_RC.mcopclass
@@ -0,0 +1,4 @@
+Buildable=true
+Interface=Arts::Synth_RC,Arts::SynthModule,Arts::Object
+Language=C++
+Library=libartsmodulessynth.la
diff --git a/arts/modules/synth/mcopclass/Synth_SEQUENCE.mcopclass b/arts/modules/synth/mcopclass/Synth_SEQUENCE.mcopclass
new file mode 100644
index 00000000..0eef9733
--- /dev/null
+++ b/arts/modules/synth/mcopclass/Synth_SEQUENCE.mcopclass
@@ -0,0 +1,4 @@
+Buildable=true
+Interface=Arts::Synth_SEQUENCE,Arts::SynthModule,Arts::Object
+Language=C++
+Library=libartsmodulessynth.la
diff --git a/arts/modules/synth/mcopclass/Synth_SEQUENCE_FREQ.mcopclass b/arts/modules/synth/mcopclass/Synth_SEQUENCE_FREQ.mcopclass
new file mode 100644
index 00000000..efa69000
--- /dev/null
+++ b/arts/modules/synth/mcopclass/Synth_SEQUENCE_FREQ.mcopclass
@@ -0,0 +1,4 @@
+Buildable=true
+Interface=Arts::Synth_SEQUENCE_FREQ,Arts::SynthModule,Arts::Object
+Language=C++
+Library=libartsmodulessynth.la
diff --git a/arts/modules/synth/mcopclass/Synth_SHELVE_CUTOFF.mcopclass b/arts/modules/synth/mcopclass/Synth_SHELVE_CUTOFF.mcopclass
new file mode 100644
index 00000000..1d25a6e8
--- /dev/null
+++ b/arts/modules/synth/mcopclass/Synth_SHELVE_CUTOFF.mcopclass
@@ -0,0 +1,4 @@
+Buildable=true
+Interface=Arts::Synth_SHELVE_CUTOFF,Arts::SynthModule,Arts::Object
+Language=C++
+Library=libartsmodulessynth.la
diff --git a/arts/modules/synth/mcopclass/Synth_STD_EQUALIZER.mcopclass b/arts/modules/synth/mcopclass/Synth_STD_EQUALIZER.mcopclass
new file mode 100644
index 00000000..8b2b65a6
--- /dev/null
+++ b/arts/modules/synth/mcopclass/Synth_STD_EQUALIZER.mcopclass
@@ -0,0 +1,4 @@
+Buildable=true
+Interface=Arts::Synth_STD_EQUALIZER,Arts::SynthModule,Arts::Object
+Language=C++
+Library=libartsmodulessynth.la
diff --git a/arts/modules/synth/mcopclass/Synth_TREMOLO.mcopclass b/arts/modules/synth/mcopclass/Synth_TREMOLO.mcopclass
new file mode 100644
index 00000000..a937293d
--- /dev/null
+++ b/arts/modules/synth/mcopclass/Synth_TREMOLO.mcopclass
@@ -0,0 +1,4 @@
+Buildable=true
+Interface=Arts::Synth_TREMOLO,Arts::SynthModule,Arts::Object
+Language=C++
+Library=libartsmodulessynth.la
diff --git a/arts/modules/synth/mcopclass/Synth_WAVE_PULSE.mcopclass b/arts/modules/synth/mcopclass/Synth_WAVE_PULSE.mcopclass
new file mode 100644
index 00000000..8ae14ccf
--- /dev/null
+++ b/arts/modules/synth/mcopclass/Synth_WAVE_PULSE.mcopclass
@@ -0,0 +1,4 @@
+Buildable=true
+Interface=Arts::Synth_WAVE_PULSE,Arts::SynthModule,Arts::Object
+Language=C++
+Library=libartsmodulessynth.la
diff --git a/arts/modules/synth/mcopclass/Synth_WAVE_SOFTSAW.mcopclass b/arts/modules/synth/mcopclass/Synth_WAVE_SOFTSAW.mcopclass
new file mode 100644
index 00000000..116680bf
--- /dev/null
+++ b/arts/modules/synth/mcopclass/Synth_WAVE_SOFTSAW.mcopclass
@@ -0,0 +1,4 @@
+Buildable=true
+Interface=Arts::Synth_WAVE_SOFTSAW,Arts::SynthModule,Arts::Object
+Language=C++
+Library=libartsmodulessynth.la
diff --git a/arts/modules/synth/mcopclass/Synth_WAVE_SQUARE.mcopclass b/arts/modules/synth/mcopclass/Synth_WAVE_SQUARE.mcopclass
new file mode 100644
index 00000000..5033f281
--- /dev/null
+++ b/arts/modules/synth/mcopclass/Synth_WAVE_SQUARE.mcopclass
@@ -0,0 +1,4 @@
+Buildable=true
+Interface=Arts::Synth_WAVE_SQUARE,Arts::SynthModule,Arts::Object
+Language=C++
+Library=libartsmodulessynth.la
diff --git a/arts/modules/synth/mcopclass/Synth_WAVE_TRI.mcopclass b/arts/modules/synth/mcopclass/Synth_WAVE_TRI.mcopclass
new file mode 100644
index 00000000..a5cbebdc
--- /dev/null
+++ b/arts/modules/synth/mcopclass/Synth_WAVE_TRI.mcopclass
@@ -0,0 +1,4 @@
+Buildable=true
+Interface=Arts::Synth_WAVE_TRI,Arts::SynthModule,Arts::Object
+Language=C++
+Library=libartsmodulessynth.la
diff --git a/arts/modules/synth/mcopclass/Synth_XFADE.mcopclass b/arts/modules/synth/mcopclass/Synth_XFADE.mcopclass
new file mode 100644
index 00000000..0b1166a8
--- /dev/null
+++ b/arts/modules/synth/mcopclass/Synth_XFADE.mcopclass
@@ -0,0 +1,4 @@
+Buildable=true
+Interface=Arts::Synth_XFADE,Arts::SynthModule,Arts::Object
+Language=C++
+Library=libartsmodulessynth.la
diff --git a/arts/modules/synth/objectcache_impl.cc b/arts/modules/synth/objectcache_impl.cc
new file mode 100644
index 00000000..d58163a6
--- /dev/null
+++ b/arts/modules/synth/objectcache_impl.cc
@@ -0,0 +1,73 @@
+/*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "artsmodulessynth.h"
+#include <iostream>
+
+using namespace Arts;
+using namespace std;
+
+namespace Arts {
+
+
+class ObjectCache_impl : public ObjectCache_skel {
+protected:
+ typedef map<string, list<Object> *> ObjectCacheMap;
+ ObjectCacheMap objects;
+
+public:
+ ~ObjectCache_impl()
+ {
+ ObjectCacheMap::iterator i;
+ for(i=objects.begin(); i != objects.end(); i++)
+ {
+ cout << "ObjectCache: deleting remaining " <<
+ i->first << " objects" << endl;
+ delete i->second;
+ }
+ }
+
+ void put(Object obj, const string& name)
+ {
+ list<Object> *l = objects[name];
+
+ if(l == 0) objects[name] = l = new list<Object>;
+ l->push_back(obj);
+ }
+
+ Object get(const string& name)
+ {
+ list<Object> *l = objects[name];
+ if(l && !l->empty())
+ {
+ Object result = l->front();
+ l->pop_front();
+
+ return result;
+ }
+ return Object::null();
+ }
+};
+
+REGISTER_IMPLEMENTATION(ObjectCache_impl);
+}
+
diff --git a/arts/modules/synth/synth_atan_saturate_impl.cc b/arts/modules/synth/synth_atan_saturate_impl.cc
new file mode 100644
index 00000000..d9220d26
--- /dev/null
+++ b/arts/modules/synth/synth_atan_saturate_impl.cc
@@ -0,0 +1,54 @@
+ /*
+
+ Copyright (C) 2000 Jeff Tranter
+ tranter@pobox.com
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include <stdio.h>
+#include <math.h>
+#include "artsmodulessynth.h"
+#include "stdsynthmodule.h"
+
+using namespace Arts;
+
+// This can be used to get the input signal to the normalized range
+// between -1 and 1 that Synth_PLAY can process. The louder the input
+// signal, the more the signal is distorted by this module. For very
+// small input signals, the output signal is about the input signal
+// (no change).
+
+class Synth_ATAN_SATURATE_impl : virtual public Synth_ATAN_SATURATE_skel,
+ virtual public StdSynthModule
+{
+protected:
+ float _inscale;
+
+public:
+ float inscale() { return _inscale; }
+
+ void inscale(float newInscale) { _inscale = newInscale; }
+
+ void calculateBlock(unsigned long samples)
+ {
+ for (unsigned long i=0; i<samples; i++)
+ outvalue[i] = atan(invalue[i]*_inscale)/(M_PI/2.0);
+ }
+};
+
+REGISTER_IMPLEMENTATION(Synth_ATAN_SATURATE_impl);
diff --git a/arts/modules/synth/synth_autopanner_impl.cc b/arts/modules/synth/synth_autopanner_impl.cc
new file mode 100644
index 00000000..9f49f0b1
--- /dev/null
+++ b/arts/modules/synth/synth_autopanner_impl.cc
@@ -0,0 +1,50 @@
+/*
+
+ Copyright (C) 2000 Jeff Tranter
+ tranter@pobox.com
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "artsmodulessynth.h"
+#include "stdsynthmodule.h"
+
+using namespace Arts;
+
+// An Autopanner is used to automatically pan the input signal between
+// the left and the right output. This makes mixes more lively. A
+// standard application would be a guitar or lead sound. Connect a
+// LFO, a sine or saw wave for example to "inlfo" and select a
+// frequency between 0.1 and 5Hz for a traditional effect or even more
+// for Special FX.
+
+class Synth_AUTOPANNER_impl : virtual public Synth_AUTOPANNER_skel,
+ virtual public StdSynthModule
+{
+public:
+ void calculateBlock(unsigned long samples)
+ {
+ unsigned long i;
+ for(i=0; i<samples; i++)
+ {
+ outvalue1[i] = invalue[i] * (1.0 - (inlfo[i] + 1.0) / 2.0);
+ outvalue2[i] = invalue[i] * (inlfo[i] + 1.0) / 2.0;
+ }
+ }
+};
+
+REGISTER_IMPLEMENTATION(Synth_AUTOPANNER_impl);
diff --git a/arts/modules/synth/synth_brickwall_limiter_impl.cc b/arts/modules/synth/synth_brickwall_limiter_impl.cc
new file mode 100644
index 00000000..107fe47a
--- /dev/null
+++ b/arts/modules/synth/synth_brickwall_limiter_impl.cc
@@ -0,0 +1,51 @@
+/*
+
+ Copyright (C) 2000 Jeff Tranter
+ tranter@pobox.com
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "artsmodulessynth.h"
+#include "stdsynthmodule.h"
+
+using namespace Arts;
+
+// A brickwall limiter is used to protect equipment (and your ears..)
+// from peaks that exceed the dynamic range of your system. It doesn't
+// sound good but it's better than digital distortion.
+
+class Synth_BRICKWALL_LIMITER_impl : virtual public Synth_BRICKWALL_LIMITER_skel,
+ virtual public StdSynthModule
+{
+public:
+ void calculateBlock(unsigned long samples)
+ {
+ unsigned long i;
+ for(i=0; i<samples; i++)
+ {
+ if (invalue[i] > 1.0)
+ outvalue[i] = 1.0;
+ else if (invalue[i] < -1.0)
+ outvalue[i] = -1.0;
+ else
+ outvalue[i] = invalue[i];
+ }
+ }
+};
+
+REGISTER_IMPLEMENTATION(Synth_BRICKWALL_LIMITER_impl);
diff --git a/arts/modules/synth/synth_capture_wav_impl.cc b/arts/modules/synth/synth_capture_wav_impl.cc
new file mode 100644
index 00000000..15416761
--- /dev/null
+++ b/arts/modules/synth/synth_capture_wav_impl.cc
@@ -0,0 +1,169 @@
+ /*
+
+ Copyright (C) 2000, 2001 Stefan Westerfeld
+ stefan@space.twc.de, Matthias Kretz <kretz@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ */
+
+#include "artsmodulessynth.h"
+#include "convert.h"
+#include "mcoputils.h"
+#include "stdsynthmodule.h"
+#include "debug.h"
+#include <fcntl.h>
+#include <string.h>
+#include <stdlib.h>
+
+using namespace std;
+namespace Arts {
+
+class Synth_CAPTURE_WAV_impl :virtual public Synth_CAPTURE_WAV_skel,
+ virtual public StdSynthModule
+{
+ bool audioinit, scaleerr, running;
+ int audiofd, byteorder, v,datalen,channels;
+
+ unsigned char *outblock;
+ unsigned long maxsamples;
+
+ string _filename;
+
+/****
+
+ WAV writing code and header taken from kwave. Many thanks go to
+ Martin Wilz who has written this ;)
+
+ ****/
+
+ struct wavheader
+ {
+ char riffid[4];
+ long filelength;
+ char wavid[4];
+ char fmtid[4];
+ long fmtlength;
+ short int mode;
+ short int channels;
+ long rate;
+ long AvgBytesPerSec;
+ short int BlockAlign;
+ short int bitspersample;
+ } header;
+
+public:
+ Synth_CAPTURE_WAV_impl();
+ void streamInit();
+ void calculateBlock(unsigned long samples);
+ void streamEnd();
+ string filename() { return _filename; }
+ void filename( const string &newFilename );
+};
+
+Synth_CAPTURE_WAV_impl::Synth_CAPTURE_WAV_impl()
+ : running(false), _filename( "capture" )
+{
+}
+
+void Synth_CAPTURE_WAV_impl::streamInit()
+{
+ /*
+ * we use createFilePath to prevent the usual symlink security issues
+ * in /tmp - add .wav manually as createFilePath substitutes . with _
+ */
+ string filename = MCOPUtils::createFilePath(_filename)+ ".wav";
+ audiofd = open(filename.c_str(),O_WRONLY|O_CREAT|O_TRUNC,0644);
+
+/* write header */
+
+ int rate=44100;
+ int bit=16;
+
+ channels = 2; /* hardcoded here - make it a parameter? */
+
+ arts_info("capturing output to %s", filename.c_str());
+ datalen=0;
+
+ strncpy (header.riffid,"RIFF",4);
+ strncpy (header.wavid,"WAVE",4);
+ strncpy (header.fmtid,"fmt ",4);
+ header.fmtlength=16;
+ header.filelength=sizeof(struct wavheader);
+ header.mode=1;
+ header.channels=channels;
+ header.rate=rate;
+ header.AvgBytesPerSec=rate*bit/8;
+ header.BlockAlign=channels*bit/8;
+ header.bitspersample=bit;
+
+ write(audiofd,&header,sizeof (struct wavheader));
+ write(audiofd,"data",4);
+ write(audiofd,&datalen,4);
+
+ maxsamples = 0;
+ outblock = 0;
+ v = 0;
+ running = true;
+}
+
+void Synth_CAPTURE_WAV_impl::calculateBlock(unsigned long samples)
+{
+ if(samples > maxsamples)
+ {
+ maxsamples = samples;
+ outblock = (unsigned char *)realloc(outblock, maxsamples * 4);
+ // 2 channels, 16 bit
+ }
+
+ if(channels == 1)
+ convert_mono_float_16le(samples,left,outblock);
+
+ if(channels == 2)
+ convert_stereo_2float_i16le(samples,left,right,outblock);
+
+ write(audiofd,outblock,samples*channels*2);
+ datalen += samples*channels*2;
+}
+
+void Synth_CAPTURE_WAV_impl::streamEnd()
+{
+/* rewrite header which now contains the correct size of the file */
+ lseek(audiofd,0,SEEK_SET);
+ header.filelength=sizeof(struct wavheader)+datalen;
+ write(audiofd,&header,sizeof (struct wavheader));
+ write(audiofd,"data",4);
+ write(audiofd,&datalen,4);
+
+ close(audiofd);
+
+ running = false;
+}
+void Synth_CAPTURE_WAV_impl::filename( const string &newFilename )
+{
+ if(_filename != newFilename) {
+ _filename = newFilename;
+ if(running)
+ {
+ streamEnd();
+ streamInit();
+ }
+ filename_changed(newFilename);
+ }
+}
+
+REGISTER_IMPLEMENTATION(Synth_CAPTURE_WAV_impl);
+
+}
diff --git a/arts/modules/synth/synth_cdelay_impl.cc b/arts/modules/synth/synth_cdelay_impl.cc
new file mode 100644
index 00000000..afac3144
--- /dev/null
+++ b/arts/modules/synth/synth_cdelay_impl.cc
@@ -0,0 +1,125 @@
+/*
+
+ Copyright (C) 2000 Jeff Tranter
+ tranter@pobox.com
+ 2001 Matthias Kretz
+ kretz@kde.org
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "artsmodulessynth.h"
+#include "stdsynthmodule.h"
+
+#include <math.h>
+#include <cstring>
+
+using namespace Arts;
+
+// This delays the input signal for an amount of time. The time
+// specification can be any number greater or equal zero.
+// The delay is constant during the calculation, that means it
+// can't be modified. This saves computing time as no interpolation is
+// done, and is useful for recursive structures. Actually it can be
+// modified, but without interpolation it won't sound too good. See
+// the description for Synth_DELAY.
+
+class Synth_CDELAY_impl : virtual public Synth_CDELAY_skel,
+ virtual public StdSynthModule
+{
+protected:
+ unsigned long _buffersize;
+ unsigned long _bitmask;
+ float *_buffer; // holds the data to be delayed (variable size)
+ float _delaytime;
+ unsigned int _readpos;
+ unsigned int _writepos;
+
+public:
+ Synth_CDELAY_impl() : _buffersize( 0 ), _bitmask( 0 ), _buffer( 0 ), _delaytime( 0 ), _readpos( 0 ), _writepos( 0 )
+ {
+ }
+
+ ~Synth_CDELAY_impl()
+ {
+ delete[] _buffer;
+ }
+
+ float time() { return _delaytime; }
+
+ void time(float newTime)
+ {
+ _delaytime = newTime;
+ double n = ceil( log( double(_delaytime * samplingRateFloat )) / log( 2. ) );
+ unsigned long newbuffersize = (unsigned long)( pow( 2, n ) );
+ unsigned long newbitmask = newbuffersize - 1;
+ if( newbuffersize != _buffersize )
+ {
+ float *newbuffer = new float[newbuffersize];
+ if( newbuffersize > _buffersize ) {
+ for( unsigned long i = 0; i < _buffersize; i++ ) {
+ newbuffer[i] = _buffer[_writepos];
+ _writepos++;
+ _writepos &= newbitmask;
+ }
+ for( unsigned long i = _buffersize; i < newbuffersize; i++ )
+ newbuffer[i] = 0;
+ } else {
+ _writepos -= newbuffersize;
+ _writepos &= newbitmask;
+ for( unsigned long i = 0; i < newbuffersize; i++ ) {
+ newbuffer[i] = _buffer[_writepos];
+ _writepos++;
+ _writepos &= newbitmask;
+ }
+ }
+ _buffer = newbuffer;
+ _buffersize = newbuffersize;
+ _bitmask = newbitmask;
+ }
+ _readpos = (unsigned long)rint( _writepos - _delaytime * samplingRateFloat ) & _bitmask;
+ time_changed( _delaytime );
+ }
+
+ void streamInit()
+ {
+ // initialize buffer to all zeroes
+ if( _buffer )
+ for( unsigned long i = 0; i < _buffersize; i++ )
+ _buffer[i] = 0.0;
+ }
+
+ void calculateBlock(unsigned long samples)
+ {
+ if( ! _buffer ) {
+ memcpy( outvalue, invalue, sizeof( float ) * samples );
+ return;
+ }
+ for( unsigned long i = 0; i < samples; i++ ) {
+ _buffer[_writepos] = invalue[i];
+ outvalue[i] = _buffer[_readpos];
+ _readpos++;
+ _readpos &= _bitmask;
+ _writepos++;
+ _writepos &= _bitmask;
+ }
+ }
+};
+
+// vim:sw=4:ts=4
+
+REGISTER_IMPLEMENTATION(Synth_CDELAY_impl);
diff --git a/arts/modules/synth/synth_compressor_impl.cc b/arts/modules/synth/synth_compressor_impl.cc
new file mode 100644
index 00000000..54c7648e
--- /dev/null
+++ b/arts/modules/synth/synth_compressor_impl.cc
@@ -0,0 +1,139 @@
+/*
+
+ Copyright (C) 2001 Matthias Kretz <kretz@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ */
+
+#include "artsmodulessynth.h"
+#include "stdsynthmodule.h"
+#include "debug.h"
+
+#include <math.h>
+#include <string.h>
+
+#ifndef LN2
+# define LN2 0.69314718
+#endif
+
+#ifndef MAX
+# define MAX(a,b) (((a) > (b) ? (a) : (b)))
+#endif
+
+using namespace std;
+namespace Arts {
+
+class Synth_COMPRESSOR_impl : virtual public Synth_COMPRESSOR_skel,
+ virtual public StdSynthModule
+{
+protected:
+ float _attack, _release, _threshold, _ratiominus1, _output;
+ float _attackfactor, _releasefactor;
+ float _volume;
+ float _compfactor;
+ bool _autooutput;
+
+public:
+ float attack() { return _attack; }
+ float release() { return _release; }
+ float threshold() { return _threshold; }
+ float ratio() { return _ratiominus1 + 1.0; }
+ float output() { return _output; }
+
+ Synth_COMPRESSOR_impl()
+ : _threshold( 1 )
+ , _ratiominus1( -0.2 )
+ , _output( 0 )
+ , _autooutput( true )
+ {
+ newCompFactor();
+ attack( 10 );
+ release( 10 );
+ }
+
+ void newCompFactor()
+ {
+ _compfactor = _output / pow( _threshold, _ratiominus1 );
+ }
+
+ void streamInit()
+ {
+ _volume = 0;
+ }
+
+ void calculateBlock(unsigned long samples)
+ {
+ for( unsigned long i = 0; i < samples; i++ ) {
+ float delta = fabs( invalue[i] ) - _volume;
+ if( delta > 0.0 )
+ _volume += _attackfactor * delta;
+ else
+ _volume += _releasefactor * delta;
+
+ if( _volume > _threshold )
+ // compress
+ // this is what it does:
+ // UtodB(x) = 20 * log( x )
+ // dBtoU(x) = pow( 10, x / 20 )
+ // outvalue[i] = dBtoU( ( UtodB( volume ) - UtodB( threshold ) ) * ratio + UtodB( threshold ) ) / volume * output * invalue[ i ];
+ // showing that it's equal to the formula below
+ // is left as an exercise to the reader.
+ outvalue[i] = pow( _volume, _ratiominus1 ) * _compfactor * invalue[ i ];
+ else
+ outvalue[i] = invalue[i] * _output;
+ }
+ }
+
+ void attack( float newAttack )
+ { // in ms
+ _attack = newAttack;
+ // _attackfactor has to be <= 1, that's why we need the MAX here
+ _attackfactor = LN2 / MAX( _attack / 1000 * samplingRateFloat, LN2 );
+ attack_changed( newAttack );
+ }
+
+ void release( float newRelease )
+ { // in ms
+ _release = newRelease;
+ // _releasefactor has to be <= 1, that's why we need the MAX here
+ _releasefactor = LN2 / MAX( _release / 1000 * samplingRateFloat, LN2 );
+ release_changed( newRelease );
+ }
+
+ void threshold( float newThreshold )
+ { // in V not in dB
+ _threshold = newThreshold;
+ newCompFactor();
+ threshold_changed( newThreshold );
+ }
+
+ void ratio( float newRatio )
+ {
+ _ratiominus1 = newRatio - 1;
+ newCompFactor();
+ ratio_changed( newRatio );
+ }
+
+ void output( float newOutput )
+ { // in V not in dB
+ _output = newOutput;
+ newCompFactor();
+ output_changed( newOutput );
+ }
+};
+
+REGISTER_IMPLEMENTATION(Synth_COMPRESSOR_impl);
+}
diff --git a/arts/modules/synth/synth_data_impl.cc b/arts/modules/synth/synth_data_impl.cc
new file mode 100644
index 00000000..7cd185d3
--- /dev/null
+++ b/arts/modules/synth/synth_data_impl.cc
@@ -0,0 +1,50 @@
+ /*
+
+ Copyright (C) 2000 Jeff Tranter
+ tranter@pobox.com
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include <stdio.h>
+#include "artsmodulessynth.h"
+#include "stdsynthmodule.h"
+
+using namespace Arts;
+
+// This module outputs a constant stream of data corresponding to the
+// value given as it's parameter.
+
+class Synth_DATA_impl : virtual public Synth_DATA_skel,
+ virtual public StdSynthModule
+{
+protected:
+ float _value;
+
+public:
+ float value() { return _value; }
+
+ void value(float newValue) { _value = newValue; }
+
+ void calculateBlock(unsigned long samples)
+ {
+ for (unsigned long i=0; i<samples; i++)
+ outvalue[i] = _value;
+ }
+};
+
+REGISTER_IMPLEMENTATION(Synth_DATA_impl);
diff --git a/arts/modules/synth/synth_debug_impl.cc b/arts/modules/synth/synth_debug_impl.cc
new file mode 100644
index 00000000..609290f7
--- /dev/null
+++ b/arts/modules/synth/synth_debug_impl.cc
@@ -0,0 +1,60 @@
+ /*
+
+ Copyright (C) 2000 Jeff Tranter
+ tranter@pobox.com
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include <stdio.h>
+#include "artsmodulessynth.h"
+#include "stdsynthmodule.h"
+
+using namespace std;
+using namespace Arts;
+
+// You can use this for debugging. It will print out the value of the
+// signal at invalue in regular intervals (ca. 1 second), combined
+// with the comment you have specified. That way you can find out if
+// some signals stay in certain ranges, or if they are there at all.
+
+class Synth_DEBUG_impl : virtual public Synth_DEBUG_skel,
+ virtual public StdSynthModule
+{
+protected:
+ string _comment;
+ int i;
+
+public:
+ string comment() { return _comment; }
+
+ void comment(const string &newComment) { _comment = newComment; }
+
+ void streamInit() { i = 0; }
+
+ void calculateBlock(unsigned long samples)
+ {
+ for (unsigned long j=0; j<samples; j++)
+ {
+ i++;
+ if ((i % 65536) == 0)
+ printf("Synth_DEBUG: %s %f\n", _comment.c_str(), invalue[j]);
+ }
+ }
+};
+
+REGISTER_IMPLEMENTATION(Synth_DEBUG_impl);
diff --git a/arts/modules/synth/synth_delay_impl.cc b/arts/modules/synth/synth_delay_impl.cc
new file mode 100644
index 00000000..f872b284
--- /dev/null
+++ b/arts/modules/synth/synth_delay_impl.cc
@@ -0,0 +1,138 @@
+/*
+
+ Copyright (C) 2000 Jeff Tranter
+ tranter@pobox.com
+ Stefan Westerfeld
+ stefan@space.twc.de
+ Jens Hahn
+ Jens.Hahn@t-online.de
+ 2001 Matthias Kretz
+ kretz@kde.org
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "artsmodulessynth.h"
+#include "stdsynthmodule.h"
+
+#include <math.h>
+
+using namespace Arts;
+
+// This delays the input signal for an amount of time. The time
+// specification must be between 0 and 1 for a delay between 0 seconds
+// and 1 second.
+//
+// This kind of delay may not be used in feedback structures. This is
+// because it's a variable delay. You can modify it's length while it
+// is running, and even set it down to zero. But since in a feedback
+// structure the own output is needed to calculate the next samples, a
+// delay whose value could drop to zero during synthesis could lead to
+// a stall situation.
+//
+// Use CDELAYs in that setup, perhaps combine a small constant delay
+// (of 0.001 seconds) with a flexible delay.
+//
+// You can also combine a CDELAY and a DELAY to achieve a variable
+// length delay with a minimum value in a feedback loop. Just make
+// sure that you have a CDELAY involved.
+
+class Synth_DELAY_impl : virtual public Synth_DELAY_skel,
+ virtual public StdSynthModule
+{
+protected:
+ unsigned long _buffersize;
+ unsigned long _bitmask;
+ float * _buffer;
+ float _maxdelay;
+ unsigned int _writepos;
+
+public:
+ Synth_DELAY_impl() : _buffersize( 0 ), _bitmask( 0 ), _buffer( 0 ), _maxdelay( 0 ), _writepos( 0 )
+ {
+ maxdelay( 1 ); // take a one second buffer if nothing else is specified
+ }
+
+ ~Synth_DELAY_impl()
+ {
+ delete[] _buffer;
+ }
+
+ void streamInit()
+ {
+ // initialize buffer to all zeroes
+ for ( unsigned long i = 0; i < _buffersize; i++ )
+ _buffer[i] = 0.0;
+ }
+
+ void calculateBlock(unsigned long samples)
+ {
+ for( unsigned long i = 0; i <samples; i++ )
+ {
+ double int_pos;
+ double error = modf( time[i] * samplingRateFloat, &int_pos );
+ unsigned long readpos1 = ( _writepos - (unsigned long)(int_pos) ) & _bitmask;
+ unsigned long readpos2 = ( readpos1 - 1 ) & _bitmask; // Shouldn't this be +1? (mkretz)
+ // No, it's right this way:
+ // ( 1 - error ) needs to be multiplied with the second
+ // sample; error with the first
+ _buffer[_writepos] = invalue[i];
+ outvalue[i] = _buffer[readpos1] * ( 1 - error ) + _buffer[readpos2] * error;
+ _writepos++;
+ _writepos &= _bitmask;
+ }
+ }
+
+ float maxdelay() { return _maxdelay; }
+
+ void maxdelay(float newmaxdelay)
+ {
+ if( newmaxdelay <= 0 )
+ return;
+ _maxdelay = newmaxdelay;
+ double n = ceil( log( double(_maxdelay * samplingRateFloat) ) / log( 2. ) );
+ unsigned long newbuffersize = (unsigned long)( pow( 2, n ) );
+ unsigned long newbitmask = newbuffersize - 1;
+ if( newbuffersize != _buffersize )
+ {
+ float *newbuffer = new float[newbuffersize];
+ if( newbuffersize > _buffersize ) {
+ for( unsigned long i = 0; i < _buffersize; i++ ) {
+ newbuffer[i] = _buffer[_writepos];
+ _writepos++;
+ _writepos &= newbitmask;
+ }
+ for( unsigned long i = _buffersize; i < newbuffersize; i++ )
+ newbuffer[i] = 0;
+ } else {
+ _writepos -= newbuffersize;
+ _writepos &= newbitmask;
+ for( unsigned long i = 0; i < newbuffersize; i++ ) {
+ newbuffer[i] = _buffer[_writepos];
+ _writepos++;
+ _writepos &= newbitmask;
+ }
+ }
+ _buffer = newbuffer;
+ _buffersize = newbuffersize;
+ _bitmask = newbitmask;
+ }
+ maxdelay_changed( _maxdelay );
+ }
+};
+
+REGISTER_IMPLEMENTATION(Synth_DELAY_impl);
diff --git a/arts/modules/synth/synth_div_impl.cc b/arts/modules/synth/synth_div_impl.cc
new file mode 100644
index 00000000..8e087ff5
--- /dev/null
+++ b/arts/modules/synth/synth_div_impl.cc
@@ -0,0 +1,45 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+ 2004 Matthias Kretz <kretz@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "artsmodulessynth.h"
+#include "stdsynthmodule.h"
+
+using namespace Arts;
+
+namespace Arts {
+
+class Synth_DIV_impl :public Synth_DIV_skel, public StdSynthModule
+{
+public:
+ void calculateBlock(unsigned long samples)
+ {
+ unsigned long i;
+
+ for(i = 0;i < samples; i++)
+ outvalue[i] = invalue1[i] / invalue2[i];
+ }
+};
+
+REGISTER_IMPLEMENTATION(Synth_DIV_impl);
+
+}
diff --git a/arts/modules/synth/synth_envelope_adsr_impl.cc b/arts/modules/synth/synth_envelope_adsr_impl.cc
new file mode 100644
index 00000000..51ddf76c
--- /dev/null
+++ b/arts/modules/synth/synth_envelope_adsr_impl.cc
@@ -0,0 +1,121 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "artsmodulessynth.h"
+#include "debug.h"
+#include "stdsynthmodule.h"
+
+using namespace Arts;
+
+class Synth_ENVELOPE_ADSR_impl : virtual public Synth_ENVELOPE_ADSR_skel,
+ virtual public StdSynthModule
+{
+protected:
+ enum { NOOUT, ATTACK, SUSTAIN, DECAY, RELEASE } currentphase;
+ float level,increment,decrement;
+public:
+ void streamInit()
+ {
+ currentphase = NOOUT;
+ level = 0;
+ }
+ void calculateBlock(unsigned long samples);
+};
+
+void Synth_ENVELOPE_ADSR_impl::calculateBlock(unsigned long samples)
+{
+ /* FIXME:
+ * should be rewritten as generic envelope, would certainly
+ * be faster & more flexible
+ */
+ unsigned long i;
+
+ for(i=0;i<samples;i++)
+ {
+ done[i] = 0;
+ if(active[i] < 0.5)
+ {
+ if(currentphase == NOOUT)
+ {
+ level = 0;
+ done[i] = 1;
+ }
+ else
+ {
+ if(currentphase != RELEASE) {
+ artsdebug("ADSR: entering release phase\n");
+ currentphase = RELEASE;
+ decrement = level / (release[i] * samplingRateFloat);
+ }
+ level -= decrement;
+ if(level <= 0)
+ {
+ level = 0;
+ currentphase = NOOUT;
+ }
+ }
+ }
+ else
+ {
+ switch(currentphase)
+ {
+ //quickly kill the note that is still there (channel busy ;)
+ case RELEASE:
+ level -= 1/200;
+ if(level <= 0) {
+ currentphase = NOOUT;
+ level = 0;
+ }
+ break;
+ case NOOUT:
+ artsdebug("ADSR: entering attack\n");
+ increment = 1 / (attack[i] * samplingRateFloat);
+ currentphase = ATTACK;
+ break;
+ case ATTACK:
+ level += increment;
+ if (level >= 1)
+ {
+ level = 1;
+ currentphase = DECAY;
+ decrement = (1-sustain[i]) /
+ (decay[i] * samplingRateFloat);
+ }
+ break;
+ case DECAY:
+ level -= decrement;
+ if (level <= sustain[i])
+ {
+ level = sustain[i];
+ currentphase = SUSTAIN;
+ }
+ break;
+ case SUSTAIN:
+ level = sustain[i];
+ break;
+ }
+ }
+ outvalue[i] = invalue[i] * level;
+ }
+}
+
+REGISTER_IMPLEMENTATION(Synth_ENVELOPE_ADSR_impl);
diff --git a/arts/modules/synth/synth_fm_source_impl.cc b/arts/modules/synth/synth_fm_source_impl.cc
new file mode 100644
index 00000000..a5b74b08
--- /dev/null
+++ b/arts/modules/synth/synth_fm_source_impl.cc
@@ -0,0 +1,61 @@
+ /*
+
+ Copyright (C) 2000 Jeff Tranter
+ tranter@pobox.com
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "artsmodulessynth.h"
+#include "stdsynthmodule.h"
+
+using namespace Arts;
+
+// This is used for frequency modulation. Put your frequency to the
+// frequency input and put another signal on the modulator input. Then
+// set modlevel to something, say 0.3. The frequency will be modulated
+// with modulator then. Just try it. Works nice when you put a
+// feedback in there, that means take a combination of the delayed
+// output signal from the Synth_FM_SOURCE (you need to put it to some
+// oscillator as it only takes the role of Synth_FREQUENCY) and some
+// other signal to get good results. Works nicely in combination with
+// Synth_WAVE_SIN oscillators.
+
+class Synth_FM_SOURCE_impl : virtual public Synth_FM_SOURCE_skel,
+ virtual public StdSynthModule
+{
+protected:
+ static const int SAMPLINGRATE = 44100;
+ float posn;
+
+public:
+ void streamInit() { posn = 0; }
+
+ void calculateBlock(unsigned long samples)
+ {
+ for (unsigned long i=0; i<samples; i++)
+ {
+ float pinc = frequency[i] / (float) SAMPLINGRATE;
+ posn += pinc;
+ if (posn > 1)
+ posn -= 1;
+ pos[i] = posn + modulator[i] * modlevel[i];
+ }
+ }
+};
+
+REGISTER_IMPLEMENTATION(Synth_FM_SOURCE_impl);
diff --git a/arts/modules/synth/synth_fx_cflanger_impl.cc b/arts/modules/synth/synth_fx_cflanger_impl.cc
new file mode 100644
index 00000000..16910958
--- /dev/null
+++ b/arts/modules/synth/synth_fx_cflanger_impl.cc
@@ -0,0 +1,96 @@
+/*
+
+ Copyright (C) 2000 Jeff Tranter
+ tranter@pobox.com
+ Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include <math.h>
+#include "artsmodulessynth.h"
+#include "stdsynthmodule.h"
+
+using namespace Arts;
+
+class Synth_FX_CFLANGER_impl : virtual public Synth_FX_CFLANGER_skel,
+ virtual public StdSynthModule
+{
+protected:
+ float _mintime;
+ float _maxtime;
+ enum { SAMPLINGRATE = 44100, MAXDELAY = 44100 };
+ float *dbuffer;
+ unsigned long dbpos;
+ float center;
+ float range;
+
+public:
+ Synth_FX_CFLANGER_impl()
+ {
+ dbuffer=new float[MAXDELAY];
+ }
+ ~Synth_FX_CFLANGER_impl()
+ {
+ delete [] dbuffer;
+ }
+
+ float mintime() { return _mintime; }
+
+ void mintime(float newMintime) { _mintime = newMintime; }
+
+ float maxtime() { return _maxtime; }
+
+ void maxtime(float newMaxtime) { _maxtime = newMaxtime; }
+
+ void streamInit()
+ {
+ center = (_maxtime + _mintime) / 2;
+ range = _maxtime - center;
+ for (int i=0; i<MAXDELAY; i++)
+ dbuffer[i] = 0;
+ dbpos = 0;
+ }
+
+ void calculateBlock(unsigned long samples)
+ {
+ unsigned long i;
+ float delay, floor_delay;
+ long start_pos, end_pos;
+ float start_val, end_val;
+
+ for(i=0; i<samples; i++)
+ {
+ dbuffer[dbpos] = invalue[i];
+ // Delaytime i.e. = 35ms + (+/- LFO[-1 bis 1] * 15ms) / 1000 * 44100
+ delay = ((center + (lfo[i] * range)) / 1000.0) * (float) SAMPLINGRATE;
+ floor_delay = floor(delay);
+ start_pos = dbpos - (long)(floor_delay);
+ end_pos = start_pos-1;
+ if (start_pos < 0) start_pos += MAXDELAY; // wrapping exception
+ if (end_pos < 0) end_pos += MAXDELAY;
+ start_val = dbuffer[start_pos];
+ end_val = dbuffer[end_pos];
+ outvalue[i] = start_val + ((delay - floor_delay) * (end_val - start_val));
+ dbpos++;
+ if (dbpos == MAXDELAY) dbpos = 0;
+ }
+ }
+};
+
+REGISTER_IMPLEMENTATION(Synth_FX_CFLANGER_impl);
diff --git a/arts/modules/synth/synth_midi_debug_impl.cc b/arts/modules/synth/synth_midi_debug_impl.cc
new file mode 100644
index 00000000..628b910b
--- /dev/null
+++ b/arts/modules/synth/synth_midi_debug_impl.cc
@@ -0,0 +1,88 @@
+/*
+
+ Copyright (C) 2000 Jeff Tranter
+ tranter@pobox.com
+
+ (C) 1998 Stefan Westerfeld
+ stefan@space.twc.de
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ */
+
+#include <stdio.h>
+#include "debug.h"
+#include "artsmodulessynth.h"
+#include "stdsynthmodule.h"
+
+using namespace Arts;
+
+class Synth_MIDI_DEBUG_impl : virtual public Synth_MIDI_DEBUG_skel,
+ virtual public StdSynthModule
+{
+ SystemMidiTimer timer;
+ MidiClient client;
+public:
+ Synth_MIDI_DEBUG self() { return Synth_MIDI_DEBUG::_from_base(_copy()); }
+
+ void streamInit()
+ {
+ printf("MIDI_DEBUG: streamInit\n");
+ MidiManager manager = Reference("global:Arts_MidiManager");
+ if(!manager.isNull())
+ {
+ client = manager.addClient(mcdRecord,mctDestination,"midi debug",
+ "Arts::Synth_MIDI_DEBUG");
+ client.addInputPort(self());
+ }
+ else
+ arts_warning("Synth_MIDI_DEBUG: no midi manager found "
+ "- not registered");
+ }
+
+ void processEvent(const MidiEvent& event)
+ {
+ printf("MIDI_DEBUG: scheduling event at %ld.%ld\n",
+ event.time.sec, event.time.usec);
+ timer.queueEvent(self(),event);
+ }
+ void processCommand(const MidiCommand& command)
+ {
+ mcopbyte channel = command.status & mcsChannelMask;
+ switch(command.status & mcsCommandMask)
+ {
+ case mcsNoteOn: printf("MIDI_DEBUG: note on channel %d, "
+ "note %d, velocity %d\n", channel,
+ command.data1, command.data2);
+ break;
+ case mcsNoteOff: printf("MIDI_DEBUG: note off channel %d, "
+ "note %d, velocity %d\n", channel,
+ command.data1, command.data2);
+ break;
+ }
+ }
+
+ TimeStamp time()
+ {
+ return timer.time();
+ }
+
+ TimeStamp playTime()
+ {
+ return timer.time();
+ }
+};
+
+REGISTER_IMPLEMENTATION(Synth_MIDI_DEBUG_impl);
diff --git a/arts/modules/synth/synth_midi_test_impl.cc b/arts/modules/synth/synth_midi_test_impl.cc
new file mode 100644
index 00000000..91714cac
--- /dev/null
+++ b/arts/modules/synth/synth_midi_test_impl.cc
@@ -0,0 +1,692 @@
+#include "artsmodulessynth.h"
+#include "artsbuilder.h"
+#include "stdsynthmodule.h"
+#include "objectmanager.h"
+#include "connect.h"
+#include "flowsystem.h"
+#include "debug.h"
+#include "dynamicrequest.h"
+#include "audiosubsys.h"
+#include <fstream>
+#include <math.h>
+#include <stdlib.h>
+
+using namespace Arts;
+using namespace std;
+
+/*-------- instrument mapping ---------*/
+
+class InstrumentMap {
+protected:
+ struct InstrumentData;
+ class Tokenizer;
+ list<InstrumentData> instruments;
+ string directory;
+ void loadLine(const string& line);
+
+public:
+ struct InstrumentParam;
+
+ void loadFromList(const string& filename, const vector<string>& list);
+ StructureDesc getInstrument(mcopbyte channel, mcopbyte note,
+ mcopbyte velocity, mcopbyte program,
+ vector<InstrumentParam>*& params);
+};
+
+struct InstrumentMap::InstrumentParam
+{
+ string param;
+ Any value;
+
+ InstrumentParam()
+ {
+ }
+
+ InstrumentParam(const InstrumentParam& src)
+ : param(src.param), value(src.value)
+ {
+ }
+
+ InstrumentParam(const string& param, const string& strValue)
+ : param(param)
+ {
+ /* put the string into the any */
+ value.type = "string";
+
+ Buffer b;
+ b.writeString(strValue);
+ b.read(value.value, b.size());
+ }
+};
+
+struct InstrumentMap::InstrumentData
+{
+ struct Range
+ {
+ int minValue, maxValue;
+ Range() : minValue(0), maxValue(0)
+ {
+ }
+ Range(int minValue, int maxValue)
+ : minValue(minValue), maxValue(maxValue)
+ {
+ }
+ bool match(int value)
+ {
+ return (value >= minValue) && (value <= maxValue);
+ }
+ };
+ Range channel, pitch, program, velocity;
+ vector<InstrumentParam> params;
+ StructureDesc instrument;
+};
+
+class InstrumentMap::Tokenizer {
+protected:
+ bool haveToken, haveNextToken;
+ string token, nextToken, input;
+ string::iterator ii;
+public:
+ Tokenizer(const string& line)
+ : haveToken(false), haveNextToken(false),
+ input(line+"\n"), ii(input.begin())
+ {
+ /* adding a \n ensures that we will definitely find the last token */
+ }
+ string getToken()
+ {
+ if(!haveMore())
+ return "";
+
+ if(haveNextToken)
+ {
+ string t = token;
+ haveNextToken = false;
+ token = nextToken;
+ return t;
+ }
+ else
+ {
+ haveToken = false;
+ return token;
+ }
+ }
+ bool haveMore()
+ {
+ if(haveToken)
+ return true;
+
+ token = "";
+ while(ii != input.end() && !haveToken)
+ {
+ const char& c = *ii++;
+
+ if(c == ' ' || c == '\t' || c == '\n')
+ {
+ if(!token.empty()) haveToken = true;
+ }
+ else if(c == '=') /* || c == '-' || c == '+')*/
+ {
+ if(!token.empty())
+ {
+ haveNextToken = true;
+ nextToken = c;
+ }
+ else
+ {
+ token = c;
+ }
+ haveToken = true;
+ }
+ else
+ {
+ token += c;
+ }
+ }
+ return haveToken;
+ }
+};
+
+void InstrumentMap::loadLine(const string& line)
+{
+ Tokenizer t(line);
+ InstrumentData id;
+ /* default: no filtering */
+ id.channel = InstrumentData::Range(0,15);
+ id.pitch = id.program = id.velocity = InstrumentData::Range(0,127);
+
+ string s[3];
+ int i = 0;
+ bool seenDo = false;
+ bool loadOk = false;
+
+ if(t.getToken() != "ON")
+ {
+ arts_warning("error in arts-map: lines must start with ON (did start with %s)\n", t.getToken().c_str());
+ return;
+ }
+
+ while(t.haveMore())
+ {
+ const string& token = t.getToken();
+
+ if(token == "DO")
+ seenDo = true;
+ else
+ {
+ s[i] = token;
+ if(i == 2) /* evaluate */
+ {
+ if(s[1] != "=")
+ {
+ arts_warning("error in arts-map: no = operator\n");
+ return;
+ }
+
+ if(seenDo)
+ {
+ if(s[0] == "structure")
+ {
+ string filename = s[2];
+
+ /* if it's no absolute path, its relative to the map */
+ if(!filename.empty() && filename[0] != '/')
+ filename = directory + "/" + s[2];
+
+ ifstream infile(filename.c_str());
+ string line;
+ vector<string> strseq;
+
+ while(getline(infile,line))
+ strseq.push_back(line);
+
+ id.instrument.loadFromList(strseq);
+ if(id.instrument.name() != "unknown")
+ {
+ loadOk = true;
+ }
+ else
+ {
+ arts_warning("mapped instrument: "
+ "can't load structure %s",s[2].c_str());
+ }
+ }
+ else
+ {
+ /* TODO: handle different datatypes */
+ id.params.push_back(InstrumentParam(s[0], s[2]));
+ }
+ }
+ else
+ {
+ InstrumentData::Range range;
+ range.minValue = atoi(s[2].c_str());
+ range.maxValue = range.minValue;
+ int i = s[2].find("-",0);
+ if(i != 0)
+ {
+ range.minValue = atoi(s[2].substr(0,i).c_str());
+ range.maxValue =
+ atoi(s[2].substr(i+1,s[2].size()-(i+1)).c_str());
+ }
+ if(s[0] == "pitch") id.pitch = range;
+ if(s[0] == "channel") id.channel = range;
+ if(s[0] == "program") id.program = range;
+ if(s[0] == "velocity") id.velocity = range;
+ }
+ i = 0;
+ }
+ else i++;
+ }
+ }
+ if(loadOk) instruments.push_back(id);
+}
+
+void InstrumentMap::loadFromList(const string& filename,
+ const vector<string>& list)
+{
+ int r = filename.rfind('/');
+ if(r > 0)
+ directory = filename.substr(0,r);
+ else
+ directory = "";
+
+ vector<string>::const_iterator i;
+ instruments.clear();
+ for(i = list.begin(); i != list.end(); i++) loadLine(*i);
+}
+
+StructureDesc InstrumentMap::getInstrument(mcopbyte channel, mcopbyte note,
+ mcopbyte velocity, mcopbyte program,
+ vector<InstrumentParam>*& params)
+{
+ list<InstrumentData>::iterator i;
+ for(i = instruments.begin(); i != instruments.end(); i++)
+ {
+ InstrumentData &id = *i;
+
+ if(id.channel.match(channel) && id.pitch.match(note) &&
+ id.velocity.match(velocity) && id.program.match(program))
+ {
+ params = &id.params;
+ return id.instrument;
+ }
+ }
+
+ return StructureDesc::null();
+}
+
+
+/*-------instrument mapping end -------*/
+
+static SynthModule get_AMAN_PLAY(Object structure)
+{
+ Object resultObj = structure._getChild("play");
+ assert(!resultObj.isNull());
+
+ SynthModule result = DynamicCast(resultObj);
+ assert(!result.isNull());
+
+ return result;
+}
+
+struct TSNote {
+ MidiPort port;
+ MidiEvent event;
+ TSNote(MidiPort port, const MidiEvent& event) :
+ port(port), event(event)
+ {
+ }
+};
+
+class AutoMidiRelease : public TimeNotify {
+public:
+ vector<MidiReleaseHelper> impls;
+ AutoMidiRelease()
+ {
+ Dispatcher::the()->ioManager()->addTimer(10, this);
+ }
+ virtual ~AutoMidiRelease()
+ {
+ Dispatcher::the()->ioManager()->removeTimer(this);
+ }
+ void notifyTime()
+ {
+ vector<MidiReleaseHelper>::iterator i = impls.begin();
+ while(i != impls.end())
+ {
+ if(i->terminate())
+ {
+ MidiReleaseHelper& helper = *i;
+
+ arts_debug("one voice terminated");
+ // put the MidiReleaseHelper and the voice into the ObjectCache
+ // (instead of simply freeing it)
+ ObjectCache cache = helper.cache();
+ SynthModule voice = helper.voice();
+ get_AMAN_PLAY(voice).stop();
+ voice.stop();
+ cache.put(voice,helper.name());
+ impls.erase(i);
+ return;
+ } else i++;
+ }
+ }
+} *autoMidiRelease;
+
+// cache startup & shutdown
+static class AutoMidiReleaseStart :public StartupClass
+{
+public:
+ void startup() { autoMidiRelease = new AutoMidiRelease(); }
+ void shutdown() { delete autoMidiRelease; }
+} autoMidiReleaseStart;
+
+class MidiReleaseHelper_impl : virtual public MidiReleaseHelper_skel,
+ virtual public StdSynthModule
+{
+protected:
+ bool _terminate;
+ SynthModule _voice;
+ ObjectCache _cache;
+ string _name;
+
+public:
+ MidiReleaseHelper_impl()
+ {
+ autoMidiRelease->impls.push_back(MidiReleaseHelper::_from_base(_copy()));
+ }
+ ~MidiReleaseHelper_impl() {
+ artsdebug("MidiReleaseHelper: one voice is gone now\n");
+ }
+
+
+ SynthModule voice() { return _voice; }
+ void voice(SynthModule voice) { _voice = voice; }
+
+ ObjectCache cache() { return _cache; }
+ void cache(ObjectCache cache) { _cache = cache; }
+
+ string name() { return _name; }
+ void name(const string& name) { _name = name; }
+
+ bool terminate() { return _terminate; }
+ void streamStart() { _terminate = false; }
+
+ void calculateBlock(unsigned long /*samples*/)
+ {
+ if(done[0] > 0.5)
+ _terminate = true;
+ }
+};
+REGISTER_IMPLEMENTATION(MidiReleaseHelper_impl);
+
+class Synth_MIDI_TEST_impl : virtual public Synth_MIDI_TEST_skel,
+ virtual public StdSynthModule {
+protected:
+ struct ChannelData {
+ SynthModule voice[128];
+ string name[128];
+ float pitchShiftValue;
+ mcopbyte program;
+ ChannelData() {
+ // initialize all voices with NULL objects (no lazy create)
+ for(int i = 0; i < 128; i++) voice[i] = SynthModule::null();
+
+ pitchShiftValue = 0.0;
+ program = 0;
+ }
+ } *channelData; /* data for all 16 midi channels */
+
+ bool useMap;
+ InstrumentMap map;
+ StructureDesc instrument;
+ StructureBuilder builder;
+ AudioManagerClient amClient;
+ ObjectCache cache;
+ MidiClient client;
+ MidiTimer timer;
+
+ string _filename;
+ string _busname;
+ string _title;
+public:
+ Synth_MIDI_TEST self() { return Synth_MIDI_TEST::_from_base(_copy()); }
+
+ Synth_MIDI_TEST_impl();
+ ~Synth_MIDI_TEST_impl();
+
+ void filename(const string& newname);
+ string filename()
+ {
+ return _filename;
+ }
+ void busname(const string& newname);
+ string busname()
+ {
+ return _busname;
+ }
+ string title()
+ {
+ return _title;
+ }
+ void noteOn(mcopbyte channel, mcopbyte note, mcopbyte velocity);
+ void noteOff(mcopbyte channel, mcopbyte note);
+ void pitchWheel(mcopbyte channel, mcopbyte lsb, mcopbyte msb);
+
+ float getFrequency(mcopbyte note,mcopbyte channel);
+
+ void streamStart();
+ void streamEnd();
+
+ TimeStamp time()
+ {
+ return timer.time();
+ }
+ TimeStamp playTime()
+ {
+ /*
+ * what the user currently hears is exactly latencySec before our
+ * port timeStamp (as this is the size of the audio buffer)
+ */
+ double latencySec = AudioSubSystem::the()->outputDelay();
+ TimeStamp t = time();
+
+ int sec = int(latencySec);
+ t.sec -= sec;
+ latencySec -= double(sec);
+ t.usec -= int(latencySec * 1000000.0);
+
+ if (t.usec < 0)
+ {
+ t.usec += 1000000;
+ t.sec -= 1;
+ }
+
+ arts_assert(t.usec >= 0 && t.usec < 1000000);
+ return t;
+ }
+ void processEvent(const MidiEvent& event)
+ {
+ timer.queueEvent(self(),event);
+ }
+ void processCommand(const MidiCommand& command)
+ {
+ mcopbyte channel = command.status & mcsChannelMask;
+
+ switch(command.status & mcsCommandMask)
+ {
+ case mcsNoteOn: noteOn(channel,command.data1,command.data2);
+ return;
+ case mcsNoteOff: noteOff(channel,command.data1);
+ return;
+ case mcsPitchWheel: pitchWheel(channel,command.data1,command.data2);
+ return;
+ case mcsProgram: channelData[channel].program = command.data1;
+ return;
+ case mcsParameter:
+ if(command.data1 == mcpAllNotesOff && command.data2 == 0)
+ for(mcopbyte note=0; note<128; note++)
+ noteOff(channel,note);
+ return;
+ }
+ }
+};
+REGISTER_IMPLEMENTATION(Synth_MIDI_TEST_impl);
+
+
+void Synth_MIDI_TEST_impl::busname(const string& newname)
+{
+ // TODO:
+ _busname = newname;
+}
+
+void Synth_MIDI_TEST_impl::filename(const string& newname)
+{
+ ifstream infile(newname.c_str());
+ string line;
+ vector<string> strseq;
+
+ while(getline(infile,line))
+ strseq.push_back(line);
+
+ _filename = newname;
+
+/* search extension */
+ string::const_reverse_iterator i;
+ string extension;
+ bool extensionok = false;
+
+ for(i = newname.rbegin(); i != newname.rend() && !extensionok; i++)
+ {
+ if(*i == '.')
+ extensionok = true;
+ else
+ extension.insert(extension.begin(), (char)tolower(*i));
+ }
+
+ if(extensionok && extension == "arts")
+ {
+ instrument.loadFromList(strseq);
+ _title = "aRts Instrument ("+instrument.name()+")";
+ useMap = false;
+ }
+ else if(extensionok && extension == "arts-map")
+ {
+ map.loadFromList(newname, strseq);
+ _title = "aRts Instrument (mapped)";
+ useMap = true;
+ }
+
+ if(!client.isNull())
+ client.title(title());
+ amClient.title(title());
+}
+
+Synth_MIDI_TEST_impl::Synth_MIDI_TEST_impl()
+ : amClient(amPlay, "aRts Instrument","Synth_MIDI_TEST")
+{
+ useMap = false;
+ client = MidiClient::null();
+ timer = SubClass("Arts::AudioMidiTimer");
+ channelData = new ChannelData[16];
+}
+
+Synth_MIDI_TEST_impl::~Synth_MIDI_TEST_impl()
+{
+ delete[] channelData;
+}
+
+void Synth_MIDI_TEST_impl::streamStart()
+{
+ // register with the midi manager
+ MidiManager manager = Reference("global:Arts_MidiManager");
+ if(!manager.isNull())
+ {
+ client = manager.addClient(mcdRecord,mctDestination,title(),
+ "Arts::Synth_MIDI_TEST");
+ client.addInputPort(self());
+ }
+ else
+ arts_warning("Synth_MIDI_TEST: no midi manager found - not registered");
+}
+
+void Synth_MIDI_TEST_impl::streamEnd()
+{
+ client = MidiClient::null();
+}
+
+void Synth_MIDI_TEST_impl::noteOn(mcopbyte channel, mcopbyte note,
+ mcopbyte velocity)
+{
+ if(velocity == 0)
+ {
+ noteOff(channel,note);
+ return;
+ }
+ if(!channelData[channel].voice[note].isNull())
+ {
+ noteOff(channel,note);
+ arts_info("Synth_MIDI_TEST: duplicate noteOn (mixed channels?)");
+ }
+
+ vector<InstrumentMap::InstrumentParam> *params = 0;
+ if(useMap)
+ {
+ mcopbyte program = channelData[channel].program;
+ StructureDesc sd = map.getInstrument(channel,note,velocity,program,params);
+ if(sd.isNull()) return;
+ instrument = sd;
+ }
+
+ Object structureObject = cache.get(instrument.name());
+ if(structureObject.isNull())
+ {
+ arts_debug("creating new structure");
+ structureObject = builder.createObject(instrument);
+
+ SynthModule play;
+ // TODO: allow changing busname!
+ if(!_busname.empty())
+ {
+ Synth_BUS_UPLINK b;
+ b.busname(_busname);
+ play = b;
+ }
+ else
+ {
+ Synth_AMAN_PLAY a(amClient);
+ play = a;
+ }
+ structureObject._addChild(play,"play");
+ connect(structureObject,"left",play,"left");
+ connect(structureObject,"right",play,"right");
+ }
+ else
+ {
+ arts_debug("used cached structure");
+ }
+
+ SynthModule structure = DynamicCast(structureObject);
+ assert(!structure.isNull());
+
+ if(params)
+ {
+ vector<InstrumentMap::InstrumentParam>::iterator pi;
+ for(pi = params->begin(); pi != params->end(); pi++)
+ {
+ DynamicRequest req(structure);
+
+ req.method("_set_"+pi->param).param(pi->value).invoke();
+ }
+ }
+ setValue(structure,"frequency",getFrequency(note,channel));
+ setValue(structure,"velocity",(float)velocity/127.0);
+ setValue(structure,"pressed",1.0);
+
+ get_AMAN_PLAY(structure).start();
+ structure.start();
+
+ channelData[channel].voice[note] = structure;
+ channelData[channel].name[note] = instrument.name();
+}
+
+void Synth_MIDI_TEST_impl::noteOff(mcopbyte channel, mcopbyte note)
+{
+ if(!channelData[channel].voice[note].isNull())
+ {
+ setValue(channelData[channel].voice[note],"pressed",0.0);
+
+ MidiReleaseHelper h;
+
+ h.voice(channelData[channel].voice[note]);
+ h.cache(cache);
+ h.name(channelData[channel].name[note]);
+
+ connect(channelData[channel].voice[note],"done",h,"done");
+ h.start();
+ assert(!h.terminate());
+ channelData[channel].voice[note] = SynthModule::null();
+ }
+}
+
+float Synth_MIDI_TEST_impl::getFrequency(mcopbyte note, mcopbyte channel)
+{
+ /* 2 semitones pitchshift */
+ return 261.63 * pow(2,((float)(note)+(channelData[channel].pitchShiftValue*2.0))/12.0)/32.0;
+}
+
+void Synth_MIDI_TEST_impl::pitchWheel(mcopbyte channel,
+ mcopbyte lsb, mcopbyte msb)
+{
+ mcopbyte note;
+
+ channelData[channel].pitchShiftValue =
+ (float)((lsb + msb*128) - (0x40*128))/8192.0;
+
+ for(note = 0; note < 128; note++)
+ {
+ if(!channelData[channel].voice[note].isNull())
+ setValue(channelData[channel].voice[note],"frequency",getFrequency(note,channel));
+ }
+}
diff --git a/arts/modules/synth/synth_moog_vcf_impl.cc b/arts/modules/synth/synth_moog_vcf_impl.cc
new file mode 100644
index 00000000..f20c8491
--- /dev/null
+++ b/arts/modules/synth/synth_moog_vcf_impl.cc
@@ -0,0 +1,91 @@
+/*
+
+ Copyright (C) 2000 Jeff Tranter
+ tranter@pobox.com
+
+ (C) 1999 Stefan Westerfeld
+ stefan@space.twc.de
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ */
+
+#include "artsmodulessynth.h"
+#include "stdsynthmodule.h"
+
+using namespace Arts;
+
+/*
+Try this. It's a really nice 4pole. Very Moog like.
+
+in[x] and out[x] are member variables, init to 0.0
+the controls:
+
+fc = cutoff, nearly linear [0,1] -> [0, fs/2]
+res = resonance [0, 4] -> [no resonance, self-oscillation]
+*/
+
+class Synth_MOOG_VCF_impl : virtual public Synth_MOOG_VCF_skel,
+ virtual public StdSynthModule
+{
+protected:
+ float _frequency, _resonance;
+ double freqcorrect;
+ double in1, in2, in3, in4;
+ double out1, out2, out3, out4;
+
+public:
+ float frequency() { return _frequency; }
+ void frequency(float newFrequency) { _frequency = newFrequency; }
+
+ float resonance() { return _resonance; }
+ void resonance(float newResonance) { _resonance = newResonance; }
+
+ void streamInit()
+ {
+ in1 = in2 = in3 = in4 = out1 = out2 = out3 = out4 = 0.0;
+ }
+
+ void calculateBlock(unsigned long samples)
+ {
+ freqcorrect = 1.16 / (double)(samplingRate / 2);
+
+ for (unsigned int i=0; i < samples; i++)
+ {
+ double input = invalue[i];
+ double fc = _frequency;
+ double res = _resonance;
+ double f = fc * freqcorrect;
+ double fb = res * (1.0 - 0.15 * f * f);
+
+ input -= out4 * fb;
+ input *= 0.35013 * (f * f) * (f * f);
+
+ out1 = input + 0.3 * in1 + (1 - f) * out1; // Pole 1
+ in1 = input;
+ out2 = out1 + 0.3 * in2 + (1 - f) * out2; // Pole 2
+ in2 = out1;
+ out3 = out2 + 0.3 * in3 + (1 - f) * out3; // Pole 3
+ in3 = out2;
+ out4 = out3 + 0.3 * in4 + (1 - f) * out4; // Pole 4
+ in4 = out3;
+
+ outvalue[i] = out4;
+ }
+ }
+
+};
+
+REGISTER_IMPLEMENTATION(Synth_MOOG_VCF_impl);
diff --git a/arts/modules/synth/synth_nil_impl.cc b/arts/modules/synth/synth_nil_impl.cc
new file mode 100644
index 00000000..ad927b85
--- /dev/null
+++ b/arts/modules/synth/synth_nil_impl.cc
@@ -0,0 +1,36 @@
+ /*
+
+ Copyright (C) 2000 Jeff Tranter
+ tranter@pobox.com
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "artsmodulessynth.h"
+#include "stdsynthmodule.h"
+
+using namespace Arts;
+
+// This module does nothing. It is only used for test purposes.
+class Synth_NIL_impl : virtual public Synth_NIL_skel,
+ virtual public StdSynthModule
+{
+public:
+ void calculateBlock(unsigned long /*samples*/) { }
+};
+
+REGISTER_IMPLEMENTATION(Synth_NIL_impl);
diff --git a/arts/modules/synth/synth_noise_impl.cc b/arts/modules/synth/synth_noise_impl.cc
new file mode 100644
index 00000000..77c41082
--- /dev/null
+++ b/arts/modules/synth/synth_noise_impl.cc
@@ -0,0 +1,63 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include <stdlib.h>
+
+#include "artsmodulessynth.h"
+#include "stdsynthmodule.h"
+
+using namespace Arts;
+
+namespace Arts {
+
+#define NOISE_SIZE 8192
+
+class Synth_NOISE_impl : virtual public Synth_NOISE_skel,
+ virtual public StdSynthModule
+{
+ static float noise[NOISE_SIZE];
+ static bool noiseInit;
+ unsigned long pos;
+public:
+ Synth_NOISE_impl()
+ {
+ if(!noiseInit)
+ {
+ for(unsigned long i=0;i<NOISE_SIZE;i++)
+ noise[i] = ((float)rand()/(float)RAND_MAX)*2.0-1.0;
+ noiseInit = true;
+ }
+ }
+ void calculateBlock(unsigned long samples)
+ {
+ unsigned long i;
+ pos = rand();
+ for(i=0;i<samples;i++) outvalue[i] = noise[pos++ & (NOISE_SIZE-1)];
+ }
+};
+
+float Synth_NOISE_impl::noise[8192];
+bool Synth_NOISE_impl::noiseInit = false;
+
+REGISTER_IMPLEMENTATION(Synth_NOISE_impl);
+
+}
diff --git a/arts/modules/synth/synth_osc_impl.cc b/arts/modules/synth/synth_osc_impl.cc
new file mode 100644
index 00000000..227f92cf
--- /dev/null
+++ b/arts/modules/synth/synth_osc_impl.cc
@@ -0,0 +1,253 @@
+ /*
+
+ Copyright (C) 2002 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "artsmodulessynth.h"
+#include "debug.h"
+#include "stdsynthmodule.h"
+#include <gsl/gsloscillator.h>
+#include <gsl/gslsignal.h>
+#include <string.h>
+
+#include <math.h>
+
+using namespace Arts;
+
+namespace Arts {
+
+static double arts_gsl_window_osc(double x)
+{
+ const double FILTER_H = 22000.0;
+ const double FILTER_L = 19000.0;
+ double f = 22050.0 * fabs(x), fact;
+
+ if(f > FILTER_H)
+ fact = 0.0;
+ else if (f < FILTER_L)
+ fact = 1.0;
+ else
+ fact = cos(M_PI/2.0*((FILTER_L-f)/(FILTER_H-FILTER_L)));
+
+ return fact;
+}
+
+class Synth_OSC_impl :public Synth_OSC_skel, public StdSynthModule
+{
+private:
+ GslOscConfig cfg;
+ GslOscData osc;
+ SynthOscWaveForm _waveForm;
+
+ bool infrequency_connected;
+ bool modulation_connected;
+ bool insync_connected;
+ bool outvalue_connected;
+ bool outsync_connected;
+
+ void updateConnected()
+ {
+ infrequency_connected = inputConnectionCount("infrequency");
+ modulation_connected = inputConnectionCount("modulation");
+ insync_connected = inputConnectionCount("insync");
+ outvalue_connected = outputConnectionCount("outvalue");
+ outsync_connected = outputConnectionCount("outsync");
+ }
+public:
+ Synth_OSC_impl() {
+ _waveForm = soWaveTriangle;
+
+ memset(&cfg, 0, sizeof(GslOscConfig));
+ memset(&osc, 0, sizeof(GslOscData));
+
+ cfg.table = 0;
+ cfg.exponential_fm = 0;
+ cfg.fm_strength = 0;
+ cfg.self_fm_strength = 0;
+ cfg.cfreq = 440;
+ cfg.fine_tune = 0;
+ cfg.pulse_width = 0.5;
+ cfg.pulse_mod_strength = 0;
+
+ waveForm(soWaveSine);
+ };
+ void apply()
+ {
+ gsl_osc_config(&osc, &cfg);
+ }
+ void streamInit()
+ {
+ updateConnected();
+ }
+ void calculateBlock(unsigned long samples)
+ {
+ if(connectionCountChanged())
+ updateConnected();
+
+ arts_debug("gop tab%p samples%ld f%p m%p is%p ov%p os%p\n",
+ cfg.table, samples, infrequency_connected?infrequency:0,
+ modulation_connected?modulation:0,
+ insync_connected?insync:0,
+ outvalue_connected?outvalue:0,
+ outsync_connected?outsync:0);
+
+ gsl_osc_process(&osc, samples, infrequency_connected?infrequency:0,
+ modulation_connected?modulation:0,
+ insync_connected?insync:0,
+ outvalue_connected?outvalue:0,
+ outsync_connected?outsync:0);
+ }
+ SynthOscWaveForm waveForm()
+ {
+ return _waveForm;
+ }
+ void waveForm(SynthOscWaveForm wf)
+ {
+ if(wf != _waveForm)
+ {
+ if(cfg.table)
+ gsl_osc_table_free(cfg.table);
+
+ float freqs[100];
+ int n_freqs = 0;
+
+ freqs[n_freqs] = 20;
+ while (freqs[n_freqs] < 22000)
+ {
+ freqs[n_freqs + 1] = freqs[n_freqs] * M_SQRT2;
+ n_freqs++;
+ }
+ arts_debug("Synth_OSC::waveForm: n_freqs = %d", n_freqs);
+ cfg.table = gsl_osc_table_create(samplingRateFloat, GslOscWaveForm(wf + 1), arts_gsl_window_osc, n_freqs, freqs);
+ _waveForm = wf;
+ apply();
+ waveForm_changed(wf);
+ }
+ }
+ bool fmExponential()
+ {
+ return cfg.exponential_fm;
+ }
+ void fmExponential(bool newFm)
+ {
+ bool oldFm = fmExponential();
+
+ if(newFm != oldFm)
+ {
+ cfg.exponential_fm = newFm;
+ apply();
+ fmExponential_changed(newFm);
+ }
+ }
+ float fmStrength()
+ {
+ return cfg.fm_strength;
+ }
+ void fmStrength(float f)
+ {
+ if(cfg.fm_strength != f)
+ {
+ cfg.fm_strength = f;
+ apply();
+ fmStrength_changed(f);
+ }
+ }
+ float fmSelfStrength()
+ {
+ return cfg.self_fm_strength;
+ }
+ void fmSelfStrength(float f)
+ {
+ if(cfg.self_fm_strength != f)
+ {
+ cfg.self_fm_strength = f;
+ apply();
+ fmSelfStrength_changed(f);
+ }
+ }
+ float phase()
+ {
+ return cfg.phase;
+ }
+ void phase(float p)
+ {
+ if(cfg.phase != p)
+ {
+ cfg.phase = p;
+ apply();
+ phase_changed(p);
+ }
+ }
+ float frequency()
+ {
+ return cfg.cfreq;
+ }
+ void frequency(float f)
+ {
+ if(cfg.cfreq != f)
+ {
+ cfg.cfreq = f;
+ apply();
+ frequency_changed(f);
+ }
+ }
+ long fineTune()
+ {
+ return cfg.fine_tune;
+ }
+ void fineTune(long f)
+ {
+ if(cfg.fine_tune != f)
+ {
+ cfg.fine_tune = f;
+ apply();
+ fineTune_changed(f);
+ }
+ }
+ float pulseWidth()
+ {
+ return cfg.pulse_width;
+ }
+ void pulseWidth(float pw)
+ {
+ if(cfg.pulse_width != pw)
+ {
+ cfg.pulse_width = pw;
+ apply();
+ pulseWidth_changed(pw);
+ }
+ }
+ float pulseModStrength()
+ {
+ return cfg.pulse_mod_strength;
+ }
+ void pulseModStrength(float pms)
+ {
+ if(cfg.pulse_mod_strength != pms)
+ {
+ cfg.pulse_mod_strength = pms;
+ apply();
+ pulseModStrength_changed(pms);
+ }
+ }
+};
+REGISTER_IMPLEMENTATION(Synth_OSC_impl);
+
+}
diff --git a/arts/modules/synth/synth_pitch_shift_fft_impl.cc b/arts/modules/synth/synth_pitch_shift_fft_impl.cc
new file mode 100644
index 00000000..f356e1b8
--- /dev/null
+++ b/arts/modules/synth/synth_pitch_shift_fft_impl.cc
@@ -0,0 +1,431 @@
+/*
+ * Copyright (C) 2002 Michael Zuercher
+ * mzuerche@iastate.edu
+ *
+ * Based on an algorithm by Stephan M. Sprenger, http://www.dspdimension.com
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list
+ * of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this
+ * list of conditions and the following disclaimer in the documentation and/or
+ * other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ */
+
+
+
+#include "artsmodulessynth.h"
+#include "stdsynthmodule.h"
+#include <stdio.h> //debug only
+#include <arts/fft.h>
+#include <string.h>
+#include <math.h>
+
+#define MAX(a,b) (((a) > (b) ? (a) : (b)))
+#define MIN(a,b) (((a) < (b) ? (a) : (b)))
+
+using namespace Arts;
+
+class Synth_PITCH_SHIFT_FFT_impl : virtual public Synth_PITCH_SHIFT_FFT_skel,
+ virtual public StdSynthModule
+{
+ private:
+ struct fftBin
+ {
+ float magnitude;
+ float frequency;
+ float phase;
+ };
+
+ bool addPi;
+
+ /* the attributes (gui changeable) */
+ /* these can happen on the fly */
+ float _scaleFactor, _speed;
+ /* these require calling setStreamOpts() */
+ unsigned int _frameSize, _oversample;
+
+ /* the buffers */
+ float *inBuffer, *outBuffer; /* circular buffers (float) */
+ float *windowedData; /* windowed and unrolled buffer (float) */
+ fftBin *analysisBuf, *synthesisBuf; /* workspaces (fftBin) */
+ float *real, *imag; /* place for the FFT to output */
+ float *windowCoeffient;
+ float *scratch; /* used to store imag IFFT results that we don't need */
+ float *phaseDiff;
+
+ /* variables to keep us in the right place of the buffers */
+ unsigned long bufferOffset;
+ /* stream not yet ready to go until we have prerolled this many windows */
+ unsigned int initStepsRemaining;
+
+ /* some commonly used variables */
+ unsigned long stepSize;
+ double expectedPhaseDiff;
+ double freqPerBin;
+
+ /* Helper functions */
+ void inWindow(float windowedData[], const float *inBuffer, const unsigned int basePopPoint);
+ void analysis(fftBin analysisBuf[], const float real[]);
+ void pitchScale(fftBin synthesisBuf[], const fftBin analysisBuf[]);
+ void synthesis(float windowedData[], fftBin synthesisBuf[]);
+ void outWindow(float *outBuffer, const unsigned int basePushPoint, const float windowedData[]);
+
+
+ public:
+ /* functions for the plugin interface */
+ float speed() { return _speed; }
+ void speed(float newSpeed) { _speed = newSpeed; }
+
+ float scaleFactor() { return _scaleFactor; }
+ void scaleFactor(float newScaleFactor) { _scaleFactor = newScaleFactor; }
+
+ long frameSize() { return (long)_frameSize; }
+ void frameSize(long newFrameSize)
+ {
+ setStreamOpts(newFrameSize, _oversample);
+ }
+
+ long oversample() { return (long)_oversample; }
+ void oversample(long newOversample)
+ {
+ setStreamOpts(_frameSize, newOversample);
+ }
+
+ /* gets called by arts when it needs more data */
+ void calculateBlock(unsigned long samples);
+
+ void streamInit()
+ {
+ inBuffer = outBuffer = NULL;
+ analysisBuf = synthesisBuf = NULL;
+ real = imag = NULL;
+ windowedData = NULL;
+ windowCoeffient = NULL;
+ scratch = NULL;
+ phaseDiff = NULL;
+
+ /* setup default stream parameters */
+ _speed = 1.0;
+ _scaleFactor = 0.9;
+ setStreamOpts(4096,2);
+
+ addPi = false;
+ }
+
+ void streamEnd()
+ {
+ /* clean up buffers */
+ delete [] inBuffer;
+ delete [] outBuffer;
+ delete [] windowedData;
+ delete [] analysisBuf;
+ delete [] synthesisBuf;
+ delete [] real;
+ delete [] imag;
+ delete [] windowCoeffient;
+ delete [] scratch;
+ delete [] phaseDiff;
+ }
+
+ void setStreamOpts(unsigned int frameSize, unsigned int oversample)
+ {
+ /* clear any buffers left around */
+ delete [] inBuffer;
+ delete [] outBuffer;
+ delete [] windowedData;
+ delete [] analysisBuf;
+ delete [] synthesisBuf;
+ delete [] real;
+ delete [] imag;
+ delete [] windowCoeffient;
+ delete [] scratch;
+ delete [] phaseDiff;
+
+ _frameSize = frameSize;
+ _oversample = oversample;
+
+ /* create the buffers */
+ inBuffer = new float[_frameSize];
+ outBuffer = new float[_frameSize];
+ windowedData = new float[_frameSize];
+ analysisBuf = new fftBin[_frameSize];
+ synthesisBuf = new fftBin[_frameSize];
+ real = new float[_frameSize];
+ imag = new float[_frameSize];
+ windowCoeffient = new float[_frameSize];
+ scratch = new float[_frameSize];
+ phaseDiff = new float[_oversample];
+
+
+ /* set up the windowing coeffients */
+ for(unsigned int sample=0; sample < _frameSize; sample++)
+ {
+ windowCoeffient[sample] = -0.5*cos(2.0*M_PI*(double)sample/(double)_frameSize)+0.5;
+ }
+
+ /* we should start at the beginning of the buffers */
+ bufferOffset = 0;
+
+ /* stream not yet ready to go until we have prerolled this many windows */
+ initStepsRemaining = _oversample;
+
+ /* calculate some commonly used variables */
+ stepSize = _frameSize / _oversample;
+ expectedPhaseDiff = 2*M_PI*(double)stepSize/(double)_frameSize;
+ freqPerBin = samplingRate/(double)_frameSize;
+
+ for(unsigned int bin=0; bin < _oversample; bin++)
+ {
+ phaseDiff[bin] = bin*expectedPhaseDiff;
+ }
+
+ memset(outBuffer, 0 ,stepSize * sizeof(float)); /* clear the first part of the output accumulator */
+ memset(analysisBuf, 0 ,_frameSize * sizeof(fftBin));
+ memset(synthesisBuf, 0 ,_frameSize * sizeof(fftBin));
+ }
+};
+
+void Synth_PITCH_SHIFT_FFT_impl::calculateBlock(unsigned long samples)
+{
+ unsigned long samplesRemaining = samples;
+
+ /* pointers to the arts streams */
+ float *inData = inStream;
+ float *outData = outStream;
+
+ while(samplesRemaining > 0)
+ {
+ /* either fill the next window, or take all we have */
+ int samplesThisPass = MIN(samplesRemaining,stepSize - (bufferOffset % stepSize));
+
+ /* copy the incoming data into the buffer */
+ memcpy(inBuffer + bufferOffset, inData, samplesThisPass * sizeof(float));
+ /* set inData to data we haven't already taken */
+ inData += samplesThisPass;
+
+ if((bufferOffset+samplesThisPass) % stepSize)
+ {
+ /* if we still have only a partial window (input is still in the
+ * middle of a window), we can't run it yet, but we have leftover
+ * output we can use */
+ }
+ else
+ {
+ /* round down the the nearest stepSize, and this window is full */
+
+ if(initStepsRemaining > 0) /* we need to have enough old data for a full block too */
+ {
+ initStepsRemaining--; /* one less step to fill before we can start for real */
+ }
+ else
+ {
+ unsigned int stepOffset = (bufferOffset + samplesThisPass) - stepSize;
+ /* now we have a complete block (not still filling at init) to add the
+ * new complete window on to */
+
+ /* ############################ prepare one stepSize ########################### */
+
+ inWindow(windowedData,inBuffer,stepOffset);
+ analysis(analysisBuf,windowedData);
+ pitchScale(synthesisBuf,analysisBuf);
+ synthesis(windowedData,synthesisBuf);
+ outWindow(outBuffer,bufferOffset,windowedData);
+
+ /* ############################################################################# */
+ }
+ }
+
+ memcpy(outData, outBuffer + bufferOffset, samplesThisPass * sizeof(float));
+ outData += samplesThisPass;
+ memset(outBuffer + bufferOffset, 0 ,samplesThisPass * sizeof(float)); /* clear the output space that we have used */
+ bufferOffset += samplesThisPass;
+ bufferOffset %= _frameSize; /* wrap if needed before the next frame starts */
+ samplesRemaining -= samplesThisPass;
+ }
+}
+
+void Synth_PITCH_SHIFT_FFT_impl::inWindow(float windowedData[], const float *inBuffer, const unsigned int basePopPoint)
+{
+ unsigned int sample;
+ for(sample=0; sample < _frameSize-basePopPoint; sample++)
+ {
+ /* window the data and unroll the buffers */
+ windowedData[sample] = inBuffer[basePopPoint + sample] * windowCoeffient[sample];
+ }
+ for(; sample < _frameSize; sample++)
+ {
+ /* window the data and unroll the buffers */
+ windowedData[sample] = inBuffer[(basePopPoint + sample) - _frameSize] * windowCoeffient[sample];
+ }
+}
+
+void Synth_PITCH_SHIFT_FFT_impl::analysis(fftBin analysisBuf[], const float windowedData[])
+{
+ float lastPhase;
+ float phaseDrift;
+
+ /* do forward FFT */
+ /* const_cast because arts_fft_float is silly */
+ arts_fft_float(_frameSize, 0, const_cast<float *>(windowedData), NULL, real, imag);
+
+ /* the actual analysis loop */
+ for(unsigned int bin=0; bin < _frameSize/2; bin++)
+ {
+ lastPhase = analysisBuf[bin].phase;
+
+ /* compute magnitude and phase */
+ analysisBuf[bin].magnitude = 2.0 * sqrt(real[bin]*real[bin] + imag[bin]*imag[bin]);
+ analysisBuf[bin].phase = atan2(imag[bin],real[bin]);
+
+
+ /* compute phase difference and subtract expected phase difference */
+ phaseDrift = (analysisBuf[bin].phase - lastPhase) - float(phaseDiff[bin % _oversample]);
+
+ /* we now need to map it into the +/- Pi interval */
+ while(phaseDrift < -M_PI)
+ phaseDrift += 2*M_PI;
+ while(phaseDrift > M_PI)
+ phaseDrift -= 2*M_PI;
+
+ /* compute true frequency */
+ analysisBuf[bin].frequency = (bin + ((phaseDrift * _oversample) / (2*M_PI)))*freqPerBin;
+ //analysisBuf[bin].frequency = (bin + (phaseDrift/(2*M_PI)))*freqPerBin;
+ }
+
+}
+
+void Synth_PITCH_SHIFT_FFT_impl::pitchScale(fftBin synthesisBuf[], const fftBin analysisBuf[])
+{
+ unsigned int sourceBin;
+ for(unsigned int destBin=0; destBin < _frameSize/2; destBin++)
+ {
+ sourceBin = (unsigned int)floor(destBin/_scaleFactor);
+ if(sourceBin < _frameSize/2)
+ {
+ /* new bin overrides existing if magnitude is higher */
+ //if(analysisBuf[sourceBin].magnitude > synthesisBuf[destBin].magnitude)
+ //{
+ synthesisBuf[destBin].magnitude = analysisBuf[sourceBin].magnitude;
+ synthesisBuf[destBin].frequency = analysisBuf[sourceBin].frequency * _scaleFactor;
+ //}
+#if 0
+ /* fill empty bins with nearest neighbor */
+ if((synthesisBuf[destBin].frequency == 0.0) && (destBin > 0))
+ {
+ cerr << "Empty bins\n";
+ synthesisBuf[destBin].frequency = synthesisBuf[destBin-1].frequency;
+ synthesisBuf[destBin].magnitude = synthesisBuf[destBin-1].magnitude;
+ }
+#endif
+ }
+ else
+ {
+ synthesisBuf[destBin].magnitude = 0;
+ }
+ }
+#if 0
+ for(unsigned int destBin=0; destBin < _frameSize/2; destBin++)
+ {
+ synthesisBuf[destBin].magnitude = analysisBuf[destBin].magnitude;
+ synthesisBuf[destBin].frequency = analysisBuf[destBin].frequency;
+ }
+#endif
+}
+
+void Synth_PITCH_SHIFT_FFT_impl::synthesis(float windowedData[], fftBin synthesisBuf[])
+{
+ double phaseDrift;
+
+#if 0
+ double test;
+ if(addPi == true)
+ test = -M_PI;
+ else
+ test = 0;
+#endif
+
+ for(unsigned int bin=0;bin < _frameSize/2; bin++)
+ {
+ /* deviation of this bin's phase from one exactly at the true bin frequency */
+ //phaseDrift = (((synthesisBuf[bin].frequency - bin*freqPerBin)/ freqPerBin)*(2*M_PI))/_oversample;
+ phaseDrift = (synthesisBuf[bin].frequency / freqPerBin - bin)*(2*M_PI)/_oversample;
+ //phaseDrift = 0;
+
+
+ /* calculate the real and imag data */
+ real[bin] = synthesisBuf[bin].magnitude * cos(synthesisBuf[bin].phase);
+ imag[bin] = synthesisBuf[bin].magnitude * sin(synthesisBuf[bin].phase);
+
+ /* accumulate current phase for this wave */
+ synthesisBuf[bin].phase += (phaseDrift + phaseDiff[bin % _oversample]);
+ //synthesisBuf[bin].phase += (phaseDrift + phaseDiff[bin % _oversample] + test);
+
+ /* keep it so that -M_PI < phase < M_PI */
+ while(synthesisBuf[bin].phase > M_PI)
+ synthesisBuf[bin].phase -= 2*M_PI;
+ while(synthesisBuf[bin].phase <= -M_PI)
+ synthesisBuf[bin].phase += 2*M_PI;
+
+
+#if 0
+ //this needs to happen so that that 'strongest wave' picking in pitchScale works
+ //but this isn't really the right place to do it
+ synthesisBuf[bin].magnitude = 0;
+ synthesisBuf[bin].frequency = 0;
+#endif
+
+ }
+
+ /* zero the conjugate numbers */
+ for(unsigned int i = _frameSize/2; i < _frameSize; i++)
+ {
+ real[i] = 0.0;
+ imag[i] = 0.0;
+ }
+
+#if 0
+ if(addPi == false)
+ addPi = true;
+ else
+ addPi = false;
+#endif
+
+ /* do the inverse transform */
+ arts_fft_float(_frameSize, 1, real, imag, windowedData, scratch);
+}
+
+void Synth_PITCH_SHIFT_FFT_impl::outWindow(float *outBuffer, const unsigned int basePushPoint, const float windowedData[])
+{
+ unsigned int sample;
+
+ for(sample=0; sample < _frameSize - basePushPoint; sample++)
+ {
+ /* window the data and accumulate it back into the circular buffer */
+ outBuffer[sample+basePushPoint] += 2.0 * windowCoeffient[sample] * windowedData[sample]/(_oversample);
+ }
+ for(; sample < _frameSize; sample++)
+ {
+ /* window the data and accumulate it back into the circular buffer */
+ outBuffer[(sample+basePushPoint) - _frameSize] += 2.0 * windowCoeffient[sample] * windowedData[sample]/(_oversample);
+ }
+}
+
+
+REGISTER_IMPLEMENTATION(Synth_PITCH_SHIFT_FFT_impl);
diff --git a/arts/modules/synth/synth_pitch_shift_impl.cc b/arts/modules/synth/synth_pitch_shift_impl.cc
new file mode 100644
index 00000000..273d9fd7
--- /dev/null
+++ b/arts/modules/synth/synth_pitch_shift_impl.cc
@@ -0,0 +1,196 @@
+/*
+
+ Copyright (C) 2000 Jeff Tranter
+ tranter@pobox.com
+
+ (C) 1999 Stefan Westerfeld
+ stefan@space.twc.de
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ */
+
+#include <math.h>
+#include "artsmodulessynth.h"
+#include "stdsynthmodule.h"
+
+using namespace Arts;
+
+class Synth_PITCH_SHIFT_impl : virtual public Synth_PITCH_SHIFT_skel,
+ virtual public StdSynthModule
+{
+protected:
+ float _speed, _frequency;
+
+ enum { MAXDELAY = 44100 };
+ float *dbuffer;
+ float lfopos, b1pos, b2pos, b1inc, b2inc;
+ bool b1reset, b2reset, initialized;
+ int dbpos;
+
+public:
+ Synth_PITCH_SHIFT_impl() : _speed(1.0), _frequency(5.0)
+ {
+ }
+
+ float speed() { return _speed; }
+ void speed(float newSpeed) { _speed = newSpeed; }
+
+ float frequency() { return _frequency; }
+ void frequency(float newFrequency) { _frequency = newFrequency; }
+
+
+ void streamInit()
+ {
+ dbuffer = new float[MAXDELAY];
+ for (dbpos=0; dbpos<MAXDELAY; dbpos++)
+ dbuffer[dbpos] = 0;
+
+ dbpos = 0;
+ initialized = false;
+ lfopos = 0;
+ }
+ void streamEnd()
+ {
+ delete[] dbuffer;
+ }
+
+ void calculateBlock(unsigned long samples)
+ {
+ float *outend = outvalue + samples;
+ float fsr = (float)samplingRate;
+ float pi2 = 2*M_PI;
+ float lfo, b1value, b2value;
+ float lfoposinc = _frequency / fsr;
+
+ if (!initialized)
+ {
+ if (_speed <= 1.0) {
+ b1pos = b2pos = 0.0;
+ b1inc = b2inc = 1.0 - _speed;
+ } else {
+ /* not yet sure what would be a nice initialization here? */
+ b1pos = b2pos = 0.0;
+ b1inc = b2inc = 0.0;
+ }
+ initialized = true;
+ }
+
+ while (outvalue < outend)
+ {
+ /*
+ * fill delay buffer with the input signal
+ */
+ dbuffer[dbpos] = *invalue++;
+
+ lfopos += lfoposinc;
+ lfopos -= floor(lfopos);
+
+ if (lfopos < 0.25) {
+ b1reset = b2reset = false;
+ }
+
+ /*
+ * _speed < 1.0 (downpitching)
+ *
+ * start with current sample and increase delay slowly
+ *
+ * _speed > 1.0 (uppitching)
+ *
+ * start with a sample from long ago and slowly decrease delay
+ */
+ if (!b1reset && lfopos > 0.25) {
+ if (_speed <= 1.0) {
+ b1pos = 0;
+ b1inc = 1 - _speed;
+ } else {
+ b1inc = 1 - _speed;
+ b1pos = 10 + ((-b1inc) * (1 / lfoposinc));
+ /* 10+ are not strictly necessary */
+ }
+ b1reset = true;
+ }
+
+ if (!b2reset && lfopos > 0.75) {
+ if (_speed <= 1.0) {
+ b2pos = 0;
+ b2inc = 1 - _speed;
+ } else{
+ b2inc = 1 - _speed;
+ b2pos = 10 + ((-b2inc) * (1/lfoposinc));
+ /* 10+ are not strictly necessary */
+ }
+ b2reset = true;
+ }
+
+ b1pos += b1inc;
+ b2pos += b2inc;
+
+ int position, position1;
+ double error,int_pos;
+
+ /*
+ * Interpolate value from buffer position 1
+ */
+ error = modf(b1pos, &int_pos);
+
+ position = dbpos - (int)int_pos;
+ if (position < 0)
+ position += MAXDELAY;
+ position1 = position - 1;
+ if (position1 < 0)
+ position1 += MAXDELAY;
+
+ b1value = dbuffer[position] * (1 - error) + dbuffer[position1] * error;
+
+ /*
+ * Interpolate value from buffer position 2
+ */
+ error = modf(b2pos,&int_pos);
+
+ position = dbpos - (int)int_pos;
+ if (position < 0)
+ position += MAXDELAY;
+ position1 = position-1;
+ if ( position1 < 0)
+ position1 += MAXDELAY;
+
+ b2value = dbuffer[position]*(1-error) + dbuffer[position1]*error;
+
+ /*
+ * Calculate output signal from these two buffers
+ */
+
+ lfo = (sin(pi2 * lfopos) + 1) / 2;
+
+ /* position sin lfo variable
+ *------------------------------------------------------------------
+ * lfo value: 0.25 1 1 => buffer 2 is used
+ * 0.75 -1 0 => buffer 1 is used
+ */
+
+ *outvalue++ = b1value * (1.0 - lfo) + b2value * lfo;
+
+ /*
+ * increment delay buffer position
+ */
+ dbpos++;
+ if (dbpos == MAXDELAY)
+ dbpos = 0;
+ }
+ }
+};
+
+REGISTER_IMPLEMENTATION(Synth_PITCH_SHIFT_impl);
diff --git a/arts/modules/synth/synth_play_pat_impl.cc b/arts/modules/synth/synth_play_pat_impl.cc
new file mode 100644
index 00000000..4913e991
--- /dev/null
+++ b/arts/modules/synth/synth_play_pat_impl.cc
@@ -0,0 +1,529 @@
+# /*
+
+ Copyright (C) 2001 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "artsmodulessynth.h"
+#include <sys/stat.h>
+#include <stdsynthmodule.h>
+#include <unistd.h>
+#include <math.h>
+#include <debug.h>
+#include <cache.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+using namespace std;
+
+namespace Arts {
+
+namespace PatchLoader {
+ typedef unsigned char byte;
+ typedef unsigned short int word;
+ typedef unsigned int dword;
+ typedef char sbyte;
+ typedef short int sword;
+ typedef int sdword;
+
+ static int pos = 0;
+ static int apos = 0;
+
+ inline void xRead(FILE *file, int len, void *data)
+ {
+ // printf("(0x%2x) - 0x%02x ... reading %d bytes\n",apos,pos,len);
+ pos += len;
+ apos += len;
+ if(fread(data, len, 1, file) != 1)
+ fprintf(stdout, "short read\n");
+ }
+
+ inline void skip(FILE *file, int len)
+ {
+ // printf("(0x%2x) - 0x%02x ... skipping %d bytes\n",apos,pos,len);
+ pos += len;
+ apos += len;
+ while(len > 0)
+ {
+ char junk;
+ if(fread(&junk, 1, 1, file) != 1)
+ fprintf(stdout, "short read\n");
+ len--;
+ }
+ }
+
+
+ inline void readBytes(FILE *file, unsigned char *bytes, int len)
+ {
+ xRead(file, len, bytes);
+ }
+
+ inline void readString(FILE *file, char *str, int len)
+ {
+ xRead(file, len, str);
+ }
+
+ /* readXXX with sizeof(xxx) == 1 */
+ inline void readByte(FILE *file, byte& b)
+ {
+ xRead(file, 1, &b);
+ }
+
+ /* readXXX with sizeof(xxx) == 2 */
+ inline void readWord(FILE *file, word& w)
+ {
+ byte h, l;
+ xRead(file, 1, &l);
+ xRead(file, 1, &h);
+ w = (h << 8) + l;
+ }
+
+ inline void readSWord(FILE *file, sword& sw)
+ {
+ word w;
+ readWord(file, w);
+ sw = (sword)w;
+ }
+
+ /* readXXX with sizeof(xxx) == 4 */
+ inline void readDWord(FILE *file, dword& dw)
+ {
+ byte h, l, hh, hl;
+ xRead(file, 1, &l);
+ xRead(file, 1, &h);
+ xRead(file, 1, &hl);
+ xRead(file, 1, &hh);
+ dw = (hh << 24) + (hl << 16) + (h << 8) + l;
+ }
+
+ struct PatHeader {
+ char id[12]; /* ID='GF1PATCH110' */
+ char manufacturer_id[10]; /* Manufacturer ID */
+ char description[60]; /* Description of the contained Instruments
+ or copyright of manufacturer. */
+ byte instruments; /* Number of instruments in this patch */
+ byte voices; /* Number of voices for sample */
+ byte channels; /* Number of output channels
+ (1=mono,2=stereo) */
+ word waveforms; /* Number of waveforms */
+ word mastervolume; /* Master volume for all samples */
+ dword size; /* Size of the following data */
+ char reserved[36]; /* reserved */
+
+ PatHeader(FILE *file)
+ {
+ readString(file, id, 12);
+ readString(file, manufacturer_id, 10);
+ readString(file, description, 60);
+ /* skip(file, 2);*/
+
+ readByte(file, instruments);
+ readByte(file, voices);
+ readByte(file, channels);
+
+ readWord(file, waveforms);
+ readWord(file, mastervolume);
+ readDWord(file, size);
+
+ readString(file, reserved, 36);
+ }
+ };
+
+ struct PatInstrument {
+ word number;
+ char name[16];
+ dword size; /* Size of the whole instrument in bytes. */
+ byte layers;
+ char reserved[40];
+
+ /* layer? */
+ word layerUnknown;
+ dword layerSize;
+ byte sampleCount; /* number of samples in this layer (?) */
+ char layerReserved[40];
+
+ PatInstrument(FILE *file)
+ {
+ readWord(file, number);
+ readString(file, name, 16);
+ readDWord(file, size);
+ readByte(file, layers);
+ readString(file, reserved, 40);
+
+ /* layer: (?) */
+ readWord(file, layerUnknown);
+ readDWord(file, layerSize);
+ readByte(file, sampleCount);
+ readString(file, reserved, 40);
+ }
+ };
+
+ struct PatPatch {
+ char filename[7]; /* Wave file name */
+ byte fractions; /* Fractions */
+ dword wavesize; /* Wave size.
+ Size of the wave digital data */
+ dword loopStart;
+ dword loopEnd;
+ word sampleRate;
+ dword minFreq;
+ dword maxFreq;
+ dword origFreq;
+ sword fineTune;
+ byte balance;
+ byte filterRate[6];
+ byte filterOffset[6];
+ byte tremoloSweep;
+ byte tremoloRate;
+ byte tremoloDepth;
+ byte vibratoSweep;
+ byte vibratoRate;
+ byte vibratoDepth;
+ byte waveFormat;
+ sword freqScale;
+ word freqScaleFactor;
+ char reserved[36];
+
+ PatPatch(FILE *file)
+ {
+ readString(file, filename, 7);
+ readByte(file, fractions);
+ readDWord(file, wavesize);
+ readDWord(file, loopStart);
+ readDWord(file, loopEnd);
+ readWord(file, sampleRate);
+ readDWord(file, minFreq);
+ readDWord(file, maxFreq);
+ readDWord(file, origFreq);
+ readSWord(file, fineTune);
+ readByte(file, balance);
+ readBytes(file, filterRate, 6);
+ readBytes(file, filterOffset, 6);
+ readByte(file, tremoloSweep);
+ readByte(file, tremoloRate);
+ readByte(file, tremoloDepth);
+ readByte(file, vibratoSweep);
+ readByte(file, vibratoRate);
+ readByte(file, vibratoDepth);
+ readByte(file, waveFormat);
+ readSWord(file, freqScale);
+ readWord(file, freqScaleFactor);
+ readString(file, reserved, 36);
+ }
+ };
+}
+
+class CachedPat : public CachedObject
+{
+protected:
+ struct stat oldstat;
+ string filename;
+ bool initOk;
+ long dataSize;
+
+ CachedPat(Cache *cache, const string& filename);
+ ~CachedPat();
+
+public:
+
+ struct Data {
+ PatchLoader::PatPatch patch;
+ mcopbyte *rawdata;
+ Data(FILE *file)
+ : patch(file)
+ {
+ rawdata = new mcopbyte[patch.wavesize];
+ fread(rawdata, 1, patch.wavesize, file);
+
+ // sign conversion only for 16bit!
+ if(patch.waveFormat & (1 << 1))
+ {
+ for(unsigned int i = 1; i < patch.wavesize; i+=2)
+ rawdata[i] ^= 0x80;
+ }
+
+ // unfold ping-pong loops
+ if(patch.waveFormat & (1 << 3))
+ {
+ int looplen = patch.loopEnd - patch.loopStart;
+ arts_assert(looplen > 0);
+
+ mcopbyte *newdata = new mcopbyte[patch.wavesize + looplen];
+
+ // copy head
+ memcpy(&newdata[0], &rawdata[0], patch.loopStart + looplen);
+
+ // 16 bit unfolding only:
+ for(int i=0; i<looplen; i+=2)
+ {
+ newdata[patch.loopStart+looplen+i] =
+ newdata[patch.loopStart+looplen-i-2];
+ newdata[patch.loopStart+looplen+i+1] =
+ newdata[patch.loopStart+looplen-i-1];
+ }
+
+ // copy tail:
+ memcpy(&newdata[patch.loopStart+2*looplen],
+ &rawdata[patch.loopStart+looplen],
+ patch.wavesize - patch.loopEnd);
+
+ delete[] rawdata;
+ rawdata = newdata;
+
+ patch.wavesize += looplen;
+ patch.loopEnd += looplen;
+ patch.waveFormat &= ~(1 << 3);
+ }
+ }
+ ~Data()
+ {
+ delete[] rawdata;
+ }
+ };
+
+ list<Data*> dList;
+
+ static CachedPat *load(Cache *cache, const string& filename);
+ /**
+ * validity test for the cache - returns false if the object is having
+ * reflecting the correct contents anymore (e.g. if the file on the
+ * disk has changed), and there is no point in keeping it in the cache any
+ * longer
+ */
+ bool isValid();
+ /**
+ * memory usage for the cache
+ */
+ int memoryUsage();
+};
+
+CachedPat *CachedPat::load(Cache *cache, const string& filename)
+{
+ CachedPat *pat;
+
+ pat = (CachedPat *)cache->get(string("CachedPat:")+filename);
+ if(!pat) {
+ pat = new CachedPat(cache, filename);
+
+ if(!pat->initOk) // loading failed
+ {
+ pat->decRef();
+ return 0;
+ }
+ }
+
+ return pat;
+}
+
+bool CachedPat::isValid()
+{
+ if(!initOk)
+ return false;
+
+ struct stat newstat;
+
+ lstat(filename.c_str(),&newstat);
+ return(newstat.st_mtime == oldstat.st_mtime);
+}
+
+int CachedPat::memoryUsage()
+{
+ return dataSize;
+}
+
+CachedPat::CachedPat(Cache *cache, const string& filename)
+ : CachedObject(cache), filename(filename), initOk(false), dataSize(0)
+{
+ setKey(string("CachedPat:")+filename);
+
+ if(lstat(filename.c_str(),&oldstat) == -1)
+ {
+ arts_info("CachedPat: Can't stat file '%s'", filename.c_str());
+ return;
+ }
+
+ FILE *patfile = fopen(filename.c_str(), "r");
+ if(patfile)
+ {
+ //PatchLoader::PatHeader header(patfile);
+ PatchLoader::PatInstrument ins(patfile);
+
+ for(int i=0;i<ins.sampleCount;i++)
+ {
+ Data *data = new Data(patfile);
+ dList.push_back(data);
+ dataSize += data->patch.wavesize;
+ }
+ fclose(patfile);
+
+ arts_debug("loaded pat %s",filename.c_str());
+ arts_debug(" %d patches, datasize total is %d bytes",
+ ins.sampleCount, dataSize);
+
+ initOk = true;
+ }
+}
+
+CachedPat::~CachedPat()
+{
+ while(!dList.empty())
+ {
+ delete dList.front();
+ dList.pop_front();
+ }
+}
+
+class Synth_PLAY_PAT_impl : virtual public Synth_PLAY_PAT_skel,
+ virtual public StdSynthModule
+{
+protected:
+ string _filename;
+ CachedPat *pat;
+ CachedPat::Data *selected;
+ float fpos;
+
+public:
+ Synth_PLAY_PAT_impl()
+ {
+ pat = 0;
+ selected = 0;
+ }
+
+ void unload()
+ {
+ if(pat)
+ {
+ pat->decRef();
+ pat = 0;
+ }
+ }
+
+ ~Synth_PLAY_PAT_impl()
+ {
+ unload();
+ }
+
+ void streamStart()
+ {
+ fpos = 0.0;
+ selected = 0;
+ }
+
+ void calculateBlock(unsigned long samples)
+ {
+ /* the normal offset is 60
+ 60 = 12*5
+ so we scale with 2^5 = 32
+ */
+ float freq = frequency[0]; /* * 32.0 / 2.0; * why /2.0? */
+ int ifreq = (int)(freq * 1024.0);
+ if(!selected && pat)
+ {
+ int bestdiff = 20000 * 1024;
+
+ list<CachedPat::Data*>::iterator i;
+ for(i = pat->dList.begin(); i != pat->dList.end(); i++)
+ {
+ int diff = ::abs(double(ifreq - (*i)->patch.origFreq));
+ if(diff < bestdiff)
+ {
+ selected = *i;
+ bestdiff = diff;
+ }
+ }
+
+ /* drums */
+ if(selected && selected->patch.freqScaleFactor == 0)
+ ifreq = selected->patch.origFreq;
+ }
+ if(selected)
+ {
+ const PatchLoader::PatPatch& patch = selected->patch;
+
+ /*
+ * thats just a *guess*, I have no idea how tuning actually
+ * should work
+ */
+#if 0
+ float tonetune = float(pat.fineTune)/float(pat.freqScaleFactor);
+ float tuning = pow(2.0, tonetune/12.0);
+ freq *= tuning;
+#endif
+ //printf("tonetune: %f\n",tonetune);
+ //printf("tuning: %f\n",tuning);
+
+ float step = double(patch.sampleRate)/samplingRateFloat *
+ float(ifreq) / float(patch.origFreq);
+ for(unsigned int i = 0; i < samples; i++)
+ {
+ // ASSUME 16bit signed, native byte order
+ int ifpos = int(fpos)*2;
+
+ // looped? bidi? backw?
+ if((patch.waveFormat & ((1 << 2) + (1 << 3) + (1 << 4)))
+ == (1 << 2))
+ {
+ while(ifpos >= signed(patch.loopEnd))
+ {
+ ifpos -= (patch.loopEnd - patch.loopStart);
+ fpos -= (patch.loopEnd - patch.loopStart)/2;
+ }
+ }
+
+ short int *x = (short int *)&selected->rawdata[ifpos];
+ float sample = (ifpos >= 0 && ifpos < signed(patch.wavesize))?
+ x[0]/32768.0:0.0;
+ float sample1 = ((ifpos+2) >= 0 && (ifpos+2) < signed(patch.wavesize))?
+ x[1]/32768.0:0.0;
+ float error = fpos - (int)fpos;
+ outvalue[i] = sample * (1.0-error) + sample1 * error;
+
+ fpos += step;
+ }
+ }
+ else
+ {
+ for(unsigned int i = 0; i < samples; i++)
+ outvalue[i] = 0.0;
+ }
+ }
+
+ void clearDList()
+ {
+ selected = 0;
+
+ }
+
+ string filename() { return _filename; }
+ void filename(const string& newFile)
+ {
+ if(newFile == _filename) return;
+
+ unload();
+ pat = CachedPat::load(Cache::the(), newFile);
+
+ _filename = newFile;
+ filename_changed(newFile);
+ }
+};
+
+REGISTER_IMPLEMENTATION(Synth_PLAY_PAT_impl);
+
+}
diff --git a/arts/modules/synth/synth_pscale_impl.cc b/arts/modules/synth/synth_pscale_impl.cc
new file mode 100644
index 00000000..9cf972db
--- /dev/null
+++ b/arts/modules/synth/synth_pscale_impl.cc
@@ -0,0 +1,53 @@
+/*
+
+ Copyright (C) 2000 Jeff Tranter
+ tranter@pobox.com
+
+ (C) 1999 Stefan Westerfeld
+ stefan@space.twc.de
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ */
+
+#include "artsmodulessynth.h"
+#include "stdsynthmodule.h"
+
+using namespace Arts;
+
+class Synth_PSCALE_impl : virtual public Synth_PSCALE_skel,
+ virtual public StdSynthModule
+{
+protected:
+ float _top;
+
+public:
+ float top() { return _top; }
+ void top(float newTop) { _top = newTop; }
+
+ void calculateBlock(unsigned long samples)
+ {
+ for (unsigned int i=0; i < samples; i++)
+ {
+ if (pos[i] >= _top)
+ outvalue[i] = invalue[i] * (1 - pos[i])/(1 - _top);
+ else
+ outvalue[i] = invalue[i] * pos[i] / _top;
+ }
+ }
+
+};
+
+REGISTER_IMPLEMENTATION(Synth_PSCALE_impl);
diff --git a/arts/modules/synth/synth_rc_impl.cc b/arts/modules/synth/synth_rc_impl.cc
new file mode 100644
index 00000000..0c62c4c6
--- /dev/null
+++ b/arts/modules/synth/synth_rc_impl.cc
@@ -0,0 +1,110 @@
+/*
+
+ Copyright (C) 2000 Jeff Tranter
+ tranter@pobox.com
+
+ (C) 1999 Stefan Westerfeld
+ stefan@space.twc.de
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ */
+
+#include <math.h>
+#include "artsmodulessynth.h"
+#include "stdsynthmodule.h"
+
+using namespace Arts;
+
+class Synth_RC_impl : virtual public Synth_RC_skel,
+ virtual public StdSynthModule
+{
+protected:
+ float _b, _f;
+ float B, dB;
+ float F, dF, oF, oU, U, Fsoll, Bsoll;
+ float oldvalue;
+
+public:
+ float b() { return _b; }
+ void b(float newB) { _b = newB; }
+
+ float f() { return _f; }
+ void f(float newF) { _f = newF; }
+
+ void streamInit()
+ {
+ oldvalue = 0;
+ B = 0;
+ F = 0; oF = 0;
+ U = 0; oU = 0;
+ }
+
+ void calculateBlock(unsigned long samples)
+ {
+ unsigned long i, hits;
+ const float zero_lower = -0.00000001;
+ const float zero_upper = 0.00000001;
+
+ if (zero_lower < invalue[0] && invalue[0] < zero_upper)
+ {
+ /* for comments see equalizer.cc/Synth_STD_EQUALIZER implementation */
+
+ /*
+ * This implementation differs from the implementation there,
+ * because it is done as a kind of powersafing. If no input is
+ * found, then no output is generated.
+ */
+ if (zero_lower < oldvalue && oldvalue < zero_upper)
+ {
+ oldvalue = 0.0;
+ B = 0.0;
+ F = 0.0; oF = 0.0;
+ U = 0.0; oU = 0.0;
+ hits = 0;
+ for (i=0; i<samples; i++)
+ {
+ if (zero_lower < invalue[i] && invalue[i] < zero_upper)
+ {
+ // try to zero out the whole block
+ outvalue[i] = 0.0;
+ hits++;
+ }
+ }
+ if (hits == samples) return;
+ }
+ }
+
+ for (i=0; i<samples; i++)
+ {
+ B = B + (invalue[i] - oldvalue); /* input into RC */
+ oldvalue = invalue[i];
+
+ Bsoll = U - oU;
+ oU = U;
+ dB = (Bsoll - B) / _b;
+ B += dB;
+ U -= dB;
+ Fsoll = U;
+ dF = (Fsoll - F) / _f;
+ F += dF; /* Energie dF wird ins Feld uebertragen */
+ U -= dF;
+ outvalue[i] = (F - oF) * (_b + _f);
+ oF = F;
+ }
+ }
+};
+
+REGISTER_IMPLEMENTATION(Synth_RC_impl);
diff --git a/arts/modules/synth/synth_sequence_freq_impl.cc b/arts/modules/synth/synth_sequence_freq_impl.cc
new file mode 100644
index 00000000..64ecd512
--- /dev/null
+++ b/arts/modules/synth/synth_sequence_freq_impl.cc
@@ -0,0 +1,131 @@
+/* This file is part of the KDE project
+ Copyright (C) 2000 Jeff Tranter <tranter@pobox.com>
+ 2003 Matthias Kretz <kretz@kde.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License version 2
+ as published by the Free Software Foundation.
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "artsmodulessynth.h"
+#include "stdsynthmodule.h"
+#include <debug.h>
+
+using namespace std;
+using namespace Arts;
+
+class Synth_SEQUENCE_FREQ_impl : virtual public Synth_SEQUENCE_FREQ_skel,
+ virtual public StdSynthModule
+{
+protected:
+ float _speed;
+ string _seq;
+ long posn, delay;
+ float *fsequence;
+ float *slen;
+
+public:
+ Synth_SEQUENCE_FREQ_impl()
+ : _speed( 1 )
+ , fsequence( 0 )
+ , slen( 0 )
+ {
+ }
+
+ ~Synth_SEQUENCE_FREQ_impl()
+ {
+ delete[] fsequence;
+ delete[] slen;
+ }
+
+ float speed() { return _speed; }
+ void speed(float newSpeed) { _speed = newSpeed; }
+
+ string seq() { return _seq; }
+ void seq(const string &newSeq)
+ {
+ _seq = newSeq;
+ parseSeqString();
+ }
+
+ void parseSeqString()
+ {
+ delete[] fsequence;
+ delete[] slen;
+
+ long bufferlen = _seq.length();
+ fsequence = new float[ bufferlen ];
+ slen = new float[ bufferlen ];
+
+ int i = 0;
+ int oldpos = 0;
+ int pos = _seq.find_first_of( ",;", 0 );
+ arts_debug( "tokenizer: parse %s", _seq.c_str() );
+ while( pos > 0 )
+ {
+ string token = _seq.substr( oldpos, pos - oldpos );
+ arts_debug( "tokenizer: pos = %d, oldpos = %d, token = %s", pos, oldpos, token.c_str() );
+ handleToken( token, i++ );
+ oldpos = pos + 1;
+ pos = _seq.find_first_of( ",;", oldpos );
+ }
+ string token = _seq.substr( oldpos, _seq.length() - oldpos );
+ arts_debug( "tokenizer: pos = %d, oldpos = %d, token = %s", pos, oldpos, token.c_str() );
+ handleToken( token, i++ );
+ fsequence[ i ] = -1.0;
+ }
+
+ void handleToken( const string & token, int i )
+ {
+ int colon = token.find( ':' );
+ if( colon > -1 )
+ {
+ slen[ i ] = atof( &token.c_str()[ colon + 1 ] );
+ fsequence[ i ] = atof( token.substr( 0, colon ).c_str() );
+ }
+ else
+ {
+ slen[ i ] = 1;
+ fsequence[ i ] = atof( token.c_str() );
+ }
+ }
+
+ void streamInit()
+ {
+ delay = 0;
+ posn = 0;
+ }
+
+ void calculateBlock(unsigned long samples)
+ {
+ for (unsigned int i=0; i < samples; i++)
+ {
+ delay++;
+ if (delay > _speed * samplingRate * slen[posn])
+ {
+ posn++;
+ if (fsequence[posn] == -1.0)
+ posn = 0;
+ delay = 0;
+ }
+ pos[i] = (int)delay / (_speed * samplingRate * slen[posn]);
+ frequency[i] = fsequence[posn];
+ }
+ }
+
+};
+
+REGISTER_IMPLEMENTATION(Synth_SEQUENCE_FREQ_impl);
+// vim: sw=4 ts=4 noet
diff --git a/arts/modules/synth/synth_sequence_impl.cc b/arts/modules/synth/synth_sequence_impl.cc
new file mode 100644
index 00000000..9c2bead4
--- /dev/null
+++ b/arts/modules/synth/synth_sequence_impl.cc
@@ -0,0 +1,132 @@
+ /*
+
+ Copyright (C) 2000 Jeff Tranter
+ tranter@pobox.com
+
+ (C) 1999 Stefan Westerfeld
+ stefan@space.twc.de
+
+ (C) 2003 Matthias Kretz
+ kretz@kde.org
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "artsmodulessynth.h"
+#include "stdsynthmodule.h"
+
+using namespace std;
+using namespace Arts;
+
+class Synth_SEQUENCE_impl : virtual public Synth_SEQUENCE_skel,
+ virtual public StdSynthModule
+{
+protected:
+ float _speed;
+ string _seq;
+ long posn, delay;
+ float *fsequence;
+ float *slen;
+
+public:
+ Synth_SEQUENCE_impl()
+ : _speed( 1 )
+ , fsequence( 0 )
+ , slen( 0 )
+ {
+ }
+
+ ~Synth_SEQUENCE_impl()
+ {
+ delete [] fsequence;
+ delete [] slen;
+ }
+
+ float speed() { return _speed; }
+ void speed(float newSpeed) { _speed = newSpeed; }
+
+ string seq() { return _seq; }
+ void seq(const string &newSeq) { _seq = newSeq; }
+
+ void streamInit()
+ {
+ char notea[][4]= {"C-", "C#", "D-", "D#", "E-", "F-", "F#", "G-", "G#", "A-", "A#-", "B-", "\0"};
+ char noteb[][3]= {"C-", "Db", "D-", "Eb", "E-", "F-", "Gb", "G-", "Ab", "A-", "Bb", "B-", "\0"};
+ float freq[] = {261.7,277.2,293.7,311.2,329.7,349.3,370.0,392.0,415.3,440.0, 466.2, 493.9, 0 };
+ float zhoch[] = {1,2,4,8,16,32,64,128,256};
+ int s = 0, i, oktave;
+ char *nptr;
+ float f;
+ char buffer[1024];
+
+ strncpy(buffer, _seq.c_str(), 1023);
+ buffer[ 1023 ] = '\0';
+ long bufferlen = strlen(buffer);
+ delete[] fsequence;
+ delete[] slen;
+ fsequence = new float[ bufferlen ];
+ slen = new float[ bufferlen ];
+ nptr = strtok(buffer, ",;");
+ while (nptr)
+ {
+ if (nptr[3] == ':')
+ slen[s] = atof(&nptr[4]);
+ else
+ slen[s] = 1;
+ fprintf(stderr," <%d> %s\n", s, nptr);
+ oktave = atol(&nptr[2]);
+ nptr[2] = 0;
+ f = 0;
+ for (i=0; notea[i][0]; i++)
+ if (strcmp(nptr,notea[i]) == 0)
+ f = freq[i];
+ for (i=0; noteb[i][0]; i++)
+ if (strcmp(nptr, noteb[i]) == 0)
+ f = freq[i];
+ f *= zhoch[oktave] / zhoch[4];
+ fsequence[s++] = f;
+ fprintf(stderr, ">%2.2f\n", f);
+ nptr = strtok(NULL,",;");
+ }
+ fsequence[s] = 0;
+ delay = 0;
+ posn = 0;
+ }
+
+ void calculateBlock(unsigned long samples)
+ {
+ for (unsigned int i=0; i < samples; i++)
+ {
+ delay++;
+ if (delay > _speed * samplingRate * slen[posn])
+ {
+ posn++;
+ if (fsequence[posn] == 0)
+ posn = 0;
+ delay = 0;
+ }
+ pos[i] = (int)delay / (_speed * samplingRate * slen[posn]);
+ frequency[i] = fsequence[posn];
+ }
+ }
+
+};
+
+REGISTER_IMPLEMENTATION(Synth_SEQUENCE_impl);
+// vim: sw=4 ts=4 noet
diff --git a/arts/modules/synth/synth_shelve_cutoff_impl.cc b/arts/modules/synth/synth_shelve_cutoff_impl.cc
new file mode 100644
index 00000000..888480e3
--- /dev/null
+++ b/arts/modules/synth/synth_shelve_cutoff_impl.cc
@@ -0,0 +1,71 @@
+/*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "artsmodulessynth.h"
+#include "stdsynthmodule.h"
+#include "c_filter_stuff.h"
+
+using namespace Arts;
+
+class Synth_SHELVE_CUTOFF_impl : virtual public Synth_SHELVE_CUTOFF_skel,
+ virtual public StdSynthModule
+{
+protected:
+ filter f;
+public:
+ void streamInit();
+ void calculateBlock(unsigned long samples);
+};
+
+REGISTER_IMPLEMENTATION(Synth_SHELVE_CUTOFF_impl);
+
+void Synth_SHELVE_CUTOFF_impl::streamInit()
+{
+ initfilter(&f);
+}
+
+void Synth_SHELVE_CUTOFF_impl::calculateBlock(unsigned long samples)
+{
+ float filterfrequency = frequency[0];
+
+ // the shelve-lowpass-filter is extremely sensitive to frequencies which
+ // are out of it's range (it produces NaN's then) so we'll be careful ;)
+ if(filterfrequency > 22000.0) filterfrequency = 22000.0;
+ if(filterfrequency < 1.0) filterfrequency = 1.0;
+ setfilter_shelvelowpass(&f,filterfrequency,80.0);
+
+ unsigned long i;
+
+ for(i=0;i<samples;i++)
+ {
+ // better paste applyfilter here instead of:
+ // *outsig++ = 0.95 * applyfilter(&f,*insig++);
+ f.x = invalue[i];
+ f.y = f.cx * f.x + f.cx1 * f.x1 + f.cx2 * f.x2
+ + f.cy1 * f.y1 + f.cy2 * f.y2;
+ f.x2 = f.x1;
+ f.x1 = f.x;
+ f.y2 = f.y1;
+ f.y1 = f.y;
+ outvalue[i] = 0.95 * f.y;
+ }
+}
diff --git a/arts/modules/synth/synth_std_equalizer_impl.cc b/arts/modules/synth/synth_std_equalizer_impl.cc
new file mode 100644
index 00000000..3500503b
--- /dev/null
+++ b/arts/modules/synth/synth_std_equalizer_impl.cc
@@ -0,0 +1,207 @@
+/*
+
+ Copyright (C) 2000 Jeff Tranter
+ tranter@pobox.com
+
+ (C) 1999 Stefan Westerfeld
+ stefan@space.twc.de
+
+ (C) 1999 Martin Lorenz
+ lorenz@ch.tum.de
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ */
+
+#include <math.h>
+#include "artsmodulessynth.h"
+#include "stdsynthmodule.h"
+
+using namespace Arts;
+
+class Synth_STD_EQUALIZER_impl : virtual public Synth_STD_EQUALIZER_skel,
+ virtual public StdSynthModule
+{
+protected:
+ float _low, _mid, _high, _frequency, _q;
+ float tlow, tmid, thigh, tfrequency;
+ float a1, a2, b0, b1, b2, x_0, x_1, x_2, y_1, y_2;
+ unsigned long all;
+
+public:
+ float low() { return _low; }
+ void low(float newLow)
+ {
+ if(newLow != _low)
+ {
+ _low = newLow;
+ calcParameters();
+ high_changed(newLow);
+ }
+ }
+
+
+ float mid() { return _mid; }
+ void mid(float newMid)
+ {
+ if(newMid != _mid)
+ {
+ _mid = newMid;
+ calcParameters();
+ mid_changed(newMid);
+ }
+ }
+
+ float high() { return _high; }
+ void high(float newHigh)
+ {
+ if(newHigh != _high)
+ {
+ _high = newHigh;
+ calcParameters();
+ high_changed(newHigh);
+ }
+ }
+
+
+ float frequency() { return _frequency; }
+ void frequency(float newFrequency)
+ {
+ if(newFrequency != _frequency)
+ {
+ _frequency = newFrequency;
+ calcParameters();
+ frequency_changed(newFrequency);
+ }
+ }
+
+ float q() { return _q; }
+ void q(float newQ)
+ {
+ if(newQ != _q)
+ {
+ _q = newQ;
+ calcParameters();
+ q_changed(newQ);
+ }
+ }
+
+ Synth_STD_EQUALIZER_impl() {
+ _low = _mid = _high = 0; _q = 0.5;
+ _frequency = 300;
+ }
+
+ void calcParameters()
+ {
+ /*
+
+ * _low, _mid, _high are in dB, transform them to tlow, tmid,
+ * thigh using:
+ * -6dB => 0.5 ; 0dB => 1 ; 6dB = 2.0 ; ...
+ */
+
+ tlow = exp(_low * 0.115524530093324); // exp(p[LOW]*ln(2)/6)
+ tmid = exp(_mid * 0.115524530093324);
+ thigh = exp(_high * 0.115524530093324);
+
+ // _frequency is given in Hz, we need the w-value (and do clipping if
+ // it exceeds SR/2)
+ const float SAMPLING_RATE = 44100.0;
+ tfrequency = _frequency;
+ if (tfrequency > SAMPLING_RATE / 2.01)
+ tfrequency = SAMPLING_RATE / 2.01;
+ float w = 2 * M_PI * tfrequency / SAMPLING_RATE;
+
+ // Calculations:
+ float t = 1/tan(w/2);
+ float tq = t/_q;
+ float t2 = t*t;
+
+ float a0 = 1+tq+t2;
+ float a0r = 1/a0;
+
+ // and now the real filter values:
+ a1 = (2 - 2 * t2) * a0r;
+ a2 = (1 - tq + t2) * a0r;
+ b0 = (tlow + tmid * tq + thigh * t2) * a0r;
+ b1 = (2 * tlow -2 * thigh * t2) * a0r;
+ b2 = (tlow - tmid * tq + thigh * t2) * a0r;
+
+ // TODO: try if we need that here, or if we can change filter
+ // coefficients without setting the state to 0
+ x_0 = x_1 = x_2 = y_1 = y_2 = 0.0;
+ all = 0;
+ }
+
+ void streamInit()
+ {
+ calcParameters();
+ }
+
+ void calculateBlock(unsigned long samples)
+ {
+ all += samples;
+
+ if (all > 1024)
+ {
+ /* The _problem_: (observed on a PII-350)
+ *
+ * I am not quite sure what happens here, but it seems to be like that:
+ *
+ * If an ordinary signal (a mp3 for instance) is sent through the
+ * equalizer, and then no more input is given (zeros as input),
+ * the y_1 and y_2 values oscillate for some time, coming closer and
+ * close to zero.
+ *
+ * But before the reach zero, they reach the smallest negative number
+ * (or smallest positive, or whatever), and stay there
+ * (because 0.005*smallest_negative will remain smallest_negative).
+ *
+ * Since then, the CPU usage for all operations on these floats
+ * increases, (since handling of smallest_negative seems to be a rare
+ * case).
+ *
+ * The _fix_:
+ *
+ * We observe the value of y_1. If it's very close to zero (may be as
+ * well smallest_positive/smallest_negative), we set it to zero,
+ * together with y_2. This shouldn't significantly influence
+ * correctness of the filter, but effectively solves the problem.
+ *
+ * If you don't believe me, try without this fix and tell me what
+ * happens on your computer.
+ */
+ const float zero_lower =-0.00000001;
+ const float zero_upper = 0.00000001;
+ all = 0;
+
+ if(zero_lower < y_1 && y_1 < zero_upper)
+ y_1 = y_2 = 0.0;
+ }
+
+ unsigned long i;
+ float tmp;
+ for (i=0; i<samples; i++)
+ {
+ x_0 = invalue[i];
+ tmp = x_0 * b0 + x_1 * b1 + x_2 * b2 - y_1 * a1 - y_2 * a2;
+ x_2 = x_1; x_1 = x_0; y_2 = y_1; y_1 = tmp;
+ outvalue[i] = tmp;
+ }
+ }
+
+};
+
+REGISTER_IMPLEMENTATION(Synth_STD_EQUALIZER_impl);
diff --git a/arts/modules/synth/synth_tremolo_impl.cc b/arts/modules/synth/synth_tremolo_impl.cc
new file mode 100644
index 00000000..2c703c52
--- /dev/null
+++ b/arts/modules/synth/synth_tremolo_impl.cc
@@ -0,0 +1,51 @@
+/*
+
+ Copyright (C) 2000 Jeff Tranter
+ tranter@pobox.com
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include <math.h>
+#include "artsmodulessynth.h"
+#include "stdsynthmodule.h"
+
+using namespace Arts;
+
+// The tremolo module modulates the amplitude according to a LFO-Wave.
+// Traditionally you would use a sine wave but why limit yourself?
+// What you get is a very intense effect that cuts through most
+// arrangements because of its high dynamic range. The tremolo effect
+// is still one of guitarists favorite effects although it's not as
+// popular as in the 1960's.
+
+class Synth_TREMOLO_impl : virtual public Synth_TREMOLO_skel,
+ virtual public StdSynthModule
+{
+public:
+ void calculateBlock(unsigned long samples)
+ {
+ unsigned long i;
+ for(i=0; i<samples; i++)
+ {
+ // simply modulate the amplitude
+ outvalue[i] = invalue[i] * fabs(inlfo[i]);
+ }
+ }
+};
+
+REGISTER_IMPLEMENTATION(Synth_TREMOLO_impl);
diff --git a/arts/modules/synth/synth_wave_pulse_impl.cc b/arts/modules/synth/synth_wave_pulse_impl.cc
new file mode 100644
index 00000000..52a2c35e
--- /dev/null
+++ b/arts/modules/synth/synth_wave_pulse_impl.cc
@@ -0,0 +1,52 @@
+ /*
+
+ Copyright (C) 2000 Jeff Tranter
+ tranter@pobox.com
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "artsmodulessynth.h"
+#include "stdsynthmodule.h"
+
+using namespace Arts;
+
+// A square wave with a programmable duty cycle. The duty cycle should
+// be in the range 0..1.
+
+class Synth_WAVE_PULSE_impl : virtual public Synth_WAVE_PULSE_skel,
+ virtual public StdSynthModule
+{
+protected:
+ float _dutycycle;
+
+public:
+ float dutycycle() { return _dutycycle; }
+
+ void dutycycle(float newDutycycle) { _dutycycle = newDutycycle; }
+
+ void calculateBlock(unsigned long samples)
+ {
+ unsigned long i;
+ for(i=0;i<samples;i++)
+ {
+ outvalue[i] = (pos[i] < _dutycycle) ? 1.0 : -1.0;
+ }
+ }
+};
+
+REGISTER_IMPLEMENTATION(Synth_WAVE_PULSE_impl);
diff --git a/arts/modules/synth/synth_wave_softsaw_impl.cc b/arts/modules/synth/synth_wave_softsaw_impl.cc
new file mode 100644
index 00000000..3818830f
--- /dev/null
+++ b/arts/modules/synth/synth_wave_softsaw_impl.cc
@@ -0,0 +1,50 @@
+ /*
+
+ Copyright (C) 2000 Jeff Tranter
+ tranter@pobox.com
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include <math.h>
+#include "artsmodulessynth.h"
+#include "stdsynthmodule.h"
+
+using namespace Arts;
+
+namespace Arts {
+
+// This is a sawtooth that has it's trough rounded off using a cosine
+// wave.
+
+class Synth_WAVE_SOFTSAW_impl : virtual public Synth_WAVE_SOFTSAW_skel,
+ virtual public StdSynthModule
+{
+public:
+ void calculateBlock(unsigned long cycles)
+ {
+ for(unsigned long i=0; i<cycles; i++)
+ if ((pos[i] < 0.1) || (pos[i] > 0.9))
+ outvalue[i] = 1 - pos[i] * 2;
+ else
+ outvalue[i] = cos(pos[i]*2*M_PI);
+ }
+};
+
+REGISTER_IMPLEMENTATION(Synth_WAVE_SOFTSAW_impl);
+
+}
diff --git a/arts/modules/synth/synth_wave_square_impl.cc b/arts/modules/synth/synth_wave_square_impl.cc
new file mode 100644
index 00000000..73e97daa
--- /dev/null
+++ b/arts/modules/synth/synth_wave_square_impl.cc
@@ -0,0 +1,39 @@
+ /*
+
+ Copyright (C) 2000 Jeff Tranter
+ tranter@pobox.com
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "artsmodulessynth.h"
+#include "stdsynthmodule.h"
+
+using namespace Arts;
+
+class Synth_WAVE_SQUARE_impl : virtual public Synth_WAVE_SQUARE_skel,
+ virtual public StdSynthModule
+{
+public:
+ void calculateBlock(unsigned long samples)
+ {
+ unsigned long i;
+ for(i=0;i<samples;i++) outvalue[i] = (pos[i] < 0.5) ? 1.0 : -1.0;
+ }
+};
+
+REGISTER_IMPLEMENTATION(Synth_WAVE_SQUARE_impl);
diff --git a/arts/modules/synth/synth_wave_tri_impl.cc b/arts/modules/synth/synth_wave_tri_impl.cc
new file mode 100644
index 00000000..c6ef34ed
--- /dev/null
+++ b/arts/modules/synth/synth_wave_tri_impl.cc
@@ -0,0 +1,39 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "artsmodulessynth.h"
+#include "stdsynthmodule.h"
+
+using namespace Arts;
+
+class Synth_WAVE_TRI_impl : virtual public Synth_WAVE_TRI_skel,
+ virtual public StdSynthModule
+{
+public:
+ void calculateBlock(unsigned long samples)
+ {
+ unsigned long i;
+ for(i=0;i<samples;i++) outvalue[i] = (pos[i] - 0.5) * 2.0;
+ }
+};
+
+REGISTER_IMPLEMENTATION(Synth_WAVE_TRI_impl);
diff --git a/arts/modules/synth/synth_xfade_impl.cc b/arts/modules/synth/synth_xfade_impl.cc
new file mode 100644
index 00000000..acf473ca
--- /dev/null
+++ b/arts/modules/synth/synth_xfade_impl.cc
@@ -0,0 +1,45 @@
+/*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "artsmodulessynth.h"
+#include "stdsynthmodule.h"
+
+using namespace Arts;
+
+class Synth_XFADE_impl : virtual public Synth_XFADE_skel,
+ virtual public StdSynthModule
+{
+public:
+ void calculateBlock(unsigned long samples)
+ {
+ unsigned long i;
+
+ for(i=0;i<samples;i++)
+ {
+ float p = (percentage[i]+1)/2;
+
+ outvalue[i] = invalue1[i]*p + invalue2[i]*(1-p);
+ }
+ }
+};
+
+REGISTER_IMPLEMENTATION(Synth_XFADE_impl);