mirror of
https://github.com/overte-org/overte.git
synced 2025-08-07 16:10:40 +02:00
146 lines
4.4 KiB
C++
146 lines
4.4 KiB
C++
//
|
|
// AudioHRTF.h
|
|
// libraries/audio/src
|
|
//
|
|
// Created by Ken Cooke on 1/17/16.
|
|
// Copyright 2016 High Fidelity, Inc.
|
|
//
|
|
// Distributed under the Apache License, Version 2.0.
|
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
|
//
|
|
|
|
#ifndef hifi_AudioHRTF_h
|
|
#define hifi_AudioHRTF_h
|
|
|
|
#include <stdint.h>
|
|
#include <string.h>
|
|
#include <algorithm>
|
|
|
|
#include "AudioHelpers.h"
|
|
|
|
static const int HRTF_AZIMUTHS = 72; // 360 / 5-degree steps
|
|
static const int HRTF_TAPS = 64; // minimum-phase FIR coefficients
|
|
static const int HRTF_TABLES = 25; // number of HRTF subjects
|
|
|
|
static const int HRTF_DELAY = 24; // max ITD in samples (1.0ms at 24KHz)
|
|
static const int HRTF_BLOCK = 240; // block processing size
|
|
|
|
static const float HRTF_GAIN = 1.0f; // HRTF global gain adjustment
|
|
|
|
// Near-field HRTF
|
|
static const float HRTF_AZIMUTH_REF = 2.0f; // IRCAM Listen HRTF was recorded at 2 meters
|
|
static const float HRTF_NEARFIELD_MAX = 1.0f; // distance in meters
|
|
static const float HRTF_NEARFIELD_MIN = 0.125f; // distance in meters
|
|
static const float HRTF_HEAD_RADIUS = 0.0875f; // average human head in meters
|
|
|
|
// Distance attenuation
|
|
static const float ATTN_DISTANCE_REF = 2.0f; // distance where attn is 0dB
|
|
static const float ATTN_GAIN_MAX = 16.0f; // max gain allowed by distance attn (+24dB)
|
|
|
|
// Distance filter
|
|
static const float LPF_DISTANCE_REF = 256.0f; // approximation of sound propogation in air
|
|
|
|
class AudioHRTF {
|
|
|
|
public:
|
|
AudioHRTF() {};
|
|
|
|
//
|
|
// input: mono source
|
|
// output: interleaved stereo mix buffer (accumulates into existing output)
|
|
// index: HRTF subject index
|
|
// azimuth: clockwise panning angle in radians
|
|
// distance: source distance in meters
|
|
// gain: gain factor for distance attenuation
|
|
// numFrames: must be HRTF_BLOCK in this version
|
|
// lpfDistance: distance filter adjustment (distance to 1kHz lowpass in meters)
|
|
//
|
|
void render(int16_t* input, float* output, int index, float azimuth, float distance, float gain, int numFrames,
|
|
float lpfDistance = LPF_DISTANCE_REF);
|
|
|
|
//
|
|
// Non-spatialized direct mix (accumulates into existing output)
|
|
//
|
|
void mixMono(int16_t* input, float* output, float gain, int numFrames);
|
|
void mixStereo(int16_t* input, float* output, float gain, int numFrames);
|
|
|
|
//
|
|
// Fast path when input is known to be silent and state as been flushed
|
|
//
|
|
void setParameterHistory(float azimuth, float distance, float gain, float lpfDistance = LPF_DISTANCE_REF) {
|
|
// new parameters become old
|
|
_azimuthState = azimuth;
|
|
_distanceState = distance;
|
|
_gainState = gain;
|
|
|
|
_lpfState = 0.5f * fastLog2f(std::max(distance, 1.0f)) / fastLog2f(std::max(lpfDistance, 2.0f));
|
|
_lpfState = std::min(std::max(_lpfState, 0.0f), 1.0f);
|
|
}
|
|
|
|
//
|
|
// HRTF local gain adjustment in amplitude (1.0 == unity)
|
|
//
|
|
void setGainAdjustment(float gain) { _gainAdjust = HRTF_GAIN * gain; };
|
|
float getGainAdjustment() { return _gainAdjust; }
|
|
|
|
// clear internal state, but retain settings
|
|
void reset() {
|
|
if (!_resetState) {
|
|
// FIR history
|
|
memset(_firState, 0, sizeof(_firState));
|
|
|
|
// integer delay history
|
|
memset(_delayState, 0, sizeof(_delayState));
|
|
|
|
// biquad history
|
|
memset(_bqState, 0, sizeof(_bqState));
|
|
|
|
// parameter history
|
|
_azimuthState = 0.0f;
|
|
_distanceState = 0.0f;
|
|
_gainState = 0.0f;
|
|
_lpfState = 0.0f;
|
|
|
|
// _gainAdjust is retained
|
|
|
|
_resetState = true;
|
|
}
|
|
}
|
|
|
|
private:
|
|
AudioHRTF(const AudioHRTF&) = delete;
|
|
AudioHRTF& operator=(const AudioHRTF&) = delete;
|
|
|
|
// SIMD channel assignmentS
|
|
enum Channel {
|
|
L0, R0,
|
|
L1, R1,
|
|
L2, R2,
|
|
L3, R3
|
|
};
|
|
|
|
// For best cache utilization when processing thousands of instances, only
|
|
// the minimum persistant state is stored here. No coefs or work buffers.
|
|
|
|
// FIR history
|
|
float _firState[HRTF_TAPS] = {};
|
|
|
|
// integer delay history
|
|
float _delayState[4][HRTF_DELAY] = {};
|
|
|
|
// biquad history
|
|
float _bqState[3][8] = {};
|
|
|
|
// parameter history
|
|
float _azimuthState = 0.0f;
|
|
float _distanceState = 0.0f;
|
|
float _gainState = 0.0f;
|
|
float _lpfState = 0.0f;
|
|
|
|
// global and local gain adjustment
|
|
float _gainAdjust = HRTF_GAIN;
|
|
|
|
bool _resetState = true;
|
|
};
|
|
|
|
#endif // AudioHRTF_h
|