diff --git a/bandshape.py b/bandshape.py new file mode 100644 index 0000000..482b66b --- /dev/null +++ b/bandshape.py @@ -0,0 +1,84 @@ +#!/usr/bin/env python3 +"""bandshape.py — эмпирическая форма полосы детектора из рендеров soothe2. + +Тон 1 кГц (tone1kq.wav / tone1k.wav), одна полоса b1 с on=1, sens=12, +freq=f_c меняется по серии t1kq_only1_ / t1k_b1f_. +Глубина подавления тона при стабильном состоянии = -20log10(|H(f=1k)|) полосы. +Кривая D(f_c) = форма |H(f_c)| (Q-ширина), нормируется на D(1000). + +Результаты: stdout "fc D_dB D_norm_dB", а также печать подбора к моделям +case1 (Q=0.707) и case8 (Q=0.9999978542327881) с хелпером cfa. +""" +import numpy as np, wave, glob, os, sys, re + +SR = 44100 + +def read_wav(path): + w = wave.open(path, 'rb') + sw, nc, n = w.getsampwidth(), w.getnchannels(), w.getnframes() + d = np.frombuffer(w.readframes(n), dtype=np.uint8).reshape(n, nc, sw) + w.close() + ch = d[:, 0, :] + if sw == 3: + v = (ch[:, 0].astype(np.int64) | (ch[:, 1].astype(np.int64) << 8) | + (ch[:, 2].astype(np.int64) << 16)) + v = (v ^ (1 << 23)) - (1 << 23) + return v.astype(np.float64) / (1 << 23) + v = (ch[:, 0].astype(np.int64) | (ch[:, 1].astype(np.int64) << 8)) + v = (v ^ (1 << 15)) - (1 << 15) + return v.astype(np.float64) / (1 << 15) + +def rms_db(x, t0, t1): + s0, s1 = int(t0 * SR), int(t1 * SR) + seg = x[s0:s1] + if seg.size == 0: return -999.0 + return 20.0 * np.log10(np.sqrt(np.mean(seg ** 2)) + 1e-12) + +def band1_freq(rpp): + data = open(rpp, 'rb').read() + s = data.decode('utf-8', 'replace') + i = s.find('VST3: soothe2') + line = s[i:].split('\n', 1)[1] + j = line.find('\n >') + import base64 + b = re.sub(r'[^A-Za-z0-9+/=]', '', line[:j]) + d = base64.b64decode(b) + for m in re.finditer(r'