AudioBiquadFilter.cpp revision 2c8e5cab3faa6d360e222b7a6c40a80083d021ac
15460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/* //device/servers/AudioFlinger/AudioBiquadFilter.cpp 25460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao** 35460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao** Copyright 2009, The Android Open Source Project 45460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao** 55460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao** Licensed under the Apache License, Version 2.0 (the "License"); 65460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao** you may not use this file except in compliance with the License. 75460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao** You may obtain a copy of the License at 85460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao** 95460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao** http://www.apache.org/licenses/LICENSE-2.0 105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao** 115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao** Unless required by applicable law or agreed to in writing, software 125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao** distributed under the License is distributed on an "AS IS" BASIS, 135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao** See the License for the specific language governing permissions and 155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao** limitations under the License. 165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao*/ 175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 18f767be5432ccac097334be48698e48621d730190Shih-wei Liao#include <string.h> 195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <assert.h> 205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include "AudioBiquadFilter.h" 225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true )) 245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false )) 255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaonamespace android { 275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaoconst audio_coef_t AudioBiquadFilter::IDENTITY_COEFS[AudioBiquadFilter::NUM_COEFS] = { AUDIO_COEF_ONE, 0, 0, 0, 0 }; 295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoAudioBiquadFilter::AudioBiquadFilter(int nChannels, int sampleRate) { 315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao configure(nChannels, sampleRate); 325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao reset(); 335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaovoid AudioBiquadFilter::configure(int nChannels, int sampleRate) { 365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao assert(nChannels > 0 && nChannels <= MAX_CHANNELS); 375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao assert(sampleRate > 0); 385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao mNumChannels = nChannels; 395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao mMaxDelta = static_cast<int64_t>(MAX_DELTA_PER_SEC) 405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao * AUDIO_COEF_ONE 415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao / sampleRate; 425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao clear(); 435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaovoid AudioBiquadFilter::reset() { 465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao memcpy(mCoefs, IDENTITY_COEFS, sizeof(mCoefs)); 475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao mCoefDirtyBits = 0; 485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao setState(STATE_BYPASS); 495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaovoid AudioBiquadFilter::clear() { 525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao memset(mDelays, 0, sizeof(mDelays)); 535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaovoid AudioBiquadFilter::setCoefs(const audio_coef_t coefs[NUM_COEFS], bool immediate) { 565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao memcpy(mTargetCoefs, coefs, sizeof(mTargetCoefs)); 575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (mState & STATE_ENABLED_MASK) { 585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (UNLIKELY(immediate)) { 595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao memcpy(mCoefs, coefs, sizeof(mCoefs)); 605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao setState(STATE_NORMAL); 615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } else { 625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao setState(STATE_TRANSITION_TO_NORMAL); 635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaovoid AudioBiquadFilter::process(const audio_sample_t in[], audio_sample_t out[], 685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int frameCount) { 695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao (this->*mCurProcessFunc)(in, out, frameCount); 705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaovoid AudioBiquadFilter::enable(bool immediate) { 735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (UNLIKELY(immediate)) { 745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao memcpy(mCoefs, mTargetCoefs, sizeof(mCoefs)); 755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao setState(STATE_NORMAL); 765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } else { 775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao setState(STATE_TRANSITION_TO_NORMAL); 785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaovoid AudioBiquadFilter::disable(bool immediate) { 825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (UNLIKELY(immediate)) { 83f767be5432ccac097334be48698e48621d730190Shih-wei Liao memcpy(mCoefs, IDENTITY_COEFS, sizeof(mCoefs)); 845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao setState(STATE_BYPASS); 855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } else { 865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao setState(STATE_TRANSITION_TO_BYPASS); 875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaovoid AudioBiquadFilter::setState(state_t state) { 915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao switch (state) { 925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao case STATE_BYPASS: 935460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao mCurProcessFunc = &AudioBiquadFilter::process_bypass; 945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao break; 955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao case STATE_TRANSITION_TO_BYPASS: 965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (mNumChannels == 1) { 975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao mCurProcessFunc = &AudioBiquadFilter::process_transition_bypass_mono; 985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } else { 995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao mCurProcessFunc = &AudioBiquadFilter::process_transition_bypass_multi; 1005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao mCoefDirtyBits = (1 << NUM_COEFS) - 1; 1025460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao break; 1035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao case STATE_TRANSITION_TO_NORMAL: 1045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (mNumChannels == 1) { 1055460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao mCurProcessFunc = &AudioBiquadFilter::process_transition_normal_mono; 1065460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } else { 1075460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao mCurProcessFunc = &AudioBiquadFilter::process_transition_normal_multi; 108f767be5432ccac097334be48698e48621d730190Shih-wei Liao } 1095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao mCoefDirtyBits = (1 << NUM_COEFS) - 1; 1105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao break; 1115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao case STATE_NORMAL: 1125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (mNumChannels == 1) { 1135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao mCurProcessFunc = &AudioBiquadFilter::process_normal_mono; 1145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } else { 1155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao mCurProcessFunc = &AudioBiquadFilter::process_normal_multi; 1165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao break; 1185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao mState = state; 1205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaobool AudioBiquadFilter::updateCoefs(const audio_coef_t coefs[NUM_COEFS], 1235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int frameCount) { 1245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int64_t maxDelta = mMaxDelta * frameCount; 1255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao for (int i = 0; i < NUM_COEFS; ++i) { 1265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (mCoefDirtyBits & (1<<i)) { 1275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao audio_coef_t diff = coefs[i] - mCoefs[i]; 1285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (diff > maxDelta) { 1295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao mCoefs[i] += maxDelta; 1305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } else if (diff < -maxDelta) { 1315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao mCoefs[i] -= maxDelta; 132f767be5432ccac097334be48698e48621d730190Shih-wei Liao } else { 1335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao mCoefs[i] = coefs[i]; 1345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao mCoefDirtyBits ^= (1<<i); 1355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 138f767be5432ccac097334be48698e48621d730190Shih-wei Liao return mCoefDirtyBits == 0; 13967e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao} 1405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaovoid AudioBiquadFilter::process_bypass(const audio_sample_t * in, 1425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao audio_sample_t * out, 1435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int frameCount) { 1445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // The common case is in-place processing, because this is what the EQ does. 1455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (UNLIKELY(in != out)) { 1465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao memcpy(out, in, frameCount * mNumChannels * sizeof(audio_sample_t)); 1475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaovoid AudioBiquadFilter::process_normal_mono(const audio_sample_t * in, 1515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao audio_sample_t * out, 1525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int frameCount) { 1535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao size_t nFrames = frameCount; 1545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao audio_sample_t x1 = mDelays[0][0]; 1555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao audio_sample_t x2 = mDelays[0][1]; 1565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao audio_sample_t y1 = mDelays[0][2]; 1575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao audio_sample_t y2 = mDelays[0][3]; 1585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao const audio_coef_t b0 = mCoefs[0]; 1595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao const audio_coef_t b1 = mCoefs[1]; 1605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao const audio_coef_t b2 = mCoefs[2]; 1615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao const audio_coef_t a1 = mCoefs[3]; 1625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao const audio_coef_t a2 = mCoefs[4]; 1635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao while (nFrames-- > 0) { 1645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao audio_sample_t x0 = *(in++); 1655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao audio_coef_sample_acc_t acc; 1665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao acc = mul_coef_sample(b0, x0); 1675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao acc = mac_coef_sample(b1, x1, acc); 1685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao acc = mac_coef_sample(b2, x2, acc); 1695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao acc = mac_coef_sample(a1, y1, acc); 1705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao acc = mac_coef_sample(a2, y2, acc); 1715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao audio_sample_t y0 = coef_sample_acc_to_sample(acc); 1725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao y2 = y1; 1735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao y1 = y0; 1745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao x2 = x1; 1755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao x1 = x0; 1765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao (*out++) = y0; 1775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao mDelays[0][0] = x1; 1795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao mDelays[0][1] = x2; 1805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao mDelays[0][2] = y1; 1815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao mDelays[0][3] = y2; 1825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaovoid AudioBiquadFilter::process_transition_normal_mono(const audio_sample_t * in, 1855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao audio_sample_t * out, 1865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int frameCount) { 1875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (updateCoefs(mTargetCoefs, frameCount)) { 1885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao setState(STATE_NORMAL); 1895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao process_normal_mono(in, out, frameCount); 1915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1935460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaovoid AudioBiquadFilter::process_transition_bypass_mono(const audio_sample_t * in, 1945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao audio_sample_t * out, 1955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int frameCount) { 1965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (updateCoefs(IDENTITY_COEFS, frameCount)) { 1975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao setState(STATE_NORMAL); 1985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao process_normal_mono(in, out, frameCount); 2005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 2015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2025460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaovoid AudioBiquadFilter::process_normal_multi(const audio_sample_t * in, 2035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao audio_sample_t * out, 2045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int frameCount) { 2055460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao const audio_coef_t b0 = mCoefs[0]; 2065460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao const audio_coef_t b1 = mCoefs[1]; 2075460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao const audio_coef_t b2 = mCoefs[2]; 2085460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao const audio_coef_t a1 = mCoefs[3]; 2095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao const audio_coef_t a2 = mCoefs[4]; 2105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao for (int ch = 0; ch < mNumChannels; ++ch) { 2115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao size_t nFrames = frameCount; 2125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao audio_sample_t x1 = mDelays[ch][0]; 2135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao audio_sample_t x2 = mDelays[ch][1]; 2145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao audio_sample_t y1 = mDelays[ch][2]; 2155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao audio_sample_t y2 = mDelays[ch][3]; 2165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao while (nFrames-- > 0) { 2175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao audio_sample_t x0 = *in; 218f767be5432ccac097334be48698e48621d730190Shih-wei Liao audio_coef_sample_acc_t acc; 2195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao acc = mul_coef_sample(b0, x0); 2205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao acc = mac_coef_sample(b1, x1, acc); 2215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao acc = mac_coef_sample(b2, x2, acc); 2225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao acc = mac_coef_sample(a1, y1, acc); 2235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao acc = mac_coef_sample(a2, y2, acc); 2245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao audio_sample_t y0 = coef_sample_acc_to_sample(acc); 2255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao y2 = y1; 2265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao y1 = y0; 227f767be5432ccac097334be48698e48621d730190Shih-wei Liao x2 = x1; 2285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao x1 = x0; 2295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao *out = y0; 2305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao in += mNumChannels; 2315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao out += mNumChannels; 2325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 2335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao mDelays[ch][0] = x1; 2345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao mDelays[ch][1] = x2; 2355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao mDelays[ch][2] = y1; 2365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao mDelays[ch][3] = y2; 2375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao in -= frameCount * mNumChannels - 1; 2385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao out -= frameCount * mNumChannels - 1; 2395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 2405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 2415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaovoid AudioBiquadFilter::process_transition_normal_multi(const audio_sample_t * in, 2435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao audio_sample_t * out, 2445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int frameCount) { 2455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (updateCoefs(mTargetCoefs, frameCount)) { 2465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao setState(STATE_NORMAL); 2475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 2485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao process_normal_multi(in, out, frameCount); 2495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 2505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaovoid AudioBiquadFilter::process_transition_bypass_multi(const audio_sample_t * in, 2525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao audio_sample_t * out, 2535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int frameCount) { 2545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (updateCoefs(IDENTITY_COEFS, frameCount)) { 2555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao setState(STATE_NORMAL); 2565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 2575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao process_normal_multi(in, out, frameCount); 2585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 2595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 260f767be5432ccac097334be48698e48621d730190Shih-wei Liao} 2615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao