diff options
author | Paul Adenot <[email protected]> | 2016-02-02 18:43:27 +0100 |
---|---|---|
committer | Paul Adenot <[email protected]> | 2016-02-06 06:29:24 +0100 |
commit | 0def655163768ff1fc0990473ce79796451b3374 (patch) | |
tree | 9b8bfa7a03922fae24ae4c40b76b8ad274b4f25d /src/cubeb_resampler_internal.h | |
parent | a7c662062d07ffa62894e46c542e778f10ac420b (diff) | |
download | cubeb-0def655163768ff1fc0990473ce79796451b3374.tar.gz cubeb-0def655163768ff1fc0990473ce79796451b3374.zip |
Make the resampler handle two opposite streams.
A duplex resampler takes two audio streams (one input and output), with
potentially different sample-rate, and a target rate. It calls back
using the data callback, deliverying input frames at the target rate,
along with a buffer that can be filled with the same number of output
frames at target_rate.
When resampling only one side, a delay line is inserted in the opposite
direction to keep as much synchronization as possible, sacrificing a few
frames of latency. This can help acoustic echo cancelation algorithms.
This is to replace a seemingly no-op resampler, that would end up being
more expensive.
The input rate is the rate of the platform level input stream, i.e. the
sample-rate at which the audio is delivered to cubeb. The output rate is
the rate of the output stream, i.e. the rate at which cubeb should
deliver the audio to the platform API. The target rate is the rate that
was asked for by the user when calling `cubeb_stream_init`.
Consequently, the audio flows like this, where ir and or are input and
output rate, and tr is the target rate:
Platform API --- Input Audio Buffer ---> Duplex Resampler ----.
ir input resampling |
ir -> tr |
prepare output audio
buffer at tr
|
cubeb_data_callback
input and output
buffers at tr
|
|
Platform API <--- Output Audio Buffer --- Duplex Resampler <--`
or output resampling
tr -> or
The configuration of the processing pipeline is done using
template-based static polymorphism and function pointers.
Diffstat (limited to 'src/cubeb_resampler_internal.h')
-rw-r--r-- | src/cubeb_resampler_internal.h | 58 |
1 files changed, 57 insertions, 1 deletions
diff --git a/src/cubeb_resampler_internal.h b/src/cubeb_resampler_internal.h index 3cef4cd..7be7871 100644 --- a/src/cubeb_resampler_internal.h +++ b/src/cubeb_resampler_internal.h @@ -76,6 +76,53 @@ protected: const uint32_t channels; }; +/** Bidirectional resampler, can resample an input and an output stream, or just + * an input stream or output stream. In this case a delay is inserted in the + * opposite direction to keep the streams synchronized. */ +template<typename T, typename InputProcessing, typename OutputProcessing> +class cubeb_resampler_speex : public cubeb_resampler { +public: + cubeb_resampler_speex(InputProcessing * input_processor, + OutputProcessing * output_processor, + cubeb_stream * s, + cubeb_data_callback cb, + void * ptr); + + virtual ~cubeb_resampler_speex(); + + virtual long fill(void * input_buffer, long * input_frames_count, + void * output_buffer, long output_frames_needed); + + virtual long latency() + { + if (input_processor && output_processor) { + assert(input_processor->latency() == output_processor->latency()); + return input_processor->latency(); + } else if (input_processor) { + return input_processor->latency(); + } else { + return output_processor->latency(); + } + } + +private: + typedef long(cubeb_resampler_speex::*processing_callback)(T * input_buffer, long * input_frames_count, T * output_buffer, long output_frames_needed); + + long fill_internal_duplex(T * input_buffer, long * input_frames_count, + T * output_buffer, long output_frames_needed); + long fill_internal_input(T * input_buffer, long * input_frames_count, + T * output_buffer, long output_frames_needed); + long fill_internal_output(T * input_buffer, long * input_frames_count, + T * output_buffer, long output_frames_needed); + + auto_ptr<InputProcessing> input_processor; + auto_ptr<OutputProcessing> output_processor; + processing_callback fill_internal; + cubeb_stream * const stream; + const cubeb_data_callback data_callback; + void * const user_ptr; +}; + /** Handles one way of a (possibly) duplex resampler, working on interleaved * audio buffers of type T. This class is designed so that the number of frames * coming out of the resampler can be precisely controled. It manages its own @@ -170,7 +217,7 @@ public: speex_resample(resampling_in_buffer.data(), &in_len, resampling_out_buffer.data(), &out_len); - assert(out_len == output_frame_count); + assert(out_len == output_frame_count ); /* This shifts back any unresampled samples to the beginning of the input buffer. */ @@ -197,6 +244,12 @@ public: - resampling_in_buffer.length() / channels; } + /** Returns the number of frames that can be produced from `input_frames` frames. */ + uint32_t output_for_input(uint32_t input_frames) + { + return (input_frames / resampling_ratio); + } + /** Returns a pointer to the input buffer, that contains empty space for at * least `frame_count` elements. This is useful so that consumer can directly * write into the input buffer of the resampler. The pointer returned is @@ -326,6 +379,9 @@ public: { return frames_needed; } + size_t output_for_input(uint32_t input_frames) { + return input_frames; + } /** The number of frames this delay line delays the stream by. * @returns The number of frames of delay. */ size_t latency() |