Old 02-08-2019, 12:44 PM   #1
ErBird
Human being with feelings
 
Join Date: Jan 2017
Posts: 75
Default JS Fender Bassman Tone Stack

Hi folks,

I've been trying, without success, to implement the "Fender Bassman Tone Stack" in JS, found in this paper:
https://ccrma.stanford.edu/~dtyeh/papers/yeh06_dafx.pdf

I've looked through the code repeatedly and can't find any mistakes. Can someone familiar with filters take a look? Have I used the difference equation properly?

Code:
desc:Bassman Tone Stack ---Faulty. Do not use.
author:Erich M. Burg

Uses the method described in:
"Discretization of the '59 Fender Bassman Tone Stack"
David T. Yeh and Julius O. Smith
DAFx-06, Montreal, Canada, September 18-20, 2006

slider1:0.5<0.001,0.999,0.001>Bass
slider2:0.5<0.001,0.999,0.001>Mid
slider3:0.5<0.001,0.999,0.001>Treble

slider5:250<0,500,1>R1 (kΩ)
slider6:1000<0,2000,1>R2 (kΩ)
slider7:25<0,200,1>R3 (kΩ)
slider8:56<0,200,1>R4 (kΩ)
slider9:25<1,100,1>C1 (nF)
slider10:20<1,100,1>C2 (nF)
slider11:20<1,100,1>C3 (nF)

@slider
c = 2*srate;
l = slider1;
m = slider2;
t = slider3;

R1 = slider5*1000;
R2 = slider6*1000;
R3 = slider7*1000;
R4 = slider8*1000;
C1 = slider9*10^-9;
C2 = slider10*10^-9;
C3 = slider11*10^-9;

b1 = t*C1*R1 + m*C3*R3 + l*(C1*R2 + C2*R2) + (C1*R3 + C2*R3);

b2 = t*(C1*C2*R1*R4 + C1*C3*R1*R4) - m^2*(C1*C3*(R3^2) + C2*C3*(R3^2))
   + m*(C1*C3*R1*R3 + C1*C3*(R3^2) + C2*C3*(R3^2))
   + l*(C1*C2*R1*R2 + C1*C2*R2*R4 + C1*C3*R2*R4)
   + l*m*(C1*C3*R2*R3 + C2*C3*R2*R3)
   + (C1*C2*R1*R3 + C1*C2*R3*R4 + C1*C3*R3*R4);

b3 = l*m*(C1*C2*C3*R1*R2*R3 + C1*C2*C3*R2*R3*R4)
   - (m^2)*(C1*C2*C3*R1*(R3^2) + C1*C2*C3*(R3^2)*R4)
   + m*(C1*C2*C3*R1*(R3^2) + C1*C2*C3*(R3^2)*R4)
   + t*C1*C2*C3*R1*R3*R4 - t*m*C1*C2*C3*R1*R3*R4
   + t*l*C1*C2*C3*R1*R2*R4;

a0 = 1;

a1 = (C1*R1 + C1*R3 + C2*R3 + C2*R4 + C3*R4)
   + m*C3*R3 + l*(C1*R2 + C2*R2);

a2 = m*(C1*C3*R1*R3 - C2*C3*R3*R4 + C1*C3*(R3^2)
   + C2*C3*(R3^2)) + l*m*(C1*C3*R2*R3 + C2*C3*R2*R3)
   - (m^2)*(C1*C3*(R3^2) + C2*C3*(R3^2)) + l*(C1*C2*R2*R4
   + C1*C2*R1*R2 + C1*C3*R2*R4 + C2*C3*R2*R4)
   + (C1*C2*R1*R4 + C1*C3*R1*R4 + C1*C2*R3*R4
   + C1*C2*R1*R3 + C1*C3*R3*R4 + C2*C3*R3*R4);

a3 = l*m*(C1*C2*C3*R1*R2*R3 + C1*C2*C3*R2*R3*R4)
   - (m^2)*(C1*C2*C3*R1*(R3^2) + C1*C2*C3*(R3^2)*R4)
   + m*(C1*C2*C3*(R3^2)*R4 + C1*C2*C3*R1*(R3^2)
   - C1*C2*C3*R1*R3*R4) + l*C1*C2*C3*R1*R2*R4
   + C1*C2*C3*R1*R3*R4;

A0_ = -a0 - a1*c - a2*(c^2) - a3*(c^3);
A1_ = -3*a0 - a1*c + a2*(c^2) + 3*a3*(c^3);
A2_ = -3*a0 + a1*c + a2*(c^2) - 3*a3*(c^3);
A3_ = -a0 + a1*c - a2*(c^2) + a3*(c^3);
B0_ = -b1*c - b2*(c^2) - b3*c^3;
B1_ = -b1*c + b2*(c^2) + 3*b3*(c^3);
B2_ = b1*c + b2*(c^2) - 3*b3*(c^3);
B3_ = b1*c - b2*(c^2) + b3*(c^3);

A1_ /= A0_;
A2_ /= A0_;
A3_ /= A0_;
B0_ /= A0_;
B1_ /= A0_;
B2_ /= A0_;
B3_ /= A0_;

@sample
//Left--------------------------------------------
spl0_old = spl0;
spl0 = B0_*spl0 + B1_*xl1 + B2_*xl2 + B3_*xl3
                - A1_*yl1 - A2_*yl2 - A3_*yl3;
     
xl3 = xl2;
xl2 = xl1;
xl1 = spl0_old;

yl3 = yl2;
yl2 = yl1;
yl1 = spl0;

//Right-------------------------------------------
spl1_old = spl1;
spl1 = B0_*spl1 + B1_*xr1 + B2_*xr2 + B3_*xr3
                - A1_*yr1 - A2_*yr2 - A3_*yr3;
     
xr3 = xr2;
xr2 = xr1;
xr1 = spl1_old;

yr3 = yr2;
yr2 = yr1;
yr1 = spl1;

Last edited by ErBird; 02-11-2019 at 01:09 PM.
ErBird is offline   Reply With Quote
Old 02-08-2019, 01:33 PM   #2
ErBird
Human being with feelings
 
Join Date: Jan 2017
Posts: 75
Default

Looks like I need to use the transposed DFII. Stay tuned.
ErBird is offline   Reply With Quote
Old 02-08-2019, 02:05 PM   #3
ErBird
Human being with feelings
 
Join Date: Jan 2017
Posts: 75
Default

Still not working, but here it is. Will update if I work out the problem.

Code:
desc:Bassman Tone Stack ---Faulty. Do not use.
author:Erich M. Burg

Uses the method described in:
"Discretization of the '59 Fender Bassman Tone Stack"
David T. Yeh and Julius O. Smith
DAFx-06, Montreal, Canada, September 18-20, 2006

slider1:0.5<0.001,0.999,0.001>Bass
slider2:0.5<0.001,0.999,0.001>Mid
slider3:0.5<0.001,0.999,0.001>Treble

slider5:250<0,500,1>R1 (kΩ)
slider6:1000<0,2000,1>R2 (kΩ)
slider7:25<0,200,1>R3 (kΩ)
slider8:56<0,200,1>R4 (kΩ)
slider9:25<1,100,1>C1 (nF)
slider10:20<1,100,1>C2 (nF)
slider11:20<1,100,1>C3 (nF)

@slider
c = 2*srate;
l = slider1;
m = slider2;
t = slider3;

R1 = slider5*1000;
R2 = slider6*1000;
R3 = slider7*1000;
R4 = slider8*1000;
C1 = slider9*10^-9;
C2 = slider10*10^-9;
C3 = slider11*10^-9;

b_1 = t*C1*R1 + m*C3*R3 + l*(C1*R2 + C2*R2) + (C1*R3 + C2*R3);

b_2 = t*(C1*C2*R1*R4 + C1*C3*R1*R4) - m^2*(C1*C3*(R3^2) + C2*C3*(R3^2))
    + m*(C1*C3*R1*R3 + C1*C3*(R3^2) + C2*C3*(R3^2))
    + l*(C1*C2*R1*R2 + C1*C2*R2*R4 + C1*C3*R2*R4)
    + l*m*(C1*C3*R2*R3 + C2*C3*R2*R3)
    + (C1*C2*R1*R3 + C1*C2*R3*R4 + C1*C3*R3*R4);

b_3 = l*m*(C1*C2*C3*R1*R2*R3 + C1*C2*C3*R2*R3*R4)
    - (m^2)*(C1*C2*C3*R1*(R3^2) + C1*C2*C3*(R3^2)*R4)
    + m*(C1*C2*C3*R1*(R3^2) + C1*C2*C3*(R3^2)*R4)
    + t*C1*C2*C3*R1*R3*R4 - t*m*C1*C2*C3*R1*R3*R4
    + t*l*C1*C2*C3*R1*R2*R4;

a_0 = 1;

a_1 = (C1*R1 + C1*R3 + C2*R3 + C2*R4 + C3*R4)
    + m*C3*R3 + l*(C1*R2 + C2*R2);

a_2 = m*(C1*C3*R1*R3 - C2*C3*R3*R4 + C1*C3*(R3^2)
    + C2*C3*(R3^2)) + l*m*(C1*C3*R2*R3 + C2*C3*R2*R3)
    - (m^2)*(C1*C3*(R3^2) + C2*C3*(R3^2)) + l*(C1*C2*R2*R4
    + C1*C2*R1*R2 + C1*C3*R2*R4 + C2*C3*R2*R4)
    + (C1*C2*R1*R4 + C1*C3*R1*R4 + C1*C2*R3*R4
    + C1*C2*R1*R3 + C1*C3*R3*R4 + C2*C3*R3*R4);

a_3 = l*m*(C1*C2*C3*R1*R2*R3 + C1*C2*C3*R2*R3*R4)
    - (m^2)*(C1*C2*C3*R1*(R3^2) + C1*C2*C3*(R3^2)*R4)
    + m*(C1*C2*C3*(R3^2)*R4 + C1*C2*C3*R1*(R3^2)
    - C1*C2*C3*R1*R3*R4) + l*C1*C2*C3*R1*R2*R4
    + C1*C2*C3*R1*R3*R4;

A0 = -a_0 - a_1*c - a_2*(c^2) - a_3*(c^3);
A1 = -3*a_0 - a_1*c + a_2*(c^2) + 3*a_3*(c^3);
A2 = -3*a_0 + a_1*c + a_2*(c^2) - 3*a_3*(c^3);
A3 = -a_0 + a_1*c - a_2*(c^2) + a_3*(c^3);
B0 = -b_1*c - b_2*(c^2) - b_3*c^3;
B1 = -b_1*c + b_2*(c^2) + 3*b_3*(c^3);
B2 = b_1*c + b_2*(c^2) - 3*b_3*(c^3);
B3 = b_1*c - b_2*(c^2) + b_3*(c^3);

A1 /= A0;
A2 /= A0;
A3 /= A0;
B0 /= A0;
B1 /= A0;
B2 /= A0;
B3 /= A0;

@sample
//Left--------------------------------------------
spl0_old = spl0;

spl0 = B0*spl0 + s1_left;

s1_left = s2_left + B1*spl0_old - A1*spl0;
s2_left = s3_left + B2*spl0_old - A2*spl0;
s3_left =           B3*spl0_old - A3*spl0;

//Right-------------------------------------------
spl1_old = spl1;

spl1 = B0*spl1 + s1_right;

s1_right = s2_right + B1*spl1_old - A1*spl1;
s2_right = s3_right + B2*spl1_old - A2*spl1;
s3_right =            B3*spl1_old - A3*spl1;

Last edited by ErBird; 02-11-2019 at 01:09 PM.
ErBird is offline   Reply With Quote
Old 02-08-2019, 10:10 PM   #4
SaulT
Human being with feelings
 
Join Date: Oct 2013
Location: Seattle, WA
Posts: 749
Default

The only real contribution I can make is that A0 should be 1, since that's the result of dividing all coefficients by A0. Can't get it to work either, though. I feel like there's an error in the math... but it's been quite some time since I've dug into circuit analysis. If I can remember any of it I'll see if I can take a look at it.
SaulT is offline   Reply With Quote
Old 02-11-2019, 01:50 AM   #5
Tale
Human being with feelings
 
Tale's Avatar
 
Join Date: Jul 2008
Location: Holland
Posts: 2,915
Default

AFAICT it's working just fine.

Do note that 25 nF for C1 is un unlikely value, it's typically 0.25 nF (i.e. 250 pF). Also note that in a real amp the bass pot is typically logarithmic, so you might want to shape l = slider1 a bit to make it more usuable.
Tale is offline   Reply With Quote
Old 02-11-2019, 01:08 PM   #6
ErBird
Human being with feelings
 
Join Date: Jan 2017
Posts: 75
Default

Quote:
Originally Posted by Tale View Post
AFAICT it's working just fine.

Do note that 25 nF for C1 is un unlikely value, it's typically 0.25 nF (i.e. 250 pF). Also note that in a real amp the bass pot is typically logarithmic, so you might want to shape l = slider1 a bit to make it more usuable.
Thanks for the help. You were right on. Here is the working version:

Code:
desc:Bassman Tone Stack
author:Erich M. Burg
version: 1.0

Uses the method described in:
"Discretization of the '59 Fender Bassman Tone Stack"
David T. Yeh and Julius O. Smith
DAFx-06, Montreal, Canada, September 18-20, 2006

slider1:0.5<0,1,0.001>Bass
slider2:0.5<0,1,0.001>Middle
slider3:0.5<0,1,0.001>Treble

in_pin:left input
in_pin:right input
out_pin:left output
out_pin:right output

@slider
c = 2*srate;

//Log Taper Pot Conversion----------------
y0.5 = 0.2; //Resistance at midpoint of pot
b = (1/y0.5-1)^2;
a = 1/(b-1);

//Pots------------------------------------
l = a*(b^slider1-1);
m = slider2;
t = slider3;

//Circuit Element Values------------------
R1 = 250;  //kΩ
R2 = 1000; //kΩ
R3 = 25;   //kΩ
R4 = 56;   //kΩ
C1 = 250;  //pF
C2 = 20;   //nF
C3 = 20;   //nF
//Conversion------------------------------
R1 = R1*1000;
R2 = R2*1000;
R3 = R3*1000;
R4 = R4*1000;
C1 = C1*10^-12;
C2 = C2*10^-9;
C3 = C3*10^-9;

//Transfer Function Coefficients----------
b_1 = t*C1*R1 + m*C3*R3 + l*(C1*R2 + C2*R2) + (C1*R3 + C2*R3);

b_2 = t*(C1*C2*R1*R4 + C1*C3*R1*R4) - m^2*(C1*C3*(R3^2) + C2*C3*(R3^2))
    + m*(C1*C3*R1*R3 + C1*C3*(R3^2) + C2*C3*(R3^2))
    + l*(C1*C2*R1*R2 + C1*C2*R2*R4 + C1*C3*R2*R4)
    + l*m*(C1*C3*R2*R3 + C2*C3*R2*R3)
    + (C1*C2*R1*R3 + C1*C2*R3*R4 + C1*C3*R3*R4);

b_3 = l*m*(C1*C2*C3*R1*R2*R3 + C1*C2*C3*R2*R3*R4)
    - (m^2)*(C1*C2*C3*R1*(R3^2) + C1*C2*C3*(R3^2)*R4)
    + m*(C1*C2*C3*R1*(R3^2) + C1*C2*C3*(R3^2)*R4)
    + t*C1*C2*C3*R1*R3*R4 - t*m*C1*C2*C3*R1*R3*R4
    + t*l*C1*C2*C3*R1*R2*R4;

a_0 = 1;

a_1 = (C1*R1 + C1*R3 + C2*R3 + C2*R4 + C3*R4)
    + m*C3*R3 + l*(C1*R2 + C2*R2);

a_2 = m*(C1*C3*R1*R3 - C2*C3*R3*R4 + C1*C3*(R3^2)
    + C2*C3*(R3^2)) + l*m*(C1*C3*R2*R3 + C2*C3*R2*R3)
    - (m^2)*(C1*C3*(R3^2) + C2*C3*(R3^2)) + l*(C1*C2*R2*R4
    + C1*C2*R1*R2 + C1*C3*R2*R4 + C2*C3*R2*R4)
    + (C1*C2*R1*R4 + C1*C3*R1*R4 + C1*C2*R3*R4
    + C1*C2*R1*R3 + C1*C3*R3*R4 + C2*C3*R3*R4);

a_3 = l*m*(C1*C2*C3*R1*R2*R3 + C1*C2*C3*R2*R3*R4)
    - (m^2)*(C1*C2*C3*R1*(R3^2) + C1*C2*C3*(R3^2)*R4)
    + m*(C1*C2*C3*(R3^2)*R4 + C1*C2*C3*R1*(R3^2)
    - C1*C2*C3*R1*R3*R4) + l*C1*C2*C3*R1*R2*R4
    + C1*C2*C3*R1*R3*R4;

//BLT Coefficients------------------------
A0 = -a_0 - a_1*c - a_2*(c^2) - a_3*(c^3);
A1 = -3*a_0 - a_1*c + a_2*(c^2) + 3*a_3*(c^3);
A2 = -3*a_0 + a_1*c + a_2*(c^2) - 3*a_3*(c^3);
A3 = -a_0 + a_1*c - a_2*(c^2) + a_3*(c^3);
B0 = -b_1*c - b_2*(c^2) - b_3*c^3;
B1 = -b_1*c + b_2*(c^2) + 3*b_3*(c^3);
B2 = b_1*c + b_2*(c^2) - 3*b_3*(c^3);
B3 = b_1*c - b_2*(c^2) + b_3*(c^3);

//Normalize Coefficients------------------
A1 /= A0;
A2 /= A0;
A3 /= A0;
B0 /= A0;
B1 /= A0;
B2 /= A0;
B3 /= A0;

@sample
//Left------------------------------------
spl0_old = spl0;

spl0 = B0*spl0 + s1_left;

s1_left = s2_left + B1*spl0_old - A1*spl0;
s2_left = s3_left + B2*spl0_old - A2*spl0;
s3_left =           B3*spl0_old - A3*spl0;

//Right-----------------------------------
spl1_old = spl1;

spl1 = B0*spl1 + s1_right;

s1_right = s2_right + B1*spl1_old - A1*spl1;
s2_right = s3_right + B2*spl1_old - A2*spl1;
s3_right =            B3*spl1_old - A3*spl1;
ErBird is offline   Reply With Quote
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -7. The time now is 06:42 PM.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2019, vBulletin Solutions Inc.