@@ -120,6 +120,61 @@ function calculateHarmonics(settings) {
120120 let invert = 1 ;
121121 let harmInc = ( settings . harmType === "Odd" || settings . harmType === "Even" ) ? 2 : 1 ;
122122
123+
124+ // data from SHARC dataset: https://web.archive.org/web/20090226034059/http://www.timbre.ws/sharc/
125+ const clarinetHarmonics = [
126+ 1.0 , 0.020330578512396693 , 0.5368506493506493 , 0.045386658795749706 ,
127+ 0.39042207792207795 , 0.13839728453364816 , 0.49614521841794573 , 0.038146399055489964 ,
128+ 0.10071428571428573 , 0.05957201889020071 , 0.0363370720188902 , 0.08095926800472256 ,
129+ 0.03358028335301062 , 0.046177685950413216 , 0.008293978748524203 , 0.026933293978748524 ,
130+ 0.011124557260920896 , 0.008400236127508854 , 0.0048524203069657615 , 0.011481700118063754 ,
131+ 0.008500590318772138 , 0.008288075560802834 , 0.0031316410861865407 , 0.0030991735537190084 ,
132+ 0.0025974025974025974 , 0.004126328217237308 , 0.000655253837072019 , 0.00017709563164108617 ,
133+ 0.00012101534828807555 , 0.0004309327036599764 , 0.000678866587957497 , 0.0006434474616292798 ,
134+ 0.0004929161747343566 , 0.0006463990554899646 , 0.00035419126328217233 , 0.00037190082644628097 ,
135+ 0.0001180637544273908 , 0.0005814639905548997
136+ ]
137+
138+ const frenchHornHarmonics = [
139+ 0.23043554773427188 , 0.6242410910690718 , 1.0 , 0.8554861416630004 ,
140+ 0.6396172459304883 , 0.5116344038715354 , 0.4244610646722393 , 0.29865816102067755 ,
141+ 0.19071271447426308 , 0.1496480422349318 , 0.12175758908930928 , 0.07521997360316762 ,
142+ 0.04647162340519138 , 0.03197096348438187 , 0.015767707875054996 , 0.01661020677518698 ,
143+ 0.009472063352397713 , 0.00906291245050594 , 0.009069511658600968 , 0.005954685437747471 ,
144+ 0.004100307963044435 , 0.004392872855257369 , 0.004025516937967444 , 0.003570171579410471 ,
145+ 0.00291684997800264 , 0.0012736471623405192 , 0.0020875494940607127 , 0.0014672239331280246 ,
146+ 0.0008205015398152222 , 0.00031896172459304885 , 0.00042894852617685877 , 0.00042454905411350635 ,
147+ 0.0002001759788825341 , 0.00022657281126264847 , 0.00020897492300923887 , 0.00010558732952045754 ,
148+ 7.259128904531456e-05 , 0.0002067751869775627 , 0.00014078310602727673 , 6.379234491860976e-05 ,
149+ 5.9392872855257375e-05 , 0.00010118785745710515 , 2.419709634843819e-05 , 0.00011218653761548615 ,
150+ 8.798944126704795e-05 , 9.458864936207654e-05 , 0.00012758468983721952 , 4.6194456665200174e-05 ,
151+ 9.238891333040035e-05 , 8.139023317201936e-05 , 0.0001847778266608007 , 0.00015618125824901012 ,
152+ 0.0001913770347558293 , 0.00015618125824901012 , 0.00017817861856577212 , 0.0002441706995160581 ,
153+ 3.7395512538495386e-05 , 2.8596568411790586e-05 , 0.00014738231412230534 , 0.00011658600967883854 ,
154+ 0.00022657281126264847 , 0.00012098548174219095 , 0.0001253849538055433 , 0.00011218653761548615 ,
155+ 5.719313682358117e-05 , 5.0593928728552574e-05 , 8.798944126704795e-05 , 0.0001539815222173339 ,
156+ 9.678838539375275e-05 , 0.00016058073031236252 , 0.00014518257809062912 , 5.279366476022877e-05
157+ ] ;
158+
159+ fluteHarmonics = [
160+ 1.0 , 0.7543711967545639 , 0.1576450304259635 , 0.1966977687626775 ,
161+ 0.1143265720081136 , 0.0762657200811359 , 0.012525354969574036 , 0.009004056795131846 ,
162+ 0.0065091277890466535 , 0.003862068965517241 , 0.002328600405679513 , 0.002464503042596349 ,
163+ 0.002342799188640974 , 0.001308316430020284 , 0.0006450304259634889 , 0.0001338742393509128 ,
164+ 0.0010304259634888438 , 0.0005436105476673428 , 0.00010750507099391482 , 0.0009574036511156186 ,
165+ 0.000744421906693712 , 0.0005578093306288032 , 0.0006754563894523326 , 0.00043002028397565926 ,
166+ 0.0003387423935091278
167+ ] ;
168+
169+ violinHarmonics = [
170+ 0.46135830072666295 , 1.0 , 0.8625675423886714 , 0.29511645239426126 ,
171+ 0.9508216880939073 , 0.2635252468790758 , 0.06555617663499161 , 0.03791503633314701 ,
172+ 0.0403204769890069 , 0.06457611328488913 , 0.006828768399478293 , 0.006172908514999069 ,
173+ 0.0010508664058133034 , 0.0038755356810136017 , 0.00038382709148500094 , 0.0020029811812930873 ,
174+ 0.004158747903856903 , 0.002397987702627166 , 0.0010527296441214832 , 0.0009782001117942985 ,
175+ 0.0007080305571082541 , 0.0008999441028507547 , 0.000456493385504006 , 0.0008347307620644682
176+ ]
177+
123178 for ( let i = 0 ; i < settings . numHarm ; i ++ ) {
124179
125180 // the amplitude of each harmonic depends on the harmonic slope setting
@@ -129,6 +184,14 @@ function calculateHarmonics(settings) {
129184 else if ( settings . harmSlope === "flat" ) harmonic_amplitude = 1 ;
130185 else if ( settings . harmSlope === "log" ) {
131186 harmonic_amplitude = Math . exp ( - 0.1 * ( harmonic_number - 1 ) ) ;
187+ } else if ( settings . harmSlope === "clarinet" ) {
188+ harmonic_amplitude = i < clarinetHarmonics . length ? clarinetHarmonics [ i ] : 0 ;
189+ } else if ( settings . harmSlope === "french horn" ) {
190+ harmonic_amplitude = i < frenchHornHarmonics . length ? frenchHornHarmonics [ i ] : 0 ;
191+ } else if ( settings . harmSlope === "flute" ) {
192+ harmonic_amplitude = i < fluteHarmonics . length ? fluteHarmonics [ i ] : 0 ;
193+ } else if ( settings . harmSlope === "violin" ) {
194+ harmonic_amplitude = i < violinHarmonics . length ? violinHarmonics [ i ] : 0 ;
132195 } else if ( settings . harmSlope === "vowel a" ) {
133196 harmonic_amplitude = formantFrequencyStrength ( harmonic_number * settings . fundFreq ,
134197 850 , 1610 , 0.2 ) ;
@@ -219,38 +282,75 @@ function normalize(arr, targetAmplitude) {
219282 arr . forEach ( ( x , n , y ) => y [ n ] = targetAmplitude * x / amp ) ;
220283}
221284
222- function filterSignal ( signal , frequency , order ) {
285+ function filterSignal ( signal , frequency , order , mode , filterKernel ) {
223286 // specify the filter parameters; Fs = sampling rate, Fc = cutoff frequency
224287
225288 // The cutoff for the antialiasing filter is set to the Nyquist frequency
226289 // of the simulated sampling process. The sampling rate of the "sampled"
227290 // signal is WEBAUDIO_MAX_SAMPLERATE / the downsampling factor. This is
228291 // divided by 2 to get the Nyquist frequency.
229- let firCalculator = new Fili . FirCoeffs ( ) ;
230292
231- let filterCoeffs = firCalculator . lowpass (
232- {
233- order : order
234- , Fs : WEBAUDIO_MAX_SAMPLERATE
235- , Fc : frequency
293+ if ( mode === "FIR" ) {
294+ let firCalculator = new Fili . FirCoeffs ( ) ;
295+
296+ let filterCoeffs = firCalculator . lowpass (
297+ {
298+ order : order
299+ , Fs : WEBAUDIO_MAX_SAMPLERATE
300+ , Fc : frequency
301+ } ) ;
302+
303+ // generate the filter
304+ let filter = new Fili . FirFilter ( filterCoeffs ) ;
305+
306+ // apply the filter
307+ // filter.multiStep(signal);
308+ signal . forEach ( ( x , n , y ) => y [ n ] = filter . singleStep ( x ) ) ;
309+
310+ // time shift the signal by half the filter order to compensate for the
311+ // delay introduced by the FIR filter
312+ const shift = order / 2 ;
313+ for ( let i = 0 ; i < signal . length - shift ; i ++ ) {
314+ signal [ i ] = signal [ i + shift ] ;
315+ }
316+ for ( let i = signal . length - shift ; i < signal . length ; i ++ ) {
317+ signal [ i ] = 0 ;
318+ }
319+
320+ if ( filterKernel ) {
321+ for ( let i = 0 ; i < filterCoeffs . length ; i ++ ) {
322+ filterKernel [ i ] = filterCoeffs [ i ] ;
323+ }
324+ }
325+ } else if ( mode === "Butterworth" || mode === "Chebyshev" ) {
326+ let iirCalculator = new Fili . CalcCascades ( ) ;
327+
328+ let characteristic = mode === "Butterworth" ? "butterworth" : "tschebyscheff05" ;
329+
330+ order = mode === "Butterworth" ? Math . min ( order , 12 ) : Math . min ( order , 4 ) ;
331+
332+ let filterCoeffs = iirCalculator . lowpass ( {
333+ order : order , // cascade 3 biquad filters (max: 12)
334+ characteristic : characteristic ,
335+ transform : characteristic === "tschebyscheff05" ? 'matchedZ' : undefined ,
336+ Fs : WEBAUDIO_MAX_SAMPLERATE , // sampling frequency
337+ Fc : frequency , // cutoff frequency / center frequency for bandpass, bandstop, peak
338+ preGain : false // adds one constant multiplication for highpass and lowpass
339+ // k = (1 + cos(omega)) * 0.5 / k = 1 with preGain == false
236340 } ) ;
237341
238- // generate the filter
239- let filter = new Fili . FirFilter ( filterCoeffs ) ;
342+ let filter = new Fili . IirFilter ( filterCoeffs ) ;
240343
241- // apply the filter
242- signal . forEach ( ( x , n , y ) => y [ n ] = filter . singleStep ( x ) ) ;
344+ signal . forEach ( ( x , n , y ) => y [ n ] = filter . singleStep ( x ) ) ;
243345
244- // time shift the signal by half the filter order to compensate for the
245- // delay introduced by the FIR filter
246- const shift = order / 2 ;
247- for ( let i = 0 ; i < signal . length - shift ; i ++ ) {
248- signal [ i ] = signal [ i + shift ] ;
249- }
250- for ( let i = signal . length - shift ; i < signal . length ; i ++ ) {
251- signal [ i ] = 0 ;
346+ if ( filterKernel ) {
347+ filterKernel [ 0 ] = 1 ;
348+ let filter = new Fili . IirFilter ( filterCoeffs ) ;
349+ filterKernel . forEach ( ( x , n , y ) => y [ n ] = filter . singleStep ( x ) ) ;
350+ }
252351 }
253- return filterCoeffs ;
352+
353+ // return filterCoeffs;
254354}
255355
256356function getDither ( ditherType ) {
@@ -396,11 +496,11 @@ function applyAntialiasingFilter(settings, fft, playback) {
396496 , Fc : cutoff
397497 } ) ;
398498
399- for ( let i = 0 ; i < filterCoeffs . length ; i ++ ) {
400- filterKernel [ i ] = filterCoeffs [ i ] ;
401- }
402499
403- filterSignal ( original , cutoff , order ) ;
500+
501+ filterSignal ( original , cutoff , order , settings . filterType , filterKernel ) ;
502+ } else {
503+ filterKernel [ 0 ] = 1 ;
404504 }
405505}
406506
@@ -489,7 +589,7 @@ function antiImagingFilter(settings, fft, playback) {
489589 ? settings . reconstructionFilterFrequency
490590 : ( WEBAUDIO_MAX_SAMPLERATE / settings . downsamplingFactor ) / 2 ;
491591
492- filterSignal ( reconstructed , freq , settings . reconstructionFilterOrder ) ; // TODO: slider for order, start at 200
592+ filterSignal ( reconstructed , freq , settings . reconstructionFilterOrder , 'FIR' ) ; // TODO: slider for order, start at 200
493593}
494594
495595function renderWavesImpl (
0 commit comments