Band-split the HRIRs when building the ambisonic decoder filters

This allows each HRIR to contribute a frequency-dependent response, essentially
acting like a dual-band decoder playing over the cube speaker array.
This commit is contained in:
Chris Robinson
2016-08-21 03:05:42 -07:00
parent d16954c34e
commit 846cdd472d
3 changed files with 74 additions and 37 deletions
+10 -10
View File
@@ -10,14 +10,7 @@
#include "almalloc.h"
typedef struct BandSplitter {
ALfloat coeff;
ALfloat lp_z1;
ALfloat lp_z2;
ALfloat hp_z1;
} BandSplitter;
static void bandsplit_init(BandSplitter *splitter, ALfloat freq_mult)
void bandsplit_init(BandSplitter *splitter, ALfloat freq_mult)
{
ALfloat w = freq_mult * F_TAU;
ALfloat cw = cosf(w);
@@ -31,8 +24,15 @@ static void bandsplit_init(BandSplitter *splitter, ALfloat freq_mult)
splitter->hp_z1 = 0.0f;
}
static void bandsplit_process(BandSplitter *splitter, ALfloat *restrict hpout, ALfloat *restrict lpout,
const ALfloat *input, ALuint count)
void bandsplit_clear(BandSplitter *splitter)
{
splitter->lp_z1 = 0.0f;
splitter->lp_z2 = 0.0f;
splitter->hp_z1 = 0.0f;
}
void bandsplit_process(BandSplitter *splitter, ALfloat *restrict hpout, ALfloat *restrict lpout,
const ALfloat *input, ALuint count)
{
ALfloat coeff, d, x;
ALfloat z1, z2;
+15
View File
@@ -22,6 +22,7 @@ void bformatdec_process(struct BFormatDec *dec, ALfloat (*restrict OutBuffer)[BU
/* Up-samples a first-order input to the decoder's configuration. */
void bformatdec_upSample(struct BFormatDec *dec, ALfloat (*restrict OutBuffer)[BUFFERSIZE], ALfloat (*restrict InSamples)[BUFFERSIZE], ALuint InChannels, ALuint SamplesToDo);
/* Stand-alone first-order upsampler. Kept here because it shares some stuff
* with bformatdec.
*/
@@ -31,4 +32,18 @@ void ambiup_reset(struct AmbiUpsampler *ambiup, const ALCdevice *device);
void ambiup_process(struct AmbiUpsampler *ambiup, ALfloat (*restrict OutBuffer)[BUFFERSIZE], ALuint OutChannels, ALfloat (*restrict InSamples)[BUFFERSIZE], ALuint SamplesToDo);
/* Band splitter. Splits a signal into two phase-matching frequency bands. */
typedef struct BandSplitter {
ALfloat coeff;
ALfloat lp_z1;
ALfloat lp_z2;
ALfloat hp_z1;
} BandSplitter;
void bandsplit_init(BandSplitter *splitter, ALfloat freq_mult);
void bandsplit_clear(BandSplitter *splitter);
void bandsplit_process(BandSplitter *splitter, ALfloat *restrict hpout, ALfloat *restrict lpout,
const ALfloat *input, ALuint count);
#endif /* BFORMATDEC_H */
+49 -27
View File
@@ -28,6 +28,7 @@
#include "alMain.h"
#include "alSource.h"
#include "alu.h"
#include "bformatdec.h"
#include "hrtf.h"
#include "compat.h"
@@ -187,20 +188,22 @@ ALuint BuildBFormatHrtf(const struct Hrtf *Hrtf, ALfloat (*coeffs)[HRIR_LENGTH][
{ DEG2RAD(-35.0f), DEG2RAD(-135.0f) },
{ DEG2RAD(-35.0f), DEG2RAD( 135.0f) },
};
static const ALfloat CubeMatrix[8][MAX_AMBI_COEFFS] = {
{ 0.25f, 0.14425f, 0.14425f, 0.14425f },
{ 0.25f, -0.14425f, 0.14425f, 0.14425f },
{ 0.25f, 0.14425f, 0.14425f, -0.14425f },
{ 0.25f, -0.14425f, 0.14425f, -0.14425f },
{ 0.25f, 0.14425f, -0.14425f, 0.14425f },
{ 0.25f, -0.14425f, -0.14425f, 0.14425f },
{ 0.25f, 0.14425f, -0.14425f, -0.14425f },
{ 0.25f, -0.14425f, -0.14425f, -0.14425f },
static const ALfloat CubeMatrix[8][2][MAX_AMBI_COEFFS] = {
{ { 0.25f, 0.14425f, 0.14425f, 0.14425f }, { 0.125f, 0.125f, 0.125f, 0.125f } },
{ { 0.25f, -0.14425f, 0.14425f, 0.14425f }, { 0.125f, -0.125f, 0.125f, 0.125f } },
{ { 0.25f, 0.14425f, 0.14425f, -0.14425f }, { 0.125f, 0.125f, 0.125f, -0.125f } },
{ { 0.25f, -0.14425f, 0.14425f, -0.14425f }, { 0.125f, -0.125f, 0.125f, -0.125f } },
{ { 0.25f, 0.14425f, -0.14425f, 0.14425f }, { 0.125f, 0.125f, -0.125f, 0.125f } },
{ { 0.25f, -0.14425f, -0.14425f, 0.14425f }, { 0.125f, -0.125f, -0.125f, 0.125f } },
{ { 0.25f, 0.14425f, -0.14425f, -0.14425f }, { 0.125f, 0.125f, -0.125f, -0.125f } },
{ { 0.25f, -0.14425f, -0.14425f, -0.14425f }, { 0.125f, -0.125f, -0.125f, -0.125f } },
};
BandSplitter splitter;
ALfloat temps[3][HRIR_LENGTH];
ALuint lidx[8], ridx[8];
ALuint min_delay = HRTF_HISTORY_LENGTH;
ALuint max_length = 0;
ALuint i, j, c;
ALuint i, j, c, b;
assert(NumChannels == 4);
@@ -229,33 +232,52 @@ ALuint BuildBFormatHrtf(const struct Hrtf *Hrtf, ALfloat (*coeffs)[HRIR_LENGTH][
min_delay = minu(min_delay, minu(Hrtf->delays[lidx[c]], Hrtf->delays[ridx[c]]));
}
memset(temps, 0, sizeof(temps));
bandsplit_init(&splitter, 400.0f / (ALfloat)Hrtf->sampleRate);
for(c = 0;c < 8;c++)
{
const ALshort *fir;
ALuint length;
ALuint delay;
/* Band-split left HRIR into low and high frequency responses. */
bandsplit_clear(&splitter);
fir = &Hrtf->coeffs[lidx[c] * Hrtf->irSize];
delay = Hrtf->delays[lidx[c]] - min_delay;
length = minu(delay + Hrtf->irSize, HRIR_LENGTH);
for(i = 0;i < NumChannels;++i)
{
ALuint k = 0;
for(j = delay;j < length;++j)
coeffs[i][j][0] += fir[k++]/32767.0f * CubeMatrix[c][i];
}
max_length = maxu(max_length, length);
for(i = 0;i < Hrtf->irSize;i++)
temps[2][i] = fir[i] / 32767.0f;
bandsplit_process(&splitter, temps[0], temps[1], temps[2], HRIR_LENGTH);
fir = &Hrtf->coeffs[ridx[c] * Hrtf->irSize];
delay = Hrtf->delays[ridx[c]] - min_delay;
length = minu(delay + Hrtf->irSize, HRIR_LENGTH);
/* Add to the left output coefficients with the specified delay. */
delay = Hrtf->delays[lidx[c]] - min_delay;
for(i = 0;i < NumChannels;++i)
{
ALuint k = 0;
for(j = delay;j < length;++j)
coeffs[i][j][1] += fir[k++]/32767.0f * CubeMatrix[c][i];
for(b = 0;b < 2;b++)
{
ALuint k = 0;
for(j = delay;j < HRIR_LENGTH;++j)
coeffs[i][j][0] += temps[b][k++] * CubeMatrix[c][b][i];
}
}
max_length = maxu(max_length, length);
max_length = maxu(max_length, minu(delay + Hrtf->irSize, HRIR_LENGTH));
/* Band-split right HRIR into low and high frequency responses. */
bandsplit_clear(&splitter);
fir = &Hrtf->coeffs[ridx[c] * Hrtf->irSize];
for(i = 0;i < Hrtf->irSize;i++)
temps[2][i] = fir[i] / 32767.0f;
bandsplit_process(&splitter, temps[0], temps[1], temps[2], HRIR_LENGTH);
/* Add to the right output coefficients with the specified delay. */
delay = Hrtf->delays[ridx[c]] - min_delay;
for(i = 0;i < NumChannels;++i)
{
for(b = 0;b < 2;b++)
{
ALuint k = 0;
for(j = delay;j < HRIR_LENGTH;++j)
coeffs[i][j][1] += temps[b][k++] * CubeMatrix[c][b][i];
}
}
max_length = maxu(max_length, minu(delay + Hrtf->irSize, HRIR_LENGTH));
}
TRACE("Skipped min delay: %u, new combined length: %u\n", min_delay, max_length);