1135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent/* //device/servers/AudioFlinger/AudioBiquadFilter.cpp 2135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent** 3135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent** Copyright 2009, The Android Open Source Project 4135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent** 5135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent** Licensed under the Apache License, Version 2.0 (the "License"); 6135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent** you may not use this file except in compliance with the License. 7135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent** You may obtain a copy of the License at 8135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent** 9135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent** http://www.apache.org/licenses/LICENSE-2.0 10135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent** 11135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent** Unless required by applicable law or agreed to in writing, software 12135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent** distributed under the License is distributed on an "AS IS" BASIS, 13135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent** See the License for the specific language governing permissions and 15135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent** limitations under the License. 16135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent*/ 17135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent 18135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent#include <string.h> 19135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent#include <assert.h> 20f6b1678f8f508b447155a81b44e214475ab634a8Glenn Kasten#include <cutils/compiler.h> 21135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent 22135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent#include "AudioBiquadFilter.h" 23135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent 24135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurentnamespace android { 25135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent 26135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurentconst audio_coef_t AudioBiquadFilter::IDENTITY_COEFS[AudioBiquadFilter::NUM_COEFS] = { AUDIO_COEF_ONE, 0, 0, 0, 0 }; 27135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent 28135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric LaurentAudioBiquadFilter::AudioBiquadFilter(int nChannels, int sampleRate) { 29135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent configure(nChannels, sampleRate); 30135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent reset(); 31135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent} 32135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent 33135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurentvoid AudioBiquadFilter::configure(int nChannels, int sampleRate) { 34135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent assert(nChannels > 0 && nChannels <= MAX_CHANNELS); 35135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent assert(sampleRate > 0); 36135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent mNumChannels = nChannels; 37135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent mMaxDelta = static_cast<int64_t>(MAX_DELTA_PER_SEC) 38135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent * AUDIO_COEF_ONE 39135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent / sampleRate; 40135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent clear(); 41135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent} 42135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent 43135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurentvoid AudioBiquadFilter::reset() { 44135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent memcpy(mCoefs, IDENTITY_COEFS, sizeof(mCoefs)); 45135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent mCoefDirtyBits = 0; 46135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent setState(STATE_BYPASS); 47135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent} 48135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent 49135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurentvoid AudioBiquadFilter::clear() { 50135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent memset(mDelays, 0, sizeof(mDelays)); 51135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent} 52135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent 53135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurentvoid AudioBiquadFilter::setCoefs(const audio_coef_t coefs[NUM_COEFS], bool immediate) { 54135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent memcpy(mTargetCoefs, coefs, sizeof(mTargetCoefs)); 55135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent if (mState & STATE_ENABLED_MASK) { 56f6b1678f8f508b447155a81b44e214475ab634a8Glenn Kasten if (CC_UNLIKELY(immediate)) { 57135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent memcpy(mCoefs, coefs, sizeof(mCoefs)); 58135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent setState(STATE_NORMAL); 59135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent } else { 60135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent setState(STATE_TRANSITION_TO_NORMAL); 61135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent } 62135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent } 63135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent} 64135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent 65135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurentvoid AudioBiquadFilter::process(const audio_sample_t in[], audio_sample_t out[], 66135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent int frameCount) { 67135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent (this->*mCurProcessFunc)(in, out, frameCount); 68135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent} 69135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent 70135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurentvoid AudioBiquadFilter::enable(bool immediate) { 71f6b1678f8f508b447155a81b44e214475ab634a8Glenn Kasten if (CC_UNLIKELY(immediate)) { 72135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent memcpy(mCoefs, mTargetCoefs, sizeof(mCoefs)); 73135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent setState(STATE_NORMAL); 74135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent } else { 75135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent setState(STATE_TRANSITION_TO_NORMAL); 76135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent } 77135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent} 78135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent 79135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurentvoid AudioBiquadFilter::disable(bool immediate) { 80f6b1678f8f508b447155a81b44e214475ab634a8Glenn Kasten if (CC_UNLIKELY(immediate)) { 81135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent memcpy(mCoefs, IDENTITY_COEFS, sizeof(mCoefs)); 82135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent setState(STATE_BYPASS); 83135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent } else { 84135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent setState(STATE_TRANSITION_TO_BYPASS); 85135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent } 86135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent} 87135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent 88135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurentvoid AudioBiquadFilter::setState(state_t state) { 89135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent switch (state) { 90135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent case STATE_BYPASS: 91135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent mCurProcessFunc = &AudioBiquadFilter::process_bypass; 92135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent break; 93135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent case STATE_TRANSITION_TO_BYPASS: 94135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent if (mNumChannels == 1) { 95135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent mCurProcessFunc = &AudioBiquadFilter::process_transition_bypass_mono; 96135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent } else { 97135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent mCurProcessFunc = &AudioBiquadFilter::process_transition_bypass_multi; 98135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent } 99135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent mCoefDirtyBits = (1 << NUM_COEFS) - 1; 100135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent break; 101135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent case STATE_TRANSITION_TO_NORMAL: 102135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent if (mNumChannels == 1) { 103135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent mCurProcessFunc = &AudioBiquadFilter::process_transition_normal_mono; 104135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent } else { 105135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent mCurProcessFunc = &AudioBiquadFilter::process_transition_normal_multi; 106135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent } 107135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent mCoefDirtyBits = (1 << NUM_COEFS) - 1; 108135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent break; 109135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent case STATE_NORMAL: 110135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent if (mNumChannels == 1) { 111135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent mCurProcessFunc = &AudioBiquadFilter::process_normal_mono; 112135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent } else { 113135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent mCurProcessFunc = &AudioBiquadFilter::process_normal_multi; 114135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent } 115135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent break; 116135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent } 117135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent mState = state; 118135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent} 119135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent 120135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurentbool AudioBiquadFilter::updateCoefs(const audio_coef_t coefs[NUM_COEFS], 121135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent int frameCount) { 122135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent int64_t maxDelta = mMaxDelta * frameCount; 123135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent for (int i = 0; i < NUM_COEFS; ++i) { 124135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent if (mCoefDirtyBits & (1<<i)) { 125135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent audio_coef_t diff = coefs[i] - mCoefs[i]; 126135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent if (diff > maxDelta) { 127135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent mCoefs[i] += maxDelta; 128135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent } else if (diff < -maxDelta) { 129135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent mCoefs[i] -= maxDelta; 130135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent } else { 131135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent mCoefs[i] = coefs[i]; 132135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent mCoefDirtyBits ^= (1<<i); 133135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent } 134135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent } 135135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent } 136135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent return mCoefDirtyBits == 0; 137135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent} 138135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent 139135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurentvoid AudioBiquadFilter::process_bypass(const audio_sample_t * in, 140135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent audio_sample_t * out, 141135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent int frameCount) { 142135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent // The common case is in-place processing, because this is what the EQ does. 143f6b1678f8f508b447155a81b44e214475ab634a8Glenn Kasten if (CC_UNLIKELY(in != out)) { 144135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent memcpy(out, in, frameCount * mNumChannels * sizeof(audio_sample_t)); 145135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent } 146135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent} 147135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent 148135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurentvoid AudioBiquadFilter::process_normal_mono(const audio_sample_t * in, 149135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent audio_sample_t * out, 150135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent int frameCount) { 151135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent size_t nFrames = frameCount; 152135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent audio_sample_t x1 = mDelays[0][0]; 153135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent audio_sample_t x2 = mDelays[0][1]; 154135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent audio_sample_t y1 = mDelays[0][2]; 155135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent audio_sample_t y2 = mDelays[0][3]; 156135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent const audio_coef_t b0 = mCoefs[0]; 157135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent const audio_coef_t b1 = mCoefs[1]; 158135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent const audio_coef_t b2 = mCoefs[2]; 159135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent const audio_coef_t a1 = mCoefs[3]; 160135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent const audio_coef_t a2 = mCoefs[4]; 161135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent while (nFrames-- > 0) { 162135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent audio_sample_t x0 = *(in++); 163135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent audio_coef_sample_acc_t acc; 164135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent acc = mul_coef_sample(b0, x0); 165135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent acc = mac_coef_sample(b1, x1, acc); 166135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent acc = mac_coef_sample(b2, x2, acc); 167135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent acc = mac_coef_sample(a1, y1, acc); 168135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent acc = mac_coef_sample(a2, y2, acc); 169135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent audio_sample_t y0 = coef_sample_acc_to_sample(acc); 170135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent y2 = y1; 171135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent y1 = y0; 172135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent x2 = x1; 173135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent x1 = x0; 174135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent (*out++) = y0; 175135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent } 176135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent mDelays[0][0] = x1; 177135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent mDelays[0][1] = x2; 178135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent mDelays[0][2] = y1; 179135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent mDelays[0][3] = y2; 180135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent} 181135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent 182135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurentvoid AudioBiquadFilter::process_transition_normal_mono(const audio_sample_t * in, 183135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent audio_sample_t * out, 184135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent int frameCount) { 185135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent if (updateCoefs(mTargetCoefs, frameCount)) { 186135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent setState(STATE_NORMAL); 187135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent } 188135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent process_normal_mono(in, out, frameCount); 189135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent} 190135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent 191135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurentvoid AudioBiquadFilter::process_transition_bypass_mono(const audio_sample_t * in, 192135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent audio_sample_t * out, 193135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent int frameCount) { 194135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent if (updateCoefs(IDENTITY_COEFS, frameCount)) { 195135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent setState(STATE_NORMAL); 196135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent } 197135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent process_normal_mono(in, out, frameCount); 198135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent} 199135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent 200135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurentvoid AudioBiquadFilter::process_normal_multi(const audio_sample_t * in, 201135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent audio_sample_t * out, 202135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent int frameCount) { 203135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent const audio_coef_t b0 = mCoefs[0]; 204135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent const audio_coef_t b1 = mCoefs[1]; 205135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent const audio_coef_t b2 = mCoefs[2]; 206135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent const audio_coef_t a1 = mCoefs[3]; 207135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent const audio_coef_t a2 = mCoefs[4]; 208135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent for (int ch = 0; ch < mNumChannels; ++ch) { 209135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent size_t nFrames = frameCount; 210135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent audio_sample_t x1 = mDelays[ch][0]; 211135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent audio_sample_t x2 = mDelays[ch][1]; 212135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent audio_sample_t y1 = mDelays[ch][2]; 213135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent audio_sample_t y2 = mDelays[ch][3]; 214135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent while (nFrames-- > 0) { 215135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent audio_sample_t x0 = *in; 216135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent audio_coef_sample_acc_t acc; 217135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent acc = mul_coef_sample(b0, x0); 218135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent acc = mac_coef_sample(b1, x1, acc); 219135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent acc = mac_coef_sample(b2, x2, acc); 220135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent acc = mac_coef_sample(a1, y1, acc); 221135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent acc = mac_coef_sample(a2, y2, acc); 222135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent audio_sample_t y0 = coef_sample_acc_to_sample(acc); 223135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent y2 = y1; 224135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent y1 = y0; 225135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent x2 = x1; 226135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent x1 = x0; 227135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent *out = y0; 228135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent in += mNumChannels; 229135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent out += mNumChannels; 230135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent } 231135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent mDelays[ch][0] = x1; 232135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent mDelays[ch][1] = x2; 233135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent mDelays[ch][2] = y1; 234135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent mDelays[ch][3] = y2; 235135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent in -= frameCount * mNumChannels - 1; 236135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent out -= frameCount * mNumChannels - 1; 237135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent } 238135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent} 239135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent 240135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurentvoid AudioBiquadFilter::process_transition_normal_multi(const audio_sample_t * in, 241135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent audio_sample_t * out, 242135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent int frameCount) { 243135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent if (updateCoefs(mTargetCoefs, frameCount)) { 244135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent setState(STATE_NORMAL); 245135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent } 246135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent process_normal_multi(in, out, frameCount); 247135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent} 248135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent 249135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurentvoid AudioBiquadFilter::process_transition_bypass_multi(const audio_sample_t * in, 250135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent audio_sample_t * out, 251135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent int frameCount) { 252135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent if (updateCoefs(IDENTITY_COEFS, frameCount)) { 253135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent setState(STATE_NORMAL); 254135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent } 255135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent process_normal_multi(in, out, frameCount); 256135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent} 257135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent 258135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent} 259