Files
soothe2-re/extract_lut.py
T

74 lines
2.7 KiB
Python

#!/usr/bin/env python3
"""extract_lut.py — извлечение LUT-кривой level->mask из коллапса.
Форма B.10 ЗАФИКСИРОВАНА (Q=0.9, gain=4.13, tilt 1.414/1.454/1.795).
По каждой из 36 точек вычисляем x=log10(L0/res) и y_lut=(1-10^(-red/20))/(depth*tilt).
Все точки должны лечь на ОДНУ монотонную кривую y_lut(x). Печатаем кривую.
"""
import numpy as np
FS = 44100.0
DEPTH = 0.8639736175537109
QS = [0.1, 0.2, 0.3, 0.5, 0.7, 1.0, 1.5, 2.0, 3.0, 5.0, 10.0]
DUAL = np.array([(10.220, 15.224), (10.219, 13.963), (10.219, 12.947),
(10.219, 11.725), (10.218, 11.119), (10.216, 10.689),
(10.210, 10.412), (10.203, 10.305), (10.182, 10.225),
(10.113, 10.183), (9.822, 10.165)])
FCS = [800.0, 900.0, 950.0, 1000.0, 1050.0, 1100.0, 1200.0]
T1KQ = np.array([7.868, 8.536, 8.726, 8.788, 8.729, 8.575, 8.115])
T1K = np.array([14.548, 15.332, 15.553, 15.626, 15.557, 15.378, 14.840])
L_DUAL = 10 ** (-7.142 / 20)
L_T1KQ = 10 ** (-18.063 / 20)
L_T1K = 1.0
TILT = {500: 1.414, 1000: 1.454, 2000: 1.795}
Q, G = 0.900, 4.132
def res_at(ft, fc, Q, g):
w0 = fc * 2 * np.pi / FS
c, s = np.cos(w0), np.sin(w0)
p = (s * 0.5) / Q
a, a2 = p * g, p / g
A = [a + 1, -2 * c, 1 - a]
B = [a2 + 1, -2 * c, 1 - a2]
w = 2 * np.pi * ft / FS
z = np.exp(-1j * w)
return np.abs(2.0 * (B[0] + B[1] * z + B[2] * z * z) /
(A[0] + A[1] * z + A[2] * z * z))
def add(pts, L, res, red, tilt, tag):
y = (1 - 10 ** (-red / 20)) / (DEPTH * tilt)
pts.append((np.log10(L / res), y, tag))
pts = []
for q in QS:
for f in (500.0, 2000.0):
add(pts, L_DUAL, res_at(f, 500, q, G), DUAL[QS.index(q)][0 if f < 1000 else 1],
TILT[f], 'dual')
for i, fc in enumerate(FCS):
r = res_at(1000, fc, 0.9999978, G)
add(pts, L_T1KQ, r, T1KQ[i], TILT[1000], 't1kq')
add(pts, L_T1K, r, T1K[i], TILT[1000], 't1k')
pts.sort()
# печать всех точек: x, y_lut
print('x=log10(L0/res) y_lut tag')
for x, y, tag in pts:
print(f'{x:+.3f} {y:.4f} {tag}')
# биннинг для кривой
import collections
bins = collections.defaultdict(list)
for x, y, tag in pts:
bins[round(x * 4) / 4].append(y)
print('\nкривая (бин 0.25 по x):')
xs, ys = [], []
for bx in sorted(bins):
v = np.mean(bins[bx])
xs.append(bx); ys.append(v)
print(f'x={bx:+.2f} y={v:.4f} (n={len(bins[bx])}, spread={np.std(bins[bx]):.4f})')
# подгонка свободной кривой к (xs, ys): монотонная интерполяция
print('\nНЕПАРАМЕТРИЧЕСКАЯ КРИВАЯ (для model):')
for bx, v in zip(xs, ys):
print(f' ({bx:+.3f}, {v:.4f}),')