blob: 8c5c6bc22309e95edc2e6b4a5ea2601ebd2aae4a [file] [log] [blame]
alexander3c798932021-03-26 21:42:19 +00001/*
Richard Burtonf32a86a2022-11-15 11:46:11 +00002 * SPDX-FileCopyrightText: Copyright 2021 Arm Limited and/or its affiliates <open-source-office@arm.com>
alexander3c798932021-03-26 21:42:19 +00003 * SPDX-License-Identifier: Apache-2.0
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17#include "Wav2LetterMfcc.hpp"
18
19#include <algorithm>
20#include <catch.hpp>
21#include <limits>
22
23/* First 512 samples from itellyou.wav. */
24const std::vector<int16_t> testWav1 = std::vector<int16_t> {
25 -3,0,1,-1,2,3,-2,2,
26 1,-2,0,3,-1,8,3,2,
27 -1,-1,2,7,3,5,6,6,
28 6,12,5,6,3,3,5,4,
29 4,6,7,7,7,3,7,2,
30 8,4,4,2,-4,-1,-1,-4,
31 2,1,-1,-4,0,-7,-6,-2,
32 -5,1,-5,-1,-7,-3,-3,-7,
33 0,-3,3,-5,0,1,-2,-2,
34 -3,-3,-7,-3,-2,-6,-5,-8,
35 -2,-8,4,-9,-4,-9,-5,-5,
36 -3,-9,-3,-9,-1,-7,-4,1,
37 -3,2,-8,-4,-4,-5,1,-3,
38 -1,0,-1,-2,-3,-2,-4,-1,
39 1,-1,3,0,3,2,0,0,
40 0,-3,1,1,0,8,3,4,
41 1,5,6,4,7,3,3,0,
42 3,6,7,6,4,5,9,9,
43 5,5,8,1,6,9,6,6,
44 7,1,8,1,5,0,5,5,
45 0,3,2,7,2,-3,3,0,
46 3,0,0,0,2,0,-1,-1,
47 -2,-3,-8,0,1,0,-3,-3,
48 -3,-2,-3,-3,-4,-6,-2,-8,
49 -9,-4,-1,-5,-3,-3,-4,-3,
50 -6,3,0,-1,-2,-9,-4,-2,
51 2,-1,3,-5,-5,-2,0,-2,
52 0,-1,-3,1,-2,9,4,5,
53 2,2,1,0,-6,-2,0,0,
54 0,-1,4,-4,3,-7,-1,5,
55 -6,-1,-5,4,3,9,-2,1,
56 3,0,0,-2,1,2,1,1,
57 0,3,2,-1,3,-3,7,0,
58 0,3,2,2,-2,3,-2,2,
59 -3,4,-1,-1,-5,-1,-3,-2,
60 1,-1,3,2,4,1,2,-2,
61 0,2,7,0,8,-3,6,-3,
62 6,1,2,-3,-1,-1,-1,1,
63 -2,2,1,2,0,-2,3,-2,
64 3,-2,1,0,-3,-1,-2,-4,
65 -6,-5,-8,-1,-4,0,-3,-1,
66 -1,-1,0,-2,-3,-7,-1,0,
67 1,5,0,5,1,1,-3,0,
68 -6,3,-8,4,-8,6,-6,1,
69 -6,-2,-5,-6,0,-5,4,-1,
70 4,-2,1,2,1,0,-2,0,
71 0,2,-2,2,-5,2,0,-2,
72 1,-2,0,5,1,0,1,5,
73 0,8,3,2,2,0,5,-2,
74 3,1,0,1,0,-2,-1,-3,
75 1,-1,3,0,3,0,-2,-1,
76 -4,-4,-4,-1,-4,-4,-3,-6,
77 -3,-7,-3,-1,-2,0,-5,-4,
78 -7,-3,-2,-2,1,2,2,8,
79 5,4,2,4,3,5,0,3,
80 3,6,4,2,2,-2,4,-2,
81 3,3,2,1,1,4,-5,2,
82 -3,0,-1,1,-2,2,5,1,
83 4,2,3,1,-1,1,0,6,
84 0,-2,-1,1,-1,2,-5,-1,
85 -5,-1,-6,-3,-3,2,4,0,
86 -1,-5,3,-4,-1,-3,-4,1,
87 -4,1,-1,-1,0,-5,-4,-2,
88 -1,-1,-3,-7,-3,-3,4,4,
89};
90
91const std::vector<int16_t> testWav2 = std::vector<int16_t> (512, 0);
92
93/* Golden mfcc output for testwav1. */
94const std::vector<float> golden_mfcc_output_testWav1 {
95 -835.24603, 21.010452, 18.699404, 7.4338417, 19.028961, -5.401735, 6.4761047, -11.400679,
96 8.392709, 12.202361, 8.403276, -13.508412, -18.307348
97};
98
99/* Golden mfcc output for the all zero wav. */
100const std::vector<float> golden_mfcc_output_testWav2 {
101 -1131.37085, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
102};
103
104
105arm::app::audio::Wav2LetterMFCC GetMFCCInstance()
106{
107 const auto sampFreq = arm::app::audio::Wav2LetterMFCC::ms_defaultSamplingFreq;
108 const auto frameLenMs = 32;
109 const auto numMfccFeats = 13;
110 const auto frameLenSamples = sampFreq * frameLenMs * 0.001;
111 return arm::app::audio::Wav2LetterMFCC(numMfccFeats, frameLenSamples);
112}
113
114template <class T>
115void TestQuantisedMFCC()
116{
117 const auto quantScale = 0.1410219967365265;
118 const auto quantOffset = 11;
119 std::vector<T> mfccOutput = GetMFCCInstance().MfccComputeQuant<T>(testWav1, quantScale, quantOffset);
120
121 long min_val = std::numeric_limits<T>::min();
122 long max_val = std::numeric_limits<T>::max();
123
124 for (size_t i = 0; i < golden_mfcc_output_testWav1.size(); i++){
125 long TestWavMfcc = (std::lround((golden_mfcc_output_testWav1[i] / quantScale) + quantOffset));
126 T quantizedTestWavMfcc = static_cast<T>(std::max(min_val, std::min(TestWavMfcc, max_val)));
127
128 REQUIRE(quantizedTestWavMfcc == Approx(mfccOutput[i]).margin(2));
129 }
130}
131
132template void TestQuantisedMFCC<int8_t>();
133template void TestQuantisedMFCC<uint8_t>();
134template void TestQuantisedMFCC<int16_t>();
135
136TEST_CASE("MFCC calculation")
137{
alexander3c798932021-03-26 21:42:19 +0000138 SECTION("FP32")
139 {
140 auto mfccOutput = GetMFCCInstance().MfccCompute(testWav1);
141 REQUIRE_THAT( mfccOutput, Catch::Approx( golden_mfcc_output_testWav1 ).margin(0.3) );
142
143 auto mfccOutput2 = GetMFCCInstance().MfccCompute(testWav2);
144 REQUIRE_THAT( mfccOutput2, Catch::Approx( golden_mfcc_output_testWav2 ).margin(0.001) );
145 }
146
147 SECTION("int8_t")
148 {
149 TestQuantisedMFCC<int8_t>();
150 }
151
152 SECTION("uint8_t")
153 {
154 TestQuantisedMFCC<uint8_t>();
155 }
156
157 SECTION("int16_t")
158 {
159 TestQuantisedMFCC<int16_t>();
160 }
161}