Skip to content

Commit

Permalink
Merge pull request #5 from meinardmueller/sjs_dependencies
Browse files Browse the repository at this point in the history
Version 1.1.2
  • Loading branch information
simonschwaer authored Nov 27, 2024
2 parents 91b6be0 + 83622be commit 0881017
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 24 deletions.
6 changes: 5 additions & 1 deletion libtsm/pitchshift.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
import scipy.interpolate
from fractions import Fraction as frac
from .tsm import hps_tsm
from .utils import normalize_length
from .utils import ensure_validity, normalize_length


def pitch_shift_original(x, n, Fs=22050) -> np.ndarray:
Expand Down Expand Up @@ -136,6 +136,8 @@ def pitch_shift(x, p, t_p=None, Fs=22050, order="res-tsm", **kwargs) -> np.ndarr
# only keep unique indices
anchor_points = anchor_points[np.unique(anchor_points[:, 1], return_index=True)[1], :]

anchor_points = ensure_validity(anchor_points)

# Time-Scale Modification
y_ps = hps_tsm(y_ps, anchor_points, Fs=Fs, **kwargs)

Expand All @@ -145,6 +147,8 @@ def pitch_shift(x, p, t_p=None, Fs=22050, order="res-tsm", **kwargs) -> np.ndarr
# only keep unique indices
anchor_points = anchor_points[np.unique(anchor_points[:, 1], return_index=True)[1], :]

anchor_points = ensure_validity(anchor_points)

# Time-Scale Modification
y_tsm = hps_tsm(x, anchor_points, Fs=Fs, **kwargs)

Expand Down
9 changes: 8 additions & 1 deletion libtsm/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,14 @@ def ensure_validity(alpha, syn_hop=128):
"""
d_ana = np.diff(alpha[:,0])
d_syn = np.diff(alpha[:,1])
not_too_steep = np.pad(np.round(d_syn / d_ana) <= syn_hop, (1,0), constant_values=True)
# divide considering d_ana = 0
ratio = np.divide(d_syn, d_ana, out=np.ones_like(d_syn, dtype=float) * syn_hop + 1, where=(d_ana != 0))
not_too_steep = np.pad(np.round(ratio) <= syn_hop, (1,0), constant_values=True)

# make sure that the last point is retained (and try to remove the second-to-last instead)
if not_too_steep[-1] == False:
not_too_steep[-2] = False
not_too_steep[-1] = True

# call recursively to remove consecutive points that are too steep
if not np.all(not_too_steep):
Expand Down
31 changes: 18 additions & 13 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@

setup(
name='libtsm',
version='1.1.1',
version='1.1.2',
description='Python Package for Time-Scale Modification and Pitch-Shifting',
author='Sebastian Rosenzweig, Simon Schwär, Jonathan Driedger and Meinard Müller',
author_email='[email protected]',
url='https://www.audiolabs-erlangen.de/resources/MIR/2021-DAFX-AdaptivePitchShifting',
download_url='https://github.com/meinardmueller/libtsm/archive/refs/tags/v1.1.0.tar.gz',
download_url='https://github.com/meinardmueller/libtsm/archive/refs/tags/v1.1.2.tar.gz',
packages=find_packages(),
long_description=long_description,
long_description_content_type='text/markdown',
Expand All @@ -24,19 +24,24 @@
],
keywords=['audio', 'music', 'tsm', 'pitch-shifting'],
license='MIT',
install_requires=['ipython >= 7.8.0',
'librosa >= 0.8.0',
'matplotlib >= 3.1.0',
'numba >= 0.51.0',
'numpy >= 1.17.0',
'pysoundfile >= 0.9.0',
install_requires=['numpy >= 1.17.0',
'scipy >= 1.3.0'],
python_requires='>=3.6',
extras_require={
'dev': ['jupyter == 1.0.*',
'nbstripout == 0.4.*'],
'tests': ['pytest == 6.2.*'],
'docs': ['sphinx == 4.0.*',
'sphinx-rtd-theme == 0.5.*'],
'dev': [ # required for running the Jupyter notebook `demo_libtsm.ipynb
'ipython >= 7.8.0',
'jupyter == 1.0.*',
'librosa >= 0.8.0',
'nbstripout == 0.4.*',
'matplotlib >= 3.1.0',
],
'test': [
'pytest == 6.2.*',
'soundfile >= 0.9.0',
],
'docs': [
'sphinx == 4.0.*',
'sphinx-rtd-theme == 0.5.*',
],
}
)
30 changes: 21 additions & 9 deletions test/test_pitch_shifting.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,11 @@

import numpy as np
import libtsm
import librosa
import soundfile as sf


def test_fixed_pitch_shift_even():
fn_in = 'data/three_sinusoidals.wav'
x, Fs = librosa.load(fn_in, sr=22050)
x, Fs = sf.read('data/three_sinusoidals.wav')

p = 1200 # cents
y_psf1 = libtsm.pitch_shift(x, p, order='res-tsm')[:, 0]
Expand All @@ -25,8 +24,7 @@ def test_fixed_pitch_shift_even():


def test_fixed_pitch_shift_odd():
fn_in = 'data/three_sinusoidals.wav'
x, Fs = librosa.load(fn_in, sr=22050)
x, Fs = sf.read('data/three_sinusoidals.wav')

p = 1231 # cents
y_psf1 = libtsm.pitch_shift(x, p, order='res-tsm')[:, 0]
Expand Down Expand Up @@ -59,9 +57,7 @@ def test_adaptive_pitch_shift1():


def test_adaptive_pitch_shift2():
# Load Audio File
fn_in = 'data/three_sinusoidals.wav'
x, Fs = librosa.load(fn_in, sr=22050)
x, Fs = sf.read('data/three_sinusoidals.wav')

# Adaptive Pitch-Shifting (Figure 3)
t = np.arange(0, len(x) / Fs, 1 / Fs) # sec
Expand All @@ -81,7 +77,7 @@ def test_adaptive_pitch_shift2():

def test_adaptive_pitch_shift3():
Fs = 48000
t = np.linspace(0, 5, int(5*Fs))
t = np.arange(int(5*Fs)) / Fs
x = 0.5 * np.sin(2 * np.pi * 220 * t)

p = np.array([0, 100, 50, -100, 0])
Expand All @@ -92,3 +88,19 @@ def test_adaptive_pitch_shift3():

assert len(x) == len(y1)
assert len(x) == len(y2)

def test_adaptive_pitch_shift_random():
Fs = 44100
x = np.random.rand(int(5*Fs)) - 0.5

# try 20 different random trajectories
for _ in range(20):
N = np.random.randint(1, 250)
p = np.random.rand(N) * 1200 - 600
t_p = np.linspace(0, 5, N)

y1 = libtsm.pitch_shift(x, p, t_p, Fs=Fs, order='res-tsm')[:, 0]
y2 = libtsm.pitch_shift(x, p, t_p, Fs=Fs, order='tsm-res')[:, 0]

assert len(x) == len(y1)
assert len(x) == len(y2)

0 comments on commit 0881017

Please sign in to comment.