diff options
Diffstat (limited to 'media/libcubeb/src/cubeb_resampler.cpp')
-rw-r--r-- | media/libcubeb/src/cubeb_resampler.cpp | 122 |
1 files changed, 86 insertions, 36 deletions
diff --git a/media/libcubeb/src/cubeb_resampler.cpp b/media/libcubeb/src/cubeb_resampler.cpp index f6676946c..2bc889340 100644 --- a/media/libcubeb/src/cubeb_resampler.cpp +++ b/media/libcubeb/src/cubeb_resampler.cpp @@ -35,29 +35,54 @@ to_speex_quality(cubeb_resampler_quality q) } } -long noop_resampler::fill(void * input_buffer, long * input_frames_count, - void * output_buffer, long output_frames) +uint32_t min_buffered_audio_frame(uint32_t sample_rate) +{ + return sample_rate / 20; +} + +template<typename T> +passthrough_resampler<T>::passthrough_resampler(cubeb_stream * s, + cubeb_data_callback cb, + void * ptr, + uint32_t input_channels, + uint32_t sample_rate) + : processor(input_channels) + , stream(s) + , data_callback(cb) + , user_ptr(ptr) + , sample_rate(sample_rate) +{ +} + +template<typename T> +long passthrough_resampler<T>::fill(void * input_buffer, long * input_frames_count, + void * output_buffer, long output_frames) { if (input_buffer) { assert(input_frames_count); } - assert((input_buffer && output_buffer && - *input_frames_count >= output_frames) || - (!input_buffer && (!input_frames_count || *input_frames_count == 0)) || - (!output_buffer && output_frames == 0)); - - if (output_buffer == nullptr) { - assert(input_buffer); - output_frames = *input_frames_count; + assert((input_buffer && output_buffer) || + (output_buffer && !input_buffer && (!input_frames_count || *input_frames_count == 0)) || + (input_buffer && !output_buffer && output_frames == 0)); + + if (input_buffer) { + if (!output_buffer) { + output_frames = *input_frames_count; + } + internal_input_buffer.push(static_cast<T*>(input_buffer), + frames_to_samples(*input_frames_count)); } - if (input_buffer && *input_frames_count != output_frames) { - assert(*input_frames_count > output_frames); + long rv = data_callback(stream, user_ptr, internal_input_buffer.data(), + output_buffer, output_frames); + + if (input_buffer) { + internal_input_buffer.pop(nullptr, frames_to_samples(output_frames)); *input_frames_count = output_frames; + drop_audio_if_needed(); } - return data_callback(stream, user_ptr, - input_buffer, output_buffer, output_frames); + return rv; } template<typename T, typename InputProcessor, typename OutputProcessor> @@ -120,27 +145,32 @@ cubeb_resampler_speex<T, InputProcessor, OutputProcessor> assert(!input_buffer && (!input_frames_count || *input_frames_count == 0) && output_buffer && output_frames_needed); - long got = 0; - T * out_unprocessed = nullptr; - long output_frames_before_processing = 0; + if (!draining) { + long got = 0; + T * out_unprocessed = nullptr; + long output_frames_before_processing = 0; + /* fill directly the input buffer of the output processor to save a copy */ + output_frames_before_processing = + output_processor->input_needed_for_output(output_frames_needed); - /* fill directly the input buffer of the output processor to save a copy */ - output_frames_before_processing = - output_processor->input_needed_for_output(output_frames_needed); + out_unprocessed = + output_processor->input_buffer(output_frames_before_processing); - out_unprocessed = - output_processor->input_buffer(output_frames_before_processing); + got = data_callback(stream, user_ptr, + nullptr, out_unprocessed, + output_frames_before_processing); - got = data_callback(stream, user_ptr, - nullptr, out_unprocessed, - output_frames_before_processing); + if (got < output_frames_before_processing) { + draining = true; - if (got < 0) { - return got; - } + if (got < 0) { + return got; + } + } - output_processor->written(got); + output_processor->written(got); + } /* Process the output. If not enough frames have been returned from the * callback, drain the processors. */ @@ -163,7 +193,10 @@ cubeb_resampler_speex<T, InputProcessor, OutputProcessor> /* process the input, and present exactly `output_frames_needed` in the * callback. */ input_processor->input(input_buffer, *input_frames_count); - resampled_input = input_processor->output(resampled_frame_count); + + size_t frames_resampled = 0; + resampled_input = input_processor->output(resampled_frame_count, &frames_resampled); + *input_frames_count = frames_resampled; long got = data_callback(stream, user_ptr, resampled_input, nullptr, resampled_frame_count); @@ -174,18 +207,22 @@ cubeb_resampler_speex<T, InputProcessor, OutputProcessor> return (*input_frames_count) * (got / resampled_frame_count); } - template<typename T, typename InputProcessor, typename OutputProcessor> long cubeb_resampler_speex<T, InputProcessor, OutputProcessor> ::fill_internal_duplex(T * in_buffer, long * input_frames_count, T * out_buffer, long output_frames_needed) { + if (draining) { + // discard input and drain any signal remaining in the resampler. + return output_processor->output(out_buffer, output_frames_needed); + } + /* The input data, after eventual resampling. This is passed to the callback. */ T * resampled_input = nullptr; /* The output buffer passed down in the callback, that might be resampled. */ T * out_unprocessed = nullptr; - size_t output_frames_before_processing = 0; + long output_frames_before_processing = 0; /* The number of frames returned from the callback. */ long got = 0; @@ -210,8 +247,11 @@ cubeb_resampler_speex<T, InputProcessor, OutputProcessor> /* process the input, and present exactly `output_frames_needed` in the * callback. */ input_processor->input(in_buffer, *input_frames_count); + + size_t frames_resampled = 0; resampled_input = - input_processor->output(output_frames_before_processing); + input_processor->output(output_frames_before_processing, &frames_resampled); + *input_frames_count = frames_resampled; } else { resampled_input = nullptr; } @@ -220,15 +260,25 @@ cubeb_resampler_speex<T, InputProcessor, OutputProcessor> resampled_input, out_unprocessed, output_frames_before_processing); - if (got < 0) { - return got; + if (got < output_frames_before_processing) { + draining = true; + + if (got < 0) { + return got; + } } output_processor->written(got); + input_processor->drop_audio_if_needed(); + /* Process the output. If not enough frames have been returned from the * callback, drain the processors. */ - return output_processor->output(out_buffer, output_frames_needed); + got = output_processor->output(out_buffer, output_frames_needed); + + output_processor->drop_audio_if_needed(); + + return got; } /* Resampler C API */ |