150a07fd2Sopenharmony_ci/*
250a07fd2Sopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd.
350a07fd2Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
450a07fd2Sopenharmony_ci * you may not use this file except in compliance with the License.
550a07fd2Sopenharmony_ci * You may obtain a copy of the License at
650a07fd2Sopenharmony_ci *
750a07fd2Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
850a07fd2Sopenharmony_ci *
950a07fd2Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
1050a07fd2Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
1150a07fd2Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1250a07fd2Sopenharmony_ci * See the License for the specific language governing permissions and
1350a07fd2Sopenharmony_ci * limitations under the License.
1450a07fd2Sopenharmony_ci */
1550a07fd2Sopenharmony_ci
1650a07fd2Sopenharmony_ci#include "daudio_latency_test.h"
1750a07fd2Sopenharmony_ci
1850a07fd2Sopenharmony_ci#include <ctime>
1950a07fd2Sopenharmony_ci#include <string>
2050a07fd2Sopenharmony_ci
2150a07fd2Sopenharmony_ci#include "daudio_errorcode.h"
2250a07fd2Sopenharmony_ci#include "daudio_log.h"
2350a07fd2Sopenharmony_ci#include "daudio_util.h"
2450a07fd2Sopenharmony_ci
2550a07fd2Sopenharmony_ci#undef DH_LOG_TAG
2650a07fd2Sopenharmony_ci#define DH_LOG_TAG "DAudioLatencyTest"
2750a07fd2Sopenharmony_cinamespace OHOS {
2850a07fd2Sopenharmony_cinamespace DistributedHardware {
2950a07fd2Sopenharmony_ciIMPLEMENT_SINGLE_INSTANCE(DAudioLatencyTest);
3050a07fd2Sopenharmony_ciconstexpr int32_t MAXSIZE = 8192;
3150a07fd2Sopenharmony_ci
3250a07fd2Sopenharmony_ciDAudioLatencyTest::DAudioLatencyTest()
3350a07fd2Sopenharmony_ci{
3450a07fd2Sopenharmony_ci    DHLOGI("DAudioLatencyTest constructed.");
3550a07fd2Sopenharmony_ci}
3650a07fd2Sopenharmony_ci
3750a07fd2Sopenharmony_ciDAudioLatencyTest::~DAudioLatencyTest()
3850a07fd2Sopenharmony_ci{
3950a07fd2Sopenharmony_ci    DHLOGI("DAudioLatencyTest deconstructed.");
4050a07fd2Sopenharmony_ci}
4150a07fd2Sopenharmony_ci
4250a07fd2Sopenharmony_ciint32_t DAudioLatencyTest::AddPlayTime(const int64_t playBeepTime)
4350a07fd2Sopenharmony_ci{
4450a07fd2Sopenharmony_ci    if (GetNowTimeUs() - lastPlayTime_ <= TWO_BEEP_TIME_INTERVAL) {
4550a07fd2Sopenharmony_ci        DHLOGE("Catch play high frame, but not in %{public}d ms.", TWO_BEEP_TIME_INTERVAL);
4650a07fd2Sopenharmony_ci        return ERR_DH_AUDIO_FAILED;
4750a07fd2Sopenharmony_ci    }
4850a07fd2Sopenharmony_ci    DHLOGI("Catch play high frame, playTime: %{public}" PRId64, playBeepTime);
4950a07fd2Sopenharmony_ci    playBeepTime_.push_back(playBeepTime);
5050a07fd2Sopenharmony_ci    lastPlayTime_ = GetNowTimeUs();
5150a07fd2Sopenharmony_ci    return DH_SUCCESS;
5250a07fd2Sopenharmony_ci}
5350a07fd2Sopenharmony_ci
5450a07fd2Sopenharmony_ciint32_t DAudioLatencyTest::AddRecordTime(const int64_t recordBeepTime)
5550a07fd2Sopenharmony_ci{
5650a07fd2Sopenharmony_ci    if (captureBeepTime_.size() >= playBeepTime_.size()) {
5750a07fd2Sopenharmony_ci        DHLOGE("Catch record high frame size error, capturesize %{public}zu, playsize %{public}zu.",
5850a07fd2Sopenharmony_ci            captureBeepTime_.size(), playBeepTime_.size());
5950a07fd2Sopenharmony_ci        return ERR_DH_AUDIO_BAD_VALUE;
6050a07fd2Sopenharmony_ci    }
6150a07fd2Sopenharmony_ci    if (GetNowTimeUs() - lastRecordTime_ <= TWO_BEEP_TIME_INTERVAL) {
6250a07fd2Sopenharmony_ci        DHLOGE("Catch record high frame, but not in %{public}d ms.", TWO_BEEP_TIME_INTERVAL);
6350a07fd2Sopenharmony_ci        return ERR_DH_AUDIO_FAILED;
6450a07fd2Sopenharmony_ci    }
6550a07fd2Sopenharmony_ci    DHLOGI("Catch record high frame, recordTime: %{public}" PRId64, recordBeepTime);
6650a07fd2Sopenharmony_ci    captureBeepTime_.push_back(recordBeepTime);
6750a07fd2Sopenharmony_ci    lastRecordTime_ = GetNowTimeUs();
6850a07fd2Sopenharmony_ci    return DH_SUCCESS;
6950a07fd2Sopenharmony_ci}
7050a07fd2Sopenharmony_ci
7150a07fd2Sopenharmony_cibool DAudioLatencyTest::IsFrameHigh(const int16_t *audioData, const int32_t size, int32_t threshhold)
7250a07fd2Sopenharmony_ci{
7350a07fd2Sopenharmony_ci    if (size > MAXSIZE) {
7450a07fd2Sopenharmony_ci        DHLOGI("size=%{public}d is over range", size);
7550a07fd2Sopenharmony_ci        return false;
7650a07fd2Sopenharmony_ci    }
7750a07fd2Sopenharmony_ci    int32_t max = 0;
7850a07fd2Sopenharmony_ci    for (int32_t i = 0; i < size; i++) {
7950a07fd2Sopenharmony_ci        int16_t f = abs(audioData[i]);
8050a07fd2Sopenharmony_ci        if (f > max) {
8150a07fd2Sopenharmony_ci            max = f;
8250a07fd2Sopenharmony_ci        }
8350a07fd2Sopenharmony_ci    }
8450a07fd2Sopenharmony_ci    return (max >= threshhold) ? true : false;
8550a07fd2Sopenharmony_ci}
8650a07fd2Sopenharmony_ci
8750a07fd2Sopenharmony_ciint64_t DAudioLatencyTest::RecordBeepTime(const uint8_t *base, const int32_t &sizePerFrame, bool &status)
8850a07fd2Sopenharmony_ci{
8950a07fd2Sopenharmony_ci    int32_t threshhold = BEEP_THRESHHOLD;
9050a07fd2Sopenharmony_ci    bool isHigh = IsFrameHigh(reinterpret_cast<int16_t *>(const_cast<uint8_t *>(base)),
9150a07fd2Sopenharmony_ci        sizePerFrame / sizeof(int16_t), threshhold);
9250a07fd2Sopenharmony_ci    if (isHigh && status) {
9350a07fd2Sopenharmony_ci        status = false;
9450a07fd2Sopenharmony_ci        return GetNowTimeUs();
9550a07fd2Sopenharmony_ci    } else if (!isHigh) {
9650a07fd2Sopenharmony_ci        status = true;
9750a07fd2Sopenharmony_ci    }
9850a07fd2Sopenharmony_ci    return 0;
9950a07fd2Sopenharmony_ci}
10050a07fd2Sopenharmony_ci
10150a07fd2Sopenharmony_ciint32_t DAudioLatencyTest::ComputeLatency()
10250a07fd2Sopenharmony_ci{
10350a07fd2Sopenharmony_ci    DHLOGD("Compute latency time.");
10450a07fd2Sopenharmony_ci    int32_t playSize = static_cast<int32_t>(playBeepTime_.size());
10550a07fd2Sopenharmony_ci    int32_t captureSize = static_cast<int32_t>(captureBeepTime_.size());
10650a07fd2Sopenharmony_ci    if (playSize == 0 || playBeepTime_.size() != captureBeepTime_.size()) {
10750a07fd2Sopenharmony_ci        DHLOGE("Record num is not equal %{public}d: %{public}d", playSize, captureSize);
10850a07fd2Sopenharmony_ci        return -1;
10950a07fd2Sopenharmony_ci    }
11050a07fd2Sopenharmony_ci    DHLOGI("Record %{public}d times frame high.", playSize);
11150a07fd2Sopenharmony_ci    int32_t sum = 0;
11250a07fd2Sopenharmony_ci    for (int32_t i = 0; i < playSize; i++) {
11350a07fd2Sopenharmony_ci        DHLOGI("Send: %{public}" PRId64", Received: %{public}" PRId64, playBeepTime_[i], captureBeepTime_[i]);
11450a07fd2Sopenharmony_ci        DHLOGI("Time is: %{public}" PRId64" ms.", (captureBeepTime_[i] - playBeepTime_[i]) / US_PER_MS);
11550a07fd2Sopenharmony_ci        sum += captureBeepTime_[i] - playBeepTime_[i];
11650a07fd2Sopenharmony_ci    }
11750a07fd2Sopenharmony_ci    DHLOGI("Audio latency in average is: %{public}d us.", sum / playSize);
11850a07fd2Sopenharmony_ci    playBeepTime_.clear();
11950a07fd2Sopenharmony_ci    captureBeepTime_.clear();
12050a07fd2Sopenharmony_ci    return sum / playSize;
12150a07fd2Sopenharmony_ci}
12250a07fd2Sopenharmony_ci} // namespace DistributedHardware
12350a07fd2Sopenharmony_ci} // namespace OHOS
124