/* * SPDX-FileCopyrightText: Copyright 2022 Arm Limited and/or its affiliates * 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 "RNNoiseProcessing.hpp" #include "log_macros.h" namespace arm { namespace app { RNNoisePreProcess::RNNoisePreProcess(TfLiteTensor* inputTensor, std::shared_ptr featureProcessor, std::shared_ptr frameFeatures) : m_inputTensor{inputTensor}, m_featureProcessor{featureProcessor}, m_frameFeatures{frameFeatures} {} bool RNNoisePreProcess::DoPreProcess(const void* data, size_t inputSize) { if (data == nullptr) { printf_err("Data pointer is null"); return false; } auto input = static_cast(data); this->m_audioFrame = rnn::vec1D32F(input, input + inputSize); m_featureProcessor->PreprocessFrame(this->m_audioFrame.data(), inputSize, *this->m_frameFeatures); QuantizeAndPopulateInput(this->m_frameFeatures->m_featuresVec, this->m_inputTensor->params.scale, this->m_inputTensor->params.zero_point, this->m_inputTensor); debug("Input tensor populated \n"); return true; } void RNNoisePreProcess::QuantizeAndPopulateInput(rnn::vec1D32F& inputFeatures, const float quantScale, const int quantOffset, TfLiteTensor* inputTensor) { const float minVal = std::numeric_limits::min(); const float maxVal = std::numeric_limits::max(); auto* inputTensorData = tflite::GetTensorData(inputTensor); for (size_t i=0; i < inputFeatures.size(); ++i) { float quantValue = ((inputFeatures[i] / quantScale) + quantOffset); inputTensorData[i] = static_cast(std::min(std::max(quantValue, minVal), maxVal)); } } RNNoisePostProcess::RNNoisePostProcess(TfLiteTensor* outputTensor, std::vector& denoisedAudioFrame, std::shared_ptr featureProcessor, std::shared_ptr frameFeatures) : m_outputTensor{outputTensor}, m_denoisedAudioFrame{denoisedAudioFrame}, m_featureProcessor{featureProcessor}, m_frameFeatures{frameFeatures} { this->m_denoisedAudioFrameFloat.reserve(denoisedAudioFrame.size()); this->m_modelOutputFloat.resize(outputTensor->bytes); } bool RNNoisePostProcess::DoPostProcess() { const auto* outputData = tflite::GetTensorData(this->m_outputTensor); auto outputQuantParams = GetTensorQuantParams(this->m_outputTensor); for (size_t i = 0; i < this->m_outputTensor->bytes; ++i) { this->m_modelOutputFloat[i] = (static_cast(outputData[i]) - outputQuantParams.offset) * outputQuantParams.scale; } this->m_featureProcessor->PostProcessFrame(this->m_modelOutputFloat, *this->m_frameFeatures, this->m_denoisedAudioFrameFloat); for (size_t i = 0; i < this->m_denoisedAudioFrame.size(); ++i) { this->m_denoisedAudioFrame[i] = static_cast( std::roundf(this->m_denoisedAudioFrameFloat[i])); } return true; } } /* namespace app */ } /* namespace arm */