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.

211 lines
5.8KB

  1. // Copyright 2014 Olivier Gillet.
  2. //
  3. // Author: Olivier Gillet (ol.gillet@gmail.com)
  4. //
  5. // Permission is hereby granted, free of charge, to any person obtaining a copy
  6. // of this software and associated documentation files (the "Software"), to deal
  7. // in the Software without restriction, including without limitation the rights
  8. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. // copies of the Software, and to permit persons to whom the Software is
  10. // furnished to do so, subject to the following conditions:
  11. //
  12. // The above copyright notice and this permission notice shall be included in
  13. // all copies or substantial portions of the Software.
  14. //
  15. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  21. // THE SOFTWARE.
  22. //
  23. // See http://creativecommons.org/licenses/MIT/ for more information.
  24. //
  25. // -----------------------------------------------------------------------------
  26. //
  27. // STFT with overlap-add.
  28. #include "clouds/dsp/pvoc/stft.h"
  29. #include <algorithm>
  30. #include "clouds/dsp/pvoc/frame_transformation.h"
  31. #include "stmlib/dsp/dsp.h"
  32. namespace clouds {
  33. using namespace std;
  34. using namespace stmlib;
  35. void STFT::Init(
  36. FFT* fft,
  37. size_t fft_size,
  38. size_t hop_size,
  39. float* fft_buffer,
  40. float* ifft_buffer,
  41. const float* window_lut,
  42. short* analysis_synthesis_buffer,
  43. Modifier* modifier) {
  44. fft_size_ = fft_size;
  45. hop_size_ = hop_size;
  46. fft_num_passes_ = 0;
  47. for (size_t t = fft_size; t > 1; t >>= 1) {
  48. ++fft_num_passes_;
  49. }
  50. buffer_size_ = fft_size_ + hop_size_;
  51. fft_ = fft;
  52. #ifdef USE_ARM_FFT
  53. arm_rfft_fast_init_f32(fft_, fft_size);
  54. #else
  55. fft_->Init();
  56. #endif // USE_ARM_FFT
  57. analysis_ = &analysis_synthesis_buffer[0];
  58. synthesis_ = &analysis_synthesis_buffer[buffer_size_];
  59. ifft_in_ = fft_in_ = fft_buffer;
  60. ifft_out_ = fft_out_ = ifft_buffer;
  61. window_ = window_lut;
  62. window_stride_ = LUT_SINE_WINDOW_4096_SIZE / fft_size;
  63. modifier_ = modifier;
  64. parameters_ = NULL;
  65. Reset();
  66. }
  67. void STFT::Reset() {
  68. buffer_ptr_ = 0;
  69. process_ptr_ = (2 * hop_size_) % buffer_size_;
  70. block_size_ = 0;
  71. fill(&analysis_[0], &analysis_[buffer_size_], 0);
  72. fill(&synthesis_[0], &synthesis_[buffer_size_], 0);
  73. ready_ = 0;
  74. done_ = 0;
  75. }
  76. void STFT::Process(
  77. const Parameters& parameters,
  78. const float* input,
  79. float* output,
  80. size_t size,
  81. size_t stride) {
  82. parameters_ = &parameters;
  83. while (size) {
  84. size_t processed = min(size, hop_size_ - block_size_);
  85. for (size_t i = 0; i < processed; ++i) {
  86. int32_t sample = *input * 32768.0f;
  87. analysis_[buffer_ptr_ + i] = Clip16(sample);
  88. *output = static_cast<float>(synthesis_[buffer_ptr_ + i]) / 16384.0f;
  89. input += stride;
  90. output += stride;
  91. }
  92. block_size_ += processed;
  93. size -= processed;
  94. buffer_ptr_ += processed;
  95. if (buffer_ptr_ >= buffer_size_) {
  96. buffer_ptr_ -= buffer_size_;
  97. }
  98. if (block_size_ >= hop_size_) {
  99. block_size_ -= hop_size_;
  100. ++ready_;
  101. }
  102. }
  103. }
  104. void STFT::Buffer() {
  105. if (ready_ == done_) {
  106. return;
  107. }
  108. // Copy block to FFT buffer and apply window.
  109. size_t source_ptr = process_ptr_;
  110. const float* w = window_;
  111. for (size_t i = 0; i < fft_size_; ++i) {
  112. fft_in_[i] = w[0] * analysis_[source_ptr];
  113. ++source_ptr;
  114. if (source_ptr >= buffer_size_) {
  115. source_ptr -= buffer_size_;
  116. }
  117. w += window_stride_;
  118. }
  119. // Compute FFT. fft_in is lost.
  120. #ifdef USE_ARM_FFT
  121. arm_rfft_fast_f32(fft_, fft_in_, fft_out_, 0);
  122. copy(&fft_out_[0], &fft_out_[fft_size_], &fft_in_[0]);
  123. // Re-arrange data.
  124. for (size_t i = 0; i < fft_size_ / 2; ++i) {
  125. fft_out_[i] = fft_in_[2 * i];
  126. fft_out_[i + fft_size_ / 2] = fft_in_[2 * i + 1];
  127. }
  128. #else
  129. if (fft_size_ != FFT::max_size) {
  130. fft_->Direct(fft_in_, fft_out_, fft_num_passes_);
  131. } else {
  132. fft_->Direct(fft_in_, fft_out_);
  133. }
  134. #endif // USE_ARM_FFT
  135. // Process in the frequency domain.
  136. if (modifier_ != NULL && parameters_ != NULL) {
  137. modifier_->Process(*parameters_, &fft_out_[0], &ifft_in_[0]);
  138. } else {
  139. copy(&fft_out_[0], &fft_out_[fft_size_], &ifft_in_[0]);
  140. }
  141. // Compute IFFT. ifft_in is lost.
  142. #ifdef USE_ARM_FFT
  143. // Re-arrange data.
  144. copy(&ifft_in_[0], &ifft_in_[fft_size_], &ifft_out_[0]);
  145. for (size_t i = 0; i < fft_size_ / 2; ++i) {
  146. ifft_in_[2 * i] = ifft_out_[i];
  147. ifft_in_[2 * i + 1] = ifft_out_[i + fft_size_ / 2];
  148. }
  149. arm_rfft_fast_f32(fft_, ifft_in_, ifft_out_, 1);
  150. #else
  151. if (fft_size_ != FFT::max_size) {
  152. fft_->Inverse(ifft_in_, ifft_out_, fft_num_passes_);
  153. } else {
  154. fft_->Inverse(ifft_in_, ifft_out_);
  155. }
  156. #endif // USE_ARM_FFT
  157. size_t destination_ptr = process_ptr_;
  158. #ifdef USE_ARM_FFT
  159. float inverse_window_size = 1.0f / \
  160. float(fft_size_ / hop_size_ >> 1);
  161. #else
  162. float inverse_window_size = 1.0f / \
  163. float(fft_size_ * fft_size_ / hop_size_ >> 1);
  164. #endif // USE_ARM_FFT
  165. w = window_;
  166. for (size_t i = 0; i < fft_size_; ++i) {
  167. float s = ifft_out_[i] * w[0] * inverse_window_size;
  168. int32_t x = static_cast<int32_t>(s);
  169. if (i < fft_size_ - hop_size_) {
  170. // Overlap-add.
  171. x += synthesis_[destination_ptr];
  172. }
  173. synthesis_[destination_ptr] = Clip16(x);
  174. ++destination_ptr;
  175. if (destination_ptr >= buffer_size_) {
  176. destination_ptr -= buffer_size_;
  177. }
  178. w += window_stride_;
  179. }
  180. ++done_;
  181. process_ptr_ += hop_size_;
  182. if (process_ptr_ >= buffer_size_) {
  183. process_ptr_ -= buffer_size_;
  184. }
  185. }
  186. } // namespace clouds