feat: restrict B in BassAnalyzer to sensible freq range
This commit is contained in:
37
rhythm.py
37
rhythm.py
@@ -13,6 +13,7 @@
|
|||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from numpy.fft import fft
|
from numpy.fft import fft
|
||||||
|
import matplotlib.pyplot as plt # for debug only
|
||||||
|
|
||||||
from hsh_signal.signal import lowpass_fft
|
from hsh_signal.signal import lowpass_fft
|
||||||
import time
|
import time
|
||||||
@@ -81,7 +82,30 @@ def gabor_wavelet(omega, nu, fs, T, tt=None):
|
|||||||
psi = 1.0 / np.sqrt(omega) * np.exp(-np.pi * (t / omega)**2) * np.exp(1j*2*np.pi * nu * t / omega)
|
psi = 1.0 / np.sqrt(omega) * np.exp(-np.pi * (t / omega)**2) * np.exp(1j*2*np.pi * nu * t / omega)
|
||||||
return psi
|
return psi
|
||||||
|
|
||||||
class BassAnalyzer:
|
class Analyzer:
|
||||||
|
def __init__(self): pass
|
||||||
|
def debug_plot(self, i1, i2):
|
||||||
|
Scp2, path = self.Scp2, self.path
|
||||||
|
fs, Dp = self.fs, self.Dp
|
||||||
|
|
||||||
|
ss, omega, nu, fsp, Wp, I, J, freqs = self.pms
|
||||||
|
|
||||||
|
Scp2_slice = np.abs(Scp2[i1:i2])
|
||||||
|
|
||||||
|
plt.figure(figsize=(8,2))
|
||||||
|
plt.imshow(Scp2_slice.T, origin='lower')
|
||||||
|
x_positions = np.arange(Scp2_slice.shape[0]//250+1)*250
|
||||||
|
if x_positions[-1] == Scp2_slice.shape[0]:
|
||||||
|
x_positions[-1] -= 1 # so last tick is shown properly
|
||||||
|
t1 = i1 / (fs / Dp)
|
||||||
|
x_labels = ['{:.1f}'.format(t1+x*Dp/fs) for x in x_positions]
|
||||||
|
plt.xticks(x_positions, x_labels)
|
||||||
|
y_positions = np.arange(Scp2_slice.shape[1]//50)*50
|
||||||
|
y_labels = ['{:.1f}'.format((nu/(omega*ss[y]))) for y in y_positions] # Hz equivalents of wavelet scale
|
||||||
|
plt.yticks(y_positions, y_labels)
|
||||||
|
plt.plot(np.arange(Scp2_slice.shape[0]), path[i1:i2], c='r')
|
||||||
|
|
||||||
|
class BassAnalyzer(Analyzer):
|
||||||
"""
|
"""
|
||||||
Rhythm analysis from songs.
|
Rhythm analysis from songs.
|
||||||
Provides a beat amplitude signal from the audio signal.
|
Provides a beat amplitude signal from the audio signal.
|
||||||
@@ -112,6 +136,7 @@ class BassAnalyzer:
|
|||||||
:param fs: sampling rate
|
:param fs: sampling rate
|
||||||
:param sig: audio signal normalized to [-1,1]
|
:param sig: audio signal normalized to [-1,1]
|
||||||
"""
|
"""
|
||||||
|
super(BassAnalyzer, self).__init__()
|
||||||
self.D = int(self.shift_sec * fs) #: spectrogram step
|
self.D = int(self.shift_sec * fs) #: spectrogram step
|
||||||
if self.Wp_force:
|
if self.Wp_force:
|
||||||
self.Wp = self.Wp_force
|
self.Wp = self.Wp_force
|
||||||
@@ -151,6 +176,11 @@ class BassAnalyzer:
|
|||||||
t8 = time.time()
|
t8 = time.time()
|
||||||
ampl = self._viterbi_ampl(Scp2, path)
|
ampl = self._viterbi_ampl(Scp2, path)
|
||||||
t9 = time.time()
|
t9 = time.time()
|
||||||
|
|
||||||
|
self.Scp2 = Scp2
|
||||||
|
self.path = path
|
||||||
|
self.pms = pms
|
||||||
|
|
||||||
if not dbg_time:
|
if not dbg_time:
|
||||||
return ampl
|
return ampl
|
||||||
else:
|
else:
|
||||||
@@ -192,6 +222,11 @@ class BassAnalyzer:
|
|||||||
pt_re = (np.diff(pt) == 1).astype(int) # rising edge
|
pt_re = (np.diff(pt) == 1).astype(int) # rising edge
|
||||||
self.B = max(np.sum(pt_re), 1) # total number of pulses in the 'pt' pulse train signal
|
self.B = max(np.sum(pt_re), 1) # total number of pulses in the 'pt' pulse train signal
|
||||||
|
|
||||||
|
# clip B, to force **reasonable** frequency range for wavelets
|
||||||
|
# (noise will otherwise cause many transitions -> high B -> bass falls below freq range -> algo fail)
|
||||||
|
B_min, B_max = 0.5 * M / (fs / self.D), 5.0 * M / (fs / self.D)
|
||||||
|
self.B = np.clip(self.B, a_min=B_min, a_max=B_max)
|
||||||
|
|
||||||
# resample 'pt' (M) at these indices -> 'ptr' (L), like original 'f' (signal padded)
|
# resample 'pt' (M) at these indices -> 'ptr' (L), like original 'f' (signal padded)
|
||||||
squashed_idxs = np.floor(np.linspace(0, L-1, L) * (M/L)).astype(int)
|
squashed_idxs = np.floor(np.linspace(0, L-1, L) * (M/L)).astype(int)
|
||||||
ptr = pt[squashed_idxs]
|
ptr = pt[squashed_idxs]
|
||||||
|
|||||||
Reference in New Issue
Block a user