aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/cubeb_resampler_internal.h
diff options
context:
space:
mode:
authorPaul Adenot <[email protected]>2016-02-02 18:43:27 +0100
committerPaul Adenot <[email protected]>2016-02-06 06:29:24 +0100
commit0def655163768ff1fc0990473ce79796451b3374 (patch)
tree9b8bfa7a03922fae24ae4c40b76b8ad274b4f25d /src/cubeb_resampler_internal.h
parenta7c662062d07ffa62894e46c542e778f10ac420b (diff)
downloadcubeb-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.h58
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()