left/right channels of head shadow filter now have independent gain + implemented all-pass filter

This commit is contained in:
Craig Hansen-Sturm 2014-08-27 17:30:11 -07:00
parent e8c3125985
commit 0881959750
2 changed files with 56 additions and 20 deletions

View file

@ -308,38 +308,37 @@ int AudioMixer::addStreamToMixForListeningNodeWithStream(PositionalAudioStream*
if (_enableFilter && shouldAttenuate) {
glm::vec3 relativePosition = streamToAdd->getPosition() - listeningNodeStream->getPosition();
if (relativePosition.z < 0) { // if the source is behind us
if (relativePosition.z < 0) { // if the source is behind us
AudioFilterHSF1s& penumbraFilter = streamToAdd->getFilter();
// calculate penumbra angle
float headPenumbraAngle = glm::angle(glm::vec3(0.0f, 0.0f, -1.0f),
glm::normalize(relativePosition));
// normalize penumbra angle
float normalizedHeadPenumbraAngle = headPenumbraAngle / PI_OVER_TWO;
if (normalizedHeadPenumbraAngle < EPSILON) {
normalizedHeadPenumbraAngle = EPSILON;
if (relativePosition.x < 0) {
headPenumbraAngle *= -1.0f; // [-pi/2,+pi/2]
}
const float SQUARE_ROOT_OF_TWO_OVER_TWO = 0.71f;
const float SQUARE_ROOT_OF_TWO_OVER_TWO = 0.71f; // half power
const float ONE_OVER_TWO_PI = 1.0f / TWO_PI;
const float FILTER_CUTOFF_FREQUENCY_HZ = 4000.0f;
float penumbraFilterGain;
float penumbraFilterFrequency;
float penumbraFilterSlope;
// calculate the updated gain. this will be tuned over time.
// consider this only a crude-first pass at correlating gain, freq and slope with penumbra angle.
penumbraFilterGain = SQUARE_ROOT_OF_TWO_OVER_TWO * (normalizedHeadPenumbraAngle + SQUARE_ROOT_OF_TWO_OVER_TWO);
penumbraFilterFrequency = FILTER_CUTOFF_FREQUENCY_HZ; // constant frequency
penumbraFilterSlope = SQUARE_ROOT_OF_TWO_OVER_TWO; // constant slope
qDebug() << "penumbra gain=" << penumbraFilterGain << ", penumbraAngle=" << normalizedHeadPenumbraAngle;
// calculate the updated gain, frequency and slope. this will be tuned over time.
const float penumbraFilterGainL = (-1.0f * ONE_OVER_TWO_PI * headPenumbraAngle ) + SQUARE_ROOT_OF_TWO_OVER_TWO;
const float penumbraFilterGainR = (+1.0f * ONE_OVER_TWO_PI * headPenumbraAngle ) + SQUARE_ROOT_OF_TWO_OVER_TWO;
const float penumbraFilterFrequency = FILTER_CUTOFF_FREQUENCY_HZ; // constant frequency
const float penumbraFilterSlope = SQUARE_ROOT_OF_TWO_OVER_TWO; // constant slope
qDebug() << "penumbra gainL="
<< penumbraFilterGainL
<< "penumbra gainR="
<< penumbraFilterGainR
<< "penumbraAngle="
<< headPenumbraAngle;
// set the gain on both filter channels
penumbraFilter.setParameters(0, 0, SAMPLE_RATE, penumbraFilterFrequency, penumbraFilterGain, penumbraFilterSlope);
penumbraFilter.setParameters(0, 1, SAMPLE_RATE, penumbraFilterFrequency, penumbraFilterGain, penumbraFilterSlope);
penumbraFilter.setParameters(0, 0, SAMPLE_RATE, penumbraFilterFrequency, penumbraFilterGainL, penumbraFilterSlope);
penumbraFilter.setParameters(0, 1, SAMPLE_RATE, penumbraFilterFrequency, penumbraFilterGainR, penumbraFilterSlope);
penumbraFilter.render(_clientSamples, _clientSamples, NETWORK_BUFFER_LENGTH_SAMPLES_STEREO / 2);
}

View file

@ -236,6 +236,43 @@ public:
}
};
//
// Implements a all-pass filter using a biquad
//
class AudioFilterALL :
public AudioFilter< AudioFilterALL >
{
public:
//
// helpers
//
void updateKernel() {
const float omega = TWO_PI * _frequency / _sampleRate;
const float cosOmega = cosf(omega);
const float alpha = 0.5f * sinf(omega) / _slope;
/*
b0 = 1 - alpha
b1 = -2*cos(w0)
b2 = 1 + alpha
a0 = 1 + alpha
a1 = -2*cos(w0)
a2 = 1 - alpha
*/
const float b0 = +1.0f - alpha;
const float b1 = -2.0f * cosOmega;
const float b2 = +1.0f + alpha;
const float a0 = +1.0f + alpha;
const float a1 = -2.0f * cosOmega;
const float a2 = +1.0f - alpha;
const float normA0 = 1.0f / a0;
_kernel.setParameters(b0 * normA0, b1 * normA0 , b2 * normA0, a1 * normA0, a2 * normA0);
}
};
//
// Implements a single-band parametric EQ using a biquad "peaking EQ" configuration
//