Spaces:
Running
Running
""" | |
| Description: libf0 utility functions | |
| Contributors: Sebastian Rosenzweig, Simon Schwär, Meinard Müller | |
| License: The MIT license, https://opensource.org/licenses/MIT | |
| This file is part of libf0. | |
""" | |
import numpy as np | |
def sonify_trajectory_with_sinusoid(f0, t, audio_len, confidence=None, Fs=22050, smooth_len=11): | |
""" | |
Sonification of trajectory with sinusoidal. Adapted from FMP notebook: C8/C8S2_FundFreqTracking.ipynb | |
Parameters | |
---------- | |
f0 : ndarray | |
F0-trajectory | |
t : ndarray | |
Time axis | |
audio_len : int | |
Desired audio length in samples | |
confidence : None or ndarray | |
Confidence values for amplitude control | |
Fs : int | |
Sampling rate | |
smooth_len : int | |
Smoothing filter length to avoid clicks in the sonification | |
Returns | |
------- | |
x_soni : ndarray | |
Sonified F0-trajectory | |
""" | |
if confidence is None: | |
confidence = np.ones_like(f0) | |
# initialize | |
x_soni = np.zeros(audio_len) | |
amplitude_mod = np.zeros(audio_len) | |
# Computation of hop size | |
sine_len = int(t[1] * Fs) | |
t = np.arange(0, sine_len) / Fs | |
phase = 0 | |
# loop over all F0 values, ensure continuous phase | |
for idx in np.arange(0, len(f0)): | |
cur_f = f0[idx] | |
cur_amp = confidence[idx] | |
if cur_f == 0: | |
phase = 0 | |
continue | |
cur_soni = np.sin(2*np.pi*(cur_f*t+phase)) | |
diff = np.maximum(0, (idx+1)*sine_len - len(x_soni)) | |
if diff > 0: | |
x_soni[idx * sine_len:(idx + 1) * sine_len - diff] = cur_soni[:-diff] | |
amplitude_mod[idx * sine_len:(idx + 1) * sine_len - diff] = cur_amp | |
else: | |
x_soni[idx*sine_len:(idx+1)*sine_len-diff] = cur_soni | |
amplitude_mod[idx*sine_len:(idx+1)*sine_len-diff] = cur_amp | |
phase += cur_f * sine_len / Fs | |
phase -= 2 * np.round(phase/2) | |
# filter amplitudes to avoid transients | |
amplitude_mod = np.convolve(amplitude_mod, np.hanning(smooth_len)/np.sum(np.hanning(smooth_len)), 'same') | |
x_soni = x_soni * amplitude_mod | |
return x_soni | |
def hz_to_cents(F, F_ref=55.0): | |
""" | |
Converts frequency in Hz to cents. | |
Parameters | |
---------- | |
F : float or ndarray | |
Frequency value in Hz | |
F_ref : float | |
Reference frequency in Hz (Default value = 55.0) | |
Returns | |
------- | |
F_cents : float or ndarray | |
Frequency in cents | |
""" | |
# Avoid division by 0 | |
F_temp = np.array(F).astype(float) | |
F_temp[F_temp == 0] = np.nan | |
F_cents = 1200 * np.log2(F_temp / F_ref) | |
return F_cents | |
def cents_to_hz(F_cents, F_ref=55.0): | |
""" | |
Converts frequency in cents to Hz. | |
Parameters | |
---------- | |
F_cents : float or ndarray | |
Frequency in cents | |
F_ref : float | |
Reference frequency in Hz (Default value = 55.0) | |
Returns | |
------- | |
F : float or ndarray | |
Frequency in Hz | |
""" | |
F = F_ref * 2 ** (F_cents / 1200) | |
# Avoid NaN output | |
F = np.nan_to_num(F, copy=False, nan=0) | |
return F | |