diff options
author | Nathan Lovato <nathan@gdquest.com> | 2020-05-15 00:11:08 +0300 |
---|---|---|
committer | Dalai Felinto <dalai@blender.org> | 2020-05-29 10:53:25 +0300 |
commit | da8963ab0e483fa67460c8fd8b75a970d03b2623 (patch) | |
tree | 3d34f88fb3e45cdfddce2165b56adb7bcbc62038 | |
parent | 9286d97d67270264665b280774ecd61616a6c151 (diff) |
Power Sequencer: fix package name and import error
Fixes an error with not passing the python tests.
-rwxr-xr-x | power_sequencer/operators/__init__.py | 14 | ||||
-rw-r--r-- | power_sequencer/operators/align_audios.py | 110 | ||||
-rw-r--r-- | power_sequencer/operators/audiosync/__init__.py | 17 | ||||
-rw-r--r-- | power_sequencer/operators/audiosync/convert_and_trim.py | 60 | ||||
-rw-r--r-- | power_sequencer/operators/audiosync/cross_correlation.py | 33 | ||||
-rw-r--r-- | power_sequencer/operators/audiosync/ensure_non_zero.py | 28 | ||||
-rw-r--r-- | power_sequencer/operators/audiosync/find_offset.py | 87 | ||||
-rw-r--r-- | power_sequencer/operators/audiosync/mfcc/__init__.py | 17 | ||||
-rw-r--r-- | power_sequencer/operators/audiosync/mfcc/mfcc.py | 91 | ||||
-rw-r--r-- | power_sequencer/operators/audiosync/mfcc/segment_axis.py | 110 | ||||
-rw-r--r-- | power_sequencer/operators/audiosync/mfcc/trfbank.py | 51 | ||||
-rw-r--r-- | power_sequencer/operators/audiosync/std_mfcc.py | 21 |
12 files changed, 10 insertions, 629 deletions
diff --git a/power_sequencer/operators/__init__.py b/power_sequencer/operators/__init__.py index 3ab79520..a362b599 100755 --- a/power_sequencer/operators/__init__.py +++ b/power_sequencer/operators/__init__.py @@ -22,14 +22,18 @@ def get_operator_classes(): """Returns the list of operators in the add-on""" this_file = os.path.dirname(__file__) module_files = [ - f for f in os.listdir(this_file) if f.endswith(".py") and not f.startswith("__init__") + f + for f in os.listdir(this_file) + if f.endswith(".py") and not f.startswith("__init__") ] module_paths = ["." + os.path.splitext(f)[0] for f in module_files] classes = [] print(__name__) for path in module_paths: - module = importlib.import_module(path, package="blender_power_sequencer.operators") - operator_names = [entry for entry in dir(module) if entry.startswith("POWER_SEQUENCER_OT")] + module = importlib.import_module(path, package="power_sequencer.operators") + operator_names = [ + entry for entry in dir(module) if entry.startswith("POWER_SEQUENCER_OT") + ] classes.extend([getattr(module, name) for name in operator_names]) return classes @@ -38,7 +42,9 @@ doc = { "sequencer.refresh_all": { "name": "Refresh All", "description": "", - "shortcuts": [({"type": "R", "value": "PRESS", "shift": True}, {}, "Refresh All")], + "shortcuts": [ + ({"type": "R", "value": "PRESS", "shift": True}, {}, "Refresh All") + ], "demo": "", "keymap": "Sequencer", } diff --git a/power_sequencer/operators/align_audios.py b/power_sequencer/operators/align_audios.py deleted file mode 100644 index 0bd99aba..00000000 --- a/power_sequencer/operators/align_audios.py +++ /dev/null @@ -1,110 +0,0 @@ -# -# Copyright (C) 2016-2020 by Nathan Lovato, Daniel Oakey, Razvan Radulescu, and contributors -# -# This file is part of Power Sequencer. -# -# Power Sequencer is free software: you can redistribute it and/or modify it under the terms of the -# GNU General Public License as published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# Power Sequencer is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; -# without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along with Power Sequencer. If -# not, see <https://www.gnu.org/licenses/>. -# -import bpy -import subprocess - -from .utils.doc import doc_name, doc_idname, doc_brief, doc_description - - -class POWER_SEQUENCER_OT_align_audios(bpy.types.Operator): - """*brief* Align two audio strips - - - Tries to synchronize the selected audio strip to the active audio strip by comparing the sound. - Useful to synchronize audio of the same event recorded with different microphones. - - To use this feature, you must have [ffmpeg](https://www.ffmpeg.org/download.html) and - [scipy](https://www.scipy.org/install.html) installed on your computer and available on the PATH (command line) to work. - - The longer the audio files, the longer the tool can take to run, as it has to convert, analyze, - and compare the audio sources to work. - """ - - doc = { - "name": doc_name(__qualname__), - "demo": "https://i.imgur.com/xkBUzDj.gif", - "description": doc_description(__doc__), - "shortcuts": [], - "keymap": "Sequencer", - } - bl_idname = doc_idname(__qualname__) - bl_label = doc["name"] - bl_description = doc_brief(doc["description"]) - bl_options = {"REGISTER", "UNDO"} - - @classmethod - def poll(cls, context): - if not context.scene: - return False - - active = context.scene.sequence_editor.active_strip - selected = context.selected_sequences - ok = ( - len(selected) == 2 - and active in selected - and all(map(lambda s: s.type == "SOUND", selected)) - ) - return ok - - def execute(self, context): - try: - import scipy - except ImportError: - self.report({"ERROR"}, "Scipy must be installed to align audios") - return {"FINISHED"} - - if not is_ffmpeg_available(): - self.report({"ERROR"}, "ffmpeg must be installed to align audios") - return {"FINISHED"} - - # This import is here because otherwise, it slows down blender startup - from .audiosync import find_offset - - scene = context.scene - - active = scene.sequence_editor.active_strip - active_filepath = bpy.path.abspath(active.sound.filepath) - - selected = context.selected_sequences - selected.pop(selected.index(active)) - - align_strip = selected[0] - align_strip_filepath = bpy.path.abspath(align_strip.sound.filepath) - - offset, score = find_offset(align_strip_filepath, active_filepath) - - initial_offset = active.frame_start - align_strip.frame_start - - fps = scene.render.fps / scene.render.fps_base - frames = int(offset * fps) - - align_strip.frame_start -= frames - initial_offset - - self.report({"INFO"}, "Alignment score: " + str(round(score, 1))) - - return {"FINISHED"} - - -def is_ffmpeg_available(): - """ - Returns true if ffmpeg is installed and available from the PATH - """ - try: - subprocess.call(["ffmpeg", "--help"], stdout=subprocess.PIPE, stderr=subprocess.PIPE) - return True - except OSError: - return False diff --git a/power_sequencer/operators/audiosync/__init__.py b/power_sequencer/operators/audiosync/__init__.py deleted file mode 100644 index 74dd6f5a..00000000 --- a/power_sequencer/operators/audiosync/__init__.py +++ /dev/null @@ -1,17 +0,0 @@ -# -# Copyright (C) 2016-2020 by Nathan Lovato, Daniel Oakey, Razvan Radulescu, and contributors -# -# This file is part of Power Sequencer. -# -# Power Sequencer is free software: you can redistribute it and/or modify it under the terms of the -# GNU General Public License as published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# Power Sequencer is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; -# without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along with Power Sequencer. If -# not, see <https://www.gnu.org/licenses/>. -# -from .find_offset import find_offset diff --git a/power_sequencer/operators/audiosync/convert_and_trim.py b/power_sequencer/operators/audiosync/convert_and_trim.py deleted file mode 100644 index fddf702d..00000000 --- a/power_sequencer/operators/audiosync/convert_and_trim.py +++ /dev/null @@ -1,60 +0,0 @@ -# -# Copyright (C) 2016-2020 by Nathan Lovato, Daniel Oakey, Razvan Radulescu, and contributors -# -# This file is part of Power Sequencer. -# -# Power Sequencer is free software: you can redistribute it and/or modify it under the terms of the -# GNU General Public License as published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# Power Sequencer is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; -# without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along with Power Sequencer. If -# not, see <https://www.gnu.org/licenses/>. -# -import subprocess -import tempfile - - -def convert_and_trim(audio_filepath, freq, dur): - """ - Uses ffmpeg to convert an audio file to a temporary wav file for use - in finding offset. - - Args - :audio: path to the audiofile to convert (string) - :freq: Samples / second in the output wav (int) - :dur: Max duration of the output wav in seconds (float) - - Returns - :outpath: path to the output wav file - """ - - tmp = tempfile.NamedTemporaryFile(mode="r+b", prefix="offset_", suffix=".wav") - outpath = tmp.name - tmp.close() - - channel_count = "1" - - subprocess.call( - [ - "ffmpeg", - "-loglevel", - "panic", - "-i", - audio_filepath, - "-ac", - channel_count, - "-ar", - str(freq), - "-t", - str(dur), - "-acodec", - "pcm_s16le", - outpath, - ] - ) - - return outpath diff --git a/power_sequencer/operators/audiosync/cross_correlation.py b/power_sequencer/operators/audiosync/cross_correlation.py deleted file mode 100644 index dc337475..00000000 --- a/power_sequencer/operators/audiosync/cross_correlation.py +++ /dev/null @@ -1,33 +0,0 @@ -# -# Copyright (C) 2016-2020 by Nathan Lovato, Daniel Oakey, Razvan Radulescu, and contributors -# -# This file is part of Power Sequencer. -# -# Power Sequencer is free software: you can redistribute it and/or modify it under the terms of the -# GNU General Public License as published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# Power Sequencer is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; -# without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along with Power Sequencer. If -# not, see <https://www.gnu.org/licenses/>. -# -import numpy as np - - -def cross_correlation(mfcc1, mfcc2, nframes): - n1, mdim1 = mfcc1.shape - # n2, mdim2 = mfcc2.shape - - n = n1 - nframes + 1 - - if n < 0: - return None - - c = np.zeros(n) - for k in range(n): - cc = np.sum(np.multiply(mfcc1[k : k + nframes], mfcc2[:nframes]), axis=0) - c[k] = np.linalg.norm(cc) - return c diff --git a/power_sequencer/operators/audiosync/ensure_non_zero.py b/power_sequencer/operators/audiosync/ensure_non_zero.py deleted file mode 100644 index 589da529..00000000 --- a/power_sequencer/operators/audiosync/ensure_non_zero.py +++ /dev/null @@ -1,28 +0,0 @@ -# -# Copyright (C) 2016-2020 by Nathan Lovato, Daniel Oakey, Razvan Radulescu, and contributors -# -# This file is part of Power Sequencer. -# -# Power Sequencer is free software: you can redistribute it and/or modify it under the terms of the -# GNU General Public License as published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# Power Sequencer is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; -# without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along with Power Sequencer. If -# not, see <https://www.gnu.org/licenses/>. -# -import numpy as np - - -def ensure_non_zero(signal): - """ - Adds a little bit of static to avoid - 'divide by zero encountered in log' during MFCC computation. - """ - - signal += np.random.random(len(signal)) * 10 ** -10 - - return signal diff --git a/power_sequencer/operators/audiosync/find_offset.py b/power_sequencer/operators/audiosync/find_offset.py deleted file mode 100644 index 02287839..00000000 --- a/power_sequencer/operators/audiosync/find_offset.py +++ /dev/null @@ -1,87 +0,0 @@ -# -# Copyright (C) 2016-2020 by Nathan Lovato, Daniel Oakey, Razvan Radulescu, and contributors -# -# This file is part of Power Sequencer. -# -# Power Sequencer is free software: you can redistribute it and/or modify it under the terms of the -# GNU General Public License as published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# Power Sequencer is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; -# without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along with Power Sequencer. If -# not, see <https://www.gnu.org/licenses/>. -# -""" -This code is an adaptation of 'audio-offset-finder' by BBC -""" -import os -import numpy as np - -from .mfcc import mfcc -from .convert_and_trim import convert_and_trim -from .std_mfcc import std_mfcc -from .cross_correlation import cross_correlation -from .ensure_non_zero import ensure_non_zero - - -def find_offset(file1, file2, freq=8000, trim=60 * 15, correl_nframes=1000): - """ - Determine the offset (in seconds) between 2 audio files - - Uses cross-correlation of standardised Mel-Frequency Cepstral - Coefficients - """ - from scipy.io import wavfile - - file1 = os.path.abspath(file1) - file2 = os.path.abspath(file2) - - wav1_path = convert_and_trim(file1, freq, trim) - wav2_path = convert_and_trim(file2, freq, trim) - - rate1, data1 = wavfile.read(wav1_path, mmap=True) - data1 = data1 / (2.0 ** 15) - - rate2, data2 = wavfile.read(wav2_path, mmap=True) - data2 = data2 / (2.0 ** 15) - - data1 = ensure_non_zero(data1) - data2 = ensure_non_zero(data2) - - mfcc1 = mfcc(data1, nwin=256, nfft=512, fs=freq, nceps=13)[0] - mfcc2 = mfcc(data2, nwin=256, nfft=512, fs=freq, nceps=13)[0] - - mfcc1 = std_mfcc(mfcc1) - mfcc2 = std_mfcc(mfcc2) - - frames1 = mfcc1.shape[0] - frames2 = mfcc2.shape[0] - - if frames1 > frames2: - flip = 1 - - else: - flip = -1 - mfcc1, mfcc2 = mfcc2, mfcc1 - - c = cross_correlation(mfcc1, mfcc2, nframes=correl_nframes) - try: - c.any() - except AttributeError: - os.remove(wav1_path) - os.remove(wav2_path) - - return 0, 0 - - max_k_index = np.argmax(c) - - offset = max_k_index * 160.0 / float(freq) - score = (c[max_k_index] - np.mean(c)) / np.std(c) - - os.remove(wav1_path) - os.remove(wav2_path) - - return offset * flip, score diff --git a/power_sequencer/operators/audiosync/mfcc/__init__.py b/power_sequencer/operators/audiosync/mfcc/__init__.py deleted file mode 100644 index 204646ca..00000000 --- a/power_sequencer/operators/audiosync/mfcc/__init__.py +++ /dev/null @@ -1,17 +0,0 @@ -# -# Copyright (C) 2016-2020 by Nathan Lovato, Daniel Oakey, Razvan Radulescu, and contributors -# -# This file is part of Power Sequencer. -# -# Power Sequencer is free software: you can redistribute it and/or modify it under the terms of the -# GNU General Public License as published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# Power Sequencer is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; -# without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along with Power Sequencer. If -# not, see <https://www.gnu.org/licenses/>. -# -from .mfcc import mfcc diff --git a/power_sequencer/operators/audiosync/mfcc/mfcc.py b/power_sequencer/operators/audiosync/mfcc/mfcc.py deleted file mode 100644 index 3cb1c7dd..00000000 --- a/power_sequencer/operators/audiosync/mfcc/mfcc.py +++ /dev/null @@ -1,91 +0,0 @@ -# -# Copyright (C) 2016-2020 by Nathan Lovato, Daniel Oakey, Razvan Radulescu, and contributors -# -# This file is part of Power Sequencer. -# -# Power Sequencer is free software: you can redistribute it and/or modify it under the terms of the -# GNU General Public License as published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# Power Sequencer is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; -# without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along with Power Sequencer. If -# not, see <https://www.gnu.org/licenses/>. -# -import numpy as np - -from scipy.signal import hamming, lfilter -from scipy.fftpack import fft -from scipy.fftpack.realtransforms import dct - -from .trfbank import trfbank -from .segment_axis import segment_axis - - -def mfcc(input, nwin=256, nfft=512, fs=16000, nceps=13): - """Compute Mel Frequency Cepstral Coefficients. - - Parameters - ---------- - input: ndarray - input from which the coefficients are computed - - Returns - ------- - ceps: ndarray - Mel-cepstrum coefficients - mspec: ndarray - Log-spectrum in the mel-domain. - - Notes - ----- - MFCC are computed as follows: - * Pre-processing in time-domain (pre-emphasizing) - * Compute the spectrum amplitude by windowing with a Hamming window - * Filter the signal in the spectral domain with a triangular - filter-bank, whose filters are approximatively linearly spaced on the - mel scale, and have equal bandwidth in the mel scale - * Compute the DCT of the log-spectrum - - References - ---------- - .. [1] S.B. Davis and P. Mermelstein, "Comparison of parametric - representations for monosyllabic word recognition in continuously - spoken sentences", IEEE Trans. Acoustics. Speech, Signal Proc. - ASSP-28 (4): 357-366, August 1980.""" - - # MFCC parameters: taken from auditory toolbox - over = nwin - 160 - # Pre-emphasis factor (to take into account the -6dB/octave rolloff of the - # radiation at the lips level) - prefac = 0.97 - - # lowfreq = 400 / 3. - lowfreq = 133.33 - # highfreq = 6855.4976 - linsc = 200 / 3.0 - logsc = 1.0711703 - - nlinfil = 13 - nlogfil = 27 - - w = hamming(nwin, sym=0) - - fbank = trfbank(fs, nfft, lowfreq, linsc, logsc, nlinfil, nlogfil)[0] - - # ------------------ - # Compute the MFCC - # ------------------ - extract = lfilter([1.0, -prefac], 1, input) - framed = segment_axis(extract, nwin, over) * w - - # Compute the spectrum magnitude - spec = np.abs(fft(framed, nfft, axis=-1)) - # Filter the spectrum through the triangle filterbank - mspec = np.log10(np.dot(spec, fbank.T)) - # Use the DCT to 'compress' the coefficients (spectrum -> cepstrum domain) - ceps = dct(mspec, type=2, norm="ortho", axis=-1)[:, :nceps] - - return ceps, mspec, spec diff --git a/power_sequencer/operators/audiosync/mfcc/segment_axis.py b/power_sequencer/operators/audiosync/mfcc/segment_axis.py deleted file mode 100644 index b5b8740c..00000000 --- a/power_sequencer/operators/audiosync/mfcc/segment_axis.py +++ /dev/null @@ -1,110 +0,0 @@ -# -# Copyright (C) 2016-2020 by Nathan Lovato, Daniel Oakey, Razvan Radulescu, and contributors -# -# This file is part of Power Sequencer. -# -# Power Sequencer is free software: you can redistribute it and/or modify it under the terms of the -# GNU General Public License as published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# Power Sequencer is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; -# without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along with Power Sequencer. If -# not, see <https://www.gnu.org/licenses/>. -# -import numpy as np -import warnings - - -def segment_axis(a, length, overlap=0, axis=None, end="cut", endvalue=0): - """Generate a new array that chops the given array along the given axis - into overlapping frames. - - example: - >>> segment_axis(arange(10), 4, 2) - array([[0, 1, 2, 3], - [2, 3, 4, 5], - [4, 5, 6, 7], - [6, 7, 8, 9]]) - - arguments: - a The array to segment - length The length of each frame - overlap The number of array elements by which the frames should overlap - axis The axis to operate on; if None, act on the flattened array - end What to do with the last frame, if the array is not evenly - divisible into pieces. Options are: - - 'cut' Simply discard the extra values - 'wrap' Copy values from the beginning of the array - 'pad' Pad with a constant value - - endvalue The value to use for end='pad' - - The array is not copied unless necessary (either because it is unevenly - strided and being flattened or because end is set to 'pad' or 'wrap'). - """ - - if axis is None: - a = np.ravel(a) # may copy - axis = 0 - - l = a.shape[axis] - - if overlap >= length: - raise ValueError("frames cannot overlap by more than 100%") - if overlap < 0 or length <= 0: - raise ValueError("overlap must be nonnegative and length must " "be positive") - - if l < length or (l - length) % (length - overlap): - if l > length: - roundup = length + (1 + (l - length) // (length - overlap)) * (length - overlap) - rounddown = length + ((l - length) // (length - overlap)) * (length - overlap) - else: - roundup = length - rounddown = 0 - assert rounddown < l < roundup - assert roundup == rounddown + (length - overlap) or (roundup == length and rounddown == 0) - a = a.swapaxes(-1, axis) - - if end == "cut": - a = a[..., :rounddown] - elif end in ["pad", "wrap"]: # copying will be necessary - s = list(a.shape) - s[-1] = roundup - b = np.empty(s, dtype=a.dtype) - b[..., :l] = a - if end == "pad": - b[..., l:] = endvalue - elif end == "wrap": - b[..., l:] = a[..., : roundup - l] - a = b - - a = a.swapaxes(-1, axis) - - l = a.shape[axis] - if l == 0: - raise ValueError( - "Not enough data points to segment array in 'cut' mode; " "try 'pad' or 'wrap'" - ) - assert l >= length - assert (l - length) % (length - overlap) == 0 - n = 1 + (l - length) // (length - overlap) - s = a.strides[axis] - newshape = a.shape[:axis] + (n, length) + a.shape[axis + 1 :] - newstrides = a.strides[:axis] + ((length - overlap) * s, s) + a.strides[axis + 1 :] - - try: - return np.ndarray.__new__( - np.ndarray, strides=newstrides, shape=newshape, buffer=a, dtype=a.dtype - ) - except TypeError: - warnings.warn("Problem with ndarray creation forces copy.") - a = a.copy() - # Shape doesn't change but strides does - newstrides = a.strides[:axis] + ((length - overlap) * s, s) + a.strides[axis + 1 :] - return np.ndarray.__new__( - np.ndarray, strides=newstrides, shape=newshape, buffer=a, dtype=a.dtype - ) diff --git a/power_sequencer/operators/audiosync/mfcc/trfbank.py b/power_sequencer/operators/audiosync/mfcc/trfbank.py deleted file mode 100644 index 15baac54..00000000 --- a/power_sequencer/operators/audiosync/mfcc/trfbank.py +++ /dev/null @@ -1,51 +0,0 @@ -# -# Copyright (C) 2016-2020 by Nathan Lovato, Daniel Oakey, Razvan Radulescu, and contributors -# -# This file is part of Power Sequencer. -# -# Power Sequencer is free software: you can redistribute it and/or modify it under the terms of the -# GNU General Public License as published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# Power Sequencer is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; -# without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along with Power Sequencer. If -# not, see <https://www.gnu.org/licenses/>. -# -import numpy as np - - -def trfbank(fs, nfft, lowfreq, linsc, logsc, nlinfilt, nlogfilt): - """Compute triangular filterbank for MFCC computation.""" - # Total number of filters - nfilt = nlinfilt + nlogfilt - - # ------------------------ - # Compute the filter bank - # ------------------------ - # Compute start/middle/end points of the triangular filters in spectral - # domain - freqs = np.zeros(nfilt + 2) - freqs[:nlinfilt] = lowfreq + np.arange(nlinfilt) * linsc - freqs[nlinfilt:] = freqs[nlinfilt - 1] * logsc ** np.arange(1, nlogfilt + 3) - heights = 2.0 / (freqs[2:] - freqs[0:-2]) - - # Compute filterbank coeff (in fft domain, in bins) - fbank = np.zeros((nfilt, nfft)) - # FFT bins (in Hz) - nfreqs = np.arange(nfft) / (1.0 * nfft) * fs - for i in range(nfilt): - low = freqs[i] - cen = freqs[i + 1] - hi = freqs[i + 2] - - lid = np.arange(np.floor(low * nfft / fs) + 1, np.floor(cen * nfft / fs) + 1, dtype=np.int) - lslope = heights[i] / (cen - low) - rid = np.arange(np.floor(cen * nfft / fs) + 1, np.floor(hi * nfft / fs) + 1, dtype=np.int) - rslope = heights[i] / (hi - cen) - fbank[i][lid] = lslope * (nfreqs[lid] - low) - fbank[i][rid] = rslope * (hi - nfreqs[rid]) - - return fbank, freqs diff --git a/power_sequencer/operators/audiosync/std_mfcc.py b/power_sequencer/operators/audiosync/std_mfcc.py deleted file mode 100644 index 8e56a2da..00000000 --- a/power_sequencer/operators/audiosync/std_mfcc.py +++ /dev/null @@ -1,21 +0,0 @@ -# -# Copyright (C) 2016-2020 by Nathan Lovato, Daniel Oakey, Razvan Radulescu, and contributors -# -# This file is part of Power Sequencer. -# -# Power Sequencer is free software: you can redistribute it and/or modify it under the terms of the -# GNU General Public License as published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# Power Sequencer is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; -# without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along with Power Sequencer. If -# not, see <https://www.gnu.org/licenses/>. -# -import numpy as np - - -def std_mfcc(mfcc): - return (mfcc - np.mean(mfcc, axis=0)) / np.std(mfcc, axis=0) |