aboutsummaryrefslogtreecommitdiffstats
path: root/Alc
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2018-02-08 01:08:02 -0800
committerChris Robinson <[email protected]>2018-02-08 01:18:40 -0800
commit20bee69955380d9ff65838c2cb005637c5c348ae (patch)
tree9120508d60369441b2c4142147ab8bdf6dbc7cc5 /Alc
parent4cd04f192d77d8e83a5d286e1edb1bcaf5f33ffd (diff)
Attempt to improve the reverb panning vectors
This should now retain the original orientation of the soundfield and merely focus on the panning vector direction, as intended.
Diffstat (limited to 'Alc')
-rw-r--r--Alc/effects/reverb.c62
1 files changed, 42 insertions, 20 deletions
diff --git a/Alc/effects/reverb.c b/Alc/effects/reverb.c
index 9fba183a..392c2258 100644
--- a/Alc/effects/reverb.c
+++ b/Alc/effects/reverb.c
@@ -1124,17 +1124,19 @@ static ALvoid UpdateLateLines(const ALfloat density, const ALfloat diffusion, co
}
}
-/* Creates a transform matrix given a reverb vector. This works by creating a
- * Z-focus transform, then a rotate transform around X, then Y, to place the
- * focal point in the direction of the vector, using the vector length as a
- * focus strength.
- *
- * This isn't technically correct since the vector is supposed to define the
- * aperture and not rotate the perceived soundfield, but in practice it's
- * probably good enough.
+/* Creates a transform matrix given a reverb vector. This works by first
+ * creating an inverse rotation around Y then X, applying a Z-focus transform,
+ * then non-inverse rotations back around X then Y, to place the focal point in
+ * the direction of the vector, using the vector length as a focus strength.
+ *
+ * This convoluted construction ultimately results in a B-Format transformation
+ * matrix that retains its original orientation, but spatially focuses the
+ * signal in the desired direction. There is probably a more efficient way to
+ * do this, but let's see how good the optimizer is.
*/
static aluMatrixf GetTransformFromVector(const ALfloat *vec)
{
+ const ALfloat sqrt_3 = 1.732050808f;
aluMatrixf zfocus, xrot, yrot;
aluMatrixf tmp1, tmp2;
ALfloat length;
@@ -1145,12 +1147,12 @@ static aluMatrixf GetTransformFromVector(const ALfloat *vec)
/* Define a Z-focus (X in Ambisonics) transform, given the panning vector
* length.
*/
- sa = sinf(minf(length, 1.0f) * (F_PI/4.0f));
+ sa = sinf(minf(length, 1.0f) * (F_PI/2.0f));
aluMatrixfSet(&zfocus,
- 1.0f/(1.0f+sa), 0.0f, 0.0f, (sa/(1.0f+sa))/1.732050808f,
- 0.0f, sqrtf((1.0f-sa)/(1.0f+sa)), 0.0f, 0.0f,
- 0.0f, 0.0f, sqrtf((1.0f-sa)/(1.0f+sa)), 0.0f,
- (sa/(1.0f+sa))*1.732050808f, 0.0f, 0.0f, 1.0f/(1.0f+sa)
+ 1.0f/(1.0f+sa), 0.0f, 0.0f, sa/(1.0f+sa)/sqrt_3,
+ 0.0f, sqrtf((1.0f-sa)/(1.0f+sa)), 0.0f, 0.0f,
+ 0.0f, 0.0f, sqrtf((1.0f-sa)/(1.0f+sa)), 0.0f,
+ sa/(1.0f+sa)*sqrt_3, 0.0f, 0.0f, 1.0f/(1.0f+sa)
);
/* Define rotation around X (Y in Ambisonics) */
@@ -1176,19 +1178,39 @@ static aluMatrixf GetTransformFromVector(const ALfloat *vec)
0.0f, -sinf(a), 0.0f, cosf(a)
);
+ /* First, define a matrix that applies the inverse of the Y- then X-
+ * rotation matrices, so that the desired direction lands on Z.
+ */
+#define MATRIX_INVMULT(_res, _m1, _m2) do { \
+ int row, col; \
+ for(col = 0;col < 4;col++) \
+ { \
+ for(row = 0;row < 4;row++) \
+ _res.m[row][col] = _m1.m[0][row]*_m2.m[col][0] + \
+ _m1.m[1][row]*_m2.m[col][1] + \
+ _m1.m[2][row]*_m2.m[col][2] + \
+ _m1.m[3][row]*_m2.m[col][3]; \
+ } \
+} while(0)
+ MATRIX_INVMULT(tmp1, xrot, yrot);
+#undef MATRIX_INVMULT
+
#define MATRIX_MULT(_res, _m1, _m2) do { \
int row, col; \
for(col = 0;col < 4;col++) \
{ \
for(row = 0;row < 4;row++) \
- _res.m[row][col] = _m1.m[row][0]*_m2.m[0][col] + _m1.m[row][1]*_m2.m[1][col] + \
- _m1.m[row][2]*_m2.m[2][col] + _m1.m[row][3]*_m2.m[3][col]; \
+ _res.m[row][col] = _m1.m[row][0]*_m2.m[0][col] + \
+ _m1.m[row][1]*_m2.m[1][col] + \
+ _m1.m[row][2]*_m2.m[2][col] + \
+ _m1.m[row][3]*_m2.m[3][col]; \
} \
} while(0)
- /* Define a matrix that first focuses on Z, then rotates around X then Y to
- * focus the output in the direction of the vector.
+ /* Now apply matrices to focus on Z, then rotate back around X then Y, to
+ * result in a focus in the direction of the vector.
*/
- MATRIX_MULT(tmp1, xrot, zfocus);
+ MATRIX_MULT(tmp2, zfocus, tmp1);
+ MATRIX_MULT(tmp1, xrot, tmp2);
MATRIX_MULT(tmp2, yrot, tmp1);
#undef MATRIX_MULT
@@ -1214,8 +1236,8 @@ static ALvoid Update3DPanning(const ALCdevice *Device, const ALfloat *Reflection
_m1.m[row][2]*_m2.m[2][col] + _m1.m[row][3]*_m2.m[3][col]; \
} \
} while(0)
- /* Create a matrix that first converts A-Format to B-Format, then rotates
- * the B-Format soundfield according to the panning vector.
+ /* Create a matrix that first converts A-Format to B-Format, then
+ * transforms the B-Format signal according to the panning vector.
*/
rot = GetTransformFromVector(ReflectionsPan);
MATRIX_MULT(transform, rot, A2B);