Roc Toolkit internal modules
Roc Toolkit: real-time audio streaming
builtin_resampler.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015 Roc Streaming authors
3  *
4  * This Source Code Form is subject to the terms of the Mozilla Public
5  * License, v. 2.0. If a copy of the MPL was not distributed with this
6  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
7  */
8 
9 //! @file roc_audio/builtin_resampler.h
10 //! @brief Built-in resampler.
11 
12 #ifndef ROC_AUDIO_BUILTIN_RESAMPLER_H_
13 #define ROC_AUDIO_BUILTIN_RESAMPLER_H_
14 
15 #include "roc_audio/frame.h"
18 #include "roc_audio/iresampler.h"
20 #include "roc_audio/sample.h"
21 #include "roc_audio/sample_spec.h"
22 #include "roc_core/array.h"
23 #include "roc_core/noncopyable.h"
24 #include "roc_core/slice.h"
25 #include "roc_core/stddefs.h"
26 #include "roc_packet/units.h"
27 
28 namespace roc {
29 namespace audio {
30 
31 //! Built-in resampler.
32 //!
33 //! Resamples audio stream with non-integer dynamically changing factor.
34 //! Implements bandlimited interpolation from this paper:
35 //! https://ccrma.stanford.edu/~jos/resample/resample.pdf
36 //!
37 //! This backend is quite CPU-hungry, but it maintains requested scaling
38 //! factor with very high precision.
39 class BuiltinResampler : public IResampler, public core::NonCopyable<> {
40 public:
41  //! Initialize.
43  FrameFactory& frame_factory,
44  ResamplerProfile profile,
45  const SampleSpec& in_spec,
46  const SampleSpec& out_spec);
47 
49 
50  //! Check if object is successfully constructed.
51  virtual bool is_valid() const;
52 
53  //! Set new resample factor.
54  //! @remarks
55  //! Resampling algorithm needs some window of input samples. The length of the window
56  //! (length of sinc impulse response) is a compromise between SNR and speed. It
57  //! depends on current resampling factor. So we choose length of input buffers to let
58  //! it handle maximum length of input. If new scaling factor breaks equation this
59  //! function returns false.
60  virtual bool set_scaling(size_t input_rate, size_t output_rate, float multiplier);
61 
62  //! Get buffer to be filled with input data.
64 
65  //! Commit buffer with input data.
66  virtual void end_push_input();
67 
68  //! Read samples from input frame and fill output frame.
69  virtual size_t pop_output(sample_t* out_data, size_t out_size);
70 
71  //! How many samples were pushed but not processed yet.
72  virtual float n_left_to_process() const;
73 
74 private:
75  typedef uint32_t fixedpoint_t;
76  typedef uint64_t long_fixedpoint_t;
77  typedef int32_t signed_fixedpoint_t;
78  typedef int64_t signed_long_fixedpoint_t;
79 
80  inline size_t channelize_index(const size_t i, const size_t ch_offset) const {
81  return i * in_spec_.num_channels() + ch_offset;
82  }
83 
84  bool alloc_frames_(FrameFactory& frame_factory);
85 
86  bool check_config_() const;
87 
88  bool fill_sinc_();
89  sample_t sinc_(fixedpoint_t x, float fract_x);
90 
91  // Computes single sample of the particular audio channel.
92  // channel_offset a serial number of the channel
93  // (e.g. left -- 0, right -- 1, etc.).
94  sample_t resample_(size_t channel_offset);
95 
96  const SampleSpec in_spec_;
97  const SampleSpec out_spec_;
98 
99  core::Slice<sample_t> frames_[3];
100  size_t n_ready_frames_;
101 
102  const sample_t* prev_frame_;
103  const sample_t* curr_frame_;
104  const sample_t* next_frame_;
105 
106  float scaling_;
107 
108  const size_t window_size_;
109  const fixedpoint_t qt_half_sinc_window_size_;
110 
111  const size_t window_interp_;
112  const size_t window_interp_bits_;
113 
114  const size_t frame_size_ch_;
115  const size_t frame_size_;
116 
117  core::Array<sample_t> sinc_table_;
118  const sample_t* sinc_table_ptr_;
119 
120  // half window len in Q8.24 in terms of input signal
121  fixedpoint_t qt_half_window_size_;
122  const fixedpoint_t qt_epsilon_;
123 
124  const fixedpoint_t qt_frame_size_;
125 
126  // time position of output sample in terms of input samples indexes
127  // for example 0 -- time position of first sample in curr_frame_
128  fixedpoint_t qt_sample_;
129 
130  // time distance between two output samples, equals to resampling factor
131  fixedpoint_t qt_dt_;
132 
133  // the step with which we iterate over the sinc_table_
134  fixedpoint_t qt_sinc_step_;
135 
136  const sample_t cutoff_freq_;
137 
138  bool valid_;
139 };
140 
141 } // namespace audio
142 } // namespace roc
143 
144 #endif // ROC_AUDIO_BUILTIN_RESAMPLER_H_
Dynamic array.
virtual void end_push_input()
Commit buffer with input data.
virtual bool set_scaling(size_t input_rate, size_t output_rate, float multiplier)
Set new resample factor.
virtual size_t pop_output(sample_t *out_data, size_t out_size)
Read samples from input frame and fill output frame.
BuiltinResampler(core::IArena &arena, FrameFactory &frame_factory, ResamplerProfile profile, const SampleSpec &in_spec, const SampleSpec &out_spec)
Initialize.
virtual float n_left_to_process() const
How many samples were pushed but not processed yet.
virtual bool is_valid() const
Check if object is successfully constructed.
virtual const core::Slice< sample_t > & begin_push_input()
Get buffer to be filled with input data.
Audio writer interface.
Definition: iresampler.h:24
Sample specification. Describes sample rate and channels.
Definition: sample_spec.h:30
size_t num_channels() const
Get number enabled channels in channel set.
IArena & arena() const
Get arena.
Memory arena interface.
Definition: iarena.h:23
Base class for non-copyable objects.
Definition: noncopyable.h:23
Audio frame.
Frame factory.
Frame reader interface.
Audio resampler interface.
float sample_t
Raw audio sample.
Definition: sample.h:22
ResamplerProfile
Resampler parameters presets.
Root namespace.
Non-copyable object.
Resampler config.
Audio sample.
Sample specifications.
Slice.
Commonly used types and functions.
Various units used in packets.