diff --git a/samplerate/converters.py b/samplerate/converters.py index 64841c2..5eb9e74 100644 --- a/samplerate/converters.py +++ b/samplerate/converters.py @@ -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) @@ -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): @@ -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') @@ -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, :] diff --git a/tests/test_samplerate.py b/tests/test_samplerate.py index de0fa78..c077362 100644 --- a/tests/test_samplerate.py +++ b/tests/test_samplerate.py @@ -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):