1 /*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #ifndef LOG_TAG
16 #define LOG_TAG "VolumeRamp"
17 #endif
18
19 #include "volume_ramp.h"
20 #include <cinttypes>
21 #include "audio_common_log.h"
22
23 namespace OHOS {
24 namespace AudioStandard {
25 using namespace std;
26 constexpr float MIN_CURVE_TIME = 0.0f;
27 constexpr float MAX_CURVE_TIME = 1.0f;
28 constexpr int32_t MS_PER_S = 1000;
29 constexpr int32_t NS_PER_MS = 1000000;
30 constexpr unsigned long VOLUME_SIZE = 2;
31
VolumeRamp()32 VolumeRamp::VolumeRamp()
33 {
34 initTime_ = -1;
35 isVolumeRampActive_ = false;
36 rampVolume_ = 1.0f;
37 }
38
SetVolumeCurve(vector<float> & volumes)39 void VolumeRamp::SetVolumeCurve(vector<float> &volumes)
40 {
41 vector<float> times = {0.0f, 1.0f};
42 CHECK_AND_RETURN_LOG(volumes.size() == VOLUME_SIZE, "Array size must 2!");
43
44 std::lock_guard<std::mutex> lock(curveMapMutex_);
45 curvePoints_.clear();
46 for (size_t i = 0; i < times.size(); i++) {
47 curvePoints_.emplace(times[i], volumes[i]);
48 }
49 }
50
SetVolumeRampConfig(float targetVolume,float currStreamVolume,int32_t duration)51 void VolumeRamp::SetVolumeRampConfig(float targetVolume, float currStreamVolume, int32_t duration)
52 {
53 vector<float> volumes;
54
55 isVolumeRampActive_ = true;
56 initTime_ = -1;
57 duration_ = duration;
58
59 if (currStreamVolume > targetVolume) {
60 volumes.assign({targetVolume, currStreamVolume});
61 rampDirection_ = RAMP_DOWN;
62 } else {
63 volumes.assign({currStreamVolume, targetVolume});
64 rampDirection_ = RAMP_UP;
65 }
66 SetVolumeCurve(volumes);
67 }
68
GetCurrentTimeMS()69 static int64_t GetCurrentTimeMS()
70 {
71 timespec tm {};
72 clock_gettime(CLOCK_MONOTONIC, &tm);
73 return tm.tv_sec * MS_PER_S + (tm.tv_nsec / NS_PER_MS);
74 }
75
GetRampVolume()76 float VolumeRamp::GetRampVolume()
77 {
78 if (!isVolumeRampActive_) {
79 return rampVolume_;
80 }
81
82 int64_t currentTime = GetCurrentTimeMS();
83
84 if (initTime_ < 0) {
85 initTime_ = currentTime;
86 scale_ = 1.0 / duration_;
87 }
88
89 float scaledTime = GetScaledTime(currentTime);
90 rampVolume_ = FindRampVolume(scaledTime);
91 return rampVolume_;
92 }
93
GetScaledTime(int64_t currentTime)94 float VolumeRamp::GetScaledTime(int64_t currentTime)
95 {
96 float offset = scale_ * (currentTime - initTime_);
97 if (rampDirection_ == RAMP_DOWN) {
98 offset = 1 - offset;
99 if (offset < MIN_CURVE_TIME) {
100 offset = MIN_CURVE_TIME;
101 isVolumeRampActive_ = false;
102 } else if (offset > MAX_CURVE_TIME) {
103 offset = MAX_CURVE_TIME;
104 }
105 } else {
106 if (offset < MIN_CURVE_TIME) {
107 offset = MIN_CURVE_TIME;
108 } else if (offset > MAX_CURVE_TIME) {
109 offset = MAX_CURVE_TIME;
110 isVolumeRampActive_ = false;
111 }
112 }
113
114 return offset;
115 }
116
FindRampVolume(float time)117 float VolumeRamp::FindRampVolume(float time)
118 {
119 std::lock_guard<std::mutex> lock(curveMapMutex_);
120 CHECK_AND_RETURN_RET_LOG(!curvePoints_.empty(), 0.0f, "Curve points map is empty");
121
122 auto lowPoint = curvePoints_.begin();
123 auto highPoint = curvePoints_.rbegin();
124
125 float volume = lowPoint->second + ((time - lowPoint->first) / (highPoint->first - lowPoint->first))
126 * (highPoint->second - lowPoint->second);
127 return volume;
128 }
129
IsActive()130 bool VolumeRamp::IsActive()
131 {
132 return isVolumeRampActive_;
133 }
134
Terminate()135 void VolumeRamp::Terminate()
136 {
137 isVolumeRampActive_ = false;
138 }
139 } // namespace AudioStandard
140 } // namespace OHOS
141