From 8375ee73339399c51847d0cffcfe59b981b31496 Mon Sep 17 00:00:00 2001 From: hellohyh001 Date: Sat, 10 Jun 2023 14:04:18 +0000 Subject: [PATCH] Audio frequency rotary vibration (part 7) Signed-off-by: hellohyh001 Change-Id: I5dbaeb296ad438bc62267c68de44f2ca9626684c --- .../conversion/include/conversion_filter.h | 133 ++++++++++++++++++ .../conversion/include/conversion_mfcc.h | 111 +++++++++++++++ .../core/algorithm/conversion/include/fft.h | 123 ++++++++++++++++ 3 files changed, 367 insertions(+) create mode 100644 vibration_convert/core/algorithm/conversion/include/conversion_filter.h create mode 100644 vibration_convert/core/algorithm/conversion/include/conversion_mfcc.h create mode 100644 vibration_convert/core/algorithm/conversion/include/fft.h diff --git a/vibration_convert/core/algorithm/conversion/include/conversion_filter.h b/vibration_convert/core/algorithm/conversion/include/conversion_filter.h new file mode 100644 index 00000000..33db5888 --- /dev/null +++ b/vibration_convert/core/algorithm/conversion/include/conversion_filter.h @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * 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. + */ + +#ifndef CONVERSION_FILTER_H +#define CONVERSION_FILTER_H + +#include +#include +#include +#include + +#include "utils.h" + +namespace OHOS { +namespace Sensors { +namespace { +constexpr size_t ARRAY_SIZE { 10 }; +} // namespace + +/** + * @brief selection of filters + */ +class ConversionFilter { +public: + ConversionFilter() = default; + /** + * @brief resonant low pass filter + * + * @param input A signal + * @param cutoff1 The cutoff frequency (in Hz) + * @param resonance The amount of resonance + */ + double FilterLowResonant(double input, double cutoff, double resonance); + /** + * @brief resonant high pass filter + * + * @param input A signal + * @param cutoff1 The cutoff frequency (in Hz) + * @param resonance The amount of resonance + */ + double FilterHighResonant(double input, double cutoff, double resonance); + + /** + * @brief resonant band pass filter + * + * @param input A signal + * @param cutoff1 The cutoff frequency (in Hz) + * @param resonance The amount of resonance + */ + double FilterBandPass(double input, double cutoff, double resonance); + + /** + * @brief simple low pass filter + * + * @param input A signal + * @param cutoff1 The cutoff frequency (between 0 and 1) + */ + double FilterLowPass(double input, double cutoff); + + /** + * @brief simple high pass filter + * + * @param input A sampling value. + * @param cutoff1 The cutoff frequency (between 0 and 1) + */ + double FilterHighPass(double input, double cutoff); + + /** + * @brief the cutoff frequency + * + * @param cut The cutoff frequency + */ + void SetCutOff(double cutoff) + { + cutoff_ = cutoff; + } + + /** + * @brief the resonance + * + * @param res The resonance + */ + void SetResonance(double resonance) + { + resonance_ = resonance; + } + + /** + * @brief Returns the cutoff value + */ + double GetCutOff() const + { + return cutoff_; + } + + /** + * @brief Return the resonance value + */ + double GetResonance() const + { + return resonance_; + } + + double HandleResonant(double input, double cutoff, double resonance, FilterMethod filterMethod); + double HandleHighPassOrLowPass(double input, double cutoff, bool isHighPass); + +private: + double cutoff_ { 0.0 }; + double resonance_ { 0.0 }; + double output_ { 0.0 }; + double inputs_[ARRAY_SIZE] { 0.0 }; + double outputs_[ARRAY_SIZE] { 0.0 }; + double speed_ { 0.0 }; + double pos_ { 0.0 }; + double pole_ { 0.0 }; + double filterCoefficient_ { 0.0 }; + int32_t sampleRate_ { 0 }; +}; +} // namespace Sensors +} // namespace OHOS +#endif // CONVERSION_FILTER_H \ No newline at end of file diff --git a/vibration_convert/core/algorithm/conversion/include/conversion_mfcc.h b/vibration_convert/core/algorithm/conversion/include/conversion_mfcc.h new file mode 100644 index 00000000..5a3e18fb --- /dev/null +++ b/vibration_convert/core/algorithm/conversion/include/conversion_mfcc.h @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * 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. + */ + +#ifndef CONVERSION_MFCC_H +#define CONVERSION_MFCC_H + +#include + +namespace OHOS { +namespace Sensors { +/** + * @brief Calculate the parameters required for MFCC + */ +struct MfccInputPara { + /** sampling rate of audio file. */ + int32_t sampleRate { 0 }; + /** Number of MEL filters. */ + int32_t nMels { 0 }; + /** The effective minimum frequency of audio. lowest frequency (in Hz). */ + double minFreq { 0.0 }; + /** Effective maximum frequency of audio. + * highest frequency (in Hz). If `zero`, use 'fmax = sr / 2.0' */ + double maxFreq { 0.0 }; +}; + +/** + * @brief Mel-frequency cepstral coefficients (MFCCs).the MFCC calculation will depend on the peak + * loudness (in decibels). + * + */ +class ConversionMfcc { +public: + ConversionMfcc() = default; + ~ConversionMfcc() = default; + + /** + * @brief Init mfcc module + * + * @param numBins The value equal hopLength for sfft. + * @param numCoeffs 12 semitones, the value is 12+1. + * @param para Calculate the parameters required for MFCC. + * + * @return Returns 0 if the operation is successful; returns a negative value otherwise. + */ + int32_t Init(uint32_t numBins, uint32_t numCoeffs, const MfccInputPara ¶); + + /** + * @brief Calculate MFCC based on power spectrum. + * + * @param powerSpectrum Log-power Mel spectrogram + * @return Return MFCC. + */ + std::vector Mfcc(const std::vector &powerSpectrum); + + /** + * @brief Get the Mel Filter Bank + * 1. Call the setup function at first. + * 2. use Slaney formula instead of HTK + * + * @return Slaney Bias + */ + std::vector GetMelFilterBank() const; + + /** + * @brief Create a Mel filter-bank. + * 1. Call the setup function at first. + * 2. use HTK formula instead of Slaney + * + * @param nFft number of FFT components + * @param para Calculate the parameters required for MFCC. + * @param frmCount Return frame counts. + * @param melBasis [shape=(n_mels, 1 + nFft/2)] Mel transform matrix + * + * @return Returns 0 if the operation is successful; returns a negative value otherwise. + */ + int32_t FiltersMel(int32_t nFft, MfccInputPara para, size_t &frmCount, std::vector &melBasis); + +private: + void HandleDiscreteCosineTransform(std::vector &mfccs); + int32_t MelFilterAndLogSquare(const std::vector &powerSpectrum); + int32_t CalcMelFilterBank(double sampleRate); + int32_t CreateDCTCoeffs(); + int32_t SetMelFilters(uint32_t idx, double binFreq, double prevFreq, double thisFreq, double nextFreq); + +private: + std::vector melBands_; + uint32_t numFilters_ { 0 }; + uint32_t numCoeffs_ { 0 }; + double minFreq_ { 0.0 }; + double maxFreq_ { 0.0 }; + uint32_t sampleRate_ { 0 }; + std::vector melFilters_; + uint32_t numBins_ { 0 }; + std::vector dctMatrix_; + std::vector coeffs_; +}; +} // namespace Sensors +} // namespace OHOS +#endif // CONVERSION_MFCC_H \ No newline at end of file diff --git a/vibration_convert/core/algorithm/conversion/include/fft.h b/vibration_convert/core/algorithm/conversion/include/fft.h new file mode 100644 index 00000000..d36a1ba9 --- /dev/null +++ b/vibration_convert/core/algorithm/conversion/include/fft.h @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * 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. + */ + +#ifndef FFT_H +#define FFT_H + +#include "utils.h" + +namespace OHOS { +namespace Sensors { +/** + * @brief The parameters and calculation results used in FFT. + * Used to encapsulate 6 parameters in the AlgFFT function. + */ +struct FftParaAndResult { + /** Number of samples */ + int32_t numSamples { 0 }; + /** The real part of the input */ + std::vector realIn; + /** The imaginary part of the input */ + std::vector imagIn; + /** The real part of the output */ + std::vector realOut; + /** The imaginary part of the output */ + std::vector imagOut; + + FftParaAndResult() = default; + explicit FftParaAndResult(int32_t size) { + numSamples = size; + realIn.resize(size, 0.0F); + imagIn.resize(size, 0.0F); + realOut.resize(size, 0.0F); + imagOut.resize(size, 0.0F); + } +}; + +class Fft { +public: + Fft() = default; + ~Fft(); + + void Init(int32_t fftSize); + + std::vector GetReal() const; + std::vector GetImg() const; + + /* Calculate the power spectrum */ + void CalcFFT(const std::vector &data, const std::vector &window); + void ConvertPolar(std::vector &magnitude, std::vector &phase); + void CalculatePowerSpectrum(const std::vector &data, const std::vector &window, + std::vector &magnitude, std::vector &phase); + /** the inverse */ + void ConvertCart(const std::vector &magnitude, const std::vector &phase); + void CalcIFFT(const std::vector &window, std::vector &finalOut); + void InverseFFTComplex(const std::vector &window, const std::vector &real, + const std::vector &imaginary, std::vector &finalOut); + void InversePowerSpectrum(const std::vector &window, const std::vector &magnitude, + const std::vector &phase, std::vector &finalOut); + void ConvertDB(const std::vector &in, std::vector &out); + int32_t GenWindow(int32_t whichFunction, int32_t numSamples, std::vector &window); + +private: + int32_t WindowFunc(int32_t whichFunction, int32_t numSamples, float *out); + uint32_t FastReverseBits(uint32_t pos, uint32_t numBits); + + /** + * @brief Power Spectrum + * + * 1. This function computes the same as AlgRealFFT, above, but adds the squares of the real and imaginary part + * of each coefficient, extracting the power and throwing away the phase. + * 2. For speed, it does not call AlgRealFFT, but duplicates some of its code. + * + * @param numSamples Number of samples. + * @param in The part of the input. + * @param out The part of the output + * + * @return Returns 0 if the operation is successful; returns a negative value otherwise. + */ + int32_t AlgPowerSpectrum(int32_t numSamples, const std::vector &in, std::vector &out); + + /** + * @brief Real Fast Fourier Transform + * + * 1. This function was based on the code in Numerical Recipes in C. + * 2.In Num. Rec., the inner loop is based on a single 1-based array of interleaved real and imaginary numbers. + * Because we have two separate zero-based arrays, our indices are quite different. + * 3. Here is the correspondence between Num. Rec. + * + * @return Returns 0 if the operation is successful; returns a negative value otherwise. + */ + int32_t AlgRealFFT(FftParaAndResult ¶Res); + int32_t AlgFFT(bool inverseTransform, FftParaAndResult ¶Res); + int32_t AlgInitFFT(); + +private: + /** fftSize */ + int32_t fftSize_ { 0 }; + /** halfFFTSize */ + int32_t half_ { 0 }; + + FftParaAndResult fftParaRes_; + /** + * 'para_' needs to be created every time the sfft occurs, so it is created once during initialization. + * It's half the size of fftParaRes_, only used in one function. + */ + FftParaAndResult para_; + uint32_t** fftBitTable_ { nullptr }; +}; +} // namespace Sensors +} // namespace OHOS +#endif // FFT_H \ No newline at end of file -- Gitee