You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

129 lines
4.1 KiB

  1. // Copyright (c) 2017 Personal (Binbin Zhang)
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #include "feature_pipeline.h"
  15. #include <algorithm>
  16. #include <utility>
  17. namespace wenet {
  18. using namespace fst;
  19. FeaturePipeline::FeaturePipeline(const FeaturePipelineConfig& config)
  20. : config_(config),
  21. feature_dim_(config.num_bins),
  22. fbank_(config.num_bins, config.sample_rate, config.frame_length,
  23. config.frame_shift, config.low_freq, config.pre_emphasis,
  24. config.scale_input_to_unit, config.log_floor, config.log_base,
  25. config.window_type, config.mel_type, config.norm_type),
  26. num_frames_(0),
  27. input_finished_(false) {}
  28. void FeaturePipeline::AcceptWaveform(const float* pcm, const int size) {
  29. std::vector<std::vector<float>> feats;
  30. std::vector<float> waves;
  31. waves.insert(waves.end(), remained_wav_.begin(), remained_wav_.end());
  32. waves.insert(waves.end(), pcm, pcm + size);
  33. int num_frames = fbank_.Compute(waves, &feats);
  34. feature_queue_.Push(std::move(feats));
  35. num_frames_ += num_frames;
  36. int left_samples = waves.size() - config_.frame_shift * num_frames;
  37. remained_wav_.resize(left_samples);
  38. std::copy(waves.begin() + config_.frame_shift * num_frames, waves.end(),
  39. remained_wav_.begin());
  40. // We are still adding wave, notify input is not finished
  41. finish_condition_.notify_one();
  42. }
  43. void FeaturePipeline::AcceptWaveform(const int16_t* pcm, const int size) {
  44. auto* float_pcm = new float[size];
  45. for (size_t i = 0; i < size; i++) {
  46. float_pcm[i] = static_cast<float>(pcm[i]);
  47. }
  48. this->AcceptWaveform(float_pcm, size);
  49. delete[] float_pcm;
  50. }
  51. void FeaturePipeline::set_input_finished() {
  52. CHECK(!input_finished_);
  53. {
  54. std::lock_guard<std::mutex> lock(mutex_);
  55. input_finished_ = true;
  56. }
  57. finish_condition_.notify_one();
  58. }
  59. bool FeaturePipeline::ReadOne(std::vector<float>* feat) {
  60. if (!feature_queue_.Empty()) {
  61. *feat = std::move(feature_queue_.Pop());
  62. return true;
  63. } else {
  64. std::unique_lock<std::mutex> lock(mutex_);
  65. while (!input_finished_) {
  66. // This will release the lock and wait for notify_one()
  67. // from AcceptWaveform() or set_input_finished()
  68. finish_condition_.wait(lock);
  69. if (!feature_queue_.Empty()) {
  70. *feat = std::move(feature_queue_.Pop());
  71. return true;
  72. }
  73. }
  74. CHECK(input_finished_);
  75. // Double check queue.empty, see issue#893 for detailed discussions.
  76. if (!feature_queue_.Empty()) {
  77. *feat = std::move(feature_queue_.Pop());
  78. return true;
  79. } else {
  80. return false;
  81. }
  82. }
  83. }
  84. bool FeaturePipeline::Read(int num_frames,
  85. std::vector<std::vector<float>>* feats) {
  86. feats->clear();
  87. if (feature_queue_.Size() >= num_frames) {
  88. *feats = std::move(feature_queue_.Pop(num_frames));
  89. return true;
  90. } else {
  91. std::unique_lock<std::mutex> lock(mutex_);
  92. while (!input_finished_) {
  93. // This will release the lock and wait for notify_one()
  94. // from AcceptWaveform() or set_input_finished()
  95. finish_condition_.wait(lock);
  96. if (feature_queue_.Size() >= num_frames) {
  97. *feats = std::move(feature_queue_.Pop(num_frames));
  98. return true;
  99. }
  100. }
  101. CHECK(input_finished_);
  102. // Double check queue.empty, see issue#893 for detailed discussions.
  103. if (feature_queue_.Size() >= num_frames) {
  104. *feats = std::move(feature_queue_.Pop(num_frames));
  105. return true;
  106. } else {
  107. *feats = std::move(feature_queue_.Pop(feature_queue_.Size()));
  108. return false;
  109. }
  110. }
  111. }
  112. void FeaturePipeline::Reset() {
  113. input_finished_ = false;
  114. num_frames_ = 0;
  115. remained_wav_.clear();
  116. feature_queue_.Clear();
  117. }
  118. } // namespace wenet