Media: downmix 7.1 AAC in the order FilmCraft now delivers it (#1701)

FilmCraft reorders AAC channel configuration 12 (7.1) to WAVE/SMPTE order,
as it does 3 to 6, so 7.1 AAC's left channel was mixed as the centre. The
downmix oracle test gains 6.1 (a program config element, left in AAC's
order) and 7.1 AAC fixtures.
This commit is contained in:
tylerjenningsw committed 2026-10-17 10:53:05 -04:00
1 parent 01ad187b97
commit ca724a3d84
2 files changed
+19 -7

No files matched your search

+9 -7
View File
@@ -65,8 +65,10 @@ pub fn stereo_gains(count: usize, aac: bool) -> Vec<Pair> {
}
/// The gains for AAC as FilmCraft's decoder hands it over: channel configurations 3 to 6 (3 to 6
/// channels) are already in WAV/SMPTE order (L R C [Cs] / [LFE] Ls Rs), everything else (mono,
/// stereo, 7 and 8 channels, program-config layouts) in AAC's element order.
/// channels) and 12 (7.1, 8 channels) are already in WAV/SMPTE order (L R C [Cs] / [LFE] Ls Rs,
/// L R C LFE Lb Rb Ls Rs), everything else (mono, stereo, program-config layouts such as the 6.1
/// ffmpeg writes) in AAC's element order. Configuration 11 (6.1) and 7 (7.1 with front wides)
/// can't be told from those by the channel count and are read in the order of the commoner one.
pub fn decoded_aac_gains(count: usize) -> Vec<Pair> {
match count {
// C L R Cs, reordered to L R C Cs: the same gains, permuted.
@@ -74,7 +76,7 @@ pub fn decoded_aac_gains(count: usize) -> Vec<Pair> {
let g = stereo_gains(4, true);
[1, 2, 0, 3].iter().filter_map(|&i| g.get(i).copied()).collect()
}
3 | 5 | 6 => stereo_gains(count, false),
3 | 5 | 6 | 8 => stereo_gains(count, false),
_ => stereo_gains(count, true),
}
}
@@ -118,9 +120,9 @@ mod tests {
}
#[test]
fn decoded_aac_is_in_wav_order_for_three_to_six_channels() {
// FilmCraft hands AAC 3.0 to 5.1 over as L R C [LFE] Ls Rs, the order of the plain layouts.
for n in [3, 5, 6] {
fn decoded_aac_is_in_wav_order_for_three_to_six_and_eight_channels() {
// FilmCraft hands AAC 3.0 to 5.1 and 7.1 over in the order of the plain layouts.
for n in [3, 5, 6, 8] {
assert_eq!(decoded_aac_gains(n), stereo_gains(n, false), "{n} channels");
}
let g = decoded_aac_gains(4);
@@ -128,7 +130,7 @@ mod tests {
assert!(g[0][0] > 0.0 && g[0][1] == 0.0 && g[1][1] > 0.0 && g[1][0] == 0.0, "L R first");
assert!(g[2][0] > 0.0 && g[2][0] == g[2][1], "the centre is third and feeds both sides");
assert!(g[3][0] > 0.0 && g[3][0] < g[2][0], "the rear centre is last, below the centre");
for n in [1, 2, 7, 8, 9] {
for n in [1, 2, 7, 9] {
assert_eq!(decoded_aac_gains(n), stereo_gains(n, true), "{n} channels");
}
}
+10
View File
@@ -94,8 +94,18 @@ fn cases() -> Vec<Case> {
let (n71, g71) = seven_one();
let k5 = 1.0 / (1.0 + 2.0 * K);
let kq = 1.0 / (1.0 + K);
let k61 = 1.0 / (1.5 + 2.0 * K);
vec![
Case { file: "dm51.m4a", layout: "5.1", names: n51, codec: &["-c:a", "aac", "-b:a", "384k"], gains: g51.clone(), tol: 0.15 },
Case {
file: "dm61.m4a",
layout: "6.1",
names: &["FL", "FR", "FC", "LFE", "BC", "SL", "SR"],
codec: &["-c:a", "aac", "-b:a", "448k"],
gains: vec![[k61, 0.0], [0.0, k61], [k61 * K, k61 * K], [0.0, 0.0], [k61 / 2.0, k61 / 2.0], [k61 * K, 0.0], [0.0, k61 * K]],
tol: 0.15,
},
Case { file: "dm71.m4a", layout: "7.1", names: n71, codec: &["-c:a", "aac", "-b:a", "512k"], gains: g71.clone(), tol: 0.15 },
Case { file: "dm51.ac3.mp4", layout: "5.1", names: n51, codec: &["-c:a", "ac3", "-b:a", "640k"], gains: g51.clone(), tol: 0.15 },
Case { file: "dm51.wav", layout: "5.1", names: n51, codec: &["-c:a", "pcm_s16le"], gains: g51.clone(), tol: 0.02 },
Case { file: "dm51.flac", layout: "5.1", names: n51, codec: &["-c:a", "flac"], gains: g51, tol: 0.02 },