fix: fs/D in lowpass, add missing fs attr
This commit is contained in:
28
rhythm.py
28
rhythm.py
@@ -15,6 +15,7 @@ import numpy as np
|
||||
from numpy.fft import fft
|
||||
|
||||
from hsh_signal.signal import lowpass_fft
|
||||
import time
|
||||
|
||||
def viterbi_highest_frequency_path_vectorized(Scp2, jump_penalty=2.0, use_log_amplitude=True):
|
||||
Scp2 = np.asarray(Scp2, dtype=float)
|
||||
@@ -127,21 +128,33 @@ class BassAnalyzer:
|
||||
self.M = (self.L-self.W) // self.D + 1 #: number of time steps
|
||||
self.fs = fs
|
||||
|
||||
def viterbi_wavelet_scalogram_amplitudes(self):
|
||||
def viterbi_wavelet_scalogram_amplitudes(self, dbg_time=False):
|
||||
"""
|
||||
Compute scalogram amplitudes from Viterbi path of highest-power frequencies.
|
||||
NOTE: downsampled from the original 'fs'.
|
||||
:returns: (fsd, sig): sampling rate, amplitude signal
|
||||
"""
|
||||
t1 = time.time()
|
||||
Spf = self._spectrogram()
|
||||
t2 = time.time()
|
||||
pto = self._pulse_train(Spf)
|
||||
t3 = time.time()
|
||||
Spf2 = self._spectrogram_2()
|
||||
t4 = time.time()
|
||||
pms = self._scalogram_params(pto)
|
||||
t5 = time.time()
|
||||
Spsi_ss = self._scalogram_wavelets(pms)
|
||||
t6 = time.time()
|
||||
Scp2 = self._scalogram(Spf2, Spsi_ss)
|
||||
t7 = time.time()
|
||||
path = self._viterbi_path(Scp2)
|
||||
t8 = time.time()
|
||||
ampl = self._viterbi_ampl(Scp2, path)
|
||||
return ampl
|
||||
t9 = time.time()
|
||||
if not dbg_time:
|
||||
return ampl
|
||||
else:
|
||||
return ampl, np.diff([t1, t2, t3, t4, t5, t6, t7, t8, t9])
|
||||
|
||||
def _spectrogram(self):
|
||||
"""W-FFT (STFTs) to determine scalogram parameters"""
|
||||
@@ -171,7 +184,7 @@ class BassAnalyzer:
|
||||
# TODO: check if 'A' needs to be a smooth signal slowly varying over time, not a const.
|
||||
#A = np.mean(g_bar) # amplitude cutoff for pulse train
|
||||
ip = int(fs)
|
||||
g_bar_l = lowpass_fft(np.pad(g_bar, (ip, ip), mode='edge'), fps=fs, cf=0.5, tw=0.05)[ip:-ip]
|
||||
g_bar_l = lowpass_fft(np.pad(g_bar, (ip, ip), mode='edge'), fps=fs/self.D, cf=0.5, tw=0.05)[ip:-ip]
|
||||
A = g_bar_l
|
||||
|
||||
# compute transitions (pulse train)
|
||||
@@ -202,6 +215,8 @@ class BassAnalyzer:
|
||||
f2 = self.f2
|
||||
Wp, Mp, Dp = self.Wp, self.Mp, self.Dp
|
||||
|
||||
# TODO(perf): 5.0 sec runtime
|
||||
|
||||
#
|
||||
# compute spectrogram: 'Spf2' (M x Wp) <- from 'f'
|
||||
#
|
||||
@@ -266,12 +281,18 @@ class BassAnalyzer:
|
||||
# T, Lp, Wp
|
||||
T, Lp, Wp = self.T, self.Lp, self.Wp
|
||||
|
||||
# TODO(perf): reduce num of wavelets, and/or parallelize into freq slices
|
||||
# TODO(perf): 3.5 sec runtime
|
||||
|
||||
# compute convolution with wavelets, by multiplication in freq-domain
|
||||
# 'Scp2' (M x I*J)
|
||||
Scp2 = np.matmul(Spf2, Spsi_ss.T) * (T/(Lp-Wp))
|
||||
return Scp2
|
||||
|
||||
def _viterbi_path(self, Scp2):
|
||||
# TODO(perf): parallelize into time slices
|
||||
# TODO(perf): 4.5 sec runtime
|
||||
|
||||
# TODO: check if we should re-weight freq-jumps, because of log-scale frequencies
|
||||
path, dp, backptr = viterbi_highest_frequency_path_vectorized(
|
||||
(np.abs(Scp2)**2).T,
|
||||
@@ -313,6 +334,7 @@ class GuitarAnalyzer:
|
||||
self.D = int(self.shift_sec * fs) #: spectrogram step
|
||||
self.L = self.f.shape[0]
|
||||
self.M = (self.L-self.W) // self.D + 1 #: number of time steps
|
||||
self.fs = fs
|
||||
|
||||
def spectrogram_power_amplitudes(self):
|
||||
"""
|
||||
|
||||
Reference in New Issue
Block a user