"""
Module: libfmp.c4.c4s4_novelty_kernel
Author: Meinard Müller, Julian Reck
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]def compute_kernel_checkerboard_box(L):
"""Compute box-like checkerboard kernel [FMP, Section 4.4.1]
Notebook: C4/C4S4_NoveltySegmentation.ipynb
Args:
L (int): Parameter specifying the kernel size 2*L+1
Returns:
kernel (np.ndarray): Kernel matrix of size (2*L+1) x (2*L+1)
"""
axis = np.arange(-L, L+1)
kernel = np.outer(np.sign(axis), np.sign(axis))
return kernel
[docs]@jit(nopython=True)
def compute_kernel_checkerboard_gaussian(L, var=1.0, normalize=True):
"""Compute Guassian-like checkerboard kernel [FMP, Section 4.4.1].
See also: https://scipython.com/blog/visualizing-the-bivariate-gaussian-distribution/
Notebook: C4/C4S4_NoveltySegmentation.ipynb
Args:
L (int): Parameter specifying the kernel size M=2*L+1
var (float): Variance parameter determing the tapering (epsilon) (Default value = 1.0)
normalize (bool): Normalize kernel (Default value = True)
Returns:
kernel (np.ndarray): Kernel matrix of size M x M
"""
taper = np.sqrt(1/2) / (L * var)
axis = np.arange(-L, L+1)
gaussian1D = np.exp(-taper**2 * (axis**2))
gaussian2D = np.outer(gaussian1D, gaussian1D)
kernel_box = np.outer(np.sign(axis), np.sign(axis))
kernel = kernel_box * gaussian2D
if normalize:
kernel = kernel / np.sum(np.abs(kernel))
return kernel
# @jit(nopython=True)
[docs]def compute_novelty_ssm(S, kernel=None, L=10, var=0.5, exclude=False):
"""Compute novelty function from SSM [FMP, Section 4.4.1]
Notebook: C4/C4S4_NoveltySegmentation.ipynb
Args:
S (np.ndarray): SSM
kernel (np.ndarray): Checkerboard kernel (if kernel==None, it will be computed) (Default value = None)
L (int): Parameter specifying the kernel size M=2*L+1 (Default value = 10)
var (float): Variance parameter determing the tapering (epsilon) (Default value = 0.5)
exclude (bool): Sets the first L and last L values of novelty function to zero (Default value = False)
Returns:
nov (np.ndarray): Novelty function
"""
if kernel is None:
kernel = compute_kernel_checkerboard_gaussian(L=L, var=var)
N = S.shape[0]
M = 2*L + 1
nov = np.zeros(N)
# np.pad does not work with numba/jit
S_padded = np.pad(S, L, mode='constant')
for n in range(N):
# Does not work with numba/jit
nov[n] = np.sum(S_padded[n:n+M, n:n+M] * kernel)
if exclude:
right = np.min([L, N])
left = np.max([0, N-L])
nov[0:right] = 0
nov[left:N] = 0
return nov