This commit is contained in:
Atlante45 2014-08-26 14:34:39 -07:00
commit b92ae53753
6 changed files with 105 additions and 41 deletions

View file

@ -275,7 +275,7 @@ void AudioMixer::addStreamToMixForListeningNodeWithStream(PositionalAudioStream*
glm::vec3 relativePosition = streamToAdd->getPosition() - listeningNodeStream->getPosition(); 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
AudioFilterPEQ1s& penumbraFilter = streamToAdd->getFilter(); AudioFilterHSF1s& penumbraFilter = streamToAdd->getFilter();
// calculate penumbra angle // calculate penumbra angle
float headPenumbraAngle = glm::angle(glm::vec3(0.0f, 0.0f, -1.0f), float headPenumbraAngle = glm::angle(glm::vec3(0.0f, 0.0f, -1.0f),
@ -288,14 +288,17 @@ void AudioMixer::addStreamToMixForListeningNodeWithStream(PositionalAudioStream*
normalizedHeadPenumbraAngle = EPSILON; normalizedHeadPenumbraAngle = EPSILON;
} }
const float SQUARE_ROOT_OF_TWO_OVER_TWO = 0.71f;
const float FILTER_CUTOFF_FREQUENCY_HZ = 4000.0f;
float penumbraFilterGain; float penumbraFilterGain;
float penumbraFilterFrequency; float penumbraFilterFrequency;
float penumbraFilterSlope; float penumbraFilterSlope;
// calculate the updated gain // calculate the updated gain. this will be tuned over time.
penumbraFilterGain = normalizedHeadPenumbraAngle; // Note this will be tuned - consider this only a crude-first pass at correlating gain with penumbra angle. // consider this only a crude-first pass at correlating gain, freq and slope with penumbra angle.
penumbraFilterFrequency = 2000.0f; penumbraFilterGain = SQUARE_ROOT_OF_TWO_OVER_TWO * (normalizedHeadPenumbraAngle + SQUARE_ROOT_OF_TWO_OVER_TWO);
penumbraFilterSlope = 1.0f; // gentle slope penumbraFilterFrequency = FILTER_CUTOFF_FREQUENCY_HZ; // constant frequency
penumbraFilterSlope = SQUARE_ROOT_OF_TWO_OVER_TWO; // constant slope
qDebug() << "penumbra gain=" << penumbraFilterGain << ", penumbraAngle=" << normalizedHeadPenumbraAngle; qDebug() << "penumbra gain=" << penumbraFilterGain << ", penumbraAngle=" << normalizedHeadPenumbraAngle;

View file

@ -95,7 +95,7 @@ public:
// Implements common base class interface for all Audio Filter Objects // Implements common base class interface for all Audio Filter Objects
// //
template< class T > template< class T >
class AudioFilterBase { class AudioFilter {
protected: protected:
@ -119,11 +119,11 @@ public:
// //
// ctor/dtor // ctor/dtor
// //
AudioFilterBase() { AudioFilter() {
setParameters(0.,0.,0.,0.); setParameters(0.,0.,0.,0.);
} }
~AudioFilterBase() { ~AudioFilter() {
} }
// //
@ -156,7 +156,7 @@ public:
// Implements a low-shelf filter using a biquad // Implements a low-shelf filter using a biquad
// //
class AudioFilterLSF : class AudioFilterLSF :
public AudioFilterBase< AudioFilterLSF > public AudioFilter< AudioFilterLSF >
{ {
public: public:
@ -164,7 +164,33 @@ public:
// helpers // helpers
// //
void updateKernel() { void updateKernel() {
// TBD
const float a = _gain;
const float aAdd1 = a + 1.0f;
const float aSub1 = a - 1.0f;
const float omega = TWO_PI * _frequency / _sampleRate;
const float aAdd1TimesCosOmega = aAdd1 * cosf(omega);
const float aSub1TimesCosOmega = aSub1 * cosf(omega);
const float alpha = 0.5f * sinf(omega) / _slope;
const float zeta = 2.0f * sqrtf(a) * alpha;
/*
b0 = A*( (A+1) - (A-1)*cos(w0) + 2*sqrt(A)*alpha )
b1 = 2*A*( (A-1) - (A+1)*cos(w0) )
b2 = A*( (A+1) - (A-1)*cos(w0) - 2*sqrt(A)*alpha )
a0 = (A+1) + (A-1)*cos(w0) + 2*sqrt(A)*alpha
a1 = -2*( (A-1) + (A+1)*cos(w0) )
a2 = (A+1) + (A-1)*cos(w0) - 2*sqrt(A)*alpha
*/
const float b0 = +1.0f * (aAdd1 - aSub1TimesCosOmega + zeta) * a;
const float b1 = +2.0f * (aSub1 - aAdd1TimesCosOmega + ZERO) * a;
const float b2 = +1.0f * (aAdd1 - aSub1TimesCosOmega - zeta) * a;
const float a0 = +1.0f * (aAdd1 + aSub1TimesCosOmega + zeta);
const float a1 = -2.0f * (aSub1 + aAdd1TimesCosOmega + ZERO);
const float a2 = +1.0f * (aAdd1 + aSub1TimesCosOmega - zeta);
const float normA0 = 1.0f / a0;
_kernel.setParameters(b0 * normA0, b1 * normA0 , b2 * normA0, a1 * normA0, a2 * normA0);
} }
}; };
@ -172,7 +198,7 @@ public:
// Implements a hi-shelf filter using a biquad // Implements a hi-shelf filter using a biquad
// //
class AudioFilterHSF : class AudioFilterHSF :
public AudioFilterBase< AudioFilterHSF > public AudioFilter< AudioFilterHSF >
{ {
public: public:
@ -180,7 +206,33 @@ public:
// helpers // helpers
// //
void updateKernel() { void updateKernel() {
// TBD
const float a = _gain;
const float aAdd1 = a + 1.0f;
const float aSub1 = a - 1.0f;
const float omega = TWO_PI * _frequency / _sampleRate;
const float aAdd1TimesCosOmega = aAdd1 * cosf(omega);
const float aSub1TimesCosOmega = aSub1 * cosf(omega);
const float alpha = 0.5f * sinf(omega) / _slope;
const float zeta = 2.0f * sqrtf(a) * alpha;
/*
b0 = A*( (A+1) + (A-1)*cos(w0) + 2*sqrt(A)*alpha )
b1 = -2*A*( (A-1) + (A+1)*cos(w0) )
b2 = A*( (A+1) + (A-1)*cos(w0) - 2*sqrt(A)*alpha )
a0 = (A+1) - (A-1)*cos(w0) + 2*sqrt(A)*alpha
a1 = 2*( (A-1) - (A+1)*cos(w0) )
a2 = (A+1) - (A-1)*cos(w0) - 2*sqrt(A)*alpha
*/
const float b0 = +1.0f * (aAdd1 + aSub1TimesCosOmega + zeta) * a;
const float b1 = -2.0f * (aSub1 + aAdd1TimesCosOmega + ZERO) * a;
const float b2 = +1.0f * (aAdd1 + aSub1TimesCosOmega - zeta) * a;
const float a0 = +1.0f * (aAdd1 - aSub1TimesCosOmega + zeta);
const float a1 = +2.0f * (aSub1 - aAdd1TimesCosOmega + ZERO);
const float a2 = +1.0f * (aAdd1 - aSub1TimesCosOmega - zeta);
const float normA0 = 1.0f / a0;
_kernel.setParameters(b0 * normA0, b1 * normA0 , b2 * normA0, a1 * normA0, a2 * normA0);
} }
}; };
@ -188,7 +240,7 @@ public:
// Implements a single-band parametric EQ using a biquad "peaking EQ" configuration // Implements a single-band parametric EQ using a biquad "peaking EQ" configuration
// //
class AudioFilterPEQ : class AudioFilterPEQ :
public AudioFilterBase< AudioFilterPEQ > public AudioFilter< AudioFilterPEQ >
{ {
public: public:
@ -197,26 +249,30 @@ public:
// //
void updateKernel() { void updateKernel() {
const float a = _gain; const float a = _gain;
const float omega = TWO_PI * _frequency / _sampleRate; const float omega = TWO_PI * _frequency / _sampleRate;
const float alpha = 0.5f * sinf(omega) / _slope; const float cosOmega = cosf(omega);
const float alpha = 0.5f * sinf(omega) / _slope;
const float alphaMulA = alpha * a;
const float alphaDivA = alpha / a;
/* /*
a0 = 1 + alpha*A b0 = 1 + alpha*A
a1 = -2*cos(w0)
a2 = 1 - alpha*A
b1 = -2*cos(w0) b1 = -2*cos(w0)
b2 = 1 - alpha/A b2 = 1 - alpha*A
a0 = 1 + alpha/A
a1 = -2*cos(w0)
a2 = 1 - alpha/A
*/ */
const float a0 = 1.0f + (alpha * a); const float b0 = +1.0f + alphaMulA;
const float a1 = -2.0f * cosf(omega); const float b1 = -2.0f * cosOmega;
const float a2 = 1.0f - (alpha * a); const float b2 = +1.0f - alphaMulA;
const float b1 = a1; const float a0 = +1.0f + alphaDivA;
const float b2 = 1.0f - (alpha / a); const float a1 = -2.0f * cosOmega;
const float a2 = +1.0f - alphaDivA;
const float scale = 1.0f / (1.0f + (alpha / a)); const float normA0 = 1.0f / a0;
_kernel.setParameters(a0 * scale, a1 * scale, a2 * scale, b1 * scale, b2 * scale); _kernel.setParameters(b0 * normA0, b1 * normA0 , b2 * normA0, a1 * normA0, a2 * normA0);
} }
}; };

View file

@ -16,29 +16,33 @@
#include "AudioFilterBank.h" #include "AudioFilterBank.h"
template<> template<>
AudioFilterLSF1s::FilterParameter AudioFilterLSF1s::_profiles[ AudioFilterLSF1s::_profileCount ][ AudioFilterLSF1s::_filterCount ] = { AudioFilterLSF1s::FilterParameter
AudioFilterLSF1s::_profiles[ AudioFilterLSF1s::_profileCount ][ AudioFilterLSF1s::_filterCount ] = {
// Freq Gain Slope // Freq Gain Slope
{ { 1000.0f, 1.0f, 1.0f } } // flat response (default) { { 1000.0f, 1.0f, 1.0f } } // flat response (default)
}; };
template<> template<>
AudioFilterHSF1s::FilterParameter AudioFilterHSF1s::_profiles[ AudioFilterHSF1s::_profileCount ][ AudioFilterHSF1s::_filterCount ] = { AudioFilterHSF1s::FilterParameter
AudioFilterHSF1s::_profiles[ AudioFilterHSF1s::_profileCount ][ AudioFilterHSF1s::_filterCount ] = {
// Freq Gain Slope // Freq Gain Slope
{ { 1000.0f, 1.0f, 1.0f } } // flat response (default) { { 1000.0f, 1.0f, 1.0f } } // flat response (default)
}; };
template<> template<>
AudioFilterPEQ1s::FilterParameter AudioFilterPEQ1s::_profiles[ AudioFilterPEQ1s::_profileCount ][ AudioFilterPEQ1s::_filterCount ] = { AudioFilterPEQ1s::FilterParameter
AudioFilterPEQ1s::_profiles[ AudioFilterPEQ1s::_profileCount ][ AudioFilterPEQ1s::_filterCount ] = {
// Freq Gain Q // Freq Gain Q
{ { 1000.0f, 1.0f, 1.0f } } // flat response (default) { { 1000.0f, 1.0f, 1.0f } } // flat response (default)
}; };
template<> template<>
AudioFilterPEQ3m::FilterParameter AudioFilterPEQ3m::_profiles[ AudioFilterPEQ3m::_profileCount ][ AudioFilterPEQ3m::_filterCount ] = { AudioFilterPEQ3m::FilterParameter
AudioFilterPEQ3m::_profiles[ AudioFilterPEQ3m::_profileCount ][ AudioFilterPEQ3m::_filterCount ] = {
// Freq Gain Q Freq Gain Q Freq Gain Q // Freq Gain Q Freq Gain Q Freq Gain Q
{ { 300.0f, 1.0f, 1.0f }, { 1000.0f, 1.0f, 1.0f }, { 4000.0f, 1.0f, 1.0f } }, // flat response (default) { { 300.0f, 1.0f, 1.0f }, { 1000.0f, 1.0f, 1.0f }, { 4000.0f, 1.0f, 1.0f } }, // flat response (default)
{ { 300.0f, 1.0f, 1.0f }, { 1000.0f, 1.0f, 1.0f }, { 4000.0f, 0.1f, 1.0f } }, // treble cut { { 300.0f, 1.0f, 1.0f }, { 1000.0f, 1.0f, 1.0f }, { 4000.0f, 0.1f, 1.0f } }, // treble cut
{ { 300.0f, 0.1f, 1.0f }, { 1000.0f, 1.0f, 1.0f }, { 4000.0f, 1.0f, 1.0f } }, // bass cut { { 300.0f, 0.1f, 1.0f }, { 1000.0f, 1.0f, 1.0f }, { 4000.0f, 1.0f, 1.0f } }, // bass cut
{ { 300.0f, 1.5f, 0.71f }, { 1000.0f, 0.5f, 1.0f }, { 4000.0f, 1.50f, 0.71f } } // smiley curve { { 300.0f, 1.5f, 0.71f }, { 1000.0f, 0.5f, 1.0f }, { 4000.0f, 1.50f, 0.71f } } // smiley curve
}; };

View file

@ -33,7 +33,8 @@ PositionalAudioStream::PositionalAudioStream(PositionalAudioStream::Type type, b
_lastPopOutputTrailingLoudness(0.0f), _lastPopOutputTrailingLoudness(0.0f),
_listenerUnattenuatedZone(NULL) _listenerUnattenuatedZone(NULL)
{ {
// constant defined in AudioMixer.h. However, we don't want to include this here, since we will soon find a better common home for these audio-related constants // constant defined in AudioMixer.h. However, we don't want to include this here
// we will soon find a better common home for these audio-related constants
const int SAMPLE_PHASE_DELAY_AT_90 = 20; const int SAMPLE_PHASE_DELAY_AT_90 = 20;
_filter.initialize(SAMPLE_RATE, (NETWORK_BUFFER_LENGTH_SAMPLES_STEREO + (SAMPLE_PHASE_DELAY_AT_90 * 2)) / 2); _filter.initialize(SAMPLE_RATE, (NETWORK_BUFFER_LENGTH_SAMPLES_STEREO + (SAMPLE_PHASE_DELAY_AT_90 * 2)) / 2);
} }

View file

@ -46,7 +46,7 @@ public:
void setListenerUnattenuatedZone(AABox* listenerUnattenuatedZone) { _listenerUnattenuatedZone = listenerUnattenuatedZone; } void setListenerUnattenuatedZone(AABox* listenerUnattenuatedZone) { _listenerUnattenuatedZone = listenerUnattenuatedZone; }
AudioFilterPEQ1s& getFilter() { return _filter; } AudioFilterHSF1s& getFilter() { return _filter; }
protected: protected:
// disallow copying of PositionalAudioStream objects // disallow copying of PositionalAudioStream objects
@ -66,7 +66,7 @@ protected:
float _lastPopOutputTrailingLoudness; float _lastPopOutputTrailingLoudness;
AABox* _listenerUnattenuatedZone; AABox* _listenerUnattenuatedZone;
AudioFilterPEQ1s _filter; AudioFilterHSF1s _filter;
}; };
#endif // hifi_PositionalAudioStream_h #endif // hifi_PositionalAudioStream_h

View file

@ -107,7 +107,7 @@ int Referential::packExtraData(unsigned char *destinationBuffer) const {
int Referential::unpackExtraData(const unsigned char* sourceBuffer, int size) { int Referential::unpackExtraData(const unsigned char* sourceBuffer, int size) {
_extraDataBuffer.clear(); _extraDataBuffer.clear();
_extraDataBuffer.setRawData(reinterpret_cast<const char*>(sourceBuffer), size); _extraDataBuffer.append(reinterpret_cast<const char*>(sourceBuffer), size);
return size; return size;
} }