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
16 #include "volume_ramp.h"
17 #include <cinttypes>
18 #include "audio_log.h"
19
20 namespace OHOS {
21 namespace AudioStandard {
22 using namespace std;
23 constexpr float MIN_CURVE_TIME = 0.0f;
24 constexpr float MAX_CURVE_TIME = 1.0f;
25 constexpr int32_t MS_PER_S = 1000;
26 constexpr int32_t NS_PER_MS = 1000000;
27 constexpr unsigned long VOLUME_SIZE = 2;
28
VolumeRamp()29 VolumeRamp::VolumeRamp()
30 {
31 initTime_ = -1;
32 isVolumeRampActive_ = false;
33 rampVolume_ = 1.0f;
34 }
35
SetVolumeCurve(vector<float> & volumes)36 void VolumeRamp::SetVolumeCurve(vector<float> &volumes)
37 {
38 vector<float> times = {0.0f, 1.0f};
39 CHECK_AND_RETURN_LOG(volumes.size() == VOLUME_SIZE, "Array size must 2!");
40
41 curvePoints_.clear();
42 for (size_t i = 0; i < times.size(); i++) {
43 curvePoints_.emplace(times[i], volumes[i]);
44 }
45 }
46
SetVolumeRampConfig(float targetVolume,float currStreamVolume,int32_t duration)47 void VolumeRamp::SetVolumeRampConfig(float targetVolume, float currStreamVolume, int32_t duration)
48 {
49 vector<float> volumes;
50
51 isVolumeRampActive_ = true;
52 initTime_ = -1;
53 duration_ = duration;
54
55 if (currStreamVolume > targetVolume) {
56 volumes.assign({targetVolume, currStreamVolume});
57 rampDirection_ = RAMP_DOWN;
58 } else {
59 volumes.assign({currStreamVolume, targetVolume});
60 rampDirection_ = RAMP_UP;
61 }
62 SetVolumeCurve(volumes);
63 }
64
GetCurrentTimeMS()65 static int64_t GetCurrentTimeMS()
66 {
67 timespec tm {};
68 clock_gettime(CLOCK_MONOTONIC, &tm);
69 return tm.tv_sec * MS_PER_S + (tm.tv_nsec / NS_PER_MS);
70 }
71
GetRampVolume()72 float VolumeRamp::GetRampVolume()
73 {
74 if (!isVolumeRampActive_) {
75 return rampVolume_;
76 }
77
78 int64_t currentTime = GetCurrentTimeMS();
79
80 if (initTime_ < 0) {
81 initTime_ = currentTime;
82 scale_ = 1.0 / duration_;
83 }
84
85 float scaledTime = GetScaledTime(currentTime);
86 rampVolume_ = FindRampVolume(scaledTime);
87 return rampVolume_;
88 }
89
GetScaledTime(int64_t currentTime)90 float VolumeRamp::GetScaledTime(int64_t currentTime)
91 {
92 float offset = scale_ * (currentTime - initTime_);
93 if (rampDirection_ == RAMP_DOWN) {
94 offset = 1 - offset;
95 if (offset < MIN_CURVE_TIME) {
96 offset = MIN_CURVE_TIME;
97 isVolumeRampActive_ = false;
98 } else if (offset > MAX_CURVE_TIME) {
99 offset = MAX_CURVE_TIME;
100 }
101 } else {
102 if (offset < MIN_CURVE_TIME) {
103 offset = MIN_CURVE_TIME;
104 } else if (offset > MAX_CURVE_TIME) {
105 offset = MAX_CURVE_TIME;
106 isVolumeRampActive_ = false;
107 }
108 }
109
110 return offset;
111 }
112
FindRampVolume(float time)113 float VolumeRamp::FindRampVolume(float time)
114 {
115 auto lowPoint = curvePoints_.begin();
116 auto highPoint = curvePoints_.rbegin();
117
118 float volume = lowPoint->second + ((time - lowPoint->first) / (highPoint->first - lowPoint->first))
119 * (highPoint->second - lowPoint->second);
120 return volume;
121 }
122
IsActive()123 bool VolumeRamp::IsActive()
124 {
125 return isVolumeRampActive_;
126 }
127
Terminate()128 void VolumeRamp::Terminate()
129 {
130 isVolumeRampActive_ = false;
131 }
132 } // namespace AudioStandard
133 } // namespace OHOS
134