diff options
Diffstat (limited to 'arts/modules/synth')
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); |