From: Stefan Fendt <stefan@sf...>  20100407 17:53:02

Maybe this is of use for someone... // Oversampled "naive" Oscillator to suppress audible aliasing. This concept // will work also with a wavetablebased oscillator. It does _not_ deliver alias // *free*output, but the alias is sufficiently suppressed to be unaudible at // 32times oversampling and above. // // Usually one would use a FIRFilter for this, but an IIRFilter works also // and gives the output some "analogue" touchup... ;) Despite that the IIR is // faster and we are not interested in having something with zerophaseshift // anyways... // // This is proof of conceptcode, so do not expect any beauty... // // (C)2010 S.Fendt, released into the public domain in the hope it will be usefull // for someone... #include <iostream> #include <fstream> #include <cmath> #include <cstdlib> class lowpassfilter { double a0,a1,a2,b1,b2; double x0,x1,x2,y1,y2,y0; public: lowpassfilter( float rel_frequency ) { double fx = cos( M_PIl*rel_frequency ); double fy = sin( M_PIl*rel_frequency ); 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 ); double px = 0; double py = 0; if( fx >= 0 ) { double sX = fx + sR*cos( asin( fy / sR ) ); px = cos(M_PIalpha*0.45)*sR+sX; py = sin(M_PIalpha*0.45)*sR; } else { double sX = fx  sR*cos( asin( fy / sR ) ); px = cos(alpha*0.45)*sR+sX; py = sin(alpha*0.45)*sR; } a0 = ( px*px + py*py  2.0 * px + 1 )/4.0; a1 = +2.0 * a0; a2 = +1.0 * a0; b1 = +2.0 * px; b2 = ( px*px + py*py ); x0 = x1 = x2 = y0 = y1 = y2 = 0.0; } inline double run( double in ) { x2 = x1; x1 = x0; x0 = in; y2 = y1; y1 = y0; y0 = x0*a0 + x1*a1 + x2*a2 + y1*b1 + y2*b2; return( y0 ); } }; class oscillator { float phase; float frequency; float samplerate; int oversampling; int pos; float out; lowpassfilter* lp0; lowpassfilter* lp1; lowpassfilter* lp2; lowpassfilter* lp3; public: oscillator(float samplerate) { this>samplerate = samplerate; this>phase = 0; this>frequency = 8000; this>oversampling = 256; // 64times oversampling runs >10times faster // than realtime on my system (E5400@...) // and is free of audible aliasing... out = 0; lp0 = new lowpassfilter( 0.66/(float)oversampling ); lp1 = new lowpassfilter( 0.66/(float)oversampling ); lp2 = new lowpassfilter( 0.66/(float)oversampling ); lp3 = new lowpassfilter( 0.66/(float)oversampling ); } ~oscillator() { } float run() { const float alpha = 0.125f/(float)oversampling; for(int n=0; n<oversampling; n++) { phase += frequency/(samplerate*(float)oversampling); phase = phase>1.0f? phase1.0f:phase; if(1) { if(phase<0.125) out = lp3>run(lp2>run(lp1>run(lp0>run( +0.5 )))); else out = lp3>run(lp2>run(lp1>run(lp0>run( 0.5 )))); } else { out = lp3>run(lp2>run(lp1>run(lp0>run( (phase0.5)*2.0 )))); } } return( out ); } void set_frequency( float frequency ) { this>frequency = frequency; } }; int main() { std::fstream fileout( "outfile.dat", std::ios::outstd::ios::binary ); float samplerate = 44100; union { float f; char c[4]; } sample; oscillator m_oscillator( samplerate ); float f0 = 100; float f1 = 8000; for(int n=0; n<(int)(samplerate*10); n++ ) { m_oscillator.set_frequency( f0*((float)n/(samplerate*10)) + f1 * (1.0(float)n/(samplerate*10)) ); sample.f = m_oscillator.run(); fileout.write( &sample.c[0], 4 ); } fileout.close(); } 