1 /*
2  * Copyright 2015 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef FLOWGRAPH_RAMP_LINEAR_H
18 #define FLOWGRAPH_RAMP_LINEAR_H
19 
20 #include <atomic>
21 #include <unistd.h>
22 #include <sys/types.h>
23 
24 #include "FlowGraphNode.h"
25 
26 namespace FLOWGRAPH_OUTER_NAMESPACE::flowgraph {
27 
28 /**
29  * When the target is modified then the output will ramp smoothly
30  * between the original and the new target value.
31  * This can be used to smooth out control values and reduce pops.
32  *
33  * The target may be updated while a ramp is in progress, which will trigger
34  * a new ramp from the current value.
35  */
36 class RampLinear : public FlowGraphFilter {
37 public:
38     explicit RampLinear(int32_t channelCount);
39 
40     virtual ~RampLinear() = default;
41 
42     int32_t onProcess(int32_t numFrames) override;
43 
44     /**
45      * This is used for the next ramp.
46      * Calling this does not affect a ramp that is in progress.
47      */
48     void setLengthInFrames(int32_t frames);
49 
getLengthInFrames()50     int32_t getLengthInFrames() const {
51         return mLengthInFrames;
52     }
53 
54     /**
55      * This may be safely called by another thread.
56      * @param target
57      */
58     void setTarget(float target);
59 
getTarget()60     float getTarget() const {
61         return mTarget.load();
62     }
63 
64     /**
65      * Force the nextSegment to start from this level.
66      *
67      * WARNING: this can cause a discontinuity if called while the ramp is being used.
68      * Only call this when setting the initial ramp.
69      *
70      * @param level
71      */
forceCurrent(float level)72     void forceCurrent(float level) {
73         mLevelFrom = level;
74         mLevelTo = level;
75     }
76 
getName()77     const char *getName() override {
78         return "RampLinear";
79     }
80 
81 private:
82 
83     float interpolateCurrent();
84 
85     std::atomic<float>  mTarget;
86 
87     int32_t             mLengthInFrames  = 48000.0f / 100.0f ; // 10 msec at 48000 Hz;
88     int32_t             mRemaining       = 0;
89     float               mScaler          = 0.0f;
90     float               mLevelFrom       = 0.0f;
91     float               mLevelTo         = 0.0f;
92 };
93 
94 } /* namespace FLOWGRAPH_OUTER_NAMESPACE::flowgraph */
95 
96 #endif //FLOWGRAPH_RAMP_LINEAR_H
97