Home | History | Annotate | Download | only in utility
      1 /*
      2  * Copyright 2017 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 AAUDIO_LINEAR_RAMP_H
     18 #define AAUDIO_LINEAR_RAMP_H
     19 
     20 #include <atomic>
     21 #include <stdint.h>
     22 
     23 /**
     24  * Generate segments along a linear ramp.
     25  * The ramp target can be updated from another thread.
     26  * When the target is updated, a new ramp is started from the current position.
     27  *
     28  * The first ramp starts at 0.0.
     29  *
     30  */
     31 class LinearRamp {
     32 public:
     33     LinearRamp() {
     34         mTarget.store(1.0f);
     35     }
     36 
     37     void setLengthInFrames(int32_t frames) {
     38         mLengthInFrames = frames;
     39     }
     40 
     41     int32_t getLengthInFrames() {
     42         return mLengthInFrames;
     43     }
     44 
     45     /**
     46      * This may be called by another thread.
     47      * @param target
     48      */
     49     void setTarget(float target) {
     50         mTarget.store(target);
     51     }
     52 
     53     float getTarget() {
     54         return mTarget.load();
     55     }
     56 
     57     /**
     58      * Force the nextSegment to start from this level.
     59      *
     60      * WARNING: this can cause a discontinuity if called while the ramp is being used.
     61      * Only call this when setting the initial ramp.
     62      *
     63      * @param level
     64      */
     65     void forceCurrent(float level) {
     66         mLevelFrom = level;
     67         mLevelTo = level; // forces a ramp if it does not match target
     68     }
     69 
     70     float getCurrent() {
     71         return mLevelFrom;
     72     }
     73 
     74     /**
     75      * Get levels for next ramp segment.
     76      *
     77      * @param frames number of frames in the segment
     78      * @param levelFrom pointer to starting amplitude
     79      * @param levelTo pointer to ending amplitude
     80      * @return true if ramp is still moving towards the target
     81      */
     82     bool nextSegment(int32_t frames, float *levelFrom, float *levelTo);
     83 
     84 private:
     85 
     86     bool isRamping();
     87 
     88     std::atomic<float>   mTarget;
     89 
     90     int32_t mLengthInFrames  = 48000 / 50; // 20 msec at 48000 Hz
     91     int32_t mRemaining       = 0;
     92     float   mLevelFrom       = 0.0f;
     93     float   mLevelTo         = 0.0f;
     94 };
     95 
     96 
     97 #endif //AAUDIO_LINEAR_RAMP_H
     98