Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

buffer input frames #6

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 19 additions & 4 deletions samplerate/converters.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,10 @@ def __init__(self, converter_type='sinc_fastest', channels=1):
self._state = ffi.gc(state, src_delete)
self._converter_type = converter_type
self._channels = channels
if channels == 1:
self._frame_buffer = np.zeros(0, dtype=np.float32)
else:
self._frame_buffer = np.zeros((0,channels), dtype=np.float32)
if error != 0:
raise ResamplingError(error)

Expand All @@ -125,6 +129,10 @@ def channels(self):
def reset(self):
"""Reset internal state."""
from samplerate.lowlevel import src_reset
if self._channels == 1:
self._frame_buffer = np.empty(0, dtype=np.float32)
else:
self._frame_buffer = np.empty((0,channels), dtype=np.float32)
return src_reset(self._state)

def set_ratio(self, new_ratio):
Expand Down Expand Up @@ -158,11 +166,12 @@ def process(self, input_data, ratio, end_of_input=False, verbose=False):
from samplerate.exceptions import ResamplingError

input_data = np.require(input_data, requirements='C', dtype=np.float32)
self._frame_buffer = np.append(self._frame_buffer, input_data, axis=0)
if input_data.ndim == 2:
num_frames, channels = input_data.shape
num_frames, channels = self._frame_buffer.shape
output_shape = (int(num_frames * ratio), channels)
elif input_data.ndim == 1:
num_frames, channels = input_data.size, 1
num_frames, channels = self._frame_buffer.shape[0], 1
output_shape = (int(num_frames * ratio), )
else:
raise ValueError('rank > 2 not supported')
Expand All @@ -173,16 +182,22 @@ def process(self, input_data, ratio, end_of_input=False, verbose=False):
output_data = np.empty(output_shape, dtype=np.float32)

(error, input_frames_used, output_frames_gen) = src_process(
self._state, input_data, output_data, ratio, end_of_input)
self._state, self._frame_buffer, output_data, ratio, end_of_input)

if error != 0:
raise ResamplingError(error)

if channels > 1:
self._frame_buffer = self._frame_buffer[input_frames_used:, :]
else:
self._frame_buffer = self._frame_buffer[input_frames_used:]

if verbose:
info = ('samplerate info:\n'
'{} input frames used\n'
'{} output frames generated\n'
.format(input_frames_used, output_frames_gen))
'{} buffer size\n'
.format(input_frames_used, output_frames_gen, self._frame_buffer.shape[0]))
print(info)

return (output_data[:output_frames_gen, :]
Expand Down
18 changes: 15 additions & 3 deletions tests/test_samplerate.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,24 @@ def test_process(data, converter_type, ratio=2.0):
src.process(input_data, ratio)


def test_match(data, converter_type, ratio=2.0):
def test_match(data, converter_type, ratio=2.123):
num_channels, input_data = data
output_simple = samplerate.resample(input_data, ratio, converter_type)
resampler = samplerate.Resampler(converter_type, channels=num_channels)
output_full = resampler.process(input_data, ratio, end_of_input=True)
assert np.allclose(output_simple, output_full)
if num_channels == 2:
output_full = np.empty((0,num_channels), dtype=np.float32)
for i in range(10):
output_full = np.append(output_full, resampler.process(input_data[100*i:100*(i+1),:], ratio), axis=0)
m = output_simple.shape[0]
output_simple = np.resize(output_simple, output_full.shape)
assert np.allclose(output_simple, output_full) and output_full.shape[0] > 0.8*m
else:
output_full = np.empty(0, dtype=np.float32)
for i in range(10):
output_full = np.append(output_full, resampler.process(input_data[100*i:100*(i+1)], ratio))
m = len(output_simple)
output_simple = np.resize(output_simple, output_full.shape)
assert np.allclose(output_simple, output_full) and len(output_full) > 0.8*m


def test_callback(data, converter_type, ratio=2.0):
Expand Down