summaryrefslogtreecommitdiffstats
path: root/arts/modules/synth/synth_osc_impl.cc
diff options
context:
space:
mode:
Diffstat (limited to 'arts/modules/synth/synth_osc_impl.cc')
-rw-r--r--arts/modules/synth/synth_osc_impl.cc253
1 files changed, 253 insertions, 0 deletions
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);
+
+}