arm_mfcc_q15.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. /* ----------------------------------------------------------------------
  2. * Project: CMSIS DSP Library
  3. * Title: arm_mfcc_q15.c
  4. * Description: MFCC function for the q15 version
  5. *
  6. * $Date: 07 September 2021
  7. * $Revision: V1.10.0
  8. *
  9. * Target Processor: Cortex-M and Cortex-A cores
  10. * -------------------------------------------------------------------- */
  11. /*
  12. * Copyright (C) 2010-2021 ARM Limited or its affiliates. All rights reserved.
  13. *
  14. * SPDX-License-Identifier: Apache-2.0
  15. *
  16. * Licensed under the Apache License, Version 2.0 (the License); you may
  17. * not use this file except in compliance with the License.
  18. * You may obtain a copy of the License at
  19. *
  20. * www.apache.org/licenses/LICENSE-2.0
  21. *
  22. * Unless required by applicable law or agreed to in writing, software
  23. * distributed under the License is distributed on an AS IS BASIS, WITHOUT
  24. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  25. * See the License for the specific language governing permissions and
  26. * limitations under the License.
  27. */
  28. #include "dsp/transform_functions.h"
  29. #include "dsp/statistics_functions.h"
  30. #include "dsp/basic_math_functions.h"
  31. #include "dsp/complex_math_functions.h"
  32. #include "dsp/fast_math_functions.h"
  33. #include "dsp/matrix_functions.h"
  34. /* Constants for Q15 implementation */
  35. #define LOG2TOLOG_Q15 0x02C5C860
  36. #define MICRO_Q15 0x00000219
  37. #define SHIFT_MELFILTER_SATURATION_Q15 10
  38. /**
  39. @ingroup MFCC
  40. */
  41. /**
  42. @addtogroup MFCCQ15
  43. @{
  44. */
  45. /**
  46. @brief MFCC Q15
  47. @param[in] S points to the mfcc instance structure
  48. @param[in] pSrc points to the input samples in Q15
  49. @param[out] pDst points to the output MFCC values in q8.7 format
  50. @param[inout] pTmp points to a temporary buffer of complex
  51. @return error status
  52. @par Description
  53. The number of input samples is the FFT length used
  54. when initializing the instance data structure.
  55. The temporary buffer has a 2*fft length.
  56. The source buffer is modified by this function.
  57. The function may saturate. If the FFT length is too
  58. big and the number of MEL filters too small then the fixed
  59. point computations may saturate.
  60. */
  61. arm_status arm_mfcc_q15(
  62. const arm_mfcc_instance_q15 * S,
  63. q15_t *pSrc,
  64. q15_t *pDst,
  65. q31_t *pTmp
  66. )
  67. {
  68. q15_t m;
  69. uint32_t index;
  70. uint32_t fftShift=0;
  71. q31_t logExponent;
  72. q63_t result;
  73. arm_matrix_instance_q15 pDctMat;
  74. uint32_t i;
  75. uint32_t coefsPos;
  76. uint32_t filterLimit;
  77. q15_t *pTmp2=(q15_t*)pTmp;
  78. arm_status status = ARM_MATH_SUCCESS;
  79. // q15
  80. arm_absmax_q15(pSrc,S->fftLen,&m,&index);
  81. if ((m != 0) && (m != 0x7FFF))
  82. {
  83. q15_t quotient;
  84. int16_t shift;
  85. status = arm_divide_q15(0x7FFF,m,&quotient,&shift);
  86. if (status != ARM_MATH_SUCCESS)
  87. {
  88. return(status);
  89. }
  90. arm_scale_q15(pSrc,quotient,shift,pSrc,S->fftLen);
  91. }
  92. // q15
  93. arm_mult_q15(pSrc,S->windowCoefs, pSrc, S->fftLen);
  94. /* Compute spectrum magnitude
  95. */
  96. fftShift = 31 - __CLZ(S->fftLen);
  97. #if defined(ARM_MFCC_CFFT_BASED)
  98. /* some HW accelerator for CMSIS-DSP used in some boards
  99. are only providing acceleration for CFFT.
  100. With ARM_MFCC_CFFT_BASED enabled, CFFT is used and the MFCC
  101. will be accelerated on those boards.
  102. The default is to use RFFT
  103. */
  104. /* Convert from real to complex */
  105. for(i=0; i < S->fftLen ; i++)
  106. {
  107. pTmp2[2*i] = pSrc[i];
  108. pTmp2[2*i+1] = 0;
  109. }
  110. arm_cfft_q15(&(S->cfft),pTmp2,0,1);
  111. #else
  112. /* Default RFFT based implementation */
  113. arm_rfft_q15(&(S->rfft),pSrc,pTmp2);
  114. #endif
  115. filterLimit = 1 + (S->fftLen >> 1);
  116. // q15 - fftShift
  117. arm_cmplx_mag_q15(pTmp2,pSrc,filterLimit);
  118. // q14 - fftShift
  119. /* Apply MEL filters */
  120. coefsPos = 0;
  121. for(i=0; i<S->nbMelFilters; i++)
  122. {
  123. arm_dot_prod_q15(pSrc+S->filterPos[i],
  124. &(S->filterCoefs[coefsPos]),
  125. S->filterLengths[i],
  126. &result);
  127. coefsPos += S->filterLengths[i];
  128. // q34.29 - fftShift
  129. result += MICRO_Q15;
  130. result >>= SHIFT_MELFILTER_SATURATION_Q15;
  131. // q34.29 - fftShift - satShift
  132. pTmp[i] = __SSAT(result,31) ;
  133. }
  134. if ((m != 0) && (m != 0x7FFF))
  135. {
  136. arm_scale_q31(pTmp,m<<16,0,pTmp,S->nbMelFilters);
  137. }
  138. // q34.29 - fftShift - satShift
  139. /* Compute the log */
  140. arm_vlog_q31(pTmp,pTmp,S->nbMelFilters);
  141. // q5.26
  142. logExponent = fftShift + 2 + SHIFT_MELFILTER_SATURATION_Q15;
  143. logExponent = logExponent * LOG2TOLOG_Q15;
  144. // q8.26
  145. arm_offset_q31(pTmp,logExponent,pTmp,S->nbMelFilters);
  146. arm_shift_q31(pTmp,-19,pTmp,S->nbMelFilters);
  147. for(i=0; i<S->nbMelFilters; i++)
  148. {
  149. pSrc[i] = __SSAT((q15_t)pTmp[i],16);
  150. }
  151. // q8.7
  152. pDctMat.numRows=S->nbDctOutputs;
  153. pDctMat.numCols=S->nbMelFilters;
  154. pDctMat.pData=(q15_t*)S->dctCoefs;
  155. arm_mat_vec_mult_q15(&pDctMat, pSrc, pDst);
  156. return(status);
  157. }
  158. /**
  159. @} end of MFCCQ15 group
  160. */