blob: 2b0e2d64aa420606c12b716836cbd9c0c05d809b [file] [log] [blame]
/* //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