firewheel_core/silence_mask.rs
1use core::u64;
2
3/// An optional optimization hint on which channels contain all
4/// zeros (silence). The first bit (`0x1`) is the first channel,
5/// the second bit is the second channel, and so on.
6#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, Hash)]
7pub struct SilenceMask(pub u64);
8
9impl SilenceMask {
10 /// A mask with no channels marked as silent
11 pub const NONE_SILENT: Self = Self(0);
12
13 /// A mask with only the first channel marked as silent
14 pub const MONO_SILENT: Self = Self(0b1);
15
16 /// A mask with only the first two channels marked as silent
17 pub const STEREO_SILENT: Self = Self(0b11);
18
19 /// Construct a new [`SilenceMask`] with all channels marked as
20 /// silent.
21 ///
22 /// `num_channels` must be less than or equal to `64`.
23 pub const fn new_all_silent(num_channels: usize) -> Self {
24 if num_channels >= 64 {
25 Self(u64::MAX)
26 } else {
27 Self((0b1 << num_channels) - 1)
28 }
29 }
30
31 /// Returns `true` if the channel is marked as silent, `false`
32 /// otherwise.
33 ///
34 /// `i` must be less than `64`.
35 pub const fn is_channel_silent(&self, i: usize) -> bool {
36 self.0 & (0b1 << i) != 0
37 }
38
39 /// Returns `true` if any channel is marked as silent, `false`
40 /// otherwise.
41 ///
42 /// `num_channels` must be less than or equal to `64`.
43 pub const fn any_channel_silent(&self, num_channels: usize) -> bool {
44 if num_channels >= 64 {
45 self.0 != 0
46 } else {
47 self.0 & ((0b1 << num_channels) - 1) != 0
48 }
49 }
50
51 /// Returns `true` if all channels are marked as silent, `false`
52 /// otherwise.
53 ///
54 /// `num_channels` must be less than or equal to `64`.
55 pub const fn all_channels_silent(&self, num_channels: usize) -> bool {
56 if num_channels >= 64 {
57 self.0 == u64::MAX
58 } else {
59 let mask = (0b1 << num_channels) - 1;
60 self.0 & mask == mask
61 }
62 }
63
64 /// Mark/un-mark the given channel as silent.
65 ///
66 /// `i` must be less than `64`.
67 pub fn set_channel(&mut self, i: usize, silent: bool) {
68 if silent {
69 self.0 |= 0b1 << i;
70 } else {
71 self.0 &= !(0b1 << i);
72 }
73 }
74
75 pub const fn union(self, other: Self) -> Self {
76 SilenceMask(self.0 & other.0)
77 }
78
79 pub fn union_with(&mut self, other: Self) {
80 self.0 &= other.0;
81 }
82}