Source code for libfmp.c3.c3s1_audio_feature

"""
Module: libfmp.c3.c3s1_audio_feature
Author: Frank Zalkow, Meinard Müller
License: The MIT license, https://opensource.org/licenses/MIT

This file is part of the FMP Notebooks (https://www.audiolabs-erlangen.de/FMP)
"""
import numpy as np
from numba import jit


[docs]@jit(nopython=True) def f_pitch(p, pitch_ref=69, freq_ref=440.0): """Computes the center frequency/ies of a MIDI pitch Notebook: C3/C3S1_SpecLogFreq-Chromagram.ipynb Args: p (float): MIDI pitch value(s) pitch_ref (float): Reference pitch (default: 69) freq_ref (float): Frequency of reference pitch (default: 440.0) Returns: freqs (float): Frequency value(s) """ return 2 ** ((p - pitch_ref) / 12) * freq_ref
[docs]@jit(nopython=True) def pool_pitch(p, Fs, N, pitch_ref=69, freq_ref=440.0): """Computes the set of frequency indices that are assigned to a given pitch Notebook: C3/C3S1_SpecLogFreq-Chromagram.ipynb Args: p (float): MIDI pitch value Fs (scalar): Sampling rate N (int): Window size of Fourier fransform pitch_ref (float): Reference pitch (default: 69) freq_ref (float): Frequency of reference pitch (default: 440.0) Returns: k (np.ndarray): Set of frequency indices """ lower = f_pitch(p - 0.5, pitch_ref, freq_ref) upper = f_pitch(p + 0.5, pitch_ref, freq_ref) k = np.arange(N // 2 + 1) k_freq = k * Fs / N # F_coef(k, Fs, N) mask = np.logical_and(lower <= k_freq, k_freq < upper) return k[mask]
[docs]@jit(nopython=True) def compute_spec_log_freq(Y, Fs, N): """Computes a log-frequency spectrogram Notebook: C3/C3S1_SpecLogFreq-Chromagram.ipynb Args: Y (np.ndarray): Magnitude or power spectrogram Fs (scalar): Sampling rate N (int): Window size of Fourier fransform Returns: Y_LF (np.ndarray): Log-frequency spectrogram F_coef_pitch (np.ndarray): Pitch values """ Y_LF = np.zeros((128, Y.shape[1])) for p in range(128): k = pool_pitch(p, Fs, N) Y_LF[p, :] = Y[k, :].sum(axis=0) F_coef_pitch = np.arange(128) return Y_LF, F_coef_pitch
[docs]@jit(nopython=True) def compute_chromagram(Y_LF): """Computes a chromagram Notebook: C3/C3S1_SpecLogFreq-Chromagram.ipynb Args: Y_LF (np.ndarray): Log-frequency spectrogram Returns: C (np.ndarray): Chromagram """ C = np.zeros((12, Y_LF.shape[1])) p = np.arange(128) for c in range(12): mask = (p % 12) == c C[c, :] = Y_LF[mask, :].sum(axis=0) return C
[docs]def note_name(p): """Returns note name of pitch Notebook: C3/C3S1_SpecLogFreq-Chromagram.ipynb Args: p (int): Pitch value Returns: name (str): Note name """ chroma = ['A', 'A$^\\sharp$', 'B', 'C', 'C$^\\sharp$', 'D', 'D$^\\sharp$', 'E', 'F', 'F$^\\sharp$', 'G', 'G$^\\sharp$'] name = chroma[(p - 69) % 12] + str(p // 12 - 1) return name