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.

128 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. FeaturePipeline::FeaturePipeline(const FeaturePipelineConfig& config)
  19. : config_(config),
  20. feature_dim_(config.num_bins),
  21. fbank_(config.num_bins, config.sample_rate, config.frame_length,
  22. config.frame_shift, config.low_freq, config.pre_emphasis,
  23. config.scale_input_to_unit, config.log_floor, config.log_base,
  24. config.window_type, config.mel_type, config.norm_type),
  25. num_frames_(0),
  26. input_finished_(false) {}
  27. void FeaturePipeline::AcceptWaveform(const float* pcm, const int size) {
  28. std::vector<std::vector<float>> feats;
  29. std::vector<float> waves;
  30. waves.insert(waves.end(), remained_wav_.begin(), remained_wav_.end());
  31. waves.insert(waves.end(), pcm, pcm + size);
  32. int num_frames = fbank_.Compute(waves, &feats);
  33. feature_queue_.Push(std::move(feats));
  34. num_frames_ += num_frames;
  35. int left_samples = waves.size() - config_.frame_shift * num_frames;
  36. remained_wav_.resize(left_samples);
  37. std::copy(waves.begin() + config_.frame_shift * num_frames, waves.end(),
  38. remained_wav_.begin());
  39. // We are still adding wave, notify input is not finished
  40. finish_condition_.notify_one();
  41. }
  42. void FeaturePipeline::AcceptWaveform(const int16_t* pcm, const int size) {
  43. auto* float_pcm = new float[size];
  44. for (size_t i = 0; i < size; i++) {
  45. float_pcm[i] = static_cast<float>(pcm[i]);
  46. }
  47. this->AcceptWaveform(float_pcm, size);
  48. delete[] float_pcm;
  49. }
  50. void FeaturePipeline::set_input_finished() {
  51. CHECK(!input_finished_);
  52. {
  53. std::lock_guard<std::mutex> lock(mutex_);
  54. input_finished_ = true;
  55. }
  56. finish_condition_.notify_one();
  57. }
  58. bool FeaturePipeline::ReadOne(std::vector<float>* feat) {
  59. if (!feature_queue_.Empty()) {
  60. *feat = std::move(feature_queue_.Pop());
  61. return true;
  62. } else {
  63. std::unique_lock<std::mutex> lock(mutex_);
  64. while (!input_finished_) {
  65. // This will release the lock and wait for notify_one()
  66. // from AcceptWaveform() or set_input_finished()
  67. finish_condition_.wait(lock);
  68. if (!feature_queue_.Empty()) {
  69. *feat = std::move(feature_queue_.Pop());
  70. return true;
  71. }
  72. }
  73. CHECK(input_finished_);
  74. // Double check queue.empty, see issue#893 for detailed discussions.
  75. if (!feature_queue_.Empty()) {
  76. *feat = std::move(feature_queue_.Pop());
  77. return true;
  78. } else {
  79. return false;
  80. }
  81. }
  82. }
  83. bool FeaturePipeline::Read(int num_frames,
  84. std::vector<std::vector<float>>* feats) {
  85. feats->clear();
  86. if (feature_queue_.Size() >= num_frames) {
  87. *feats = std::move(feature_queue_.Pop(num_frames));
  88. return true;
  89. } else {
  90. std::unique_lock<std::mutex> lock(mutex_);
  91. while (!input_finished_) {
  92. // This will release the lock and wait for notify_one()
  93. // from AcceptWaveform() or set_input_finished()
  94. finish_condition_.wait(lock);
  95. if (feature_queue_.Size() >= num_frames) {
  96. *feats = std::move(feature_queue_.Pop(num_frames));
  97. return true;
  98. }
  99. }
  100. CHECK(input_finished_);
  101. // Double check queue.empty, see issue#893 for detailed discussions.
  102. if (feature_queue_.Size() >= num_frames) {
  103. *feats = std::move(feature_queue_.Pop(num_frames));
  104. return true;
  105. } else {
  106. *feats = std::move(feature_queue_.Pop(feature_queue_.Size()));
  107. return false;
  108. }
  109. }
  110. }
  111. void FeaturePipeline::Reset() {
  112. input_finished_ = false;
  113. num_frames_ = 0;
  114. remained_wav_.clear();
  115. feature_queue_.Clear();
  116. }
  117. } // namespace wenet