1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
|
#!/usr/bin/env perl
use Math::Complex;
use Math::Trig;
# proportion of total resistance for a log taper pot
sub logpot($) {
my $x = shift;
my $ym = 0.2;
my $b = ( ( 1. / $ym ) - 1. );
$b = $b * $b;
my $a = 1. / ( $b - 1. );
return $a * ( $b**$x ) - $a;
}
# proportion of resistance between two points on a log pot
sub logprop($$$) {
my ( $v, $t1, $t2 ) = @_;
$v = logpot($v);
$t1 = logpot($t1);
$t2 = logpot($t2);
return ( $v - $t1 ) / ( $t2 - $t1 );
}
# compute impedance of two elements in parallel
sub par($$) {
my ( $a, $b ) = @_;
return 1. / ( ( 1. / $a ) + ( 1. / $b ) );
}
# impedance of capacitor in nF at frequency f
sub cap($$) {
my ( $c, $f ) = @_;
my $z = $c * 1.e-9 * 2 * pi * $f;
$z = -i / $z;
return $z;
}
@fns = ();
@frqs = ();
# calc gain at frequeny f and knob position k (0-10)
sub calc_gain($$) {
my ( $f, $k ) = @_;
# position of taps on pot.
my $te = 0.4; # terminal e
my $td = 0.6; # terminal d
my $rac = 470000.;
#terminal c is input
#terminal b is output
#terminal a is ground
# loads on terminals d and e
my $ld = 18000. + cap( 47., $f ); #18k+47nF
my $le = 4700. + cap( 250., $f ); #4.7k+250nF
#compute resistances of track
my $rae = $rac * logpot($te);
my $rad = $rac * logpot($td);
my $red = $rad - $rae;
my $rdc = $rac - $rad;
my $tot = $rae + $red + $rdc;
print "Track resistances: $rae + $red + $rdc = $tot\n";
# next compute the efective impedances of each leg
my $erae = par( $rae, $le );
my $erad = par( $erae + $red, $ld );
my $ered = $erad - $erae;
my $erac = $erad + $rdc;
my $erdc = $erac - $erad;
my $etot = $erac;
# input filter
$etot += 150000. + cap( 15., $f ); # 150k +15nF
#balance control
$etot += par( 1100., cap( 120., $f ) );
print "Effective total impedance $erae + $ered + $erdc = $erac\n";
# compute the potentials for a 1V input
my $pe = $erae / $etot;
my $pd = $erad / $etot;
my $pa = $erac / $etot;
my $ped = $pd - $pe;
my $pda = $pa - $pd;
my $v = $k / 10.;
my $hf;
if ( $v < $te ) {
$hf = $pe * logprop( $v, 0, $te );
}
elsif ( $v < $td ) {
$hf = $pe + ( $ped * logprop( $v, $te, $td ) );
}
else {
$hf = $pd + ( $pda * logprop( $v, $td, 1. ) );
}
return abs($hf);
}
open P, "|gnuplot";
print P "set term png size 1280,1024\n";
print P "set output 'volume.png'\n";
print P "set logscale x\n";
print P "set logscale y\n";
print P "set yrange [:1.1]\n";
print P "set xlabel 'frequency/Hz'\n";
print P "set ylabel 'gain'\n";
print P "plot ";
for ( my $k = 1 ; $k < 10.5 ; ++$k ) {
my $gmax = 0;
for ( my $f = 20 ; $f < 20000.1 ; $f *= 1.1 ) {
my $g = calc_gain( $f, $k );
$gmax = $g if $g > $gmax;
}
my $fn = "volume-" . $k . ".dat";
open F, ">", $fn;
for ( my $f = 20 ; $f < 20000.1 ; $f *= 1.1 ) {
my $g = calc_gain( $f, $k );
print F $f, " ", $g, " ", $g / $gmax, "\n";
}
close F;
print P " '" . $fn . "' using 1:2 with lines title '" . $k . "',";
}
print "\n";
close P;
|