1 /* ----------------------------------------------------------------------
2  * Project:      CMSIS DSP Library
3  * Title:        arm_mfcc_f32.c
4  * Description:  MFCC function for the f32 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 
29 
30 
31 #include "dsp/transform_functions.h"
32 #include "dsp/statistics_functions.h"
33 #include "dsp/basic_math_functions.h"
34 #include "dsp/complex_math_functions.h"
35 #include "dsp/fast_math_functions.h"
36 #include "dsp/matrix_functions.h"
37 
38 /**
39   @ingroup MFCC
40  */
41 
42 
43 
44 /**
45   @addtogroup MFCCF32
46   @{
47  */
48 
49 /**
50   @brief         MFCC F32
51   @param[in]    S       points to the mfcc instance structure
52   @param[in]     pSrc points to the input samples
53   @param[out]     pDst  points to the output MFCC values
54   @param[inout]     pTmp  points to a temporary buffer of complex
55 
56   @par           Description
57                    The number of input samples if the FFT length used
58                    when initializing the instance data structure.
59 
60                    The temporary buffer has a 2*fft length size when MFCC
61                    is implemented with CFFT.
62                    It has length FFT Length + 2 when implemented with RFFT
63                    (default implementation).
64 
65                    The source buffer is modified by this function.
66 
67  */
arm_mfcc_f32(const arm_mfcc_instance_f32 * S,float32_t * pSrc,float32_t * pDst,float32_t * pTmp)68 void arm_mfcc_f32(
69   const arm_mfcc_instance_f32 * S,
70   float32_t *pSrc,
71   float32_t *pDst,
72   float32_t *pTmp
73   )
74 {
75   float32_t maxValue;
76   uint32_t  index;
77   uint32_t i;
78   float32_t result;
79   const float32_t *coefs=S->filterCoefs;
80   arm_matrix_instance_f32 pDctMat;
81 
82   /* Normalize */
83   arm_absmax_f32(pSrc,S->fftLen,&maxValue,&index);
84 
85   if (maxValue != 0.0f)
86   {
87      arm_scale_f32(pSrc,1.0f/maxValue,pSrc,S->fftLen);
88   }
89 
90   /* Multiply by window */
91   arm_mult_f32(pSrc,S->windowCoefs,pSrc,S->fftLen);
92 
93   /* Compute spectrum magnitude
94   */
95 #if defined(ARM_MFCC_CFFT_BASED)
96   /* some HW accelerator for CMSIS-DSP used in some boards
97      are only providing acceleration for CFFT.
98      With ARM_MFCC_CFFT_BASED enabled, CFFT is used and the MFCC
99      will be accelerated on those boards.
100 
101      The default is to use RFFT
102   */
103   /* Convert from real to complex */
104   for(i=0; i < S->fftLen ; i++)
105   {
106     pTmp[2*i] = pSrc[i];
107     pTmp[2*i+1] = 0.0f;
108   }
109   arm_cfft_f32(&(S->cfft),pTmp,0,1);
110 #else
111   /* Default RFFT based implementation */
112   arm_rfft_fast_f32(&(S->rfft),pSrc,pTmp,0);
113   /* Unpack real values */
114   pTmp[S->fftLen]=pTmp[1];
115   pTmp[S->fftLen+1]=0.0f;
116   pTmp[1]=0.0f;
117 #endif
118   arm_cmplx_mag_f32(pTmp,pSrc,S->fftLen);
119   if (maxValue != 0.0f)
120   {
121      arm_scale_f32(pSrc,maxValue,pSrc,S->fftLen);
122   }
123 
124   /* Apply MEL filters */
125   for(i=0; i<S->nbMelFilters; i++)
126   {
127       arm_dot_prod_f32(pSrc+S->filterPos[i],
128         coefs,
129         S->filterLengths[i],
130         &result);
131 
132       coefs += S->filterLengths[i];
133 
134       pTmp[i] = result;
135 
136   }
137 
138   /* Compute the log */
139   arm_offset_f32(pTmp,1.0e-6f,pTmp,S->nbMelFilters);
140   arm_vlog_f32(pTmp,pTmp,S->nbMelFilters);
141 
142   /* Multiply with the DCT matrix */
143 
144   pDctMat.numRows=S->nbDctOutputs;
145   pDctMat.numCols=S->nbMelFilters;
146   pDctMat.pData=(float32_t*)S->dctCoefs;
147 
148   arm_mat_vec_mult_f32(&pDctMat, pTmp, pDst);
149 
150 
151 }
152 
153 /**
154   @} end of MFCCF32 group
155  */
156