deepvoice_detection / soundbay /utils /signal_processing.py
moshedd's picture
Multi-model bioacoustic detection Space
42579e8 verified
Raw
History Blame Contribute Delete
2.52 kB
import librosa
import numpy as np
import torch
class LibrosaMelSpectrogram:
"""
Defining and computing a mel-spectrogram transform using pre-defined parameters
Input:
init args:
sr: sample rate
n_mels: number of mel frequency bins
fmin: minimum frequency
call args:
sample: audio segment vector
Output:
melspectrogram: numpy array with size n_mels*t (signal length)
"""
def __init__(self, sr, n_mels, fmin):
self.sr = sr
self.n_mels = n_mels
self.n_fft = n_mels*20
self.hop_length = int(sr / n_mels)
self.fmin = fmin
self.fmax = sr//2
def __call__(self, sample):
slice_len = 1
sample_numpy = sample.numpy().ravel() # convert to numpy and flatten
melspectrogram = librosa.feature.melspectrogram(sample_numpy, sr=self.sr, n_mels=self.n_mels, n_fft=self.n_fft,
hop_length=self.hop_length, fmin=self.fmin, fmax=self.fmax)
return melspectrogram
class LibrosaPcen:
"""
Defining and computing pcen (Per-Channel Energy Normalization) transform using pre-defined parameters
Input:
init args:
sr: sample rate
n_mels: number of mel-frequency bins
fmin: minimum frequency
call args:
sample: audio segment vector
Output:
pcen: per-channel energy normalized version of signal - torch tensor
"""
def __init__(self, sr, hop_length=None, n_mels=None, fmin=0):
self.sr = sr
if hop_length is not None:
self.hop_length = hop_length
elif n_mels is not None:
self.hop_length = int(sr / n_mels)
else:
raise ValueError("Either hop_length or n_mels must be provided")
self.fmin = fmin
self.fmax = sr//2
def __call__(self, sample, gain=0.6, bias=0.1, power=0.2, time_constant=0.4, eps=1e-9):
if isinstance(sample, torch.Tensor):
sample = sample.numpy()
sample = np.squeeze(sample) # remove leading singleton dims for librosa compatibility
pcen_librosa = librosa.pcen(sample, sr=self.sr, hop_length=self.hop_length, gain=gain, bias=bias, power=power,
time_constant=time_constant, eps=eps)
pcen_librosa = np.expand_dims(pcen_librosa, 0) # add channel dim -> (1, n_freq, n_time)
return torch.from_numpy(pcen_librosa).float()