15fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent/* //device/include/server/AudioFlinger/AudioBiquadFilter.h 25fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent** 35fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent** Copyright 2007, The Android Open Source Project 45fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent** 55fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent** Licensed under the Apache License, Version 2.0 (the "License"); 65fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent** you may not use this file except in compliance with the License. 75fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent** You may obtain a copy of the License at 85fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent** 95fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent** http://www.apache.org/licenses/LICENSE-2.0 105fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent** 115fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent** Unless required by applicable law or agreed to in writing, software 125fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent** distributed under the License is distributed on an "AS IS" BASIS, 135fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 145fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent** See the License for the specific language governing permissions and 155fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent** limitations under the License. 165fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent*/ 175fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent 185fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent#ifndef ANDROID_AUDIO_BIQUAD_FILTER_H 195fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent#define ANDROID_AUDIO_BIQUAD_FILTER_H 205fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent 215fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent#include "AudioCommon.h" 225fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent 235fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurentnamespace android { 245fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent// A biquad filter. 255fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent// Implements the recursion y[n]=a0*y[n-1]+a1*y[n-2]+b0*x[n]+b1*x[n-1]+b2*x[n-2] 265fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent// (the a0 and a1 coefficients have an opposite sign to the common convention) 275fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent// The filter works on fixed sized blocks of data (frameCount multi-channel 285fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent// samples, as defined during construction). An arbitrary number of interlaced 295fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent// channels is supported. 305fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent// Filter can operate in an enabled (active) or disabled (bypassed) states. 315fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent// A mechanism for suppression of artifacts caused by abrupt coefficient changes 325fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent// is implemented: normally, when the enable(), disable() and setCoefs() methods 335fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent// are called without the immediate flag set, the filter smoothly transitions 345fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent// from its current state to the desired state. 355fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurentclass AudioBiquadFilter { 365fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurentpublic: 375fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent // Max number of channels (can be changed here, and everything should work). 385fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent static const int MAX_CHANNELS = 2; 395fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent // Number of coefficients. 405fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent static const int NUM_COEFS = 5; 415fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent 425fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent // Constructor. 435fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent // nChannels Number of input/output channels. 445fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent // sampleRate Sample rate, in Hz. 455fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent AudioBiquadFilter(int nChannels, int sampleRate); 465fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent 475fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent // Reconfiguration of the filter. Implies clear(). 485fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent // nChannels Number of input/output channels. 495fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent // sampleRate Sample rate, in Hz. 505fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent void configure(int nChannels, int sampleRate); 515fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent 525fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent // Resets the internal state of the filter. 535fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent // Coefficients are reset to identity, state becomes disabled. This change 545fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent // happens immediately and might cause discontinuities in the output. 555fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent // Delay lines are not cleared. 565fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent void reset(); 575fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent 585fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent // Clears the delay lines. 595fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent // This change happens immediately and might cause discontinuities in the 605fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent // output. 615fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent void clear(); 625fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent 635fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent // Sets the coefficients. 645fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent // If called when filter is disabled, will have no immediate effect, but the 655fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent // new coefficients will be set and used next time the filter is enabled. 665fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent // coefs The new coefficients. 675fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent // immediate If true, transitions to new coefficients smoothly, without 685fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent // introducing discontinuities in the output. Otherwise, 695fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent // transitions immediately. 705fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent void setCoefs(const audio_coef_t coefs[NUM_COEFS], bool immediate = false); 715fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent 725fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent // Process a buffer of data. Always processes frameCount multi-channel 735fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent // samples. Processing can be done in-place, by passing the same buffer as 745fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent // both arguments. 755fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent // in The input buffer. Should be of size frameCount * nChannels. 765fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent // out The output buffer. Should be of size frameCount * nChannels. 775fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent // frameCount Number of multi-channel samples to process. 785fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent void process(const audio_sample_t in[], audio_sample_t out[], 795fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent int frameCount); 805fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent 815fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent // Enables (activates) the filter. 825fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent // immediate If true, transitions to new state smoothly, without 835fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent // introducing discontinuities in the output. Otherwise, 845fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent // transitions immediately. 855fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent void enable(bool immediate = false); 865fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent 875fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent // Disables (bypasses) the filter. 885fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent // immediate If true, transitions to new state smoothly, without 895fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent // introducing discontinuities in the output. Otherwise, 905fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent // transitions immediately. 915fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent void disable(bool immediate = false); 925fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent 935fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurentprivate: 945fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent // A prototype of the actual processing function. Has the same semantics as 955fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent // the process() method. 965fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent typedef void (AudioBiquadFilter::*process_func)(const audio_sample_t[], 975fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent audio_sample_t[], 985fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent int frameCount); 995fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent 1005fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent // The maximum rate of coefficient change, measured in coefficient units per 1015fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent // second. 1025fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent static const audio_coef_t MAX_DELTA_PER_SEC = 2000; 1035fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent 1045fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent // Coefficients of identity transformation. 1055fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent static const audio_coef_t IDENTITY_COEFS[NUM_COEFS]; 1065fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent 1075fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent // Filter state. 1085fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent enum state_t { 1095fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent // Bypass. 1105fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent STATE_BYPASS = 0x01, 1115fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent // In the process of smooth transition to bypass state. 1125fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent STATE_TRANSITION_TO_BYPASS = 0x02, 1135fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent // In the process of smooth transition to normal (enabled) state. 1145fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent STATE_TRANSITION_TO_NORMAL = 0x04, 1155fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent // In normal (enabled) state. 1165fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent STATE_NORMAL = 0x05, 1175fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent // A bit-mask for determining whether the filter is enabled or disabled 1185fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent // in the eyes of the client. 1195fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent STATE_ENABLED_MASK = 0x04 1205fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent }; 1215fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent 1225fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent // Number of channels. 1235fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent int mNumChannels; 1245fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent // Current state. 1255fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent state_t mState; 1265fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent // Maximum coefficient delta per sample. 1275fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent audio_coef_t mMaxDelta; 1285fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent 1295fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent // A bit-mask designating for which coefficients the current value is not 1305fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent // necessarily identical to the target value (since we're in transition 1315fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent // state). 1325fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent uint32_t mCoefDirtyBits; 1335fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent // The current coefficients. 1345fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent audio_coef_t mCoefs[NUM_COEFS]; 1355fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent // The target coefficients. Will not be identical to mCoefs if we are in a 1365fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent // transition state. 1375fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent audio_coef_t mTargetCoefs[NUM_COEFS]; 1385fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent 1395fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent // The delay lines. 1405fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent audio_sample_t mDelays[MAX_CHANNELS][4]; 1415fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent 1425fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent // Current processing function (determines according to current state and 1435fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent // number of channels). 1445fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent process_func mCurProcessFunc; 1455fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent 1465fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent // Sets a new state. Updates the processing function accordingly, and sets 1475fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent // the dirty bits if changing to a transition state. 1485fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent void setState(state_t state); 1495fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent 1505fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent // In a transition state, modifies the current coefs towards the passed 1515fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent // coefs, while keeping a smooth change rate. Whenever a coef reaches its 1525fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent // target value, the dirty bit is cleared. If all are clear, the function 1535fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent // returns true, and we can then change to our target state. 1545fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent bool updateCoefs(const audio_coef_t coefs[NUM_COEFS], int frameCount); 1555fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent 1565fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent // Processing function when in disabled state. 1575fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent void process_bypass(const audio_sample_t * in, audio_sample_t * out, 1585fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent int frameCount); 1595fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent // Processing function when in normal state, mono. 1605fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent void process_normal_mono(const audio_sample_t * in, audio_sample_t * out, 1615fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent int frameCount); 1625fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent // Processing function when transitioning to normal state, mono. 1635fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent void process_transition_normal_mono(const audio_sample_t * in, 1645fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent audio_sample_t * out, int frameCount); 1655fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent // Processing function when transitioning to bypass state, mono. 1665fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent void process_transition_bypass_mono(const audio_sample_t * in, 1675fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent audio_sample_t * out, int frameCount); 1685fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent // Processing function when in normal state, multi-channel. 1695fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent void process_normal_multi(const audio_sample_t * in, audio_sample_t * out, 1705fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent int frameCount); 1715fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent // Processing function when transitioning to normal state, multi-channel. 1725fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent void process_transition_normal_multi(const audio_sample_t * in, 1735fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent audio_sample_t * out, int frameCount); 1745fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent // Processing function when transitioning to bypass state, multi-channel. 1755fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent void process_transition_bypass_multi(const audio_sample_t * in, 1765fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent audio_sample_t * out, int frameCount); 1775fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent}; 1785fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent} 1795fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent 1805fe37c6838de9fbd959ad19ba44aa3d00d1b4e6fEric Laurent#endif // ANDROID_AUDIO_BIQUAD_FILTER_H 181