summaryrefslogtreecommitdiff
path: root/source/use_case/ad/src
diff options
context:
space:
mode:
Diffstat (limited to 'source/use_case/ad/src')
-rw-r--r--source/use_case/ad/src/AdMelSpectrogram.cc93
-rw-r--r--source/use_case/ad/src/AdModel.cc54
-rw-r--r--source/use_case/ad/src/AdProcessing.cc208
-rw-r--r--source/use_case/ad/src/MainLoop.cc25
-rw-r--r--source/use_case/ad/src/MelSpectrogram.cc316
5 files changed, 23 insertions, 673 deletions
diff --git a/source/use_case/ad/src/AdMelSpectrogram.cc b/source/use_case/ad/src/AdMelSpectrogram.cc
deleted file mode 100644
index 14b9323..0000000
--- a/source/use_case/ad/src/AdMelSpectrogram.cc
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright (c) 2021 Arm Limited. All rights reserved.
- * SPDX-License-Identifier: Apache-2.0
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#include "AdMelSpectrogram.hpp"
-#include "PlatformMath.hpp"
-#include "log_macros.h"
-
-#include <cfloat>
-
-namespace arm {
-namespace app {
-namespace audio {
-
- bool AdMelSpectrogram::ApplyMelFilterBank(
- std::vector<float>& fftVec,
- std::vector<std::vector<float>>& melFilterBank,
- std::vector<uint32_t>& filterBankFilterFirst,
- std::vector<uint32_t>& filterBankFilterLast,
- std::vector<float>& melEnergies)
- {
- const size_t numBanks = melEnergies.size();
-
- if (numBanks != filterBankFilterFirst.size() ||
- numBanks != filterBankFilterLast.size()) {
- printf_err("unexpected filter bank lengths\n");
- return false;
- }
-
- for (size_t bin = 0; bin < numBanks; ++bin) {
- auto filterBankIter = melFilterBank[bin].begin();
- auto end = melFilterBank[bin].end();
- float melEnergy = FLT_MIN; /* Avoid log of zero at later stages. */
- const uint32_t firstIndex = filterBankFilterFirst[bin];
- const uint32_t lastIndex = std::min<int32_t>(filterBankFilterLast[bin], fftVec.size() - 1);
-
- for (uint32_t i = firstIndex; i <= lastIndex && filterBankIter != end; ++i) {
- melEnergy += (*filterBankIter++ * fftVec[i]);
- }
-
- melEnergies[bin] = melEnergy;
- }
-
- return true;
- }
-
- void AdMelSpectrogram::ConvertToLogarithmicScale(
- std::vector<float>& melEnergies)
- {
- /* Container for natural logarithms of mel energies */
- std::vector <float> vecLogEnergies(melEnergies.size(), 0.f);
-
- /* Because we are taking natural logs, we need to multiply by log10(e).
- * Also, for wav2letter model, we scale our log10 values by 10 */
- constexpr float multiplier = 10.0 * /* default scalar */
- 0.4342944819032518; /* log10f(std::exp(1.0))*/
-
- /* Take log of the whole vector */
- math::MathUtils::VecLogarithmF32(melEnergies, vecLogEnergies);
-
- /* Scale the log values. */
- for (auto iterM = melEnergies.begin(), iterL = vecLogEnergies.begin();
- iterM != melEnergies.end() && iterL != vecLogEnergies.end(); ++iterM, ++iterL) {
-
- *iterM = *iterL * multiplier;
- }
- }
-
- float AdMelSpectrogram::GetMelFilterBankNormaliser(
- const float& leftMel,
- const float& rightMel,
- const bool useHTKMethod)
- {
- /* Slaney normalization for mel weights. */
- return (2.0f / (AdMelSpectrogram::InverseMelScale(rightMel, useHTKMethod) -
- AdMelSpectrogram::InverseMelScale(leftMel, useHTKMethod)));
- }
-
-} /* namespace audio */
-} /* namespace app */
-} /* namespace arm */
diff --git a/source/use_case/ad/src/AdModel.cc b/source/use_case/ad/src/AdModel.cc
deleted file mode 100644
index a2ef260..0000000
--- a/source/use_case/ad/src/AdModel.cc
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (c) 2021 Arm Limited. All rights reserved.
- * SPDX-License-Identifier: Apache-2.0
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#include "AdModel.hpp"
-#include "log_macros.h"
-
-const tflite::MicroOpResolver& arm::app::AdModel::GetOpResolver()
-{
- return this->m_opResolver;
-}
-
-bool arm::app::AdModel::EnlistOperations()
-{
- this->m_opResolver.AddAveragePool2D();
- this->m_opResolver.AddConv2D();
- this->m_opResolver.AddDepthwiseConv2D();
- this->m_opResolver.AddRelu6();
- this->m_opResolver.AddReshape();
-
-#if defined(ARM_NPU)
- if (kTfLiteOk == this->m_opResolver.AddEthosU()) {
- info("Added %s support to op resolver\n",
- tflite::GetString_ETHOSU());
- } else {
- printf_err("Failed to add Arm NPU support to op resolver.");
- return false;
- }
-#endif /* ARM_NPU */
- return true;
-}
-
-extern uint8_t* GetModelPointer();
-const uint8_t* arm::app::AdModel::ModelPointer()
-{
- return GetModelPointer();
-}
-extern size_t GetModelLen();
-size_t arm::app::AdModel::ModelSize()
-{
- return GetModelLen();
-}
diff --git a/source/use_case/ad/src/AdProcessing.cc b/source/use_case/ad/src/AdProcessing.cc
deleted file mode 100644
index a33131c..0000000
--- a/source/use_case/ad/src/AdProcessing.cc
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
- * Copyright (c) 2022 Arm Limited. All rights reserved.
- * SPDX-License-Identifier: Apache-2.0
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#include "AdProcessing.hpp"
-
-#include "AdModel.hpp"
-
-namespace arm {
-namespace app {
-
-AdPreProcess::AdPreProcess(TfLiteTensor* inputTensor,
- uint32_t melSpectrogramFrameLen,
- uint32_t melSpectrogramFrameStride,
- float adModelTrainingMean):
- m_validInstance{false},
- m_melSpectrogramFrameLen{melSpectrogramFrameLen},
- m_melSpectrogramFrameStride{melSpectrogramFrameStride},
- /**< Model is trained on features downsampled 2x */
- m_inputResizeScale{2},
- /**< We are choosing to move by 20 frames across the audio for each inference. */
- m_numMelSpecVectorsInAudioStride{20},
- m_audioDataStride{m_numMelSpecVectorsInAudioStride * melSpectrogramFrameStride},
- m_melSpec{melSpectrogramFrameLen}
-{
- if (!inputTensor) {
- printf_err("Invalid input tensor provided to pre-process\n");
- return;
- }
-
- TfLiteIntArray* inputShape = inputTensor->dims;
-
- if (!inputShape) {
- printf_err("Invalid input tensor dims\n");
- return;
- }
-
- const uint32_t kNumRows = inputShape->data[AdModel::ms_inputRowsIdx];
- const uint32_t kNumCols = inputShape->data[AdModel::ms_inputColsIdx];
-
- /* Deduce the data length required for 1 inference from the network parameters. */
- this->m_audioDataWindowSize = (((this->m_inputResizeScale * kNumCols) - 1) *
- melSpectrogramFrameStride) +
- melSpectrogramFrameLen;
- this->m_numReusedFeatureVectors = kNumRows -
- (this->m_numMelSpecVectorsInAudioStride /
- this->m_inputResizeScale);
- this->m_melSpec.Init();
-
- /* Creating a Mel Spectrogram sliding window for the data required for 1 inference.
- * "resizing" done here by multiplying stride by resize scale. */
- this->m_melWindowSlider = audio::SlidingWindow<const int16_t>(
- nullptr, /* to be populated later. */
- this->m_audioDataWindowSize,
- melSpectrogramFrameLen,
- melSpectrogramFrameStride * this->m_inputResizeScale);
-
- /* Construct feature calculation function. */
- this->m_featureCalc = GetFeatureCalculator(this->m_melSpec, inputTensor,
- this->m_numReusedFeatureVectors,
- adModelTrainingMean);
- this->m_validInstance = true;
-}
-
-bool AdPreProcess::DoPreProcess(const void* input, size_t inputSize)
-{
- /* Check that we have a valid instance. */
- if (!this->m_validInstance) {
- printf_err("Invalid pre-processor instance\n");
- return false;
- }
-
- /* We expect that we can traverse the size with which the MEL spectrogram
- * sliding window was initialised with. */
- if (!input || inputSize < this->m_audioDataWindowSize) {
- printf_err("Invalid input provided for pre-processing\n");
- return false;
- }
-
- /* We moved to the next window - set the features sliding to the new address. */
- this->m_melWindowSlider.Reset(static_cast<const int16_t*>(input));
-
- /* The first window does not have cache ready. */
- const bool useCache = this->m_audioWindowIndex > 0 && this->m_numReusedFeatureVectors > 0;
-
- /* Start calculating features inside one audio sliding window. */
- while (this->m_melWindowSlider.HasNext()) {
- const int16_t* melSpecWindow = this->m_melWindowSlider.Next();
- std::vector<int16_t> melSpecAudioData = std::vector<int16_t>(
- melSpecWindow,
- melSpecWindow + this->m_melSpectrogramFrameLen);
-
- /* Compute features for this window and write them to input tensor. */
- this->m_featureCalc(melSpecAudioData,
- this->m_melWindowSlider.Index(),
- useCache,
- this->m_numMelSpecVectorsInAudioStride,
- this->m_inputResizeScale);
- }
-
- return true;
-}
-
-uint32_t AdPreProcess::GetAudioWindowSize()
-{
- return this->m_audioDataWindowSize;
-}
-
-uint32_t AdPreProcess::GetAudioDataStride()
-{
- return this->m_audioDataStride;
-}
-
-void AdPreProcess::SetAudioWindowIndex(uint32_t idx)
-{
- this->m_audioWindowIndex = idx;
-}
-
-AdPostProcess::AdPostProcess(TfLiteTensor* outputTensor) :
- m_outputTensor {outputTensor}
-{}
-
-bool AdPostProcess::DoPostProcess()
-{
- switch (this->m_outputTensor->type) {
- case kTfLiteInt8:
- this->Dequantize<int8_t>();
- break;
- default:
- printf_err("Unsupported tensor type");
- return false;
- }
-
- math::MathUtils::SoftmaxF32(this->m_dequantizedOutputVec);
- return true;
-}
-
-float AdPostProcess::GetOutputValue(uint32_t index)
-{
- if (index < this->m_dequantizedOutputVec.size()) {
- return this->m_dequantizedOutputVec[index];
- }
- printf_err("Invalid index for output\n");
- return 0.0;
-}
-
-std::function<void (std::vector<int16_t>&, int, bool, size_t, size_t)>
-GetFeatureCalculator(audio::AdMelSpectrogram& melSpec,
- TfLiteTensor* inputTensor,
- size_t cacheSize,
- float trainingMean)
-{
- std::function<void (std::vector<int16_t>&, size_t, bool, size_t, size_t)> melSpecFeatureCalc;
-
- TfLiteQuantization quant = inputTensor->quantization;
-
- if (kTfLiteAffineQuantization == quant.type) {
-
- auto* quantParams = static_cast<TfLiteAffineQuantization*>(quant.params);
- const float quantScale = quantParams->scale->data[0];
- const int quantOffset = quantParams->zero_point->data[0];
-
- switch (inputTensor->type) {
- case kTfLiteInt8: {
- melSpecFeatureCalc = FeatureCalc<int8_t>(
- inputTensor,
- cacheSize,
- [=, &melSpec](std::vector<int16_t>& audioDataWindow) {
- return melSpec.MelSpecComputeQuant<int8_t>(
- audioDataWindow,
- quantScale,
- quantOffset,
- trainingMean);
- }
- );
- break;
- }
- default:
- printf_err("Tensor type %s not supported\n", TfLiteTypeGetName(inputTensor->type));
- }
- } else {
- melSpecFeatureCalc = FeatureCalc<float>(
- inputTensor,
- cacheSize,
- [=, &melSpec](
- std::vector<int16_t>& audioDataWindow) {
- return melSpec.ComputeMelSpec(
- audioDataWindow,
- trainingMean);
- });
- }
- return melSpecFeatureCalc;
-}
-
-} /* namespace app */
-} /* namespace arm */
diff --git a/source/use_case/ad/src/MainLoop.cc b/source/use_case/ad/src/MainLoop.cc
index 140359b..e9f7b4e 100644
--- a/source/use_case/ad/src/MainLoop.cc
+++ b/source/use_case/ad/src/MainLoop.cc
@@ -18,7 +18,17 @@
#include "AdModel.hpp" /* Model class for running inference */
#include "UseCaseCommonUtils.hpp" /* Utils functions */
#include "UseCaseHandler.hpp" /* Handlers for different user options */
-#include "log_macros.h"
+#include "log_macros.h" /* Logging functions */
+#include "BufAttributes.hpp" /* Buffer attributes to be applied */
+
+namespace arm {
+ namespace app {
+ static uint8_t tensorArena[ACTIVATION_BUF_SZ] ACTIVATION_BUF_ATTRIBUTE;
+ } /* namespace app */
+} /* namespace arm */
+
+extern uint8_t* GetModelPointer();
+extern size_t GetModelLen();
enum opcodes
{
@@ -49,12 +59,23 @@ void main_loop()
arm::app::AdModel model; /* Model wrapper object. */
/* Load the model. */
- if (!model.Init())
+ if (!model.Init(arm::app::tensorArena,
+ sizeof(arm::app::tensorArena),
+ GetModelPointer(),
+ GetModelLen()))
{
printf_err("failed to initialise model\n");
return;
}
+#if !defined(ARM_NPU)
+ /* If it is not a NPU build check if the model contains a NPU operator */
+ if (model.ContainsEthosUOperator()) {
+ printf_err("No driver support for Ethos-U operator found in the model.\n");
+ return;
+ }
+#endif /* ARM_NPU */
+
/* Instantiate application context. */
arm::app::ApplicationContext caseContext;
diff --git a/source/use_case/ad/src/MelSpectrogram.cc b/source/use_case/ad/src/MelSpectrogram.cc
deleted file mode 100644
index ff0c536..0000000
--- a/source/use_case/ad/src/MelSpectrogram.cc
+++ /dev/null
@@ -1,316 +0,0 @@
-/*
- * Copyright (c) 2021 Arm Limited. All rights reserved.
- * SPDX-License-Identifier: Apache-2.0
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#include "MelSpectrogram.hpp"
-
-#include "PlatformMath.hpp"
-#include "log_macros.h"
-
-#include <cfloat>
-#include <cinttypes>
-
-namespace arm {
-namespace app {
-namespace audio {
-
- MelSpecParams::MelSpecParams(
- const float samplingFreq,
- const uint32_t numFbankBins,
- const float melLoFreq,
- const float melHiFreq,
- const uint32_t frameLen,
- const bool useHtkMethod):
- m_samplingFreq(samplingFreq),
- m_numFbankBins(numFbankBins),
- m_melLoFreq(melLoFreq),
- m_melHiFreq(melHiFreq),
- m_frameLen(frameLen),
-
- /* Smallest power of 2 >= frame length. */
- m_frameLenPadded(pow(2, ceil((log(frameLen)/log(2))))),
- m_useHtkMethod(useHtkMethod)
- {}
-
- std::string MelSpecParams::Str() const
- {
- char strC[1024];
- snprintf(strC, sizeof(strC) - 1, "\n \
- \n\t Sampling frequency: %f\
- \n\t Number of filter banks: %" PRIu32 "\
- \n\t Mel frequency limit (low): %f\
- \n\t Mel frequency limit (high): %f\
- \n\t Frame length: %" PRIu32 "\
- \n\t Padded frame length: %" PRIu32 "\
- \n\t Using HTK for Mel scale: %s\n",
- this->m_samplingFreq, this->m_numFbankBins, this->m_melLoFreq,
- this->m_melHiFreq, this->m_frameLen,
- this->m_frameLenPadded, this->m_useHtkMethod ? "yes" : "no");
- return std::string{strC};
- }
-
- MelSpectrogram::MelSpectrogram(const MelSpecParams& params):
- m_params(params),
- m_filterBankInitialised(false)
- {
- this->m_buffer = std::vector<float>(
- this->m_params.m_frameLenPadded, 0.0);
- this->m_frame = std::vector<float>(
- this->m_params.m_frameLenPadded, 0.0);
- this->m_melEnergies = std::vector<float>(
- this->m_params.m_numFbankBins, 0.0);
-
- this->m_windowFunc = std::vector<float>(this->m_params.m_frameLen);
- const auto multiplier = static_cast<float>(2 * M_PI / this->m_params.m_frameLen);
-
- /* Create window function. */
- for (size_t i = 0; i < this->m_params.m_frameLen; ++i) {
- this->m_windowFunc[i] = (0.5 - (0.5 *
- math::MathUtils::CosineF32(static_cast<float>(i) * multiplier)));
- }
-
- math::MathUtils::FftInitF32(this->m_params.m_frameLenPadded, this->m_fftInstance);
- debug("Instantiated Mel Spectrogram object: %s\n", this->m_params.Str().c_str());
- }
-
- void MelSpectrogram::Init()
- {
- this->InitMelFilterBank();
- }
-
- float MelSpectrogram::MelScale(const float freq, const bool useHTKMethod)
- {
- if (useHTKMethod) {
- return 1127.0f * logf (1.0f + freq / 700.0f);
- } else {
- /* Slaney formula for mel scale. */
- float mel = freq / ms_freqStep;
-
- if (freq >= ms_minLogHz) {
- mel = ms_minLogMel + logf(freq / ms_minLogHz) / ms_logStep;
- }
- return mel;
- }
- }
-
- float MelSpectrogram::InverseMelScale(const float melFreq, const bool useHTKMethod)
- {
- if (useHTKMethod) {
- return 700.0f * (expf (melFreq / 1127.0f) - 1.0f);
- } else {
- /* Slaney formula for inverse mel scale. */
- float freq = ms_freqStep * melFreq;
-
- if (melFreq >= ms_minLogMel) {
- freq = ms_minLogHz * expf(ms_logStep * (melFreq - ms_minLogMel));
- }
- return freq;
- }
- }
-
- bool MelSpectrogram::ApplyMelFilterBank(
- std::vector<float>& fftVec,
- std::vector<std::vector<float>>& melFilterBank,
- std::vector<uint32_t>& filterBankFilterFirst,
- std::vector<uint32_t>& filterBankFilterLast,
- std::vector<float>& melEnergies)
- {
- const size_t numBanks = melEnergies.size();
-
- if (numBanks != filterBankFilterFirst.size() ||
- numBanks != filterBankFilterLast.size()) {
- printf_err("unexpected filter bank lengths\n");
- return false;
- }
-
- for (size_t bin = 0; bin < numBanks; ++bin) {
- auto filterBankIter = melFilterBank[bin].begin();
- auto end = melFilterBank[bin].end();
- float melEnergy = FLT_MIN; /* Avoid log of zero at later stages */
- const uint32_t firstIndex = filterBankFilterFirst[bin];
- const uint32_t lastIndex = std::min<int32_t>(filterBankFilterLast[bin], fftVec.size() - 1);
-
- for (uint32_t i = firstIndex; i <= lastIndex && filterBankIter != end; ++i) {
- float energyRep = math::MathUtils::SqrtF32(fftVec[i]);
- melEnergy += (*filterBankIter++ * energyRep);
- }
-
- melEnergies[bin] = melEnergy;
- }
-
- return true;
- }
-
- void MelSpectrogram::ConvertToLogarithmicScale(std::vector<float>& melEnergies)
- {
- for (float& melEnergy : melEnergies) {
- melEnergy = logf(melEnergy);
- }
- }
-
- void MelSpectrogram::ConvertToPowerSpectrum()
- {
- const uint32_t halfDim = this->m_buffer.size() / 2;
-
- /* Handle this special case. */
- float firstEnergy = this->m_buffer[0] * this->m_buffer[0];
- float lastEnergy = this->m_buffer[1] * this->m_buffer[1];
-
- math::MathUtils::ComplexMagnitudeSquaredF32(
- this->m_buffer.data(),
- this->m_buffer.size(),
- this->m_buffer.data(),
- this->m_buffer.size()/2);
-
- this->m_buffer[0] = firstEnergy;
- this->m_buffer[halfDim] = lastEnergy;
- }
-
- float MelSpectrogram::GetMelFilterBankNormaliser(
- const float& leftMel,
- const float& rightMel,
- const bool useHTKMethod)
- {
- UNUSED(leftMel);
- UNUSED(rightMel);
- UNUSED(useHTKMethod);
-
- /* By default, no normalisation => return 1 */
- return 1.f;
- }
-
- void MelSpectrogram::InitMelFilterBank()
- {
- if (!this->IsMelFilterBankInited()) {
- this->m_melFilterBank = this->CreateMelFilterBank();
- this->m_filterBankInitialised = true;
- }
- }
-
- bool MelSpectrogram::IsMelFilterBankInited() const
- {
- return this->m_filterBankInitialised;
- }
-
- std::vector<float> MelSpectrogram::ComputeMelSpec(const std::vector<int16_t>& audioData, float trainingMean)
- {
- this->InitMelFilterBank();
-
- /* TensorFlow way of normalizing .wav data to (-1, 1). */
- constexpr float normaliser = 1.0/(1<<15);
- for (size_t i = 0; i < this->m_params.m_frameLen; ++i) {
- this->m_frame[i] = static_cast<float>(audioData[i]) * normaliser;
- }
-
- /* Apply window function to input frame. */
- for(size_t i = 0; i < this->m_params.m_frameLen; ++i) {
- this->m_frame[i] *= this->m_windowFunc[i];
- }
-
- /* Set remaining frame values to 0. */
- std::fill(this->m_frame.begin() + this->m_params.m_frameLen,this->m_frame.end(), 0);
-
- /* Compute FFT. */
- math::MathUtils::FftF32(this->m_frame, this->m_buffer, this->m_fftInstance);
-
- /* Convert to power spectrum. */
- this->ConvertToPowerSpectrum();
-
- /* Apply mel filterbanks. */
- if (!this->ApplyMelFilterBank(this->m_buffer,
- this->m_melFilterBank,
- this->m_filterBankFilterFirst,
- this->m_filterBankFilterLast,
- this->m_melEnergies)) {
- printf_err("Failed to apply MEL filter banks\n");
- }
-
- /* Convert to logarithmic scale */
- this->ConvertToLogarithmicScale(this->m_melEnergies);
-
- /* Perform mean subtraction. */
- for (auto& energy:this->m_melEnergies) {
- energy -= trainingMean;
- }
-
- return this->m_melEnergies;
- }
-
- std::vector<std::vector<float>> MelSpectrogram::CreateMelFilterBank()
- {
- size_t numFftBins = this->m_params.m_frameLenPadded / 2;
- float fftBinWidth = static_cast<float>(this->m_params.m_samplingFreq) / this->m_params.m_frameLenPadded;
-
- float melLowFreq = MelSpectrogram::MelScale(this->m_params.m_melLoFreq,
- this->m_params.m_useHtkMethod);
- float melHighFreq = MelSpectrogram::MelScale(this->m_params.m_melHiFreq,
- this->m_params.m_useHtkMethod);
- float melFreqDelta = (melHighFreq - melLowFreq) / (this->m_params.m_numFbankBins + 1);
-
- std::vector<float> thisBin = std::vector<float>(numFftBins);
- std::vector<std::vector<float>> melFilterBank(
- this->m_params.m_numFbankBins);
- this->m_filterBankFilterFirst =
- std::vector<uint32_t>(this->m_params.m_numFbankBins);
- this->m_filterBankFilterLast =
- std::vector<uint32_t>(this->m_params.m_numFbankBins);
-
- for (size_t bin = 0; bin < this->m_params.m_numFbankBins; bin++) {
- float leftMel = melLowFreq + bin * melFreqDelta;
- float centerMel = melLowFreq + (bin + 1) * melFreqDelta;
- float rightMel = melLowFreq + (bin + 2) * melFreqDelta;
-
- uint32_t firstIndex = 0;
- uint32_t lastIndex = 0;
- bool firstIndexFound = false;
- const float normaliser = this->GetMelFilterBankNormaliser(leftMel, rightMel, this->m_params.m_useHtkMethod);
-
- for (size_t i = 0; i < numFftBins; ++i) {
- float freq = (fftBinWidth * i); /* Center freq of this fft bin. */
- float mel = MelSpectrogram::MelScale(freq, this->m_params.m_useHtkMethod);
- thisBin[i] = 0.0;
-
- if (mel > leftMel && mel < rightMel) {
- float weight;
- if (mel <= centerMel) {
- weight = (mel - leftMel) / (centerMel - leftMel);
- } else {
- weight = (rightMel - mel) / (rightMel - centerMel);
- }
-
- thisBin[i] = weight * normaliser;
- if (!firstIndexFound) {
- firstIndex = i;
- firstIndexFound = true;
- }
- lastIndex = i;
- }
- }
-
- this->m_filterBankFilterFirst[bin] = firstIndex;
- this->m_filterBankFilterLast[bin] = lastIndex;
-
- /* Copy the part we care about. */
- for (uint32_t i = firstIndex; i <= lastIndex; ++i) {
- melFilterBank[bin].push_back(thisBin[i]);
- }
- }
-
- return melFilterBank;
- }
-
-} /* namespace audio */
-} /* namespace app */
-} /* namespace arm */