ChannelMask: Implement BitOr and BitAnd

This also adds associated constants for common channels.
This commit is contained in:
Serial 2024-04-09 19:37:41 -04:00 committed by Alex
parent 2f2263378b
commit 8eb7c06adb
2 changed files with 67 additions and 5 deletions

View file

@ -7,11 +7,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
### Added
- `WriteOptions` ([issue](https://github.com/Serial-ATA/lofty-rs/issues/228)) ([PR](https://github.com/Serial-ATA/lofty-rs/pull/361)):
- **WriteOptions** ([issue](https://github.com/Serial-ATA/lofty-rs/issues/228)) ([PR](https://github.com/Serial-ATA/lofty-rs/pull/361)):
- ⚠️ Important ⚠️: This update introduces `WriteOptions` to allow for finer grained control over how
Lofty writes tags. These are best used as global user-configurable options, as most options will
not apply to all files. The defaults are set to be as safe as possible,
see [here](https://docs.rs/lofty/latest/lofty/struct.WriteOptions.html#impl-Default-for-WriteOptions).
- **ChannelMask** ([PR](https://github.com/Serial-ATA/lofty-rs/pull/370))
- `BitAnd` and `BitOr` implementations
- Associated constants for common channels, ex. `ChannelMask::FRONT_LEFT`
### Fixed
- **Vorbis**: Fix panic when reading properties of zero-length files ([issue](https://github.com/Serial-ATA/lofty-rs/issues/342)) ([PR](https://github.com/Serial-ATA/lofty-rs/pull/365))

View file

@ -86,29 +86,72 @@ impl FileProperties {
}
}
use std::ops::{Add, BitAnd, BitOr};
macro_rules! define_channels {
([
$(
$(#[$meta:meta])?
$name:ident => $shift:literal
),+
]) => {
impl ChannelMask {
$(
$(#[$meta])?
#[allow(missing_docs)]
pub const $name: Self = Self(1 << $shift);
)+
}
};
}
/// Channel mask
///
/// A mask of (at least) 18 bits, one for each channel.
///
/// * Standard speaker channels: <https://www.wikipedia.org/wiki/Surround_sound>
/// * Standard speaker channels: <https://en.wikipedia.org/wiki/Surround_sound#Channel_notation>
/// * CAF channel bitmap: <https://developer.apple.com/library/archive/documentation/MusicAudio/Reference/CAFSpec/CAF_spec/CAF_spec.html#//apple_ref/doc/uid/TP40001862-CH210-BCGBHHHI>
/// * WAV default channel ordering: <https://learn.microsoft.com/en-us/previous-versions/windows/hardware/design/dn653308(v=vs.85)?redirectedfrom=MSDN#default-channel-ordering>
/// * WAV default channel ordering: <https://learn.microsoft.com/en-us/previous-versions/windows/hardware/design/dn653308(v=vs.85)>
/// * FFmpeg: <https://ffmpeg.org/doxygen/trunk/group__channel__masks.html>
#[derive(Debug, Clone, Copy, Eq, PartialEq, Default)]
#[repr(transparent)]
pub struct ChannelMask(pub(crate) u32);
define_channels! {
[
FRONT_LEFT => 0,
FRONT_RIGHT => 1,
FRONT_CENTER => 2,
LOW_FREQUENCY => 3,
BACK_LEFT => 4,
BACK_RIGHT => 5,
FRONT_LEFT_OF_CENTER => 6,
FRONT_RIGHT_OF_CENTER => 7,
BACK_CENTER => 8,
SIDE_LEFT => 9,
SIDE_RIGHT => 10,
TOP_CENTER => 11,
TOP_FRONT_LEFT => 12,
TOP_FRONT_CENTER => 13,
TOP_FRONT_RIGHT => 14,
TOP_BACK_LEFT => 15,
TOP_BACK_CENTER => 16,
TOP_BACK_RIGHT => 17
]
}
impl ChannelMask {
/// A single front center channel
#[must_use]
pub const fn mono() -> Self {
Self(0x4) // front center
Self::FRONT_CENTER
}
/// Front left+right channels
#[must_use]
pub const fn stereo() -> Self {
Self(0x3) // front left (0x1) + front right (0x2)
// TODO: #![feature(const_trait_impl)]
Self(Self::FRONT_LEFT.0 | Self::FRONT_RIGHT.0)
}
/// The bit mask
@ -118,6 +161,22 @@ impl ChannelMask {
}
}
impl BitOr for ChannelMask {
type Output = Self;
fn bitor(self, rhs: Self) -> Self {
Self(self.0 | rhs.0)
}
}
impl BitAnd for ChannelMask {
type Output = Self;
fn bitand(self, rhs: Self) -> Self {
Self(self.0 & rhs.0)
}
}
#[cfg(test)]
mod tests {
use crate::aac::{AACProperties, AacFile};