You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdemultimedia/arts/modules/synth/synth_osc_impl.cc

254 lines
5.1 KiB

/*
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 <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);
}