blob: e88d9327a09a30ce9bd8c160eb0e66ca468525cd [file] [log] [blame]
alexander3c798932021-03-26 21:42:19 +00001/*
Richard Burtonf32a86a2022-11-15 11:46:11 +00002 * SPDX-FileCopyrightText: Copyright 2021-2022 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 "DataStructures.hpp"
18#include "AsrGoldenFeatures.hpp"
alexander3c798932021-03-26 21:42:19 +000019#include "Wav2LetterPreprocess.hpp"
20
alexander31ae9f02022-02-10 16:15:54 +000021#include "log_macros.h"
22
alexander3c798932021-03-26 21:42:19 +000023#include <catch.hpp>
24#include <random>
25
Richard Burtonb40ecf82022-04-22 16:14:57 +010026class TestPreprocess : public arm::app::AsrPreProcess {
alexander3c798932021-03-26 21:42:19 +000027public:
alexander3c798932021-03-26 21:42:19 +000028
alexanderc350cdc2021-04-29 20:36:09 +010029 static bool ComputeDeltas(arm::app::Array2d<float>& mfcc,
alexander3c798932021-03-26 21:42:19 +000030 arm::app::Array2d<float>& delta1,
31 arm::app::Array2d<float>& delta2)
32 {
Richard Burtonb40ecf82022-04-22 16:14:57 +010033 return AsrPreProcess::ComputeDeltas(mfcc, delta1, delta2);
alexander3c798932021-03-26 21:42:19 +000034 }
35
alexanderc350cdc2021-04-29 20:36:09 +010036 static void NormaliseVec(arm::app::Array2d<float>& vec)
alexander3c798932021-03-26 21:42:19 +000037 {
Richard Burtonb40ecf82022-04-22 16:14:57 +010038 return AsrPreProcess::StandardizeVecF32(vec);
alexander3c798932021-03-26 21:42:19 +000039 }
40};
41
42template<class T>
43void CheckOutputs(const std::vector<T> goldenOutput, std::vector<T> output)
44{
45 const size_t goldenSize = goldenOutput.size();
46 const size_t realSize = output.size();
47
48 REQUIRE(realSize == goldenSize);
49 REQUIRE_THAT(output, Catch::Approx( goldenOutput ).margin(0.0001));
50}
51template void CheckOutputs<float>(const std::vector<float> goldenOutput, std::vector<float> output);
52
53void populateBuffer(const float* input, size_t size, size_t numMfccFeats, std::vector<std::vector<float>>& buf)
54{
55 size_t time = 0;
56 for (size_t i = 0; i < size; ++i) {
57 if (i > 0 && i % numMfccFeats == 0) {
58 ++time;
59 }
60 float featureValue = *(input + i);
61 buf[i % numMfccFeats][time] = featureValue;
62 }
63}
64
65void populateArray2dWithVectorOfVector(std::vector<std::vector<float>> vec, arm::app::Array2d<float>& buf)
66{
67 for (size_t i = 0; i < vec.size(); ++i) {
68 for (size_t j = 0; j < vec[i].size(); ++j) {
69 buf(i, j) = vec[i][j];
70 }
71 }
72}
73
74TEST_CASE("Floating point asr features calculation", "[ASR]")
75{
alexander3c798932021-03-26 21:42:19 +000076
77 SECTION("First and second diff")
78 {
79 constexpr uint32_t numMfccFeats = 13;
80 constexpr uint32_t numFeatVectors = 296;
81
82 arm::app::Array2d<float> mfccBuf(numMfccFeats, numFeatVectors);
83 arm::app::Array2d<float> delta1Buf(numMfccFeats, numFeatVectors);
84 arm::app::Array2d<float> delta2Buf(numMfccFeats, numFeatVectors);
85
86 std::vector<std::vector<float>> goldenMfccBuf(numMfccFeats, std::vector<float>(numFeatVectors));
87 std::vector<std::vector<float>> goldenDelta1Buf(numMfccFeats, std::vector<float>(numFeatVectors));
88 std::vector<std::vector<float>> goldenDelta2Buf(numMfccFeats, std::vector<float>(numFeatVectors));
89
90 populateBuffer(golden_asr_mfcc, golden_asr_mfcc_len, numMfccFeats, goldenMfccBuf);
91 populateBuffer(golden_diff1_features, golden_diff1_len, numMfccFeats, goldenDelta1Buf);
92 populateBuffer(golden_diff2_features, golden_diff2_len, numMfccFeats, goldenDelta2Buf);
93
94 populateArray2dWithVectorOfVector(goldenMfccBuf, mfccBuf);
95 std::fill(delta1Buf.begin(), delta1Buf.end(), 0.f);
96 std::fill(delta2Buf.begin(), delta2Buf.end(), 0.f);
97
alexanderc350cdc2021-04-29 20:36:09 +010098 TestPreprocess::ComputeDeltas(mfccBuf, delta1Buf, delta2Buf);
alexander3c798932021-03-26 21:42:19 +000099
100 /* First 4 and last 4 values are different because we pad AFTER diff calculated. */
101 for (size_t i = 0; i < numMfccFeats; ++i) {
102 const float* start_goldenDelta1Buf = goldenDelta1Buf[i].data() + 4;
103 const float* start_delta1 = delta1Buf.begin() + i * delta1Buf.size(1) + 4;
104 std::vector<float> goldenDataDelta1(start_goldenDelta1Buf, start_goldenDelta1Buf + numFeatVectors - 8);
105 std::vector<float> tensorDataDelta1(start_delta1, start_delta1 + numFeatVectors - 8);
106
107 CheckOutputs<float>(goldenDataDelta1,tensorDataDelta1);
108
109 const float* start_goldenDelta2Buf = goldenDelta2Buf[i].data() + 4;
110 const float* start_delta2 = delta2Buf.begin() + i * delta2Buf.size(1) + 4;
111 std::vector<float> goldenDataDelta2(start_goldenDelta2Buf, start_goldenDelta2Buf + numFeatVectors - 8);
112 std::vector<float> tensorDataDelta2(start_delta2, start_delta2 + numFeatVectors - 8);
113
114 CheckOutputs<float>(goldenDataDelta2,tensorDataDelta2);
115 }
116
117 }
118
alexander3c798932021-03-26 21:42:19 +0000119 SECTION("Norm") {
120 auto checker = [&](arm::app::Array2d<float>& d, std::vector<float>& g) {
alexanderc350cdc2021-04-29 20:36:09 +0100121 TestPreprocess::NormaliseVec(d);
alexander3c798932021-03-26 21:42:19 +0000122 std::vector<float> d_vec(d.begin(), d.end());
123 REQUIRE_THAT(g, Catch::Approx(d_vec));
124 };
125
126 std::vector<std::vector<float>> norm0vec{{1, 1}, {1, 1}};
127 std::vector<float> goldenNorm0 {0, 0, 0, 0};
128 arm::app::Array2d<float> norm0(2, 2);
129 populateArray2dWithVectorOfVector(norm0vec, norm0);
130 checker(norm0, goldenNorm0);
131
132 std::vector<std::vector<float>> norm1vec{{1, 2, 3, 4, 5}, {6, 7, 8, 9, 0}};
133 std::vector<float> goldenNorm1 {
134 -1.218543592, -0.87038828, -0.522232968, -0.174077656, 0.174077656,
135 0.522232968, 0.87038828, 1.218543592, 1.566698904, -1.566698904};
136 arm::app::Array2d<float> norm1(2, 5);
137 populateArray2dWithVectorOfVector(norm1vec, norm1);
138 checker(norm1, goldenNorm1);
139 }
140}