AudioBiquadFilter.cpp revision 135ad07e33d30e5202deb21061a0e3ecf0ffad35
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> 20135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent 21135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent#include "AudioBiquadFilter.h" 22135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent 23135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true )) 24135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false )) 25135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent 26135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurentnamespace android { 27135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent 28135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurentconst audio_coef_t AudioBiquadFilter::IDENTITY_COEFS[AudioBiquadFilter::NUM_COEFS] = { AUDIO_COEF_ONE, 0, 0, 0, 0 }; 29135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent 30135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric LaurentAudioBiquadFilter::AudioBiquadFilter(int nChannels, int sampleRate) { 31135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent configure(nChannels, sampleRate); 32135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent reset(); 33135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent} 34135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent 35135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurentvoid AudioBiquadFilter::configure(int nChannels, int sampleRate) { 36135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent assert(nChannels > 0 && nChannels <= MAX_CHANNELS); 37135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent assert(sampleRate > 0); 38135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent mNumChannels = nChannels; 39135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent mMaxDelta = static_cast<int64_t>(MAX_DELTA_PER_SEC) 40135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent * AUDIO_COEF_ONE 41135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent / sampleRate; 42135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent clear(); 43135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent} 44135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent 45135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurentvoid AudioBiquadFilter::reset() { 46135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent memcpy(mCoefs, IDENTITY_COEFS, sizeof(mCoefs)); 47135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent mCoefDirtyBits = 0; 48135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent setState(STATE_BYPASS); 49135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent} 50135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent 51135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurentvoid AudioBiquadFilter::clear() { 52135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent memset(mDelays, 0, sizeof(mDelays)); 53135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent} 54135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent 55135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurentvoid AudioBiquadFilter::setCoefs(const audio_coef_t coefs[NUM_COEFS], bool immediate) { 56135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent memcpy(mTargetCoefs, coefs, sizeof(mTargetCoefs)); 57135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent if (mState & STATE_ENABLED_MASK) { 58135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent if (UNLIKELY(immediate)) { 59135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent memcpy(mCoefs, coefs, sizeof(mCoefs)); 60135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent setState(STATE_NORMAL); 61135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent } else { 62135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent setState(STATE_TRANSITION_TO_NORMAL); 63135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent } 64135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent } 65135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent} 66135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent 67135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurentvoid AudioBiquadFilter::process(const audio_sample_t in[], audio_sample_t out[], 68135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent int frameCount) { 69135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent (this->*mCurProcessFunc)(in, out, frameCount); 70135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent} 71135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent 72135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurentvoid AudioBiquadFilter::enable(bool immediate) { 73135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent if (UNLIKELY(immediate)) { 74135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent memcpy(mCoefs, mTargetCoefs, sizeof(mCoefs)); 75135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent setState(STATE_NORMAL); 76135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent } else { 77135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent setState(STATE_TRANSITION_TO_NORMAL); 78135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent } 79135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent} 80135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent 81135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurentvoid AudioBiquadFilter::disable(bool immediate) { 82135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent if (UNLIKELY(immediate)) { 83135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent memcpy(mCoefs, IDENTITY_COEFS, sizeof(mCoefs)); 84135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent setState(STATE_BYPASS); 85135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent } else { 86135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent setState(STATE_TRANSITION_TO_BYPASS); 87135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent } 88135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent} 89135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent 90135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurentvoid AudioBiquadFilter::setState(state_t state) { 91135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent switch (state) { 92135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent case STATE_BYPASS: 93135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent mCurProcessFunc = &AudioBiquadFilter::process_bypass; 94135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent break; 95135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent case STATE_TRANSITION_TO_BYPASS: 96135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent if (mNumChannels == 1) { 97135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent mCurProcessFunc = &AudioBiquadFilter::process_transition_bypass_mono; 98135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent } else { 99135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent mCurProcessFunc = &AudioBiquadFilter::process_transition_bypass_multi; 100135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent } 101135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent mCoefDirtyBits = (1 << NUM_COEFS) - 1; 102135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent break; 103135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent case STATE_TRANSITION_TO_NORMAL: 104135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent if (mNumChannels == 1) { 105135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent mCurProcessFunc = &AudioBiquadFilter::process_transition_normal_mono; 106135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent } else { 107135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent mCurProcessFunc = &AudioBiquadFilter::process_transition_normal_multi; 108135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent } 109135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent mCoefDirtyBits = (1 << NUM_COEFS) - 1; 110135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent break; 111135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent case STATE_NORMAL: 112135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent if (mNumChannels == 1) { 113135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent mCurProcessFunc = &AudioBiquadFilter::process_normal_mono; 114135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent } else { 115135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent mCurProcessFunc = &AudioBiquadFilter::process_normal_multi; 116135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent } 117135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent break; 118135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent } 119135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent mState = state; 120135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent} 121135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent 122135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurentbool AudioBiquadFilter::updateCoefs(const audio_coef_t coefs[NUM_COEFS], 123135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent int frameCount) { 124135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent int64_t maxDelta = mMaxDelta * frameCount; 125135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent for (int i = 0; i < NUM_COEFS; ++i) { 126135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent if (mCoefDirtyBits & (1<<i)) { 127135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent audio_coef_t diff = coefs[i] - mCoefs[i]; 128135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent if (diff > maxDelta) { 129135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent mCoefs[i] += maxDelta; 130135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent } else if (diff < -maxDelta) { 131135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent mCoefs[i] -= maxDelta; 132135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent } else { 133135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent mCoefs[i] = coefs[i]; 134135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent mCoefDirtyBits ^= (1<<i); 135135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent } 136135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent } 137135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent } 138135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent return mCoefDirtyBits == 0; 139135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent} 140135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent 141135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurentvoid AudioBiquadFilter::process_bypass(const audio_sample_t * in, 142135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent audio_sample_t * out, 143135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent int frameCount) { 144135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent // The common case is in-place processing, because this is what the EQ does. 145135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent if (UNLIKELY(in != out)) { 146135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent memcpy(out, in, frameCount * mNumChannels * sizeof(audio_sample_t)); 147135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent } 148135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent} 149135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent 150135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurentvoid AudioBiquadFilter::process_normal_mono(const audio_sample_t * in, 151135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent audio_sample_t * out, 152135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent int frameCount) { 153135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent size_t nFrames = frameCount; 154135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent audio_sample_t x1 = mDelays[0][0]; 155135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent audio_sample_t x2 = mDelays[0][1]; 156135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent audio_sample_t y1 = mDelays[0][2]; 157135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent audio_sample_t y2 = mDelays[0][3]; 158135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent const audio_coef_t b0 = mCoefs[0]; 159135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent const audio_coef_t b1 = mCoefs[1]; 160135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent const audio_coef_t b2 = mCoefs[2]; 161135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent const audio_coef_t a1 = mCoefs[3]; 162135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent const audio_coef_t a2 = mCoefs[4]; 163135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent while (nFrames-- > 0) { 164135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent audio_sample_t x0 = *(in++); 165135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent audio_coef_sample_acc_t acc; 166135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent acc = mul_coef_sample(b0, x0); 167135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent acc = mac_coef_sample(b1, x1, acc); 168135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent acc = mac_coef_sample(b2, x2, acc); 169135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent acc = mac_coef_sample(a1, y1, acc); 170135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent acc = mac_coef_sample(a2, y2, acc); 171135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent audio_sample_t y0 = coef_sample_acc_to_sample(acc); 172135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent y2 = y1; 173135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent y1 = y0; 174135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent x2 = x1; 175135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent x1 = x0; 176135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent (*out++) = y0; 177135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent } 178135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent mDelays[0][0] = x1; 179135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent mDelays[0][1] = x2; 180135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent mDelays[0][2] = y1; 181135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent mDelays[0][3] = y2; 182135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent} 183135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent 184135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurentvoid AudioBiquadFilter::process_transition_normal_mono(const audio_sample_t * in, 185135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent audio_sample_t * out, 186135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent int frameCount) { 187135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent if (updateCoefs(mTargetCoefs, frameCount)) { 188135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent setState(STATE_NORMAL); 189135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent } 190135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent process_normal_mono(in, out, frameCount); 191135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent} 192135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent 193135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurentvoid AudioBiquadFilter::process_transition_bypass_mono(const audio_sample_t * in, 194135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent audio_sample_t * out, 195135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent int frameCount) { 196135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent if (updateCoefs(IDENTITY_COEFS, frameCount)) { 197135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent setState(STATE_NORMAL); 198135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent } 199135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent process_normal_mono(in, out, frameCount); 200135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent} 201135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent 202135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurentvoid AudioBiquadFilter::process_normal_multi(const audio_sample_t * in, 203135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent audio_sample_t * out, 204135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent int frameCount) { 205135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent const audio_coef_t b0 = mCoefs[0]; 206135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent const audio_coef_t b1 = mCoefs[1]; 207135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent const audio_coef_t b2 = mCoefs[2]; 208135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent const audio_coef_t a1 = mCoefs[3]; 209135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent const audio_coef_t a2 = mCoefs[4]; 210135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent for (int ch = 0; ch < mNumChannels; ++ch) { 211135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent size_t nFrames = frameCount; 212135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent audio_sample_t x1 = mDelays[ch][0]; 213135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent audio_sample_t x2 = mDelays[ch][1]; 214135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent audio_sample_t y1 = mDelays[ch][2]; 215135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent audio_sample_t y2 = mDelays[ch][3]; 216135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent while (nFrames-- > 0) { 217135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent audio_sample_t x0 = *in; 218135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent audio_coef_sample_acc_t acc; 219135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent acc = mul_coef_sample(b0, x0); 220135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent acc = mac_coef_sample(b1, x1, acc); 221135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent acc = mac_coef_sample(b2, x2, acc); 222135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent acc = mac_coef_sample(a1, y1, acc); 223135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent acc = mac_coef_sample(a2, y2, acc); 224135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent audio_sample_t y0 = coef_sample_acc_to_sample(acc); 225135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent y2 = y1; 226135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent y1 = y0; 227135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent x2 = x1; 228135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent x1 = x0; 229135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent *out = y0; 230135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent in += mNumChannels; 231135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent out += mNumChannels; 232135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent } 233135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent mDelays[ch][0] = x1; 234135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent mDelays[ch][1] = x2; 235135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent mDelays[ch][2] = y1; 236135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent mDelays[ch][3] = y2; 237135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent in -= frameCount * mNumChannels - 1; 238135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent out -= frameCount * mNumChannels - 1; 239135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent } 240135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent} 241135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent 242135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurentvoid AudioBiquadFilter::process_transition_normal_multi(const audio_sample_t * in, 243135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent audio_sample_t * out, 244135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent int frameCount) { 245135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent if (updateCoefs(mTargetCoefs, frameCount)) { 246135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent setState(STATE_NORMAL); 247135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent } 248135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent process_normal_multi(in, out, frameCount); 249135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent} 250135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent 251135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurentvoid AudioBiquadFilter::process_transition_bypass_multi(const audio_sample_t * in, 252135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent audio_sample_t * out, 253135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent int frameCount) { 254135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent if (updateCoefs(IDENTITY_COEFS, frameCount)) { 255135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent setState(STATE_NORMAL); 256135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent } 257135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent process_normal_multi(in, out, frameCount); 258135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent} 259135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent 260135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent} 261