Move channel buffers from stack to structs so theyt can be reused when mixing with...
[jack_mixer.git] / scale.py
blob95eb74456800315d811cefe5ca6c9f5d86be744d
1 #!/usr/bin/env python
3 # This file is part of jack_mixer
5 # Copyright (C) 2006 Nedko Arnaudov <nedko@arnaudov.name>
6 #
7 # This program is free software; you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; version 2 of the License
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 import math
21 import fpconst
23 class threshold:
24 '''Encapsulates scale linear function edge and coefficients for scale = a * dB + b formula'''
25 def __init__(self, db, scale):
26 self.db = db
27 self.scale = scale
28 self.text = "%.0f" % math.fabs(db)
30 def calculate_coefficients(self, prev):
31 self.a = (prev.scale - self.scale) / (prev.db - self.db)
32 self.b = self.scale - self.a * self.db
33 #print "%.0f dB - %.0f dB: scale = %f * dB + %f" % (prev.db, self.db, self.a, self.b)
35 def db_to_scale(self, db):
36 return self.a * db + self.b
38 def scale_to_db(self, scale):
39 return (scale - self.b) / self.a
41 class base:
42 '''Scale abstraction, various scale implementation derive from this class'''
43 def __init__(self, scale_id, description):
44 self.scale = []
45 self.marks = []
46 self.db_max = fpconst.NegInf
47 self.scale_id = scale_id
48 self.description = description
50 def add_threshold(self, db, scale, mark):
51 thr = threshold(db, scale)
52 self.scale.append(thr)
53 if mark:
54 self.marks.append(thr)
56 def add_mark(self, db):
57 mark = threshold(db, -1.0)
58 self.marks.append(mark)
59 if db > self.db_max:
60 self.db_max = db
62 def calculate_coefficients(self):
63 prev = None
64 for i in self.scale:
65 if prev != None:
66 i.calculate_coefficients(prev)
67 prev = i
69 def get_marks(self):
70 return self.marks
72 def scale_marks(self):
73 for i in self.marks:
74 if i.scale == -1.0:
75 i.scale = self.db_to_scale(i.db)
77 def db_to_scale(self, db):
78 '''Convert dBFS value to number in range 0.0-1.0 used in GUI'''
79 prev = None
80 for i in self.scale:
81 if db < i.db:
82 #print "Match at %f dB treshold" % i.db
83 if prev == None:
84 return 0.0
85 return i.db_to_scale(db)
86 prev = i
87 return 1.0
89 def scale_to_db(self, scale):
90 '''Convert number in range 0.0-1.0 used in GUI to dBFS value'''
91 prev = None
92 for i in self.scale:
93 if scale <= i.scale:
94 if prev == None:
95 return fpconst.NegInf;
96 return i.scale_to_db(scale)
97 prev = i
98 return self.db_max
100 # IEC 60268-18 Peak programme level meters - Digital audio peak level meter
101 # Adapted from meterpridge, may be wrong, I'm not buying standards, event if they cost $45
102 # If someone has the standart, please eighter share it with me or fix the code.
103 class iec_268(base):
104 '''IEC 60268-18 Peak programme level meters - Digital audio peak level meter'''
105 def __init__(self):
106 base.__init__(self, "iec_268", "IEC 60268-18 Peak programme level meters - Digital audio peak level meter")
107 self.add_threshold(-70.0, 0.0, False)
108 self.add_threshold(-60.0, 0.05, True)
109 self.add_threshold(-50.0, 0.075, True)
110 self.add_threshold(-40.0, 0.15, True)
111 self.add_mark(-35.0)
112 self.add_threshold(-30.0, 0.3, True)
113 self.add_mark(-25.0)
114 self.add_threshold(-20.0, 0.5, True)
115 self.add_mark(-15.0)
116 self.add_mark(-10.0)
117 self.add_mark(-5.0)
118 self.add_threshold(0.0, 1.0, True)
119 self.calculate_coefficients()
120 self.scale_marks()
122 class iec_268_minimalistic(base):
123 '''IEC 60268-18 Peak programme level meters - Digital audio peak level meter, fewer marks'''
124 def __init__(self):
125 base.__init__(self, "iec_268_minimalistic", "IEC 60268-18 Peak programme level meters - Digital audio peak level meter, fewer marks")
126 self.add_threshold(-70.0, 0.0, False)
127 self.add_threshold(-60.0, 0.05, True)
128 self.add_threshold(-50.0, 0.075, False)
129 self.add_threshold(-40.0, 0.15, True)
130 self.add_threshold(-30.0, 0.3, True)
131 self.add_threshold(-20.0, 0.5, True)
132 self.add_mark(-10.0)
133 self.add_threshold(0.0, 1.0, True)
134 self.calculate_coefficients()
135 self.scale_marks()
137 class linear_70dB(base):
138 '''Linear scale with range from -70 to 0 dBFS'''
139 def __init__(self):
140 base.__init__(self, "linear_70dB", "Linear scale with range from -70 to 0 dBFS")
141 self.add_threshold(-70.0, 0.0, False)
142 self.add_mark(-60.0)
143 self.add_mark(-50.0)
144 self.add_mark(-40.0)
145 self.add_mark(-35.0)
146 self.add_mark(-30.0)
147 self.add_mark(-25.0)
148 self.add_mark(-20.0)
149 self.add_mark(-15.0)
150 self.add_mark(-10.0)
151 self.add_mark(-5.0)
152 self.add_threshold(0.0, 1.0, True)
153 self.calculate_coefficients()
154 self.scale_marks()
156 class linear_30dB(base):
157 '''Linear scale with range from -30 to +30 dBFS'''
158 def __init__(self):
159 base.__init__(self, "linear_30dB", "Linear scale with range from -30 to +30 dBFS")
160 self.add_threshold(-30.0, 0.0, False)
161 self.add_threshold(+30.0, 1.0, True)
162 self.calculate_coefficients()
163 self.scale_marks()
165 def scale_test1(scale):
166 for i in range(-97 * 2, 1, 1):
167 db = float(i)/2.0
168 print "%5.1f dB maps to %f" % (db, scale.db_to_scale(db))
170 def scale_test2(scale):
171 for i in range(101):
172 s = float(i)/100.0
173 print "%.2f maps to %.1f dB" % (s, scale.scale_to_db(s))
175 def print_db_to_scale(db):
176 print "%-.1f dB maps to %f" % (db, scale.db_to_scale(db))
178 def scale_test3(scale):
179 print_db_to_scale(+77.0)
180 print_db_to_scale(+7.0)
181 print_db_to_scale(0.0)
182 print_db_to_scale(-107.0)
184 #scale = linear_30dB()
185 #scale_test2(scale)
186 #scale_test3(scale)