/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "artsmodulessynth.h" #include "debug.h" #include "stdsynthmodule.h" #include #include #include #include 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); }