aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/cubeb_mixer.cpp
diff options
context:
space:
mode:
authorChun-Min Chang <[email protected]>2017-03-14 15:00:11 +0800
committerAlex Chronopoulos <[email protected]>2017-03-15 13:09:32 +0100
commit9238299442f03e459feb8f77461931799192326d (patch)
treec93515e1b3598381157d3f91a77ddb17f8193e7b /src/cubeb_mixer.cpp
parentb0425467a46dfec89575489db7360aeda1c13374 (diff)
downloadcubeb-9238299442f03e459feb8f77461931799192326d.tar.gz
cubeb-9238299442f03e459feb8f77461931799192326d.zip
Merge two downmix_3f2 into one
Diffstat (limited to 'src/cubeb_mixer.cpp')
-rw-r--r--src/cubeb_mixer.cpp116
1 files changed, 28 insertions, 88 deletions
diff --git a/src/cubeb_mixer.cpp b/src/cubeb_mixer.cpp
index 182d1e5..8a0bb32 100644
--- a/src/cubeb_mixer.cpp
+++ b/src/cubeb_mixer.cpp
@@ -198,76 +198,37 @@ static float const DOWNMIX_MATRIX_3F2_LFE[SUPPORTED_LAYOUT_NUM][MAX_OUTPUT_CHANN
}
};
-/* Convert audio data from 3F2(-LFE) to 1F, 2F, 3F, 2F1, 3F1, 2F2 and their LFEs. */
-#if !defined(USE_AUDIOUNIT)
+// Convert audio data from 3F2(-LFE) to 1F, 2F, 3F, 2F1, 3F1, 2F2 and their LFEs.
+//
// ITU-R BS.775-3[1] provides spec for downmixing 3F2 data to 1F, 2F, 3F, 2F1,
// 3F1, 2F2 data. We simply add LFE to its defined matrix. If both the input
-// and output have LFE channel, then we pass it's data. If only input has LFE,
-// then we drop it. If only output has LFE, then we append 0 to its channel.
-//
-// Example: Downmixing from 3F2-LFE to stereo:
+// and output have LFE channel, then we pass it's data. If only input or output
+// has LFE, then we either drop it or append 0 to the LFE channel.
//
+// Fig. 1:
// |<-------------- 1 -------------->|<-------------- 2 -------------->|
// +----+----+----+------+-----+-----+----+----+----+------+-----+-----+
// | L0 | R0 | C0 | LFE0 | LS0 | RS0 | L1 | R1 | C1 | LFE1 | LS1 | RS1 | ...
// +----+----+----+------+-----+-----+----+----+----+------+-----+-----+
//
-// | Downmix
-// v
-//
+// Fig. 2:
// |<-- 1 -->|<-- 2 -->|
// +----+----+----+----+
// | L0 | R0 | L1 | R1 | ...
// +----+----+----+----+
//
-// where L0 = L0 + 0.707 * (C0 + LS0), R0 = R0 + 0.707 * (C0 + RS0),
-// L1 = L1 + 0.707 * (C1 + LS1), R1 = R1 + 0.707 * (C1 + RS1), ...
-//
-template<typename T>
-bool
-downmix_3f2(T const * const in, unsigned long inframes, T * out, cubeb_channel_layout in_layout, cubeb_channel_layout out_layout)
-{
- if ((in_layout != CUBEB_LAYOUT_3F2 && in_layout != CUBEB_LAYOUT_3F2_LFE) ||
- out_layout < CUBEB_LAYOUT_MONO || out_layout > CUBEB_LAYOUT_2F2_LFE) {
- return false;
- }
-
- unsigned int in_channels = CUBEB_CHANNEL_LAYOUT_MAPS[in_layout].channels;
- unsigned int out_channels = CUBEB_CHANNEL_LAYOUT_MAPS[out_layout].channels;
-
- // Conversion from 3F2 to 2F2-LFE or 3F1-LFE is allowed, so we use '<=' instead of '<'.
- assert(out_channels <= in_channels);
-
- auto & downmix_matrix = DOWNMIX_MATRIX_3F2_LFE[out_layout - CUBEB_LAYOUT_MONO]; // The matrix is started from mono.
- for (unsigned long i = 0, out_index = 0; i < inframes * in_channels; i += in_channels, out_index += out_channels) {
- for (unsigned int j = 0; j < out_channels; ++j) {
- T sample = 0;
- for (unsigned int k = 0 ; k < INPUT_CHANNEL_NUM ; ++k) {
- // 3F2-LFE has 6 channels: L, R, C, LFE, LS, RS, while 3F2 has only 5
- // channels: L, R, C, LS, RS. Thus, we need to append 0 to LFE(index 3)
- // to simulate a 3F2-LFE data when input layout is 3F2.
- T data = (in_layout == CUBEB_LAYOUT_3F2_LFE) ? in[i + k] : (k == 3) ? 0 : in[i + ((k < 3) ? k : k - 1)];
- sample += downmix_matrix[j][k] * data;
- }
- out[out_index + j] = sample;
- }
- }
-
- return true;
-}
-#else
-// This is an in-place version downmixing only for OSX.
+// The figures above shows an example for downmixing from 3F2-LFE(Fig. 1) to
+// to stereo(Fig. 2), where L0 = L0 + 0.707 * (C0 + LS0),
+// R0 = R0 + 0.707 * (C0 + RS0), L1 = L1 + 0.707 * (C1 + LS1),
+// R1 = R1 + 0.707 * (C1 + RS1), ...
//
+// Nevertheless, the downmixing method is a little bit different on OSX.
// The audio rendering mechanism on OS X will drop the extra channels beyond
-// the channels that audio device can provide. To keep all information,
-// we need to downmix the audio data by ourselves.
-//
-// The trick here is that OSX allows us to set the layout containing other
-// channels that the output device can NOT provide. Therefore, OSX expects we
-// will fill the buffer for playing sound by the layout we set, so there are
-// some will-be-dropped data in the buffer. For example, if we set layout to
-// 3F2-LFE for a stereo device and we fill the buffer with data for left, right,
-// center, low frequency effects, left surround, right surround channels,
+// the channels that audio device can provide. The trick here is that OSX allows
+// us to set the layout containing other channels that the output device can
+// NOT provide. For example, setting 3F2-LFE layout to a stereo device is fine.
+// Therefore, OSX expects we fill the buffer for playing sound by the defined
+// layout, so there are some will-be-dropped data in the buffer:
//
// +---+---+---+-----+----+----+
// | L | R | C | LFE | LS | RS | ...
@@ -275,44 +236,20 @@ downmix_3f2(T const * const in, unsigned long inframes, T * out, cubeb_channel_l
// ^ ^ ^ ^
// The data for these four channels will be dropped!
//
-// then the data for non-stereo channels will be ignored. To keep all the sounds,
-// we need to downmix the audio into the following format:
-//
-// |<-- gap -->|
-// +----+----+---+---+---+---+
-// | L' | R' | x | x | x | x | ...
-// +----+----+---+---+---+---+
-// ^ ^ ^ ^
-// Useless channel data ...
-//
-// where L' = L + 0.707 * (C + LS) and R' = R + 0.707 * (C + RS).
-//
-// Generally, we will change the buffer data like the following figure:
-//
-// |<-------------- 1 -------------->|<-------------- 2 -------------->|
-// +----+----+----+------+-----+-----+----+----+----+------+-----+-----+
-// | L0 | R0 | C0 | LFE0 | LS0 | RS0 | L1 | R1 | C1 | LFE1 | LS1 | RS1 | ...
-// +----+----+----+------+-----+-----+----+----+----+------+-----+-----+
-//
-// | Downmix
-// v
+// To keep all the information, we need to downmix the data before it's dropped
+// The figure below shows an example for downmixing from 3F2-LFE(Fig. 1)
+// to stereo(Fig. 3) on OSX.
//
+// Fig. 3:
// |<---------- 1 ---------->|<---------- 2 ---------->|
// +----+----+---+---+---+---+----+----+---+---+---+---+
// | L0 | R0 | x | x | x | x | L1 | R1 | x | x | x | x | ...
// +----+----+---+---+---+---+----+----+---+---+---+---+
// |<-- gap -->| |<-- gap -->|
-//
-// where L0 = L0 + 0.707 * (C0 + LS0), R0 = R0 + 0.707 * (C0 + RS0),
-// L1 = L1 + 0.707 * (C1 + LS1), R1 = R1 + 0.707 * (C1 + RS1), ...
-//
template<typename T>
bool
downmix_3f2(T const * const in, unsigned long inframes, T * out, cubeb_channel_layout in_layout, cubeb_channel_layout out_layout)
{
- // Avoid allocating buffers in audio callback, so we reuse the same buffer.
- assert(in == out);
-
if ((in_layout != CUBEB_LAYOUT_3F2 && in_layout != CUBEB_LAYOUT_3F2_LFE) ||
out_layout < CUBEB_LAYOUT_MONO || out_layout > CUBEB_LAYOUT_2F2_LFE) {
return false;
@@ -325,9 +262,8 @@ downmix_3f2(T const * const in, unsigned long inframes, T * out, cubeb_channel_l
assert(out_channels <= in_channels);
auto & downmix_matrix = DOWNMIX_MATRIX_3F2_LFE[out_layout - CUBEB_LAYOUT_MONO]; // The matrix is started from mono.
- // The difference between this method and the normal version is that we use
- // "out_index += in_channels" instead of "out_index += out_channels".
- for (unsigned long i = 0, out_index = 0; i < inframes * in_channels; i += in_channels, out_index += in_channels) {
+ unsigned long out_index = 0;
+ for (unsigned long i = 0 ; i < inframes * in_channels; i += in_channels) {
for (unsigned int j = 0; j < out_channels; ++j) {
T sample = 0;
for (unsigned int k = 0 ; k < INPUT_CHANNEL_NUM ; ++k) {
@@ -339,11 +275,15 @@ downmix_3f2(T const * const in, unsigned long inframes, T * out, cubeb_channel_l
}
out[out_index + j] = sample;
}
+#if defined(USE_AUDIOUNIT)
+ out_index += in_channels;
+#else
+ out_index += out_channels;
+#endif
}
return true;
}
-#endif
/* Map the audio data by channel name. */
template<class T>
@@ -428,7 +368,7 @@ cubeb_downmix(T const * const in, long inframes, T * out,
return;
}
- // We only support downmix from audio 5.1 for now.
+ // We only support downmix for audio 5.1 currently.
#if defined(USE_AUDIOUNIT)
return;
#endif