common.cpp 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. //-----------------------------------------------------------------------------
  2. // Copyright 2012 Masanori Morise
  3. // Author: mmorise [at] yamanashi.ac.jp (Masanori Morise)
  4. // Last update: 2017/04/29
  5. //
  6. // common.cpp includes functions used in at least two files.
  7. // (1) Common functions
  8. // (2) FFT, IFFT and minimum phase analysis.
  9. //
  10. // In FFT analysis and minimum phase analysis,
  11. // Functions "Initialize*()" allocate the mamory.
  12. // Functions "Destroy*()" free the accolated memory.
  13. // FFT size is used for initialization, and structs are used to keep the memory.
  14. // Functions "GetMinimumPhaseSpectrum()" calculate minimum phase spectrum.
  15. // Forward and inverse FFT do not have the function "Get*()",
  16. // because forward FFT and inverse FFT can run in one step.
  17. //
  18. //-----------------------------------------------------------------------------
  19. #include "world/common.h"
  20. #include <math.h>
  21. #include "world/constantnumbers.h"
  22. #include "world/matlabfunctions.h"
  23. namespace {
  24. static void SetParametersForLinearSmoothing(int boundary, int fft_size, int fs,
  25. double width, const double *power_spectrum, double *mirroring_spectrum,
  26. double *mirroring_segment, double *frequency_axis) {
  27. for (int i = 0; i < boundary; ++i)
  28. mirroring_spectrum[i] = power_spectrum[boundary - i];
  29. for (int i = boundary; i < fft_size / 2 + boundary; ++i)
  30. mirroring_spectrum[i] = power_spectrum[i - boundary];
  31. for (int i = fft_size / 2 + boundary; i <= fft_size / 2 + boundary * 2; ++i)
  32. mirroring_spectrum[i] =
  33. power_spectrum[fft_size / 2 - (i - (fft_size / 2 + boundary))];
  34. mirroring_segment[0] = mirroring_spectrum[0] * fs / fft_size;
  35. for (int i = 1; i < fft_size / 2 + boundary * 2 + 1; ++i)
  36. mirroring_segment[i] = mirroring_spectrum[i] * fs / fft_size +
  37. mirroring_segment[i - 1];
  38. for (int i = 0; i <= fft_size / 2; ++i)
  39. frequency_axis[i] = static_cast<double>(i) / fft_size *
  40. fs - width / 2.0;
  41. }
  42. } // namespace
  43. //-----------------------------------------------------------------------------
  44. int GetSuitableFFTSize(int sample) {
  45. return static_cast<int>(pow(2.0,
  46. static_cast<int>(log(static_cast<double>(sample)) / world::kLog2) + 1.0));
  47. }
  48. void DCCorrection(const double *input, double f0, int fs, int fft_size,
  49. double *output) {
  50. int upper_limit = 2 + static_cast<int>(f0 * fft_size / fs);
  51. double *low_frequency_replica = new double[upper_limit];
  52. double *low_frequency_axis = new double[upper_limit];
  53. for (int i = 0; i < upper_limit; ++i)
  54. low_frequency_axis[i] = static_cast<double>(i) * fs / fft_size;
  55. int upper_limit_replica = upper_limit - 1;
  56. interp1Q(f0 - low_frequency_axis[0],
  57. -static_cast<double>(fs) / fft_size, input, upper_limit + 1,
  58. low_frequency_axis, upper_limit_replica, low_frequency_replica);
  59. for (int i = 0; i < upper_limit_replica; ++i)
  60. output[i] = input[i] + low_frequency_replica[i];
  61. delete[] low_frequency_replica;
  62. delete[] low_frequency_axis;
  63. }
  64. void LinearSmoothing(const double *input, double width, int fs, int fft_size,
  65. double *output) {
  66. int boundary = static_cast<int>(width * fft_size / fs) + 1;
  67. // These parameters are set by the other function.
  68. double *mirroring_spectrum = new double[fft_size / 2 + boundary * 2 + 1];
  69. double *mirroring_segment = new double[fft_size / 2 + boundary * 2 + 1];
  70. double *frequency_axis = new double[fft_size / 2 + 1];
  71. SetParametersForLinearSmoothing(boundary, fft_size, fs, width,
  72. input, mirroring_spectrum, mirroring_segment, frequency_axis);
  73. double *low_levels = new double[fft_size / 2 + 1];
  74. double *high_levels = new double[fft_size / 2 + 1];
  75. double origin_of_mirroring_axis = -(boundary - 0.5) * fs / fft_size;
  76. double discrete_frequency_interval = static_cast<double>(fs) / fft_size;
  77. interp1Q(origin_of_mirroring_axis, discrete_frequency_interval,
  78. mirroring_segment, fft_size / 2 + boundary * 2 + 1, frequency_axis,
  79. fft_size / 2 + 1, low_levels);
  80. for (int i = 0; i <= fft_size / 2; ++i) frequency_axis[i] += width;
  81. interp1Q(origin_of_mirroring_axis, discrete_frequency_interval,
  82. mirroring_segment, fft_size / 2 + boundary * 2 + 1, frequency_axis,
  83. fft_size / 2 + 1, high_levels);
  84. for (int i = 0; i <= fft_size / 2; ++i)
  85. output[i] = (high_levels[i] - low_levels[i]) / width;
  86. delete[] mirroring_spectrum;
  87. delete[] mirroring_segment;
  88. delete[] frequency_axis;
  89. delete[] low_levels;
  90. delete[] high_levels;
  91. }
  92. void NuttallWindow(int y_length, double *y) {
  93. double tmp;
  94. for (int i = 0; i < y_length; ++i) {
  95. tmp = i / (y_length - 1.0);
  96. y[i] = 0.355768 - 0.487396 * cos(2.0 * world::kPi * tmp) +
  97. 0.144232 * cos(4.0 * world::kPi * tmp) -
  98. 0.012604 * cos(6.0 * world::kPi * tmp);
  99. }
  100. }
  101. //-----------------------------------------------------------------------------
  102. // FFT, IFFT and minimum phase analysis
  103. void InitializeForwardRealFFT(int fft_size, ForwardRealFFT *forward_real_fft) {
  104. forward_real_fft->fft_size = fft_size;
  105. forward_real_fft->waveform = new double[fft_size];
  106. forward_real_fft->spectrum = new fft_complex[fft_size];
  107. forward_real_fft->forward_fft = fft_plan_dft_r2c_1d(fft_size,
  108. forward_real_fft->waveform, forward_real_fft->spectrum, FFT_ESTIMATE);
  109. }
  110. void DestroyForwardRealFFT(ForwardRealFFT *forward_real_fft) {
  111. fft_destroy_plan(forward_real_fft->forward_fft);
  112. delete[] forward_real_fft->spectrum;
  113. delete[] forward_real_fft->waveform;
  114. }
  115. void InitializeInverseRealFFT(int fft_size, InverseRealFFT *inverse_real_fft) {
  116. inverse_real_fft->fft_size = fft_size;
  117. inverse_real_fft->waveform = new double[fft_size];
  118. inverse_real_fft->spectrum = new fft_complex[fft_size];
  119. inverse_real_fft->inverse_fft = fft_plan_dft_c2r_1d(fft_size,
  120. inverse_real_fft->spectrum, inverse_real_fft->waveform, FFT_ESTIMATE);
  121. }
  122. void DestroyInverseRealFFT(InverseRealFFT *inverse_real_fft) {
  123. fft_destroy_plan(inverse_real_fft->inverse_fft);
  124. delete[] inverse_real_fft->spectrum;
  125. delete[] inverse_real_fft->waveform;
  126. }
  127. void InitializeInverseComplexFFT(int fft_size,
  128. InverseComplexFFT *inverse_complex_fft) {
  129. inverse_complex_fft->fft_size = fft_size;
  130. inverse_complex_fft->input = new fft_complex[fft_size];
  131. inverse_complex_fft->output = new fft_complex[fft_size];
  132. inverse_complex_fft->inverse_fft = fft_plan_dft_1d(fft_size,
  133. inverse_complex_fft->input, inverse_complex_fft->output,
  134. FFT_BACKWARD, FFT_ESTIMATE);
  135. }
  136. void DestroyInverseComplexFFT(InverseComplexFFT *inverse_complex_fft) {
  137. fft_destroy_plan(inverse_complex_fft->inverse_fft);
  138. delete[] inverse_complex_fft->input;
  139. delete[] inverse_complex_fft->output;
  140. }
  141. void InitializeMinimumPhaseAnalysis(int fft_size,
  142. MinimumPhaseAnalysis *minimum_phase) {
  143. minimum_phase->fft_size = fft_size;
  144. minimum_phase->log_spectrum = new double[fft_size];
  145. minimum_phase->minimum_phase_spectrum = new fft_complex[fft_size];
  146. minimum_phase->cepstrum = new fft_complex[fft_size];
  147. minimum_phase->inverse_fft = fft_plan_dft_r2c_1d(fft_size,
  148. minimum_phase->log_spectrum, minimum_phase->cepstrum, FFT_ESTIMATE);
  149. minimum_phase->forward_fft = fft_plan_dft_1d(fft_size,
  150. minimum_phase->cepstrum, minimum_phase->minimum_phase_spectrum,
  151. FFT_FORWARD, FFT_ESTIMATE);
  152. }
  153. void GetMinimumPhaseSpectrum(const MinimumPhaseAnalysis *minimum_phase) {
  154. // Mirroring
  155. for (int i = minimum_phase->fft_size / 2 + 1;
  156. i < minimum_phase->fft_size; ++i)
  157. minimum_phase->log_spectrum[i] =
  158. minimum_phase->log_spectrum[minimum_phase->fft_size - i];
  159. // This fft_plan carries out "forward" FFT.
  160. // To carriy out the Inverse FFT, the sign of imaginary part
  161. // is inverted after FFT.
  162. fft_execute(minimum_phase->inverse_fft);
  163. minimum_phase->cepstrum[0][1] *= -1.0;
  164. for (int i = 1; i < minimum_phase->fft_size / 2; ++i) {
  165. minimum_phase->cepstrum[i][0] *= 2.0;
  166. minimum_phase->cepstrum[i][1] *= -2.0;
  167. }
  168. minimum_phase->cepstrum[minimum_phase->fft_size / 2][1] *= -1.0;
  169. for (int i = minimum_phase->fft_size / 2 + 1;
  170. i < minimum_phase->fft_size; ++i) {
  171. minimum_phase->cepstrum[i][0] = 0.0;
  172. minimum_phase->cepstrum[i][1] = 0.0;
  173. }
  174. fft_execute(minimum_phase->forward_fft);
  175. // Since x is complex number, calculation of exp(x) is as following.
  176. // Note: This FFT library does not keep the aliasing.
  177. double tmp;
  178. for (int i = 0; i <= minimum_phase->fft_size / 2; ++i) {
  179. tmp = exp(minimum_phase->minimum_phase_spectrum[i][0] /
  180. minimum_phase->fft_size);
  181. minimum_phase->minimum_phase_spectrum[i][0] = tmp *
  182. cos(minimum_phase->minimum_phase_spectrum[i][1] /
  183. minimum_phase->fft_size);
  184. minimum_phase->minimum_phase_spectrum[i][1] = tmp *
  185. sin(minimum_phase->minimum_phase_spectrum[i][1] /
  186. minimum_phase->fft_size);
  187. }
  188. }
  189. void DestroyMinimumPhaseAnalysis(MinimumPhaseAnalysis *minimum_phase) {
  190. fft_destroy_plan(minimum_phase->forward_fft);
  191. fft_destroy_plan(minimum_phase->inverse_fft);
  192. delete[] minimum_phase->cepstrum;
  193. delete[] minimum_phase->log_spectrum;
  194. delete[] minimum_phase->minimum_phase_spectrum;
  195. }
  196. float interp_linear(float *x, float *y, int nx, float ref) {
  197. int i;
  198. for (i = 0; i < nx - 1; i++) {
  199. if (ref >= x[i] && ref <= x[i + 1]) {
  200. float x1 = x[i];
  201. float x2 = x[i + 1];
  202. float tmp = (ref - x1) / (x2 - x1);
  203. return y[i] * (1 - tmp) + y[i + 1] * tmp;
  204. }
  205. }
  206. }