|
|
|
@ -219,6 +219,7 @@ enum {
|
|
|
|
|
MIXTYPE_MULTI_SAVEONLY_MONOVOL,
|
|
|
|
|
MIXTYPE_MULTI_STEREOVOL,
|
|
|
|
|
MIXTYPE_MULTI_SAVEONLY_STEREOVOL,
|
|
|
|
|
MIXTYPE_STEREOEXPAND,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
@ -232,7 +233,8 @@ template <int MIXTYPE, int NCHAN,
|
|
|
|
|
void stereoVolumeHelper(TO*& out, const TI*& in, const TV *vol, F f) {
|
|
|
|
|
static_assert(NCHAN > 0 && NCHAN <= 8);
|
|
|
|
|
static_assert(MIXTYPE == MIXTYPE_MULTI_STEREOVOL
|
|
|
|
|
|| MIXTYPE == MIXTYPE_MULTI_SAVEONLY_STEREOVOL);
|
|
|
|
|
|| MIXTYPE == MIXTYPE_MULTI_SAVEONLY_STEREOVOL
|
|
|
|
|
|| MIXTYPE == MIXTYPE_STEREOEXPAND);
|
|
|
|
|
auto proc = [](auto& a, const auto& b) {
|
|
|
|
|
if constexpr (MIXTYPE == MIXTYPE_MULTI_STEREOVOL) {
|
|
|
|
|
a += b;
|
|
|
|
@ -240,14 +242,22 @@ void stereoVolumeHelper(TO*& out, const TI*& in, const TV *vol, F f) {
|
|
|
|
|
a = b;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
auto inp = [&in]() -> const TI& {
|
|
|
|
|
if constexpr (MIXTYPE == MIXTYPE_STEREOEXPAND) {
|
|
|
|
|
return *in;
|
|
|
|
|
} else {
|
|
|
|
|
return *in++;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// HALs should only expose the canonical channel masks.
|
|
|
|
|
proc(*out++, f(*in++, vol[0])); // front left
|
|
|
|
|
proc(*out++, f(inp(), vol[0])); // front left
|
|
|
|
|
if constexpr (NCHAN == 1) return;
|
|
|
|
|
proc(*out++, f(*in++, vol[1])); // front right
|
|
|
|
|
proc(*out++, f(inp(), vol[1])); // front right
|
|
|
|
|
if constexpr (NCHAN == 2) return;
|
|
|
|
|
if constexpr (NCHAN == 4) {
|
|
|
|
|
proc(*out++, f(*in++, vol[0])); // back left
|
|
|
|
|
proc(*out++, f(*in++, vol[1])); // back right
|
|
|
|
|
proc(*out++, f(inp(), vol[0])); // back left
|
|
|
|
|
proc(*out++, f(inp(), vol[1])); // back right
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -258,25 +268,25 @@ void stereoVolumeHelper(TO*& out, const TI*& in, const TV *vol, F f) {
|
|
|
|
|
} else {
|
|
|
|
|
center = (vol[0] >> 1) + (vol[1] >> 1); // rounds to 0.
|
|
|
|
|
}
|
|
|
|
|
proc(*out++, f(*in++, center)); // center (or 2.1 LFE)
|
|
|
|
|
proc(*out++, f(inp(), center)); // center (or 2.1 LFE)
|
|
|
|
|
if constexpr (NCHAN == 3) return;
|
|
|
|
|
if constexpr (NCHAN == 5) {
|
|
|
|
|
proc(*out++, f(*in++, vol[0])); // back left
|
|
|
|
|
proc(*out++, f(*in++, vol[1])); // back right
|
|
|
|
|
proc(*out++, f(inp(), vol[0])); // back left
|
|
|
|
|
proc(*out++, f(inp(), vol[1])); // back right
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
proc(*out++, f(*in++, center)); // lfe
|
|
|
|
|
proc(*out++, f(*in++, vol[0])); // back left
|
|
|
|
|
proc(*out++, f(*in++, vol[1])); // back right
|
|
|
|
|
proc(*out++, f(inp(), center)); // lfe
|
|
|
|
|
proc(*out++, f(inp(), vol[0])); // back left
|
|
|
|
|
proc(*out++, f(inp(), vol[1])); // back right
|
|
|
|
|
if constexpr (NCHAN == 6) return;
|
|
|
|
|
if constexpr (NCHAN == 7) {
|
|
|
|
|
proc(*out++, f(*in++, center)); // back center
|
|
|
|
|
proc(*out++, f(inp(), center)); // back center
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
// NCHAN == 8
|
|
|
|
|
proc(*out++, f(*in++, vol[0])); // side left
|
|
|
|
|
proc(*out++, f(*in++, vol[1])); // side right
|
|
|
|
|
proc(*out++, f(inp(), vol[0])); // side left
|
|
|
|
|
proc(*out++, f(inp(), vol[1])); // side right
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
@ -326,6 +336,11 @@ void stereoVolumeHelper(TO*& out, const TI*& in, const TV *vol, F f) {
|
|
|
|
|
* MIXTYPE_MULTI_SAVEONLY_STEREOVOL:
|
|
|
|
|
* Same as MIXTYPE_MULTI_SAVEONLY, but uses only volume[0] and volume[1].
|
|
|
|
|
*
|
|
|
|
|
* MIXTYPE_STEREOEXPAND:
|
|
|
|
|
* Stereo input channel. NCHAN represents number of output channels.
|
|
|
|
|
* Expand size 2 array "in" and "vol" to multi-channel output. Note
|
|
|
|
|
* that the 2 array is assumed to have replicated L+R.
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
template <int MIXTYPE, int NCHAN,
|
|
|
|
@ -366,11 +381,13 @@ inline void volumeRampMulti(TO* out, size_t frameCount,
|
|
|
|
|
}
|
|
|
|
|
vol[0] += volinc[0];
|
|
|
|
|
} else if constexpr (MIXTYPE == MIXTYPE_MULTI_STEREOVOL
|
|
|
|
|
|| MIXTYPE == MIXTYPE_MULTI_SAVEONLY_STEREOVOL) {
|
|
|
|
|
|| MIXTYPE == MIXTYPE_MULTI_SAVEONLY_STEREOVOL
|
|
|
|
|
|| MIXTYPE == MIXTYPE_STEREOEXPAND) {
|
|
|
|
|
stereoVolumeHelper<MIXTYPE, NCHAN>(
|
|
|
|
|
out, in, vol, [&auxaccum] (auto &a, const auto &b) {
|
|
|
|
|
return MixMulAux<TO, TI, TV, TA>(a, b, &auxaccum);
|
|
|
|
|
});
|
|
|
|
|
if constexpr (MIXTYPE == MIXTYPE_STEREOEXPAND) in += 2;
|
|
|
|
|
vol[0] += volinc[0];
|
|
|
|
|
vol[1] += volinc[1];
|
|
|
|
|
} else /* constexpr */ {
|
|
|
|
@ -409,10 +426,12 @@ inline void volumeRampMulti(TO* out, size_t frameCount,
|
|
|
|
|
}
|
|
|
|
|
vol[0] += volinc[0];
|
|
|
|
|
} else if constexpr (MIXTYPE == MIXTYPE_MULTI_STEREOVOL
|
|
|
|
|
|| MIXTYPE == MIXTYPE_MULTI_SAVEONLY_STEREOVOL) {
|
|
|
|
|
|| MIXTYPE == MIXTYPE_MULTI_SAVEONLY_STEREOVOL
|
|
|
|
|
|| MIXTYPE == MIXTYPE_STEREOEXPAND) {
|
|
|
|
|
stereoVolumeHelper<MIXTYPE, NCHAN>(out, in, vol, [] (auto &a, const auto &b) {
|
|
|
|
|
return MixMul<TO, TI, TV>(a, b);
|
|
|
|
|
});
|
|
|
|
|
if constexpr (MIXTYPE == MIXTYPE_STEREOEXPAND) in += 2;
|
|
|
|
|
vol[0] += volinc[0];
|
|
|
|
|
vol[1] += volinc[1];
|
|
|
|
|
} else /* constexpr */ {
|
|
|
|
@ -455,11 +474,13 @@ inline void volumeMulti(TO* out, size_t frameCount,
|
|
|
|
|
*out++ = MixMulAux<TO, TI, TV, TA>(*in++, vol[0], &auxaccum);
|
|
|
|
|
}
|
|
|
|
|
} else if constexpr (MIXTYPE == MIXTYPE_MULTI_STEREOVOL
|
|
|
|
|
|| MIXTYPE == MIXTYPE_MULTI_SAVEONLY_STEREOVOL) {
|
|
|
|
|
|| MIXTYPE == MIXTYPE_MULTI_SAVEONLY_STEREOVOL
|
|
|
|
|
|| MIXTYPE == MIXTYPE_STEREOEXPAND) {
|
|
|
|
|
stereoVolumeHelper<MIXTYPE, NCHAN>(
|
|
|
|
|
out, in, vol, [&auxaccum] (auto &a, const auto &b) {
|
|
|
|
|
return MixMulAux<TO, TI, TV, TA>(a, b, &auxaccum);
|
|
|
|
|
});
|
|
|
|
|
if constexpr (MIXTYPE == MIXTYPE_STEREOEXPAND) in += 2;
|
|
|
|
|
} else /* constexpr */ {
|
|
|
|
|
static_assert(dependent_false<MIXTYPE>, "invalid mixtype");
|
|
|
|
|
}
|
|
|
|
@ -490,10 +511,12 @@ inline void volumeMulti(TO* out, size_t frameCount,
|
|
|
|
|
*out++ = MixMul<TO, TI, TV>(*in++, vol[0]);
|
|
|
|
|
}
|
|
|
|
|
} else if constexpr (MIXTYPE == MIXTYPE_MULTI_STEREOVOL
|
|
|
|
|
|| MIXTYPE == MIXTYPE_MULTI_SAVEONLY_STEREOVOL) {
|
|
|
|
|
|| MIXTYPE == MIXTYPE_MULTI_SAVEONLY_STEREOVOL
|
|
|
|
|
|| MIXTYPE == MIXTYPE_STEREOEXPAND) {
|
|
|
|
|
stereoVolumeHelper<MIXTYPE, NCHAN>(out, in, vol, [] (auto &a, const auto &b) {
|
|
|
|
|
return MixMul<TO, TI, TV>(a, b);
|
|
|
|
|
});
|
|
|
|
|
if constexpr (MIXTYPE == MIXTYPE_STEREOEXPAND) in += 2;
|
|
|
|
|
} else /* constexpr */ {
|
|
|
|
|
static_assert(dependent_false<MIXTYPE>, "invalid mixtype");
|
|
|
|
|
}
|
|
|
|
|