1use vst3::Steinberg::Vst::*;
3
4#[derive(Clone, Debug, Eq, PartialEq, thiserror::Error)]
5pub enum LayoutError {
6 #[error("unsupported speaker bit {0}")]
7 UnknownBit(u32),
8 #[error("unknown default layout for {0} channels")]
9 UnknownChannels(u16),
10 #[error("unsupported VST 2 speaker type {0}")]
11 UnknownSpeaker(i32),
12 #[error("duplicate or unordered speaker arrangement")]
13 Order,
14 #[error("empty speaker arrangement (0 channels)")]
15 Empty,
16 #[error("{0} main bus is missing or its channel count disagrees with arrangement {1:#x}")]
17 Bus(&'static str, u64),
18}
19
20const SPEAKERS: [(u64, u32); 18] = [
21 (kSpeakerL, 0x1),
22 (kSpeakerR, 0x2),
23 (kSpeakerC, 0x4),
24 (kSpeakerLfe, 0x8),
25 (kSpeakerLs, 0x10),
26 (kSpeakerRs, 0x20),
27 (kSpeakerLc, 0x40),
28 (kSpeakerRc, 0x80),
29 (kSpeakerCs, 0x100),
30 (kSpeakerSl, 0x200),
31 (kSpeakerSr, 0x400),
32 (kSpeakerTc, 0x800),
33 (kSpeakerTfl, 0x1000),
34 (kSpeakerTfc, 0x2000),
35 (kSpeakerTfr, 0x4000),
36 (kSpeakerTrl, 0x8000),
37 (kSpeakerTrc, 0x10000),
38 (kSpeakerTrr, 0x20000),
39];
40
41pub fn wave_bits(arrangement: u64) -> Result<Vec<u32>, LayoutError> {
42 if arrangement == 0 {
43 return Err(LayoutError::Empty);
44 }
45 let known = SPEAKERS.iter().fold(0, |bits, (speaker, _)| bits | speaker);
46 let unknown = arrangement & !known;
47 if unknown != 0 {
48 return Err(LayoutError::UnknownBit(unknown.trailing_zeros()));
49 }
50 Ok(SPEAKERS
51 .iter()
52 .filter_map(|(speaker, wave)| (arrangement & speaker != 0).then_some(*wave))
53 .collect())
54}
55
56pub fn main_bus(buses: &[crate::Bus], direction: &'static str) -> Result<Vec<u32>, LayoutError> {
58 let bus = buses.first().ok_or(LayoutError::Bus(direction, 0))?;
59 let bits = wave_bits(bus.arrangement)?;
60 if bus.channels == 0 || bus.channels > 32 || bits.len() != usize::from(bus.channels) {
61 return Err(LayoutError::Bus(direction, bus.arrangement));
62 }
63 Ok(bits)
64}
65
66pub fn default_arrangement(channels: u16) -> Result<u64, LayoutError> {
67 match channels {
68 1 => Ok(kSpeakerC),
69 2 => Ok(kSpeakerL | kSpeakerR),
70 6 => Ok(kSpeakerL | kSpeakerR | kSpeakerC | kSpeakerLfe | kSpeakerLs | kSpeakerRs),
71 8 => Ok(kSpeakerL
72 | kSpeakerR
73 | kSpeakerC
74 | kSpeakerLfe
75 | kSpeakerLs
76 | kSpeakerRs
77 | kSpeakerSl
78 | kSpeakerSr),
79 _ => Err(LayoutError::UnknownChannels(channels)),
80 }
81}
82
83pub fn vst2_arrangement(speakers: &[i32]) -> Result<u64, LayoutError> {
86 let mut result = 0;
87 let mut previous = 0;
88 for speaker in speakers {
89 let bit = match speaker {
90 0 | 3 => kSpeakerC,
91 1 => kSpeakerL,
92 2 => kSpeakerR,
93 4 => kSpeakerLfe,
94 5 => kSpeakerLs,
95 6 => kSpeakerRs,
96 10 => kSpeakerSl,
97 11 => kSpeakerSr,
98 other => return Err(LayoutError::UnknownSpeaker(*other)),
99 };
100 if bit <= previous {
101 return Err(LayoutError::Order);
102 }
103 previous = bit;
104 result |= bit;
105 }
106 Ok(result)
107}
108
109#[cfg(test)]
110mod tests {
111 use super::*;
112 #[test]
113 fn common_layouts() {
114 for (channels, expected) in [
115 (1, vec![4]),
116 (2, vec![1, 2]),
117 (6, vec![1, 2, 4, 8, 16, 32]),
118 (8, vec![1, 2, 4, 8, 16, 32, 512, 1024]),
119 ] {
120 assert_eq!(
121 wave_bits(default_arrangement(channels).unwrap()).unwrap(),
122 expected
123 );
124 }
125 assert_eq!(
126 wave_bits(kSpeakerL | kSpeakerR | kSpeakerLs | kSpeakerRs).unwrap(),
127 [1, 2, 16, 32]
128 );
129 assert_eq!(
130 wave_bits(kSpeakerL | kSpeakerR | kSpeakerC | kSpeakerLs | kSpeakerRs).unwrap(),
131 [1, 2, 4, 16, 32]
132 );
133 for (bit, wave) in SPEAKERS {
134 assert_eq!(wave_bits(bit).unwrap(), [wave]);
135 }
136 assert_eq!(wave_bits((1 << 18) - 1).unwrap().len(), 18);
137 }
138 #[test]
139 fn unknown_layouts_are_errors() {
140 for bit in 18..64 {
141 assert_eq!(wave_bits(1 << bit), Err(LayoutError::UnknownBit(bit)));
142 }
143 for count in [0, 3, 4, 5, 7, 9, 32] {
144 assert!(default_arrangement(count).is_err());
145 }
146 assert!(vst2_arrangement(&[1, 1]).is_err());
147 assert!(vst2_arrangement(&[2, 1]).is_err());
148 assert!(vst2_arrangement(&[99]).is_err());
149 assert_eq!(
150 vst2_arrangement(&[1, 2, 3, 4, 5, 6]).unwrap(),
151 default_arrangement(6).unwrap()
152 );
153 }
154}