resample.h 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. /**
  2. * Copyright 2013 Pegah Ghahremani
  3. * 2014 IMSL, PKU-HKUST (author: Wei Shi)
  4. * 2014 Yanqing Sun, Junjie Wang
  5. * 2014 Johns Hopkins University (author: Daniel Povey)
  6. * Copyright 2023 Xiaomi Corporation (authors: Fangjun Kuang)
  7. *
  8. * See LICENSE for clarification regarding multiple authors
  9. *
  10. * Licensed under the Apache License, Version 2.0 (the "License");
  11. * you may not use this file except in compliance with the License.
  12. * You may obtain a copy of the License at
  13. *
  14. * http://www.apache.org/licenses/LICENSE-2.0
  15. *
  16. * Unless required by applicable law or agreed to in writing, software
  17. * distributed under the License is distributed on an "AS IS" BASIS,
  18. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  19. * See the License for the specific language governing permissions and
  20. * limitations under the License.
  21. */
  22. // this file is copied and modified from
  23. // kaldi/src/feat/resample.h
  24. #pragma once
  25. #include <cstdint>
  26. #include <vector>
  27. namespace funasr {
  28. /*
  29. We require that the input and output sampling rate be specified as
  30. integers, as this is an easy way to specify that their ratio be rational.
  31. */
  32. class LinearResample {
  33. public:
  34. /// Constructor. We make the input and output sample rates integers, because
  35. /// we are going to need to find a common divisor. This should just remind
  36. /// you that they need to be integers. The filter cutoff needs to be less
  37. /// than samp_rate_in_hz/2 and less than samp_rate_out_hz/2. num_zeros
  38. /// controls the sharpness of the filter, more == sharper but less efficient.
  39. /// We suggest around 4 to 10 for normal use.
  40. LinearResample(int32_t samp_rate_in_hz, int32_t samp_rate_out_hz,
  41. float filter_cutoff_hz, int32_t num_zeros);
  42. /// Calling the function Reset() resets the state of the object prior to
  43. /// processing a new signal; it is only necessary if you have called
  44. /// Resample(x, x_size, false, y) for some signal, leading to a remainder of
  45. /// the signal being called, but then abandon processing the signal before
  46. /// calling Resample(x, x_size, true, y) for the last piece. Call it
  47. /// unnecessarily between signals will not do any harm.
  48. void Reset();
  49. /// This function does the resampling. If you call it with flush == true and
  50. /// you have never called it with flush == false, it just resamples the input
  51. /// signal (it resizes the output to a suitable number of samples).
  52. ///
  53. /// You can also use this function to process a signal a piece at a time.
  54. /// suppose you break it into piece1, piece2, ... pieceN. You can call
  55. /// \code{.cc}
  56. /// Resample(piece1, piece1_size, false, &output1);
  57. /// Resample(piece2, piece2_size, false, &output2);
  58. /// Resample(piece3, piece3_size, true, &output3);
  59. /// \endcode
  60. /// If you call it with flush == false, it won't output the last few samples
  61. /// but will remember them, so that if you later give it a second piece of
  62. /// the input signal it can process it correctly.
  63. /// If your most recent call to the object was with flush == false, it will
  64. /// have internal state; you can remove this by calling Reset().
  65. /// Empty input is acceptable.
  66. void Resample(const float *input, int32_t input_dim, bool flush,
  67. std::vector<float> *output);
  68. //// Return the input and output sampling rates (for checks, for example)
  69. int32_t GetInputSamplingRate() const { return samp_rate_in_; }
  70. int32_t GetOutputSamplingRate() const { return samp_rate_out_; }
  71. private:
  72. void SetIndexesAndWeights();
  73. float FilterFunc(float) const;
  74. /// This function outputs the number of output samples we will output
  75. /// for a signal with "input_num_samp" input samples. If flush == true,
  76. /// we return the largest n such that
  77. /// (n/samp_rate_out_) is in the interval [ 0, input_num_samp/samp_rate_in_ ),
  78. /// and note that the interval is half-open. If flush == false,
  79. /// define window_width as num_zeros / (2.0 * filter_cutoff_);
  80. /// we return the largest n such that (n/samp_rate_out_) is in the interval
  81. /// [ 0, input_num_samp/samp_rate_in_ - window_width ).
  82. int64_t GetNumOutputSamples(int64_t input_num_samp, bool flush) const;
  83. /// Given an output-sample index, this function outputs to *first_samp_in the
  84. /// first input-sample index that we have a weight on (may be negative),
  85. /// and to *samp_out_wrapped the index into weights_ where we can get the
  86. /// corresponding weights on the input.
  87. inline void GetIndexes(int64_t samp_out, int64_t *first_samp_in,
  88. int32_t *samp_out_wrapped) const;
  89. void SetRemainder(const float *input, int32_t input_dim);
  90. private:
  91. // The following variables are provided by the user.
  92. int32_t samp_rate_in_;
  93. int32_t samp_rate_out_;
  94. float filter_cutoff_;
  95. int32_t num_zeros_;
  96. int32_t input_samples_in_unit_; ///< The number of input samples in the
  97. ///< smallest repeating unit: num_samp_in_ =
  98. ///< samp_rate_in_hz / Gcd(samp_rate_in_hz,
  99. ///< samp_rate_out_hz)
  100. int32_t output_samples_in_unit_; ///< The number of output samples in the
  101. ///< smallest repeating unit: num_samp_out_
  102. ///< = samp_rate_out_hz /
  103. ///< Gcd(samp_rate_in_hz, samp_rate_out_hz)
  104. /// The first input-sample index that we sum over, for this output-sample
  105. /// index. May be negative; any truncation at the beginning is handled
  106. /// separately. This is just for the first few output samples, but we can
  107. /// extrapolate the correct input-sample index for arbitrary output samples.
  108. std::vector<int32_t> first_index_;
  109. /// Weights on the input samples, for this output-sample index.
  110. std::vector<std::vector<float>> weights_;
  111. // the following variables keep track of where we are in a particular signal,
  112. // if it is being provided over multiple calls to Resample().
  113. int64_t input_sample_offset_; ///< The number of input samples we have
  114. ///< already received for this signal
  115. ///< (including anything in remainder_)
  116. int64_t output_sample_offset_; ///< The number of samples we have already
  117. ///< output for this signal.
  118. std::vector<float> input_remainder_; ///< A small trailing part of the
  119. ///< previously seen input signal.
  120. };
  121. } // namespace funasr