1e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk/* 2e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk * Copyright 2017 The Android Open Source Project 3e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk * 4e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk * Licensed under the Apache License, Version 2.0 (the "License"); 5e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk * you may not use this file except in compliance with the License. 6e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk * You may obtain a copy of the License at 7e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk * 8e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk * http://www.apache.org/licenses/LICENSE-2.0 9e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk * 10e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk * Unless required by applicable law or agreed to in writing, software 11e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk * distributed under the License is distributed on an "AS IS" BASIS, 12e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk * See the License for the specific language governing permissions and 14e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk * limitations under the License. 15e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk */ 16e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk 17e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk#ifndef AAUDIO_LINEAR_RAMP_H 18e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk#define AAUDIO_LINEAR_RAMP_H 19e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk 20e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk#include <atomic> 21e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk#include <stdint.h> 22e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk 23e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk/** 24e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk * Generate segments along a linear ramp. 25e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk * The ramp target can be updated from another thread. 26e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk * When the target is updated, a new ramp is started from the current position. 27e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk * 28e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk * The first ramp starts at 0.0. 29e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk * 30e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk */ 31e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burkclass LinearRamp { 32e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burkpublic: 33e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk LinearRamp() { 34e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk mTarget.store(1.0f); 35e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk } 36e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk 37e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk void setLengthInFrames(int32_t frames) { 38e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk mLengthInFrames = frames; 39e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk } 40e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk 41e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk int32_t getLengthInFrames() { 42e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk return mLengthInFrames; 43e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk } 44e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk 45e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk /** 46e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk * This may be called by another thread. 47e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk * @param target 48e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk */ 49e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk void setTarget(float target) { 50e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk mTarget.store(target); 51e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk } 52e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk 53e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk float getTarget() { 54e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk return mTarget.load(); 55e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk } 56e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk 57e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk /** 58e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk * Force the nextSegment to start from this level. 59e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk * 60e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk * WARNING: this can cause a discontinuity if called while the ramp is being used. 61e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk * Only call this when setting the initial ramp. 62e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk * 63e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk * @param level 64e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk */ 65e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk void forceCurrent(float level) { 66e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk mLevelFrom = level; 67e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk mLevelTo = level; // forces a ramp if it does not match target 68e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk } 69e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk 70e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk float getCurrent() { 71e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk return mLevelFrom; 72e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk } 73e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk 74e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk /** 75e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk * Get levels for next ramp segment. 76e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk * 77e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk * @param frames number of frames in the segment 78e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk * @param levelFrom pointer to starting amplitude 79e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk * @param levelTo pointer to ending amplitude 80e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk * @return true if ramp is still moving towards the target 81e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk */ 82e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk bool nextSegment(int32_t frames, float *levelFrom, float *levelTo); 83e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk 84e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burkprivate: 85e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk 86e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk bool isRamping(); 87e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk 88e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk std::atomic<float> mTarget; 89e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk 90e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk int32_t mLengthInFrames = 48000 / 50; // 20 msec at 48000 Hz 91e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk int32_t mRemaining = 0; 92e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk float mLevelFrom = 0.0f; 93e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk float mLevelTo = 0.0f; 94e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk}; 95e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk 96e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk 97e572f469de5dca1078a79d3d80e5b04f96ae7505Phil Burk#endif //AAUDIO_LINEAR_RAMP_H 98