/* //device/include/server/AudioFlinger/AudioBiquadFilter.h ** ** Copyright 2007, The Android Open Source Project ** ** Licensed under the Apache License, Version 2.0 (the "License"); ** you may not use this file except in compliance with the License. ** You may obtain a copy of the License at ** ** http://www.apache.org/licenses/LICENSE-2.0 ** ** Unless required by applicable law or agreed to in writing, software ** distributed under the License is distributed on an "AS IS" BASIS, ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ** See the License for the specific language governing permissions and ** limitations under the License. */ #ifndef ANDROID_AUDIO_BIQUAD_FILTER_H #define ANDROID_AUDIO_BIQUAD_FILTER_H #include "AudioCommon.h" namespace android { // A biquad filter. // Implements the recursion y[n]=a0*y[n-1]+a1*y[n-2]+b0*x[n]+b1*x[n-1]+b2*x[n-2] // (the a0 and a1 coefficients have an opposite sign to the common convention) // The filter works on fixed sized blocks of data (frameCount multi-channel // samples, as defined during construction). An arbitrary number of interlaced // channels is supported. // Filter can operate in an enabled (active) or disabled (bypassed) states. // A mechanism for suppression of artifacts caused by abrupt coefficient changes // is implemented: normally, when the enable(), disable() and setCoefs() methods // are called without the immediate flag set, the filter smoothly transitions // from its current state to the desired state. class AudioBiquadFilter { public: // Max number of channels (can be changed here, and everything should work). static const int MAX_CHANNELS = 2; // Number of coefficients. static const int NUM_COEFS = 5; // Constructor. // nChannels Number of input/output channels. // sampleRate Sample rate, in Hz. AudioBiquadFilter(int nChannels, int sampleRate); // Reconfiguration of the filter. Implies clear(). // nChannels Number of input/output channels. // sampleRate Sample rate, in Hz. void configure(int nChannels, int sampleRate); // Resets the internal state of the filter. // Coefficients are reset to identity, state becomes disabled. This change // happens immediately and might cause discontinuities in the output. // Delay lines are not cleared. void reset(); // Clears the delay lines. // This change happens immediately and might cause discontinuities in the // output. void clear(); // Sets the coefficients. // If called when filter is disabled, will have no immediate effect, but the // new coefficients will be set and used next time the filter is enabled. // coefs The new coefficients. // immediate If true, transitions to new coefficients smoothly, without // introducing discontinuities in the output. Otherwise, // transitions immediately. void setCoefs(const audio_coef_t coefs[NUM_COEFS], bool immediate = false); // Process a buffer of data. Always processes frameCount multi-channel // samples. Processing can be done in-place, by passing the same buffer as // both arguments. // in The input buffer. Should be of size frameCount * nChannels. // out The output buffer. Should be of size frameCount * nChannels. // frameCount Number of multi-channel samples to process. void process(const audio_sample_t in[], audio_sample_t out[], int frameCount); // Enables (activates) the filter. // immediate If true, transitions to new state smoothly, without // introducing discontinuities in the output. Otherwise, // transitions immediately. void enable(bool immediate = false); // Disables (bypasses) the filter. // immediate If true, transitions to new state smoothly, without // introducing discontinuities in the output. Otherwise, // transitions immediately. void disable(bool immediate = false); private: // A prototype of the actual processing function. Has the same semantics as // the process() method. typedef void (AudioBiquadFilter::*process_func)(const audio_sample_t[], audio_sample_t[], int frameCount); // The maximum rate of coefficient change, measured in coefficient units per // second. static const audio_coef_t MAX_DELTA_PER_SEC = 2000; // Coefficients of identity transformation. static const audio_coef_t IDENTITY_COEFS[NUM_COEFS]; // Filter state. enum state_t { // Bypass. STATE_BYPASS = 0x01, // In the process of smooth transition to bypass state. STATE_TRANSITION_TO_BYPASS = 0x02, // In the process of smooth transition to normal (enabled) state. STATE_TRANSITION_TO_NORMAL = 0x04, // In normal (enabled) state. STATE_NORMAL = 0x05, // A bit-mask for determining whether the filter is enabled or disabled // in the eyes of the client. STATE_ENABLED_MASK = 0x04 }; // Number of channels. int mNumChannels; // Current state. state_t mState; // Maximum coefficient delta per sample. audio_coef_t mMaxDelta; // A bit-mask designating for which coefficients the current value is not // necessarily identical to the target value (since we're in transition // state). uint32_t mCoefDirtyBits; // The current coefficients. audio_coef_t mCoefs[NUM_COEFS]; // The target coefficients. Will not be identical to mCoefs if we are in a // transition state. audio_coef_t mTargetCoefs[NUM_COEFS]; // The delay lines. audio_sample_t mDelays[MAX_CHANNELS][4]; // Current processing function (determines according to current state and // number of channels). process_func mCurProcessFunc; // Sets a new state. Updates the processing function accordingly, and sets // the dirty bits if changing to a transition state. void setState(state_t state); // In a transition state, modifies the current coefs towards the passed // coefs, while keeping a smooth change rate. Whenever a coef reaches its // target value, the dirty bit is cleared. If all are clear, the function // returns true, and we can then change to our target state. bool updateCoefs(const audio_coef_t coefs[NUM_COEFS], int frameCount); // Processing function when in disabled state. void process_bypass(const audio_sample_t * in, audio_sample_t * out, int frameCount); // Processing function when in normal state, mono. void process_normal_mono(const audio_sample_t * in, audio_sample_t * out, int frameCount); // Processing function when transitioning to normal state, mono. void process_transition_normal_mono(const audio_sample_t * in, audio_sample_t * out, int frameCount); // Processing function when transitioning to bypass state, mono. void process_transition_bypass_mono(const audio_sample_t * in, audio_sample_t * out, int frameCount); // Processing function when in normal state, multi-channel. void process_normal_multi(const audio_sample_t * in, audio_sample_t * out, int frameCount); // Processing function when transitioning to normal state, multi-channel. void process_transition_normal_multi(const audio_sample_t * in, audio_sample_t * out, int frameCount); // Processing function when transitioning to bypass state, multi-channel. void process_transition_bypass_multi(const audio_sample_t * in, audio_sample_t * out, int frameCount); }; } #endif // ANDROID_AUDIO_BIQUAD_FILTER_H