Ok, here we go...
This patch changes the oscillators in such a way that they can be
oversampled up to 16x now. The only plugin currently using this feature
is Tripple-Oscillator (in which for the time being an
oversampling-factor of 8 is hardcoded currently). On my machine (slow
Intel dual-core) I still can play 32+ Instances of Tripple-Oscillator
with this patch applied, so it's not too slow anyways... But on the long
run there could be a knob reflecting the oversampling-setting for a
particular instance of a plugin, so you do not waste CPU-time with
oversampling bass-sounds...
The main benefit from this approach compared to my last attemt (using
wavetables for alias-free waveform-generation) is, that it works with
the higher-order modulations (AM, FM, Sync, PM). The main drawback is,
that it isn't halfway that fast and while alias is suppressed reasonably
it's not completely alias-free...
But as said above: this shouldn't be a problem, as you only would use
this feature adaptively for higher-pitched (and/or modulated) lead
voices anyways...
Please test and comment...
Stefan
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 0269a19..730eb60 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -440,8 +440,14 @@ CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/plugins/zynaddsubfx/zynaddsubfx.rc.in ${CMAKE
# set compiler flags
#SET(CMAKE_BUILD_TYPE relwithdebug)
+
+# original flags
SET(CMAKE_C_FLAGS "-O2 -g -Wall ${CMAKE_C_FLAGS}")
SET(CMAKE_CXX_FLAGS "-O2 -g -fno-exceptions -Wall ${CMAKE_CXX_FLAGS}")
+# my flags
+#SET(CMAKE_C_FLAGS "-O1 -g -Wall ${CMAKE_C_FLAGS}")
+#SET(CMAKE_CXX_FLAGS "-O1 -g -Wall ${CMAKE_CXX_FLAGS}")
+
#SET(CMAKE_C_FLAGS_${CMAKE_BUILD_TYPE} "${CMAKE_C_FLAGS}")
#SET(CMAKE_CXX_FLAGS_${CMAKE_BUILD_TYPE} "${CMAKE_CXX_FLAGS}")
diff --git a/include/Oscillator.h b/include/Oscillator.h
index edf7c03..2b3107c 100644
--- a/include/Oscillator.h
+++ b/include/Oscillator.h
@@ -36,7 +36,6 @@
#include "sample_buffer.h"
#include "lmms_constants.h"
-
class sampleBuffer;
class IntModel;
@@ -74,9 +73,13 @@ public:
const float & _detuning,
const float & _phase_offset,
const float & _volume,
- Oscillator * _m_subOsc = NULL );
+ Oscillator * _m_subOsc = NULL,
+ const float _oversampling = 1.0,
+ const bool _is_master = false );
+
virtual ~Oscillator()
{
+ delete [] m_temp_ab;
delete m_subOsc;
}
@@ -165,8 +168,17 @@ private:
Oscillator * m_subOsc;
float m_phaseOffset;
float m_phase;
+
const sampleBuffer * m_userWave;
+ static float m_filter[31][257];
+
+ static bool m_is_initialized;
+
+ float m_oversampling;
+ bool m_is_master;
+ sampleFrame* m_temp_ab;
+ fpp_t m_temp_size;
void updateNoSub( sampleFrame * _ab, const fpp_t _frames,
const ch_cnt_t _chnl );
diff --git a/include/basic_filters.h b/include/basic_filters.h
index 2462978..baaf5aa 100644
--- a/include/basic_filters.h
+++ b/include/basic_filters.h
@@ -35,6 +35,8 @@
#include <math.h>
+#include <iostream>
+
#include "lmms_basics.h"
#include "Mixer.h"
#include "templates.h"
@@ -57,6 +59,9 @@ public:
AllPass,
Moog,
DoubleLowPass,
+ Lowpass_RC6,
+ Bandpass_RC6,
+ Highpass_RC6,
Lowpass_RC12,
Bandpass_RC12,
Highpass_RC12,
@@ -107,6 +112,13 @@ public:
m_rca( 0.0f ),
m_rcb( 1.0f ),
m_rcc( 0.0f ),
+
+ m_rca0( 0.0 ),
+ m_rca1( 0.0 ),
+ m_rca2( 0.0 ),
+ m_rcb1( 0.0 ),
+ m_rcb2( 0.0 ),
+
m_doubleFilter( false ),
m_sampleRate( (float) _sample_rate ),
m_subFilter( NULL )
@@ -137,7 +149,16 @@ public:
m_rclp0[_chnl] = m_rcbp0[_chnl] = m_rchp0[_chnl] = m_rclast0[_chnl] = 0.0f;
m_rclp1[_chnl] = m_rcbp1[_chnl] = m_rchp1[_chnl] = m_rclast1[_chnl] = 0.0f;
- for(int i=0; i<6; i++)
+ // reset in/out history for new RC-filters
+ m_rcx00[_chnl] = m_rcx10[_chnl] = m_rcx20[_chnl] =0.0f;
+ m_rcy00[_chnl] = 0.0001f; m_rcy10[_chnl] = -0.0001f; m_rcy20[_chnl] = 0.0001f;
+ m_rcx01[_chnl] = m_rcx11[_chnl] = m_rcx21[_chnl] =0.0f;
+ m_rcy01[_chnl] = 0.0001f; m_rcy11[_chnl] = -0.0001f; m_rcy21[_chnl] = 0.0001f;
+ m_rcx02[_chnl] = m_rcx12[_chnl] = m_rcx22[_chnl] = m_rcy02[_chnl] = m_rcy12[_chnl] = m_rcy22[_chnl] = 0.0f;
+ m_rcx03[_chnl] = m_rcx13[_chnl] = m_rcx23[_chnl] = m_rcy03[_chnl] = m_rcy13[_chnl] = m_rcy23[_chnl] = 0.0f;
+
+ // reset in/out history for formant-filter
+ for(int i=0; i<12; i++)
m_vflp[i][_chnl] = m_vfbp[i][_chnl] = m_vfhp[i][_chnl] = m_vflast[i][_chnl] = 0.0f;
}
}
@@ -153,6 +174,7 @@ public:
// four cascaded onepole filters
// (bilinear transform)
+#if 0
m_y1[_chnl] = tLimit(
( x + m_oldx[_chnl] ) * m_p
- m_k * m_y1[_chnl],
@@ -169,6 +191,11 @@ public:
( m_y3[_chnl] + m_oldy3[_chnl] ) * m_p
- m_k * m_y4[_chnl],
-10.0f, 10.0f );
+#endif
+ m_y1[_chnl] = atan( ( ( x + m_oldx[_chnl] ) * m_p - m_k * m_y1[_chnl] ) / 2.f )*2.f;
+ m_y2[_chnl] = atan( ( ( m_y1[_chnl] + m_oldy1[_chnl] ) * m_p - m_k * m_y2[_chnl] ) / 2.f )*2.f;
+ m_y3[_chnl] = atan( ( ( m_y2[_chnl] + m_oldy2[_chnl] ) * m_p - m_k * m_y3[_chnl] ) / 2.f )*2.f;
+ m_y4[_chnl] = atan( ( ( m_y3[_chnl] + m_oldy3[_chnl] ) * m_p - m_k * m_y4[_chnl] ) / 2.f )*2.f;
m_oldx[_chnl] = x;
m_oldy1[_chnl] = m_y1[_chnl];
@@ -180,55 +207,171 @@ public:
}
- // 4-times oversampled simulation of an active RC-Bandpass,-Lowpass,-Highpass-
- // Filter-Network as it was used in nearly all modern analog synthesizers. This
- // can be driven up to self-oscillation (BTW: do not remove the limits!!!).
- // (C) 1998 ... 2009 S.Fendt. Released under the GPL v2.0 or any later version.
-
+ case Lowpass_RC6:
+ case Bandpass_RC6:
+ case Highpass_RC6:
case Lowpass_RC12:
case Bandpass_RC12:
case Highpass_RC12:
+ case Lowpass_RC24:
+ case Bandpass_RC24:
+ case Highpass_RC24:
{
- sample_t lp, hp, bp;
-
- sample_t in;
-
- // 4-times oversampled... (even the moog-filter would benefit from this)
- for( int n = 4; n != 0; --n )
- {
- in = _in0 + m_rcbp0[_chnl] * m_rcq;
- in = (in > +1.f) ? +1.f : in;
- in = (in < -1.f) ? -1.f : in;
-
- lp = in * m_rcb + m_rclp0[_chnl] * m_rca;
- lp = (lp > +1.f) ? +1.f : lp;
- lp = (lp < -1.f) ? -1.f : lp;
-
- hp = m_rcc * ( m_rchp0[_chnl] + in - m_rclast0[_chnl] );
- hp = (hp > +1.f) ? +1.f : hp;
- hp = (hp < -1.f) ? -1.f : hp;
-
- bp = hp * m_rcb + m_rcbp0[_chnl] * m_rca;
- bp = (bp > +1.f) ? +1.f : bp;
- bp = (bp < -1.f) ? -1.f : bp;
-
- m_rclast0[_chnl] = in;
- m_rclp0[_chnl] = lp;
- m_rchp0[_chnl] = hp;
- m_rcbp0[_chnl] = bp;
- }
-
- if( m_type == Lowpass_RC12 )
- out = lp;
- else if( m_type == Bandpass_RC12 )
- out = bp;
- else
- out = hp;
-
- return( out );
+ // This is a conversion of the active RC-filters which were
+ // used in most popular analog synthesizers to a pole-zero
+ // design. Because we need 6dB/12dB/24dB per octave filters
+ // as all of these were commonly used in real synths and we
+ // need to have the ability to internaly overdrive the filter,
+ // we do it like in the real thing: using multiple stages of
+ // 6dB/Octave coupled one after the other and clip their re-
+ // spective in-/out-channels.
+
+ // Stage 1: 6dB/Octave
+ // ============================================================
+
+ // update input history
+ m_rcx20[_chnl] = m_rcx10[_chnl];
+ m_rcx10[_chnl] = m_rcx00[_chnl];
+
+ // fill in sample and leave some headroom of 6dB for resonance
+ // inject a little noise, so we really get self-oszillation
+ m_rcx00[_chnl] = _in0;
+
+ // update output history
+ m_rcy20[_chnl] = m_rcy10[_chnl];
+ m_rcy10[_chnl] = m_rcy00[_chnl];
+
+ // clip input before calculation like an op-amp would do...
+ //m_rcx00[_chnl] = (m_rcx00[_chnl]>+1.0)? +1.0:m_rcx00[_chnl];
+ //m_rcx00[_chnl] = (m_rcx00[_chnl]<-1.0)? -1.0:m_rcx00[_chnl];
+
+ // update the filter
+ m_rcy00[_chnl] = m_rca0 * m_rcx00[_chnl] +
+ m_rca1 * m_rcx10[_chnl] +
+ m_rca2 * m_rcx20[_chnl] +
+ m_rcb1 * m_rcy10[_chnl] +
+ m_rcb2 * m_rcy20[_chnl] ;
+
+ // clip output after calculation like an op-amp would do...
+// m_rcy00[_chnl] = saturate( m_rcy00[_chnl] );
+ m_rcy00[_chnl] = (m_rcy00[_chnl]>+4.0)? +4.0:m_rcy00[_chnl];
+ m_rcy00[_chnl] = (m_rcy00[_chnl]<-4.0)? -4.0:m_rcy00[_chnl];
+
+ if( m_type == Lowpass_RC6 ||
+ m_type == Highpass_RC6 ||
+ m_type == Bandpass_RC6 )
+ {
+ return( m_rcy00[_chnl] );
+ }
+
+ // m_rcy00[_chnl] now contains the output for the first 6dB
+ // stage. This will be used as input for the second stage...
+
+ // Stage 2: 12dB/Octave
+ // ============================================================
+
+ // update input history
+ m_rcx21[_chnl] = m_rcx11[_chnl];
+ m_rcx11[_chnl] = m_rcx01[_chnl];
+ m_rcx01[_chnl] = m_rcy00[_chnl]; // input from former stage...
+
+ // update output history
+ m_rcy21[_chnl] = m_rcy11[_chnl];
+ m_rcy11[_chnl] = m_rcy01[_chnl];
+
+ // clip input before calculation like an op-amp would do...
+ //m_rcx01[_chnl] = (m_rcx01[_chnl]>+1.0)? +1.0:m_rcx01[_chnl];
+ //m_rcx01[_chnl] = (m_rcx01[_chnl]<-1.0)? -1.0:m_rcx01[_chnl];
+
+ // update the filter
+ m_rcy01[_chnl] = m_rca0 * m_rcx01[_chnl] +
+ m_rca1 * m_rcx11[_chnl] +
+ m_rca2 * m_rcx21[_chnl] +
+ m_rcb1 * m_rcy11[_chnl] +
+ m_rcb2 * m_rcy21[_chnl];
+
+ // clip output after calculation like an op-amp would do...
+ //m_rcy01[_chnl] = saturate( m_rcy01[_chnl] );
+ m_rcy01[_chnl] = (m_rcy01[_chnl]>+4.0)? +4.0:m_rcy01[_chnl];
+ m_rcy01[_chnl] = (m_rcy01[_chnl]<-4.0)? -4.0:m_rcy01[_chnl];
+
+ // m_rcy01[_chnl] now contains the output for the second 6dB
+ // stage. This will be used as input for the third stage...
+
+ if( m_type == Lowpass_RC12 ||
+ m_type == Highpass_RC12 ||
+ m_type == Bandpass_RC12 )
+ {
+ return( m_rcy01[_chnl] );
+ }
+
+ // Stage 3: 18dB/Octave
+ // ============================================================
+
+ // update input history
+ m_rcx22[_chnl] = m_rcx12[_chnl];
+ m_rcx12[_chnl] = m_rcx02[_chnl];
+ m_rcx02[_chnl] = m_rcy01[_chnl]; // input from former stage...
+
+ // update output history
+ m_rcy22[_chnl] = m_rcy12[_chnl];
+ m_rcy12[_chnl] = m_rcy02[_chnl];
+
+ // clip input before calculation like an op-amp would do...
+ //m_rcx02[_chnl] = (m_rcx02[_chnl]>+1.0)? +1.0:m_rcx02[_chnl];
+ //m_rcx02[_chnl] = (m_rcx02[_chnl]<-1.0)? -1.0:m_rcx02[_chnl];
+
+ // update the filter
+ m_rcy02[_chnl] = m_rca0 * m_rcx02[_chnl] +
+ m_rca1 * m_rcx12[_chnl] +
+ m_rca2 * m_rcx22[_chnl] +
+ m_rcb1 * m_rcy12[_chnl] +
+ m_rcb2 * m_rcy22[_chnl] ;
+
+ // clip output after calculation like an op-amp would do...
+ //m_rcy02[_chnl] = saturate( m_rcy02[_chnl] );
+ m_rcy02[_chnl] = (m_rcy02[_chnl]>+4.0)? +4.0:m_rcy02[_chnl];
+ m_rcy02[_chnl] = (m_rcy02[_chnl]<-4.0)? -4.0:m_rcy02[_chnl];
+
+ // m_rcy02[_chnl] now contains the output for the third 6dB
+ // stage. This will be used as input for the fourth stage...
+
+ // Stage 4: 24dB/Octave
+ // ============================================================
+
+ // update input history
+ m_rcx23[_chnl] = m_rcx13[_chnl];
+ m_rcx13[_chnl] = m_rcx03[_chnl];
+ m_rcx03[_chnl] = m_rcy02[_chnl]; // input from former stage...
+
+ // update output history
+ m_rcy23[_chnl] = m_rcy13[_chnl];
+ m_rcy13[_chnl] = m_rcy03[_chnl];
+
+ // clip input before calculation like an op-amp would do...
+ //m_rcx03[_chnl] = (m_rcx03[_chnl]>+1.0)? +1.0:m_rcx03[_chnl];
+ //m_rcx03[_chnl] = (m_rcx03[_chnl]<-1.0)? -1.0:m_rcx03[_chnl];
+
+ // update the filter
+ m_rcy03[_chnl] = m_rca0 * m_rcx03[_chnl] +
+ m_rca1 * m_rcx13[_chnl] +
+ m_rca2 * m_rcx23[_chnl] +
+ m_rcb1 * m_rcy13[_chnl] +
+ m_rcb2 * m_rcy23[_chnl] ;
+
+ // clip output after calculation like an op-amp would do...
+ //m_rcy03[_chnl] = saturate( m_rcy03[_chnl] );
+ m_rcy03[_chnl] = (m_rcy03[_chnl]>+4.0)? +4.0:m_rcy03[_chnl];
+ m_rcy03[_chnl] = (m_rcy03[_chnl]<-4.0)? -4.0:m_rcy03[_chnl];
+
+ // m_rcy02[_chnl] now contains the output for the third 6dB
+ // stage. This will be used as input for the fourth stage...
+
+ return( m_rcy03[_chnl] );
break;
}
+#if 0
case Lowpass_RC24:
case Bandpass_RC24:
case Highpass_RC24:
@@ -237,10 +380,10 @@ public:
sample_t in;
- for( int n = 4; n != 0; --n )
+ for( int n = 1; n != 0; --n )
{
// first stage is as for the 12dB case...
- in = _in0 + m_rcbp0[_chnl] * m_rcq;
+ in = _in0 + m_rcbp0[_chnl] * m_rcq + ((float)(rand()%1000)-500.f)/(500.f*32768.f);
in = (in > +1.f) ? +1.f : in;
in = (in < -1.f) ? -1.f : in;
@@ -312,148 +455,162 @@ public:
return out;
break;
}
+#endif
case Formantfilter:
{
sample_t lp, hp, bp, in;
out = 0;
- for(int o=0; o<4; o++)
+ for(int o=0; o<1; o++)
{
// first formant
- in = _in0 + m_vfbp[0][_chnl] * m_vfq;
- in = (in > +1.f) ? +1.f : in;
- in = (in < -1.f) ? -1.f : in;
+ in = _in0 + m_vfbp[0][_chnl] * m_vfq[0] + ((float)(rand()%1000)-500.f)/(500.f*32768.f);
lp = in * m_vfb[0] + m_vflp[0][_chnl] * m_vfa[0];
- lp = (lp > +1.f) ? +1.f : lp;
- lp = (lp < -1.f) ? -1.f : lp;
-
hp = m_vfc[0] * ( m_vfhp[0][_chnl] + in - m_vflast[0][_chnl] );
- hp = (hp > +1.f) ? +1.f : hp;
- hp = (hp < -1.f) ? -1.f : hp;
-
bp = hp * m_vfb[0] + m_vfbp[0][_chnl] * m_vfa[0];
- bp = (bp > +1.f) ? +1.f : bp;
- bp = (bp < -1.f) ? -1.f : bp;
m_vflast[0][_chnl] = in;
m_vflp[0][_chnl] = lp;
m_vfhp[0][_chnl] = hp;
m_vfbp[0][_chnl] = bp;
- in = bp + m_vfbp[2][_chnl] * m_vfq;
- in = (in > +1.f) ? +1.f : in;
- in = (in < -1.f) ? -1.f : in;
+ in = bp + m_vfbp[1][_chnl] * m_vfq[0];
- lp = in * m_vfb[0] + m_vflp[2][_chnl] * m_vfa[0];
- lp = (lp > +1.f) ? +1.f : lp;
- lp = (lp < -1.f) ? -1.f : lp;
+ lp = in * m_vfb[0] + m_vflp[1][_chnl] * m_vfa[0];
+ hp = m_vfc[0] * ( m_vfhp[1][_chnl] + in - m_vflast[1][_chnl] );
+ bp = hp * m_vfb[0] + m_vfbp[1][_chnl] * m_vfa[0];
- hp = m_vfc[0] * ( m_vfhp[2][_chnl] + in - m_vflast[2][_chnl] );
- hp = (hp > +1.f) ? +1.f : hp;
- hp = (hp < -1.f) ? -1.f : hp;
+ m_vflast[1][_chnl] = in;
+ m_vflp[1][_chnl] = lp;
+ m_vfhp[1][_chnl] = hp;
+ m_vfbp[1][_chnl] = bp;
+
+ in = bp + m_vfbp[2][_chnl] * m_vfq[0];
+ lp = in * m_vfb[0] + m_vflp[2][_chnl] * m_vfa[0];
+ hp = m_vfc[0] * ( m_vfhp[2][_chnl] + in - m_vflast[2][_chnl] );
bp = hp * m_vfb[0] + m_vfbp[2][_chnl] * m_vfa[0];
- bp = (bp > +1.f) ? +1.f : bp;
- bp = (bp < -1.f) ? -1.f : bp;
m_vflast[2][_chnl] = in;
m_vflp[2][_chnl] = lp;
m_vfhp[2][_chnl] = hp;
m_vfbp[2][_chnl] = bp;
-
- in = bp + m_vfbp[4][_chnl] * m_vfq;
- in = (in > +1.f) ? +1.f : in;
- in = (in < -1.f) ? -1.f : in;
- lp = in * m_vfb[0] + m_vflp[4][_chnl] * m_vfa[0];
- lp = (lp > +1.f) ? +1.f : lp;
- lp = (lp < -1.f) ? -1.f : lp;
+ out += bp;
- hp = m_vfc[0] * ( m_vfhp[4][_chnl] + in - m_vflast[4][_chnl] );
- hp = (hp > +1.f) ? +1.f : hp;
- hp = (hp < -1.f) ? -1.f : hp;
+ // second formant
+ in = _in0 + m_vfbp[3][_chnl] * m_vfq[1] + ((float)(rand()%1000)-500.f)/(500.f*32768.f);
- bp = hp * m_vfb[0] + m_vfbp[4][_chnl] * m_vfa[0];
- bp = (bp > +1.f) ? +1.f : bp;
- bp = (bp < -1.f) ? -1.f : bp;
+ lp = in * m_vfb[1] + m_vflp[3][_chnl] * m_vfa[1];
+ hp = m_vfc[1] * ( m_vfhp[3][_chnl] + in - m_vflast[3][_chnl] );
+ bp = hp * m_vfb[1] + m_vfbp[3][_chnl] * m_vfa[1];
+
+ m_vflast[3][_chnl] = in;
+ m_vflp[3][_chnl] = lp;
+ m_vfhp[3][_chnl] = hp;
+ m_vfbp[3][_chnl] = bp;
+
+ in = bp + m_vfbp[4][_chnl] * m_vfq[1];
+
+ lp = in * m_vfb[1] + m_vflp[4][_chnl] * m_vfa[1];
+ hp = m_vfc[1] * ( m_vfhp[4][_chnl] + in - m_vflast[4][_chnl] );
+ bp = hp * m_vfb[1] + m_vfbp[4][_chnl] * m_vfa[1];
m_vflast[4][_chnl] = in;
m_vflp[4][_chnl] = lp;
m_vfhp[4][_chnl] = hp;
m_vfbp[4][_chnl] = bp;
+
+ in = bp + m_vfbp[5][_chnl] * m_vfq[1];
+
+ lp = in * m_vfb[1] + m_vflp[5][_chnl] * m_vfa[1];
+ hp = m_vfc[1] * ( m_vfhp[5][_chnl] + in - m_vflast[5][_chnl] );
+ bp = hp * m_vfb[1] + m_vfbp[5][_chnl] * m_vfa[1];
+
+ m_vflast[5][_chnl] = in;
+ m_vflp[5][_chnl] = lp;
+ m_vfhp[5][_chnl] = hp;
+ m_vfbp[5][_chnl] = bp;
out += bp;
- // second formant
- in = _in0 + m_vfbp[0][_chnl] * m_vfq;
- in = (in > +1.f) ? +1.f : in;
- in = (in < -1.f) ? -1.f : in;
+ // third formant
+ in = _in0 + m_vfbp[6][_chnl] * m_vfq[2] + ((float)(rand()%1000)-500.f)/(500.f*32768.f);
- lp = in * m_vfb[1] + m_vflp[1][_chnl] * m_vfa[1];
- lp = (lp > +1.f) ? +1.f : lp;
- lp = (lp < -1.f) ? -1.f : lp;
+ lp = in * m_vfb[2] + m_vflp[6][_chnl] * m_vfa[2];
+ hp = m_vfc[2] * ( m_vfhp[6][_chnl] + in - m_vflast[6][_chnl] );
+ bp = hp * m_vfb[2] + m_vfbp[6][_chnl] * m_vfa[2];
- hp = m_vfc[1] * ( m_vfhp[1][_chnl] + in - m_vflast[1][_chnl] );
- hp = (hp > +1.f) ? +1.f : hp;
- hp = (hp < -1.f) ? -1.f : hp;
+ m_vflast[6][_chnl] = in;
+ m_vflp[6][_chnl] = lp;
+ m_vfhp[6][_chnl] = hp;
+ m_vfbp[6][_chnl] = bp;
- bp = hp * m_vfb[1] + m_vfbp[1][_chnl] * m_vfa[1];
- bp = (bp > +1.f) ? +1.f : bp;
- bp = (bp < -1.f) ? -1.f : bp;
+ in = bp + m_vfbp[7][_chnl] * m_vfq[2];
- m_vflast[1][_chnl] = in;
- m_vflp[1][_chnl] = lp;
- m_vfhp[1][_chnl] = hp;
- m_vfbp[1][_chnl] = bp;
+ lp = in * m_vfb[2] + m_vflp[7][_chnl] * m_vfa[2];
+ hp = m_vfc[2] * ( m_vfhp[7][_chnl] + in - m_vflast[7][_chnl] );
+ bp = hp * m_vfb[2] + m_vfbp[7][_chnl] * m_vfa[2];
- in = bp + m_vfbp[3][_chnl] * m_vfq;
- in = (in > +1.f) ? +1.f : in;
- in = (in < -1.f) ? -1.f : in;
+ m_vflast[7][_chnl] = in;
+ m_vflp[7][_chnl] = lp;
+ m_vfhp[7][_chnl] = hp;
+ m_vfbp[7][_chnl] = bp;
+
+ in = bp + m_vfbp[8][_chnl] * m_vfq[2];
- lp = in * m_vfb[1] + m_vflp[3][_chnl] * m_vfa[1];
- lp = (lp > +1.f) ? +1.f : lp;
- lp = (lp < -1.f) ? -1.f : lp;
+ lp = in * m_vfb[2] + m_vflp[8][_chnl] * m_vfa[2];
+ hp = m_vfc[2] * ( m_vfhp[8][_chnl] + in - m_vflast[8][_chnl] );
+ bp = hp * m_vfb[2] + m_vfbp[8][_chnl] * m_vfa[2];
- hp = m_vfc[1] * ( m_vfhp[3][_chnl] + in - m_vflast[3][_chnl] );
- hp = (hp > +1.f) ? +1.f : hp;
- hp = (hp < -1.f) ? -1.f : hp;
+ m_vflast[8][_chnl] = in;
+ m_vflp[8][_chnl] = lp;
+ m_vfhp[8][_chnl] = hp;
+ m_vfbp[8][_chnl] = bp;
- bp = hp * m_vfb[1] + m_vfbp[3][_chnl] * m_vfa[1];
- bp = (bp > +1.f) ? +1.f : bp;
- bp = (bp < -1.f) ? -1.f : bp;
+ out += bp;
- m_vflast[3][_chnl] = in;
- m_vflp[3][_chnl] = lp;
- m_vfhp[3][_chnl] = hp;
- m_vfbp[3][_chnl] = bp;
+ // fourth formant
+ in = _in0 + m_vfbp[9][_chnl] * m_vfq[3] + ((float)(rand()%1000)-500.f)/(500.f*32768.f);
- in = bp + m_vfbp[5][_chnl] * m_vfq;
- in = (in > +1.f) ? +1.f : in;
- in = (in < -1.f) ? -1.f : in;
+ lp = in * m_vfb[3] + m_vflp[9][_chnl] * m_vfa[3];
+ hp = m_vfc[3] * ( m_vfhp[9][_chnl] + in - m_vflast[9][_chnl] );
+ bp = hp * m_vfb[3] + m_vfbp[9][_chnl] * m_vfa[3];
- lp = in * m_vfb[1] + m_vflp[5][_chnl] * m_vfa[1];
- lp = (lp > +1.f) ? +1.f : lp;
- lp = (lp < -1.f) ? -1.f : lp;
+ m_vflast[9][_chnl] = in;
+ m_vflp[9][_chnl] = lp;
+ m_vfhp[9][_chnl] = hp;
+ m_vfbp[9][_chnl] = bp;
- hp = m_vfc[1] * ( m_vfhp[5][_chnl] + in - m_vflast[5][_chnl] );
- hp = (hp > +1.f) ? +1.f : hp;
- hp = (hp < -1.f) ? -1.f : hp;
+ in = bp + m_vfbp[10][_chnl] * m_vfq[3];
- bp = hp * m_vfb[1] + m_vfbp[5][_chnl] * m_vfa[1];
- bp = (bp > +1.f) ? +1.f : bp;
- bp = (bp < -1.f) ? -1.f : bp;
+ lp = in * m_vfb[3] + m_vflp[10][_chnl] * m_vfa[3];
+ hp = m_vfc[3] * ( m_vfhp[10][_chnl] + in - m_vflast[10][_chnl] );
+ bp = hp * m_vfb[3] + m_vfbp[10][_chnl] * m_vfa[3];
- m_vflast[5][_chnl] = in;
- m_vflp[5][_chnl] = lp;
- m_vfhp[5][_chnl] = hp;
- m_vfbp[5][_chnl] = bp;
+ m_vflast[10][_chnl] = in;
+ m_vflp[10][_chnl] = lp;
+ m_vfhp[10][_chnl] = hp;
+ m_vfbp[10][_chnl] = bp;
+
+ in = bp + m_vfbp[11][_chnl] * m_vfq[3];
+
+ lp = in * m_vfb[3] + m_vflp[11][_chnl] * m_vfa[3];
+ hp = m_vfc[3] * ( m_vfhp[11][_chnl] + in - m_vflast[11][_chnl] );
+ bp = hp * m_vfb[3] + m_vfbp[11][_chnl] * m_vfa[3];
+
+ m_vflast[11][_chnl] = in;
+ m_vflp[11][_chnl] = lp;
+ m_vfhp[11][_chnl] = hp;
+ m_vfbp[11][_chnl] = bp;
out += bp;
+
}
- return( out/2.0f );
+ return( out/4.0f );
break;
}
@@ -483,7 +640,6 @@ public:
return out;
}
-
inline void calcFilterCoeffs( float _freq, float _q
/*, const bool _q_is_bandwidth = false*/ )
{
@@ -492,36 +648,257 @@ public:
// bad noise out of the filter...
_q = qMax( _q, minQ() );
- if( m_type == Lowpass_RC12 ||
- m_type == Bandpass_RC12 ||
- m_type == Highpass_RC12 ||
- m_type == Lowpass_RC24 ||
+ if( m_type == Lowpass_RC6 ||
+ m_type == Lowpass_RC12 ||
+ m_type == Lowpass_RC24 ||
+ m_type == Highpass_RC6 ||
+ m_type == Highpass_RC12 ||
+ m_type == Highpass_RC24 )
+ {
+ // Note:
+ // =====
+ // The z-plane does *not* use a simple polar mapping as it might be
+ // implicated by some (or most?) DSP-litrature... The reason why
+ // nearly all filters are constructed in the s-plane instead of the
+ // z-plane is that the mapping of the area surrounded by the unity-
+ // circle on the z-Plane is a not-so-trivial stereographic mapping.
+ // Because the transformation H(s) -> H(z) can not be done without
+ // error, I will use that stereographic mapping directly...
+
+ // limit lower frequency-range and push q a little beyond the unity-
+ // circle for maximum Q, so we get a raising, "unstable" filter...
+ if( _freq < 25.f )
+ {
+ _freq = 25.f;
+ }
+
+ _q *= 1.01;
+
+ // frequency-position on the unity-circle...
+ long double fx = cos( 2.0*M_PIl*_freq/m_sampleRate );
+ long double fy = sin( 2.0*M_PIl*_freq/m_sampleRate );
+
+ long double px = 0;
+ long double py = 0;
+ // calculate stereographic mapping for given q-factor [0.0;1.0]
+ long double sD = sqrt( pow( (-1.0) - fx, 2.0 ) + pow( -fy, 2.0 ) )/
+ sqrt( pow( (+1.0) - fx, 2.0 ) + pow( -fy, 2.0 ) );
+ long double sR = sD/fabs( pow(sD, 2.0) - 1.0 )*2.0;
+
+ // get arround the infinity-problem at fx==0... so limit the radius
+ // of the Apollonios-circle to 10000. In context to the size of the
+ // used range on the z-plane this is infinit enough...
+ if( sR > 10000 ) sR=10000;
+
+ long double alpha = asin( fy / sR );
+
+ if( fx >= 0 )
+ {
+ long double sX = fx + sR*cos( asin( fy / sR ) );
+ px = cos(M_PI-alpha*_q/10.0)*sR+sX;
+ py = sin(M_PI-alpha*_q/10.0)*sR;
+ }
+ else
+ {
+ long double sX = fx - sR*cos( asin( fy / sR ) );
+ px = cos(alpha*_q/10.0)*sR+sX;
+ py = sin(alpha*_q/10.0)*sR;
+ }
+
+ switch( m_type )
+ {
+ case Highpass_RC6:
+ case Highpass_RC12:
+ case Highpass_RC24:
+ {
+ m_rca0 = ( px*px + py*py + 2.0 * px + 1 )/4.0;
+
+ m_rca1 = -2.0 * m_rca0;
+ m_rca2 = 1.0 * m_rca0;
+
+ m_rcb1 = 2.0 * px;
+ m_rcb2 = -( px*px + py*py );
+
+ break;
+ }
+ case Lowpass_RC6:
+ case Lowpass_RC12:
+ case Lowpass_RC24:
+ {
+ m_rca0 = ( px*px + py*py - 2.0 * px + 1 )/4.0;
+
+ m_rca1 = +2.0 * m_rca0;
+ m_rca2 = +1.0 * m_rca0;
+
+ m_rcb1 = +2.0 * px;
+ m_rcb2 = -( px*px + py*py );
+
+ break;
+ }
+ default:
+ {
+ m_rca0 = m_rca1 = m_rca2 = m_rcb1 = m_rcb2 = 0.0;
+ break;
+ }
+ }
+
+ //std::cerr << "f:" << _freq << " a0:" << m_rca0 << " a1:" << m_rca1 << " a2:" << m_rca2 << " b1:" << m_rcb1 << " b2:" << m_rcb2 << "\n";
+ }
+
+
+ if( m_type == Bandpass_RC6 ||
+ m_type == Bandpass_RC12 ||
+ m_type == Bandpass_RC24 )
+ {
+ if( _freq < 50.f )
+ {
+ _freq = 50.f;
+ }
+ _freq = round(_freq);
+ _q *= 1.01;
+
+ //if( _q > 9.999 ) _q = 9.999;
+
+ //float _q_ = _q / 10.0;
+ //float _rc_ = 2*M_PI*_freq/m_sampleRate;
+ //float _r_ = (0.1455*powf(_rc_-M_PI/2, 2)+0.0370*powf(_rc_-M_PI/2, 4)+0.4157342)*(1-_q_)+_q_*1.001;
+
+ //float px = _r_*cos(_rc_);
+ //float py = _r_*sin(_rc_);
+
+ double fx = cos( 2*M_PI*_freq/m_sampleRate );
+ double fy = sin( 2*M_PI*_freq/m_sampleRate );
+
+ double px = 0;
+ double py = 0;
+ double zx = 0;
+ // calculate stereographic mapping for given q-factor [0.0;1.0]
+ double sD = sqrt( pow( (-1.0) - fx, 2.0 ) + pow( -fy, 2.0 ) )/
+ sqrt( pow( (+1.0) - fx, 2.0 ) + pow( -fy, 2.0 ) );
+ double sR = sD/fabs( pow(sD, 2.0) - 1.0 )*2.0;
+ if( sR > 10000 ) sR=10000;
+ double alpha = asin( fy / sR );
+
+ if( fx > 0.0 )
+ {
+ double sX = fx + sR*cos( asin( fy / sR ) );
+ zx = cos(M_PI-0.0)*sR+sX;
+ px = cos(M_PI-alpha*_q/10.0)*sR+sX;
+ py = sin(M_PI-alpha*_q/10.0)*sR;
+ }
+ else
+ if( fx < 0.0 )
+ {
+ double sX = fx - sR*cos( asin( fy / sR ) );
+ zx = cos(0.0)*sR+sX;
+ px = cos(alpha*_q/10.0)*sR+sX;
+ py = sin(alpha*_q/10.0)*sR;
+ }
+ else
+ if( fx == 0.0 )
+ {
+ std::cerr << "=";
+ px = 0.0;
+ py = _q/10.0;
+ }
+
+// float a = powf( px - _r_*px, 2) - (py - _r_*py) * (py + _r_*py);
+// float b = (px - _r_*px)*(2*py);
+// float c = (px - 1.0)*(px + 1.0)-powf(py,2);
+// float d = (py)*(px-1)+(py)*(px+1);
+
+ float a = powf( fx - px, 2) - (fy - py) * (fy + py);
+ float b = (fx - px)*(2*fy);
+ float c = (fx - 1.0)*(fx + 1.0)-powf(fy,2);
+ float d = (fy)*(fx-1)+(fy)*(fx+1);
+
+ m_rca0 = 4.0 * + sqrtf( a*a + b*b ) / sqrt( c*c + d*d );
+
+ double Z = pow(py,4.0) +
+ 2.0*pow(px,2.0)*pow(py,2.0) -
+ 4.0*fx*px*pow(py,2.0) -
+ 2.0*pow(fy,2.0)*pow(py,2.0) +
+ 2.0*pow(fx,2.0)*pow(py,2.0) +
+ pow(px,4.0) -
+ 4.0*fx*pow(px,3) +
+ 2.0*pow(fy,2)*pow(px,2) +
+ 6.0*pow(fx,2)*pow(px,2) -
+ 4.0*fx*pow(fy,2)*px -
+ 4.0*pow(fx,3)*px +
+ pow(fy,4) +
+ 2.0*pow(fx,2) * pow(fy,2) +
+ pow(fx,4);
+ if( Z < 0 ) Z=0;
+ double _Z_ = sqrt( Z );
+ double _N_ = ( pow(zx,2) - 2.0*fx*zx + pow(fy,2) + pow(fx,2) );
+
+ m_rca0 = _Z_/_N_;
+
+ //double v = 1/(m_rcb1 + m_rcb2);
+ //m_rcb1 *= v;
+ //m_rcb2 *= v;
+
+// m_rca0 = (1.1f-_r_);
+// m_rca0 = m_rca0 < 0.01? 0.01:m_rca0;
+
+// m_rca1 = 0.0;
+// m_rca2 = -1.0 * m_rca0;
+m_rca1 = -2.0*m_rca0*zx;
+m_rca2 = m_rca0*(zx*zx);
+
+ m_rcb1 = 2.0 * px;
+ m_rcb2 = -( px*px + py*py );
+
+// std::cerr << "f:" << _freq << " Z:" << Z << " _Z_:" << _Z_ << " _N_:" << _N_ << " a0:" << m_rca0 << " a1:" << m_rca1 << " a2:" << m_rca2 << " b1:" << m_rcb1 << " b2:" << m_rcb2 << "\n";
+ }
+
+
+
+#if 0
+ if( m_type == Lowpass_RC24 ||
m_type == Bandpass_RC24 ||
m_type == Highpass_RC24 )
{
- if( _freq < 50.f )
+ if( _freq < 5.f )
{
- _freq = 50.f;
+ _freq = 5.f;
}
- m_rca = 1.0f - (1.0f/(m_sampleRate*4)) / ( (1.0f/(_freq*2.0f*M_PI)) + (1.0f/(m_sampleRate*4)) );
+ m_rca = 1.0f - (1.0f/(m_sampleRate*1)) / ( (1.0f/(_freq*2.0f*M_PI)) + (1.0f/(m_sampleRate*1)) );
m_rcb = 1.0f - m_rca;
- m_rcc = (1.0f/(_freq*2.0f*M_PI)) / ( (1.0f/(_freq*2.0f*M_PI)) + (1.0f/(m_sampleRate*4)) );
+ m_rcc = (1.0f/(_freq*2.0f*M_PI)) / ( (1.0f/(_freq*2.0f*M_PI)) + (1.0f/(m_sampleRate*1)) );
- // Stretch Q/resonance, as self-oscillation reliably starts at a q of ~2.5 - ~2.6
- m_rcq = _q/4.f;
+ m_rca = 1.0f-2.0f*sin(_freq/m_sampleRate*M_PI);
+ m_rcb = 1.0f-m_rca;
+ m_rcc = m_rcb;
+
+ // Stretch Q/resonance, as self-oscillation reliably starts at a q of 1.0, now.
+ // The factor of 8 was chosen to make the filter react approximately like the
+ // slightly incorrect previous variant and to leave some room for overdriving
+ // the filter internally...
+ m_rcq = (_q * (1+1/m_rca))/8.00f;
}
+#endif
if( m_type == Formantfilter )
{
- // formats for a, e, i, o, u, a
- const float _f[5][2] = { { 1000, 1400 }, { 500, 2300 },
- { 320, 3200 },
- { 500, 1000 },
- { 320, 800 } };
-
- // Stretch Q/resonance
- m_vfq = _q/4.f;
+ // formats for a, e, i, o, u
+#if 0
+ const float _f[5][3] = {
+ { 1000, 1400, 3000 },
+ { 500, 2300, 4600 },
+ { 320, 3200, 6400 },
+ { 500, 1000, 1500 },
+ { 320, 800, 1000 } };
+#else
+ const float _f[5][4] = {
+ { 500, 1000, 1400, 2800 },
+ { 250, 500, 2300, 4600 },
+ { 160, 320, 3200, 6400 },
+
+ { 250, 500, 1000, 2000 },
+ { 160, 320, 800, 1600 } };
+#endif
// frequency in lmms ranges from 1Hz to 14000Hz
const int vowel = (int)( floor( _freq/14000.f * 4.f ) );
@@ -535,31 +912,62 @@ public:
const float f1 = _f[vowel+0][1] * ( 1.0f - fract ) +
_f[vowel+1][1] * ( fract );
- m_vfa[0] = 1.0f - (1.0f/(m_sampleRate*4)) /
+ const float f2 = _f[vowel+0][2] * ( 1.0f - fract ) +
+ _f[vowel+1][2] * ( fract );
+
+ const float f3 = _f[vowel+0][3] * ( 1.0f - fract ) +
+ _f[vowel+1][3] * ( fract );
+
+ // coeffs for f1
+ m_vfa[0] = 1.0f - (1.0f/(m_sampleRate*1)) /
( (1.0f/(f0*2.0f*M_PI)) +
- (1.0f/(m_sampleRate*4)) );
+ (1.0f/(m_sampleRate*1)) );
m_vfb[0] = 1.0f - m_vfa[0];
m_vfc[0] = (1.0f/(f0*2.0f*M_PI)) /
( (1.0f/(f0*2.0f*M_PI)) +
- (1.0f/(m_sampleRate*4)) );
+ (1.0f/(m_sampleRate*1)) );
+ m_vfq[0] = (_q * (1+1/m_vfa[0]))/10.00f;
- m_vfa[1] = 1.0f - (1.0f/(m_sampleRate*4)) /
+ // coeffs for f2
+ m_vfa[1] = 1.0f - (1.0f/(m_sampleRate*1)) /
( (1.0f/(f1*2.0f*M_PI)) +
- (1.0f/(m_sampleRate*4)) );
+ (1.0f/(m_sampleRate*1)) );
m_vfb[1] = 1.0f - m_vfa[1];
m_vfc[1] = (1.0f/(f1*2.0f*M_PI)) /
( (1.0f/(f1*2.0f*M_PI)) +
- (1.0f/(m_sampleRate*4)) );
+ (1.0f/(m_sampleRate*1)) );
+ m_vfq[1] = (_q * (1+1/m_vfa[1]))/10.00f;
+
+ // coeffs for f3
+ m_vfa[2] = 1.0f - (1.0f/(m_sampleRate*1)) /
+ ( (1.0f/(f2*2.0f*M_PI)) +
+ (1.0f/(m_sampleRate*1)) );
+ m_vfb[2] = 1.0f - m_vfa[2];
+ m_vfc[2] = (1.0f/(f2*2.0f*M_PI)) /
+ ( (1.0f/(f2*2.0f*M_PI)) +
+ (1.0f/(m_sampleRate*1)) );
+ m_vfq[2] = (_q * (1+1/m_vfa[2]))/10.00f;
+
+ // coeffs for f4
+ m_vfa[3] = 1.0f - (1.0f/(m_sampleRate*1)) /
+ ( (1.0f/(f3*2.0f*M_PI)) +
+ (1.0f/(m_sampleRate*1)) );
+ m_vfb[3] = 1.0f - m_vfa[3];
+ m_vfc[3] = (1.0f/(f3*2.0f*M_PI)) /
+ ( (1.0f/(f3*2.0f*M_PI)) +
+ (1.0f/(m_sampleRate*1)) );
+ m_vfq[3] = (_q * (1+1/m_vfa[3]))/10.00f;
}
if( m_type == Moog )
{
// [ 0 - 0.5 ]
- const float f = _freq / m_sampleRate;
+ const double f = _freq / m_sampleRate;
// (Empirical tunning)
m_p = ( 3.6f - 3.2f * f ) * f;
m_k = 2.0f * m_p - 1;
- m_r = _q * powf( M_E, ( 1 - m_p ) * 1.386249f );
+ //m_r = _q * powf( M_E, ( 1 - m_p ) * 1.386249f );
+ m_r = (_q/10.f) * powf( M_E, ( 1 - m_p ) * 1.386249f );
if( m_doubleFilter )
{
@@ -639,15 +1047,18 @@ private:
float m_b0a0, m_b1a0, m_b2a0, m_a1a0, m_a2a0;
// coeffs for moog-filter
- float m_r, m_p, m_k;
+ double m_r, m_p, m_k;
// coeffs for RC-type-filters
float m_rca, m_rcb, m_rcc, m_rcq;
+ long double m_rca0, m_rca1, m_rca2;
+ long double m_rcb1, m_rcb2;
+
// coeffs for formant-filters
- float m_vfa[4], m_vfb[4], m_vfc[4], m_vfq;
+ float m_vfa[4], m_vfb[4], m_vfc[4], m_vfq[4];
- typedef sample_t frame[CHANNELS];
+ typedef long double frame[CHANNELS];
// in/out history
frame m_ou1, m_ou2, m_in1, m_in2;
@@ -659,8 +1070,14 @@ private:
frame m_rcbp0, m_rclp0, m_rchp0, m_rclast0;
frame m_rcbp1, m_rclp1, m_rchp1, m_rclast1;
+ // in/out history for new RC-type-filters
+ frame m_rcx00, m_rcx10, m_rcx20, m_rcy00, m_rcy10, m_rcy20;
+ frame m_rcx01, m_rcx11, m_rcx21, m_rcy01, m_rcy11, m_rcy21;
+ frame m_rcx02, m_rcx12, m_rcx22, m_rcy02, m_rcy12, m_rcy22;
+ frame m_rcx03, m_rcx13, m_rcx23, m_rcy03, m_rcy13, m_rcy23;
+
// in/out history for Formant-filters
- frame m_vfbp[6], m_vflp[6], m_vfhp[6], m_vflast[6];
+ frame m_vfbp[12], m_vflp[12], m_vfhp[12], m_vflast[12];
FilterTypes m_type;
bool m_doubleFilter;
diff --git a/plugins/triple_oscillator/TripleOscillator.cpp b/plugins/triple_oscillator/TripleOscillator.cpp
index a025546..d37f75e 100644
--- a/plugins/triple_oscillator/TripleOscillator.cpp
+++ b/plugins/triple_oscillator/TripleOscillator.cpp
@@ -340,16 +340,22 @@ QString TripleOscillator::nodeName() const
}
-
-
void TripleOscillator::playNote( notePlayHandle * _n,
sampleFrame * _working_buffer )
{
+ const float over=8; // this can (and most probably should?) be made fine-
+ // tuneable for each instance of the Oscillators. So it
+ // does not waste CPU-Cycles were it isn't needed...
+ // 8x oversampling usually is enough... but if desired,
+ // up to 16x oversampling is allowed by the current code.
+
if( _n->totalFramesPlayed() == 0 || _n->m_pluginData == NULL )
{
Oscillator * oscs_l[NUM_OF_OSCILLATORS];
Oscillator * oscs_r[NUM_OF_OSCILLATORS];
+ // SMF-Remark: initializing only three oscillators like this... is hmm,...
+ // a little bit weird, isn't it?
for( Sint8 i = NUM_OF_OSCILLATORS - 1; i >= 0; --i )
{
// prepare phase randomness for note
@@ -364,33 +370,69 @@ void TripleOscillator::playNote( notePlayHandle * _n,
_n->frequency(),
m_osc[i]->m_detuningLeft,
m_osc[i]->m_phaseOffsetLeft,
- m_osc[i]->m_volumeLeft );
+ m_osc[i]->m_volumeLeft,
+ NULL,
+ over,
+ false );
oscs_r[i] = new Oscillator(
&m_osc[i]->m_waveShapeModel,
&m_osc[i]->m_modulationAlgoModel,
_n->frequency(),
m_osc[i]->m_detuningRight,
m_osc[i]->m_phaseOffsetRight,
- m_osc[i]->m_volumeRight );
+ m_osc[i]->m_volumeRight,
+ NULL,
+ over,
+ false );
}
else
{
- oscs_l[i] = new Oscillator(
- &m_osc[i]->m_waveShapeModel,
- &m_osc[i]->m_modulationAlgoModel,
- _n->frequency(),
- m_osc[i]->m_detuningLeft,
- m_osc[i]->m_phaseOffsetLeft,
- m_osc[i]->m_volumeLeft,
- oscs_l[i + 1] );
- oscs_r[i] = new Oscillator(
- &m_osc[i]->m_waveShapeModel,
- &m_osc[i]->m_modulationAlgoModel,
- _n->frequency(),
- m_osc[i]->m_detuningRight,
- m_osc[i]->m_phaseOffsetRight,
- m_osc[i]->m_volumeRight,
- oscs_r[i + 1] );
+ if( i != 0 ) // it's not the master-oscillator, so handle it as
+ { // usual...
+ oscs_l[i] = new Oscillator(
+ &m_osc[i]->m_waveShapeModel,
+ &m_osc[i]->m_modulationAlgoModel,
+ _n->frequency(),
+ m_osc[i]->m_detuningLeft,
+ m_osc[i]->m_phaseOffsetLeft,
+ m_osc[i]->m_volumeLeft,
+ oscs_l[i + 1],
+ over,
+ false );
+ oscs_r[i] = new Oscillator(
+ &m_osc[i]->m_waveShapeModel,
+ &m_osc[i]->m_modulationAlgoModel,
+ _n->frequency(),
+ m_osc[i]->m_detuningRight,
+ m_osc[i]->m_phaseOffsetRight,
+ m_osc[i]->m_volumeRight,
+ oscs_r[i + 1],
+ over,
+ false );
+ }
+ else // this is the master-oscillator, tell it about...
+ {
+ oscs_l[i] = new Oscillator(
+ &m_osc[i]->m_waveShapeModel,
+ &m_osc[i]->m_modulationAlgoModel,
+ _n->frequency(),
+ m_osc[i]->m_detuningLeft,
+ m_osc[i]->m_phaseOffsetLeft,
+ m_osc[i]->m_volumeLeft,
+ oscs_l[i + 1],
+ over,
+ true );
+ oscs_r[i] = new Oscillator(
+ &m_osc[i]->m_waveShapeModel,
+ &m_osc[i]->m_modulationAlgoModel,
+ _n->frequency(),
+ m_osc[i]->m_detuningRight,
+ m_osc[i]->m_phaseOffsetRight,
+ m_osc[i]->m_volumeRight,
+ oscs_r[i + 1],
+ over,
+ true );
+ }
}
oscs_l[i]->setUserWave( m_osc[i]->m_sampleBuffer );
diff --git a/src/core/InstrumentSoundShaping.cpp b/src/core/InstrumentSoundShaping.cpp
index edd456a..ecaa2f3 100644
--- a/src/core/InstrumentSoundShaping.cpp
+++ b/src/core/InstrumentSoundShaping.cpp
@@ -87,6 +87,9 @@ InstrumentSoundShaping::InstrumentSoundShaping(
m_filterModel.addItem( tr( "Allpass" ), new PixmapLoader( "filter_ap" ) );
m_filterModel.addItem( tr( "Moog" ), new PixmapLoader( "filter_lp" ) );
m_filterModel.addItem( tr( "2x LowPass" ), new PixmapLoader( "filter_2lp" ) );
+ m_filterModel.addItem( tr( "RC LowPass 6dB" ), new PixmapLoader( "filter_lp" ) );
+ m_filterModel.addItem( tr( "RC BandPass 6dB" ), new PixmapLoader( "filter_bp" ) );
+ m_filterModel.addItem( tr( "RC HighPass 6dB" ), new PixmapLoader( "filter_hp" ) );
m_filterModel.addItem( tr( "RC LowPass 12dB" ), new PixmapLoader( "filter_lp" ) );
m_filterModel.addItem( tr( "RC BandPass 12dB" ), new PixmapLoader( "filter_bp" ) );
m_filterModel.addItem( tr( "RC HighPass 12dB" ), new PixmapLoader( "filter_hp" ) );
diff --git a/src/core/Oscillator.cpp b/src/core/Oscillator.cpp
index 7b5c8a6..cd67781 100644
--- a/src/core/Oscillator.cpp
+++ b/src/core/Oscillator.cpp
@@ -27,7 +27,10 @@
#include "Mixer.h"
#include "AutomatableModel.h"
+#include <iostream>
+bool Oscillator::m_is_initialized = false;
+float Oscillator::m_filter[31][257];
Oscillator::Oscillator( const IntModel * _wave_shape_model,
const IntModel * _mod_algo_model,
@@ -35,7 +38,9 @@ Oscillator::Oscillator( const IntModel * _wave_shape_model,
const float & _detuning,
const float & _phase_offset,
const float & _volume,
- Oscillator * _sub_osc ) :
+ Oscillator * _sub_osc,
+ const float _oversampling,
+ const bool _is_master ) :
m_waveShapeModel( _wave_shape_model ),
m_modulationAlgoModel( _mod_algo_model ),
m_freq( _freq ),
@@ -45,10 +50,60 @@ Oscillator::Oscillator( const IntModel * _wave_shape_model,
m_subOsc( _sub_osc ),
m_phaseOffset( _phase_offset ),
m_phase( _phase_offset ),
- m_userWave( NULL )
+ m_userWave( NULL ),
+ m_oversampling( _oversampling ),
+ m_is_master( _is_master ),
+ m_temp_ab( 0 ),
+ m_temp_size( 0 )
{
-}
+ if(!m_is_initialized)
+ {
+ std::cerr << "### Oscillator::Oscillator(...); initializing filter coefficient-tables.\n";
+
+ for(int m=0; m<31; ++m)
+ {
+ // we use a Lanzcos-window, so we can tell how long the filter-trail is...
+ const int fir_length = 8*m;
+
+ // clear the current filter-table
+ for(int n=-fir_length; n<=+fir_length; ++n)
+ {
+ m_filter[m][128+n] = 0;
+ }
+
+ // calculate the filter coefficients for the current entry in the table...
+ for(int n=-fir_length; n<=+fir_length; ++n)
+ {
+ float v=0;
+ if( n != 0 )
+ {
+ v = sinf( n*M_PI/(float)(m+2)*0.8616 ) / ( n*M_PI/(float)(m+2)*0.8616 );
+ v *= sinf( n*M_PI/(float)fir_length ) / ( n*M_PI/(float)fir_length );
+ }
+ else
+ {
+ v = 1.0;
+ }
+ m_filter[m][128+n] = v;
+ }
+
+ // normalize the filter, so it's using a gain of 1.0
+ float norm = 0;
+ for(int n=-fir_length; n<=+fir_length; ++n)
+ {
+ norm += m_filter[m][128+n];
+ }
+ for(int n=-fir_length; n<=+fir_length; ++n)
+ {
+ m_filter[m][128+n] /= norm;
+ }
+ }
+
+ // flag that we are ready to process without any further initialisation
+ m_is_initialized = true;
+ }
+}
@@ -60,30 +115,104 @@ void Oscillator::update( sampleFrame * _ab, const fpp_t _frames,
Mixer::clearAudioBuffer( _ab, _frames );
return;
}
- if( m_subOsc != NULL )
- {
- switch( m_modulationAlgoModel->value() )
- {
- case PhaseModulation:
- updatePM( _ab, _frames, _chnl );
- break;
- case AmplitudeModulation:
- updateAM( _ab, _frames, _chnl );
- break;
- case SignalMix:
- updateMix( _ab, _frames, _chnl );
- break;
- case SynchronizedBySubOsc:
- updateSync( _ab, _frames, _chnl );
- break;
- case FrequencyModulation:
- updateFM( _ab, _frames, _chnl );
- }
- }
- else
- {
- updateNoSub( _ab, _frames, _chnl );
- }
+ if( m_oversampling == 1.0 || m_is_master == false ) // no further oversampling ?
+ {
+ // just use the old code...
+ if( m_subOsc != NULL )
+ {
+ switch( m_modulationAlgoModel->value() )
+ {
+ case PhaseModulation:
+ updatePM( _ab, _frames, _chnl );
+ break;
+ case AmplitudeModulation:
+ updateAM( _ab, _frames, _chnl );
+ break;
+ case SignalMix:
+ updateMix( _ab, _frames, _chnl );
+ break;
+ case SynchronizedBySubOsc:
+ updateSync( _ab, _frames, _chnl );
+ break;
+ case FrequencyModulation:
+ updateFM( _ab, _frames, _chnl );
+ }
+ }
+ else
+ {
+ updateNoSub( _ab, _frames, _chnl );
+ }
+ }
+#if 1
+ else
+ {
+ // the new code differs only in the regard of using a shadow sample-buffer
+ // instead of _ab with sizeof(_ab)*m_oversampling.
+
+ const fpp_t m_temp_frames = _frames * m_oversampling;
+
+ if( m_temp_size != m_temp_frames || !m_temp_ab )
+ {
+ delete [] m_temp_ab;
+ m_temp_ab = new sampleFrame[ m_temp_frames*2 ];
+ m_temp_size = m_temp_frames;
+
+ for( fpp_t frame = 0; frame < m_temp_frames*2; ++frame )
+ {
+ m_temp_ab[frame][_chnl] = 0.0;
+ }
+ }
+
+ for( fpp_t frame = 0; frame < m_temp_frames; ++frame )
+ {
+ m_temp_ab[frame][_chnl] = m_temp_ab[frame+m_temp_frames][_chnl];
+ }
+
+ if( m_subOsc != NULL )
+ {
+ switch( m_modulationAlgoModel->value() )
+ {
+ case PhaseModulation:
+ updatePM( m_temp_ab+m_temp_frames, m_temp_frames, _chnl );
+ break;
+ case AmplitudeModulation:
+ updateAM( m_temp_ab+m_temp_frames, m_temp_frames, _chnl );
+ break;
+ case SignalMix:
+ updateMix( m_temp_ab+m_temp_frames, m_temp_frames, _chnl );
+ break;
+ case SynchronizedBySubOsc:
+ updateSync( m_temp_ab+m_temp_frames, m_temp_frames, _chnl );
+ break;
+ case FrequencyModulation:
+ updateFM( m_temp_ab+m_temp_frames, m_temp_frames, _chnl );
+ }
+ }
+ else
+ {
+ updateNoSub( m_temp_ab+m_temp_frames, m_temp_frames, _chnl );
+ }
+
+ const int fir_length = 8*m_oversampling;
+ const int fir_index = m_oversampling-2;
+
+ for( fpp_t frame = 0; frame < _frames; ++frame )
+ {
+ float value = 0;
+ const int _f = frame*m_oversampling+m_temp_frames-(2*fir_length+1);
+
+ if( m_temp_ab )
+ for( int n=-fir_length; n<+fir_length; ++n )
+ {
+ float a = (float)m_temp_ab[_f+n][_chnl];
+ float b = m_filter[fir_index][n+128];
+ value = value + a*b;
+ }
+ _ab[frame][_chnl] = value;
+ }
+
+ }
+#endif
}
@@ -340,7 +469,7 @@ float Oscillator::syncInit( sampleFrame * _ab, const fpp_t _frames,
m_subOsc->update( _ab, _frames, _chnl );
}
recalcPhase();
- return( m_freq * m_detuning );
+ return( m_freq * m_detuning / m_oversampling );
}
@@ -352,7 +481,7 @@ void Oscillator::updateNoSub( sampleFrame * _ab, const fpp_t _frames,
const ch_cnt_t _chnl )
{
recalcPhase();
- const float osc_coeff = m_freq * m_detuning;
+ const float osc_coeff = m_freq * m_detuning / m_oversampling;
for( fpp_t frame = 0; frame < _frames; ++frame )
{
@@ -371,7 +500,7 @@ void Oscillator::updatePM( sampleFrame * _ab, const fpp_t _frames,
{
m_subOsc->update( _ab, _frames, _chnl );
recalcPhase();
- const float osc_coeff = m_freq * m_detuning;
+ const float osc_coeff = m_freq * m_detuning / m_oversampling;
for( fpp_t frame = 0; frame < _frames; ++frame )
{
@@ -392,7 +521,7 @@ void Oscillator::updateAM( sampleFrame * _ab, const fpp_t _frames,
{
m_subOsc->update( _ab, _frames, _chnl );
recalcPhase();
- const float osc_coeff = m_freq * m_detuning;
+ const float osc_coeff = m_freq * m_detuning / m_oversampling;
for( fpp_t frame = 0; frame < _frames; ++frame )
{
@@ -411,7 +540,7 @@ void Oscillator::updateMix( sampleFrame * _ab, const fpp_t _frames,
{
m_subOsc->update( _ab, _frames, _chnl );
recalcPhase();
- const float osc_coeff = m_freq * m_detuning;
+ const float osc_coeff = m_freq * m_detuning / m_oversampling;
for( fpp_t frame = 0; frame < _frames; ++frame )
{
@@ -431,7 +560,7 @@ void Oscillator::updateSync( sampleFrame * _ab, const fpp_t _frames,
{
const float sub_osc_coeff = m_subOsc->syncInit( _ab, _frames, _chnl );
recalcPhase();
- const float osc_coeff = m_freq * m_detuning;
+ const float osc_coeff = m_freq * m_detuning / m_oversampling;
for( fpp_t frame = 0; frame < _frames ; ++frame )
{
@@ -454,7 +583,7 @@ void Oscillator::updateFM( sampleFrame * _ab, const fpp_t _frames,
{
m_subOsc->update( _ab, _frames, _chnl );
recalcPhase();
- const float osc_coeff = m_freq * m_detuning;
+ const float osc_coeff = m_freq * m_detuning / m_oversampling;
const float sampleRateCorrection = 44100.0f /
engine::mixer()->processingSampleRate();
------------------------------------------------------------------------------
Start uncovering the many advantages of virtual appliances
and start using them to simplify application deployment and
accelerate your shift to cloud computing
http://p.sf.net/sfu/novell-sfdev2dev
_______________________________________________
LMMS-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/lmms-devel