diff --git a/vibration_convert/core/algorithm/conversion/include/fft.h b/vibration_convert/core/algorithm/conversion/include/fft.h index d36a1ba90c95e37729c19b7284792bf4d20d6d87..7b1a17867711dd74c77f42cee7f28ccec187e539 100644 --- a/vibration_convert/core/algorithm/conversion/include/fft.h +++ b/vibration_convert/core/algorithm/conversion/include/fft.h @@ -102,6 +102,8 @@ private: */ int32_t AlgRealFFT(FftParaAndResult ¶Res); int32_t AlgFFT(bool inverseTransform, FftParaAndResult ¶Res); + void Normalize(FftParaAndResult ¶Res); + int32_t PreprocessData(uint32_t numSamples, FftParaAndResult ¶Res); int32_t AlgInitFFT(); private: diff --git a/vibration_convert/core/algorithm/conversion/src/fft.cpp b/vibration_convert/core/algorithm/conversion/src/fft.cpp index dba1a427b9695f6931c4ba0d9374188c5ccbcf9c..f57c66098595c1a1333e5ff7598ecadd184536db 100644 --- a/vibration_convert/core/algorithm/conversion/src/fft.cpp +++ b/vibration_convert/core/algorithm/conversion/src/fft.cpp @@ -56,7 +56,7 @@ inline uint32_t Fft::FastReverseBits(uint32_t pos, uint32_t numBits) { if (numBits <= MAX_FAST_BITS && numBits >= 1) { return fftBitTable_[numBits - 1][pos]; - } + } return ReverseBits(pos, numBits); } @@ -87,34 +87,13 @@ int32_t Fft::AlgFFT(bool inverseTransform, FftParaAndResult ¶Res) SEN_HILOGE("The parameter is invalid,numSamples:%{public}d", numSamples); return Sensors::PARAMETER_ERROR; } - if (fftBitTable_ == nullptr) { - if (AlgInitFFT() != Sensors::SUCCESS) { - SEN_HILOGE("fftBitTable_ failed to allocate memory"); - return Sensors::ERROR; - } - } - double angleNumerator = 2 * M_PI; - if (inverseTransform) { - angleNumerator = -angleNumerator; - } - uint32_t numBits = ObtainNumberOfBits(numSamples); - if (numBits < 1) { - SEN_HILOGE("numBits is an invalid value"); + if (PreprocessData(numSamples, paraRes) != Sensors::SUCCESS) { + SEN_HILOGE("PreprocessData failed"); return Sensors::ERROR; } - /* - * Do simultaneous data copy and bit-reversal ordering into outputs... - */ - for (uint32_t i = 0; i < numSamples; ++i) { - uint32_t j = FastReverseBits(i, numBits); - paraRes.realOut[j] = paraRes.realIn[i]; - paraRes.imagOut[j] = (paraRes.imagIn.empty()) ? 0.0F : paraRes.imagIn[i]; - } - - /* - * Do the FFT itself... - */ + // Do the FFT itself... int32_t blockEnd = 1; + double angleNumerator = inverseTransform ? -(2 * M_PI) : (2 * M_PI); for (int32_t blockSize = 2; blockSize <= paraRes.numSamples; blockSize <<= 1) { double deltaAngle = angleNumerator / static_cast(blockSize); float twoSinMagnitude = sin(-2 * deltaAngle); @@ -145,16 +124,38 @@ int32_t Fft::AlgFFT(bool inverseTransform, FftParaAndResult ¶Res) } blockEnd = blockSize; } - - /* - ** Need to normalize if inverse transform... - */ + // Need to normalize if inverse transform if (inverseTransform) { - float denom = static_cast(paraRes.numSamples); - for (int32_t i = 0; i < paraRes.numSamples; ++i) { - paraRes.realOut[i] /= denom; - paraRes.imagOut[i] /= denom; - } + Normalize(paraRes); + } + return Sensors::SUCCESS; +} + +void Fft::Normalize(FftParaAndResult ¶Res) +{ + float denom = static_cast(paraRes.numSamples); + for (int32_t i = 0; i < paraRes.numSamples; ++i) { + paraRes.realOut[i] /= denom; + paraRes.imagOut[i] /= denom; + } +} + +int32_t Fft::PreprocessData(uint32_t numSamples, FftParaAndResult ¶Res) +{ + if ((fftBitTable_ == nullptr) && (AlgInitFFT() != Sensors::SUCCESS)) { + SEN_HILOGE("fftBitTable_ failed to allocate memory"); + return Sensors::ERROR; + } + uint32_t numBits = ObtainNumberOfBits(numSamples); + if (numBits < 1) { + SEN_HILOGE("numBits is an invalid value"); + return Sensors::ERROR; + } + // Do simultaneous data copy and bit-reversal ordering into outputs... + for (uint32_t i = 0; i < numSamples; ++i) { + uint32_t j = FastReverseBits(i, numBits); + paraRes.realOut[j] = paraRes.realIn[i]; + paraRes.imagOut[j] = (paraRes.imagIn.empty()) ? 0.0F : paraRes.imagIn[i]; } return Sensors::SUCCESS; } diff --git a/vibration_convert/core/native/include/generate_vibration_json_file.h b/vibration_convert/core/native/include/generate_vibration_json_file.h new file mode 100644 index 0000000000000000000000000000000000000000..f03242e846f2d70f03a156e32629a8679e79b8db --- /dev/null +++ b/vibration_convert/core/native/include/generate_vibration_json_file.h @@ -0,0 +1,38 @@ +/* + * 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 GENERATE_VIBRATION_JSON_FILE_H +#define GENERATE_VIBRATION_JSON_FILE_H + +#include +#include + +#include + +#include "vibration_convert_type.h" + +namespace OHOS { +namespace Sensors { +class GenerateVibrationJsonFile { +public: + GenerateVibrationJsonFile() = default; + ~GenerateVibrationJsonFile() = default; + int32_t GenerateJsonFile(std::vector &hapticEvents); + template + int32_t DebugJsonFile(const std::string &pathName, const std::vector &srcDatas); +}; +} // namespace Sensors +} // namespace OHOS +#endif // GENERATE_VIBRATION_JSON_FILE_H \ No newline at end of file diff --git a/vibration_convert/core/native/src/generate_vibration_json_file.cpp b/vibration_convert/core/native/src/generate_vibration_json_file.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6135a0086f522aba1e3b0618281a0defc9d95e54 --- /dev/null +++ b/vibration_convert/core/native/src/generate_vibration_json_file.cpp @@ -0,0 +1,97 @@ +/* + * 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. + */ + +#include "generate_vibration_json_file.h" + +#include +#include +#include + +#include "json/json.h" + +#include "sensor_log.h" +#include "sensors_errors.h" + +namespace OHOS { +namespace Sensors { +namespace { +constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, Sensors::SENSOR_LOG_DOMAIN, "GenerateVibrationJsonFile" }; +} + +int32_t GenerateVibrationJsonFile::GenerateJsonFile(std::vector &hapticEvents) +{ + Json::Value meta; + meta["Create"] = "2023-04-27"; + meta["Discription"] = "A json file format demo"; + meta["Version"] = 1.0; + meta["ChannelNumber"] = 1; + Json::Value root; + root["MetaData"] = meta; + Json::Value pattern; + for (const auto &event : hapticEvents) { + Json::Value eventValue; + eventValue["Type"] = ((event.vibrateTag != EVENT_TAG_TRANSIENT) ? "continuous" : "transient"); + eventValue["StartTime"] = event.startTime; + eventValue["Parameters"]["Intensity"] = event.intensity; + eventValue["Parameters"]["Frequency"] = event.frequency; + if (event.vibrateTag != EVENT_TAG_TRANSIENT) { + eventValue["Duration"] = event.duration; + } + Json::Value ev; + ev["Event"] = eventValue; + pattern.append(ev); + } + Json::Value channel; + channel["Parameters"]["Index"] = 1; + channel["Pattern"] = pattern; + Json::Value channels; + channels.append(channel); + root["Channels"] = channels; + std::ofstream ofs("demo.json", std::ios::out); + if (!ofs.is_open()) { + SEN_HILOGE("File open failed, errno:%{public}d", errno); + return Sensors::ERROR; + } + ofs << root << std::endl; + ofs.close(); + return Sensors::SUCCESS; +} + +template +int32_t GenerateVibrationJsonFile::DebugJsonFile(const std::string &pathName, const std::vector &srcDatas) +{ + if (access(pathName.c_str(), 0) != 0) { + SEN_HILOGE("File not exist, errno:%{public}d", errno); + return Sensors::ERROR; + } + if (srcDatas.empty()) { + SEN_HILOGE("srcDatas is empty"); + return Sensors::ERROR; + } + Json::Value dataValue; + for (const auto &data : srcDatas) { + dataValue.append(data); + } + std::ofstream ofs(pathName, std::ios::out); + if (!ofs.is_open()) { + SEN_HILOGE("File open failed, errno:%{public}d", errno); + return Sensors::ERROR; + } + ofs << dataValue << std::endl; + ofs.close(); + return Sensors::SUCCESS; +} +} // namespace Sensors +} // namespace OHOS diff --git a/vibration_convert/core/native/test/unittest/data.h b/vibration_convert/core/native/test/unittest/data.h new file mode 100644 index 0000000000000000000000000000000000000000..ca3eb9ca34ee9a64e7d19d08f8e4e56f81f7eead --- /dev/null +++ b/vibration_convert/core/native/test/unittest/data.h @@ -0,0 +1,43 @@ +/* + * 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 UT_TEST_DATA_H +#define UT_TEST_DATA_H + +#include + +namespace OHOS { +namespace Sensors { +std::vector AudioSrcDatas = { + -1.07167597889201E-05, + 4.03729791287332E-06, + -7.82590905146207E-06, + 3.05969280134377E-07, + 7.12184328222065E-06, + -3.03215460917272E-06, + 9.08821220946265E-06, + 6.13942620475427E-06, + -0.000012067862371623, + -7.65803724789293E-06, + 1.38535085625335E-06, + -2.61832525438876E-07, + -1.25710883480678E-07, + 2.61069516227507E-07, + 0.00393714383244514, + 0.0 +}; +} // namespace Sensors +} // namespace OHOS +#endif // UT_TEST_DATA_H \ No newline at end of file diff --git a/vibration_convert/core/native/test/unittest/generate_json_test.cpp b/vibration_convert/core/native/test/unittest/generate_json_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..88735acb2ef940486d05c8e58996562146f8b923 --- /dev/null +++ b/vibration_convert/core/native/test/unittest/generate_json_test.cpp @@ -0,0 +1,108 @@ +/* + * 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. + */ + +#include + +#include + +#include "audio_utils.h" +#include "data.h" +#include "generate_vibration_json_file.h" +#include "sensor_log.h" +#include "sensors_errors.h" +#include "utils.h" +#include "vibration_convert_core.h" +#include "vibration_convert_type.h" + +namespace OHOS { +namespace Sensors { +using namespace testing::ext; +using namespace OHOS::HiviewDFX; + +namespace { + constexpr HiLogLabel LABEL = { LOG_CORE, OHOS::Sensors::SENSOR_LOG_DOMAIN, "GenerateJsonFileTest" }; +} // namespace + +class GenerateJsonFileTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp(); + void TearDown(); +}; + +void GenerateJsonFileTest::SetUpTestCase() {} + +void GenerateJsonFileTest::TearDownTestCase() {} + +void GenerateJsonFileTest::SetUp() {} + +void GenerateJsonFileTest::TearDown() {} + +HWTEST_F(GenerateJsonFileTest, GenerateJsonFileTest_001, TestSize.Level1) +{ + HapticEvent event = { + .tag = EVENT_TAG_TRANSIENT, + .startTime = 10, + .duration = 30, + .intensity = 90, + .frequency = 100 + }; + HapticEvent event1 = { + .tag = EVENT_TAG_CONTINUOUS, + .startTime = 40, + .duration = 56, + .intensity = 90, + .frequency = 100 + }; + HapticEvent event2 = { + .tag = EVENT_TAG_CONTINUOUS, + .startTime = 97, + .duration = 86, + .intensity = 77, + .frequency = 80 + }; + HapticEvent event3 = { + .tag = EVENT_TAG_TRANSIENT, + .startTime = 200, + .duration = 30, + .intensity = 44, + .frequency = 55 + }; + std::vector vtEvents; + vtEvents.push_back(event); + vtEvents.push_back(event1); + vtEvents.push_back(event2); + vtEvents.push_back(event3); + OHOS::Sensors::GenerateVibrationJsonFile generateJson; + int32_t ret = generateJson.GenerateJsonFile(vtEvents); + EXPECT_EQ(ret, 0); +} +HWTEST_F(GenerateJsonFileTest, GenerateJsonFileTest_002, TestSize.Level1) +{ + AudioSetting audioSetting; + audioSetting.transientDetection = 30; + audioSetting.intensityTreshold = 30; + audioSetting.frequencyTreshold = 50; + audioSetting.frequencyMaxValue = 80; + audioSetting.frequencyMinValue = 20; + std::vector data = AudioSrcDatas; + std::vector vtEvents = {}; + VibrationConvertCore vibrationConvertCore; + int32_t ret = vibrationConvertCore.ConvertAudioToHaptic(audioSetting, data, vtEvents); + EXPECT_EQ(ret, 0); +} +} // namespace Sensors +} // namespace OHOS \ No newline at end of file