Skip to content

Commit 2ca177f

Browse files
authoredAug 5, 2022
Merge pull request #109 from bmcfee/032-tweaks
faster import, no int outputs
2 parents 29d3487 + 716a704 commit 2ca177f

File tree

8 files changed

+70
-97
lines changed

8 files changed

+70
-97
lines changed
 

‎.github/workflows/ci-minimal.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ jobs:
3434
shell: bash -l {0}
3535
run: |
3636
mamba install typing_extensions!=4.2 pytest
37-
mamba install pip numpy==1.17 scipy==1.0 numba==0.47
37+
mamba install pip numpy==1.17 scipy==1.0 numba==0.53
3838
3939
- name: Install
4040
shell: bash -l {0}

‎docs/changes.rst

+7
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
Changes
22
-------
33

4+
v0.4.0
5+
~~~~~~
6+
2022-08-05
7+
8+
- `#109 <https://github.com/bmcfee/resampy/pull/109>`_ Reduced import time and switched to parallel=False by default.
9+
- `#109 <https://github.com/bmcfee/resampy/pull/109>`_ Integer-valued inputs now produce floating point outputs.
10+
411
v0.3.1
512
~~~~~~
613
2022-07-07

‎docs/example.rst

+25-25
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,31 @@ The next block illustrates resampling along an arbitrary dimension.
7272
7373
# y_low is now a 10-by-3-(5*11025)-by-2 tensor of data
7474
75+
Integer-valued samples
76+
======================
77+
Integer-valued inputs are supported, but because resampy interpolates between
78+
sample values, it will always produce a floating-point output.
79+
If you really need integer-valued outputs after resampling, you'll have to cast the
80+
output array as demonstrated below.
81+
82+
.. code-block:: python
83+
:linenos:
84+
85+
import numpy as np
86+
import resampy
87+
88+
sr_orig = 22050
89+
90+
# Create 5 seconds of random integer noise
91+
x = np.random.randint(-32768, high=32767, size=5*sr_orig, dtype=np.int16)
92+
93+
# resample, y will be floating-point type
94+
y = resampy.resample(x, sr_orig, 11025)
95+
96+
# Cast back to match x's dtype
97+
y_int = y.astype(x.dtype)
98+
99+
75100
Advanced filtering
76101
==================
77102
resampy allows you to control the design of the filters used in resampling operations.
@@ -100,28 +125,3 @@ resampy allows you to control the design of the filters used in resampling opera
100125
y = resampy.resample(x, sr_orig, sr_new, filter='kaiser_fast')
101126
102127
103-
Benchmarking
104-
============
105-
Benchmarking `resampy` is relatively simple, using `ipython`'s ``%timeit`` magic.
106-
The following example demonstrates resampling a monophonic signal of 400000 samples from
107-
22.05 KHz to 16 KHz using both `resampy` and `scipy.signal.resample`.
108-
109-
.. code-block:: python
110-
111-
In [1]: import numpy as np
112-
113-
In [2]: import scipy
114-
115-
In [3]: import resampy
116-
117-
In [4]: x = np.random.randn(400000)
118-
119-
In [5]: sr_in, sr_out = 22050, 16000
120-
121-
In [6]: %timeit resampy.resample(x, sr_in, sr_out, axis=-1)
122-
1 loop, best of 3: 199 ms per loop
123-
124-
In [7]: %timeit scipy.signal.resample(x,
125-
...: int(x.shape[-1] * sr_out / float(sr_in)),
126-
...: axis=-1)
127-
1 loop, best of 3: 6min 5s per loop

‎resampy/core.py

+13-4
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313

1414
def resample(
15-
x, sr_orig, sr_new, axis=-1, filter="kaiser_best", parallel=True, **kwargs
15+
x, sr_orig, sr_new, axis=-1, filter="kaiser_best", parallel=False, **kwargs
1616
):
1717
"""Resample a signal x from sr_orig to sr_new along a given axis.
1818
@@ -116,7 +116,12 @@ def resample(
116116
)
117117

118118
# Preserve contiguity of input (if it exists)
119-
y = np.zeros_like(x, shape=shape)
119+
if np.issubdtype(x.dtype, np.integer):
120+
dtype = np.float32
121+
else:
122+
dtype = x.dtype
123+
124+
y = np.zeros_like(x, dtype=dtype, shape=shape)
120125

121126
interp_win, precision, _ = get_filter(filter, **kwargs)
122127

@@ -155,7 +160,7 @@ def resample(
155160

156161

157162
def resample_nu(
158-
x, sr_orig, t_out, axis=-1, filter="kaiser_best", parallel=True, **kwargs
163+
x, sr_orig, t_out, axis=-1, filter="kaiser_best", parallel=False, **kwargs
159164
):
160165
"""Interpolate a signal x at specified positions (t_out) along a given axis.
161166
@@ -239,7 +244,11 @@ def resample_nu(
239244
shape = list(x.shape)
240245
shape[axis] = len(t_out)
241246

242-
y = np.zeros_like(x, shape=shape)
247+
if np.issubdtype(x.dtype, np.integer):
248+
dtype = np.float32
249+
else:
250+
dtype = x.dtype
251+
y = np.zeros_like(x, dtype=dtype, shape=shape)
243252

244253
interp_win, precision, _ = get_filter(filter, **kwargs)
245254

‎resampy/interpn.py

+1-62
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,7 @@
11
#!/usr/bin/env python
22
"""Numba implementation of resampler"""
33

4-
from numba import (
5-
guvectorize,
6-
float32,
7-
float64,
8-
jit,
9-
prange,
10-
int16,
11-
int32,
12-
int64,
13-
complex64,
14-
complex128,
15-
)
4+
from numba import guvectorize, jit, prange
165

176

187
def _resample_loop(x, t_out, interp_win, interp_delta, num_table, scale, y):
@@ -82,31 +71,6 @@ def _resample_loop(x, t_out, interp_win, interp_delta, num_table, scale, y):
8271

8372

8473
@guvectorize(
85-
[
86-
(int16[:], float64[:], float64[:], float64[:], int32, float32, int16[:]),
87-
(int32[:], float64[:], float64[:], float64[:], int32, float32, int32[:]),
88-
(int64[:], float64[:], float64[:], float64[:], int32, float32, int64[:]),
89-
(float32[:], float64[:], float64[:], float64[:], int32, float32, float32[:]),
90-
(float64[:], float64[:], float64[:], float64[:], int32, float32, float64[:]),
91-
(
92-
complex64[:],
93-
float64[:],
94-
float64[:],
95-
float64[:],
96-
int32,
97-
float32,
98-
complex64[:],
99-
),
100-
(
101-
complex128[:],
102-
float64[:],
103-
float64[:],
104-
float64[:],
105-
int32,
106-
float32,
107-
complex128[:],
108-
),
109-
],
11074
"(n),(m),(p),(p),(),()->(m)",
11175
nopython=True,
11276
)
@@ -115,31 +79,6 @@ def resample_f_p(x, t_out, interp_win, interp_delta, num_table, scale, y):
11579

11680

11781
@guvectorize(
118-
[
119-
(int16[:], float64[:], float64[:], float64[:], int32, float32, int16[:]),
120-
(int32[:], float64[:], float64[:], float64[:], int32, float32, int32[:]),
121-
(int64[:], float64[:], float64[:], float64[:], int32, float32, int64[:]),
122-
(float32[:], float64[:], float64[:], float64[:], int32, float32, float32[:]),
123-
(float64[:], float64[:], float64[:], float64[:], int32, float32, float64[:]),
124-
(
125-
complex64[:],
126-
float64[:],
127-
float64[:],
128-
float64[:],
129-
int32,
130-
float32,
131-
complex64[:],
132-
),
133-
(
134-
complex128[:],
135-
float64[:],
136-
float64[:],
137-
float64[:],
138-
int32,
139-
float32,
140-
complex128[:],
141-
),
142-
],
14382
"(n),(m),(p),(p),(),()->(m)",
14483
nopython=True,
14584
)

‎resampy/version.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@
22
# -*- coding: utf-8 -*-
33
"""Version info"""
44

5-
short_version = '0.3'
6-
version = '0.3.1'
5+
short_version = '0.4'
6+
version = '0.4.0'

‎setup.cfg

+1-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ install_package_data = True
3939
python_requires >= 3.6
4040
install_requires =
4141
numpy>=1.17
42-
numba>=0.47
42+
numba>=0.53
4343

4444
[options.package_data]
4545
resampy = data/*

‎tests/test_core.py

+20-2
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ def test_bad_num_zeros():
7777

7878

7979
@pytest.mark.parametrize('dtype', [np.float32, np.float64,
80-
np.int16, np.int32, np.int64])
80+
np.complex64, np.complex128])
8181
def test_dtype(dtype):
8282
x = np.random.randn(100).astype(dtype)
8383

@@ -86,8 +86,26 @@ def test_dtype(dtype):
8686
assert x.dtype == y.dtype
8787

8888

89+
@pytest.mark.parametrize('dtype', [np.int16, np.int32, np.int64])
90+
def test_dtype_int(dtype):
91+
x = (32767 * np.random.randn(100)).astype(dtype)
92+
93+
y = resampy.resample(x, 100, 200)
94+
95+
assert y.dtype == np.float32
96+
97+
98+
@pytest.mark.parametrize('dtype', [np.int16, np.int32, np.int64])
99+
def test_dtype_int_nu(dtype):
100+
x = (32767 * np.random.randn(100)).astype(dtype)
101+
t = np.arange(2 * len(x) - 1) / 2
102+
103+
y = resampy.resample_nu(x, 1., t)
104+
assert y.dtype == np.float32
105+
106+
89107
@pytest.mark.parametrize('dtype', [np.float32, np.float64,
90-
np.int16, np.int32, np.int64])
108+
np.complex64, np.complex128])
91109
def test_resample_nu_dtype(dtype):
92110
x = np.random.randn(100).astype(dtype)
93111
t = np.arange(2 * len(x) - 1) / 2

0 commit comments

Comments
 (0)
Please sign in to comment.