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 #define LOG_TAG "RampLinear" 18 //#define LOG_NDEBUG 0 19 #include <utils/Log.h> 20 21 #include <algorithm> 22 #include <unistd.h> 23 #include "FlowGraphNode.h" 24 #include "RampLinear.h" 25 26 using namespace FLOWGRAPH_OUTER_NAMESPACE::flowgraph; 27 RampLinear(int32_t channelCount)28RampLinear::RampLinear(int32_t channelCount) 29 : FlowGraphFilter(channelCount) { 30 mTarget.store(1.0f); 31 } 32 setLengthInFrames(int32_t frames)33void RampLinear::setLengthInFrames(int32_t frames) { 34 mLengthInFrames = frames; 35 } 36 setTarget(float target)37void RampLinear::setTarget(float target) { 38 if (std::isnan(target)) { 39 ALOGE("%s rejected to set target as nan", __func__); 40 return; 41 } 42 mTarget.store(target); 43 // If the ramp has not been used then start immediately at this level. 44 if (mLastCallCount == kInitialCallCount) { 45 forceCurrent(target); 46 } 47 } 48 interpolateCurrent()49float RampLinear::interpolateCurrent() { 50 return mLevelTo - (mRemaining * mScaler); 51 } 52 onProcess(int32_t numFrames)53int32_t RampLinear::onProcess(int32_t numFrames) { 54 const float *inputBuffer = input.getBuffer(); 55 float *outputBuffer = output.getBuffer(); 56 int32_t channelCount = output.getSamplesPerFrame(); 57 58 float target = getTarget(); 59 if (target != mLevelTo) { 60 // Start new ramp. Continue from previous level. 61 mLevelFrom = interpolateCurrent(); 62 mLevelTo = target; 63 mRemaining = mLengthInFrames; 64 mScaler = (mLevelTo - mLevelFrom) / mLengthInFrames; // for interpolation 65 } 66 67 int32_t framesLeft = numFrames; 68 69 if (mRemaining > 0) { // Ramping? This doesn't happen very often. 70 int32_t framesToRamp = std::min(framesLeft, mRemaining); 71 framesLeft -= framesToRamp; 72 while (framesToRamp > 0) { 73 float currentLevel = interpolateCurrent(); 74 for (int ch = 0; ch < channelCount; ch++) { 75 *outputBuffer++ = *inputBuffer++ * currentLevel; 76 } 77 mRemaining--; 78 framesToRamp--; 79 } 80 } 81 82 // Process any frames after the ramp. 83 int32_t samplesLeft = framesLeft * channelCount; 84 for (int i = 0; i < samplesLeft; i++) { 85 *outputBuffer++ = *inputBuffer++ * mLevelTo; 86 } 87 88 return numFrames; 89 } 90