mirror of
https://github.com/Serial-ATA/lofty-rs
synced 2024-11-10 06:34:18 +00:00
Opus: Create a ChannelMask
for OpusProperties
This commit is contained in:
parent
5c69024b91
commit
1ff1f8a441
3 changed files with 60 additions and 2 deletions
|
@ -2,7 +2,7 @@ use super::find_last_page;
|
|||
use crate::error::Result;
|
||||
use crate::macros::decode_err;
|
||||
use crate::math::RoundedDivision;
|
||||
use crate::properties::FileProperties;
|
||||
use crate::properties::{ChannelMask, FileProperties};
|
||||
|
||||
use std::io::{Read, Seek, SeekFrom};
|
||||
use std::time::Duration;
|
||||
|
@ -18,6 +18,7 @@ pub struct OpusProperties {
|
|||
pub(crate) overall_bitrate: u32,
|
||||
pub(crate) audio_bitrate: u32,
|
||||
pub(crate) channels: u8,
|
||||
pub(crate) channel_mask: ChannelMask,
|
||||
pub(crate) version: u8,
|
||||
pub(crate) input_sample_rate: u32,
|
||||
}
|
||||
|
@ -31,7 +32,7 @@ impl From<OpusProperties> for FileProperties {
|
|||
sample_rate: Some(input.input_sample_rate),
|
||||
bit_depth: None,
|
||||
channels: Some(input.channels),
|
||||
channel_mask: None,
|
||||
channel_mask: Some(input.channel_mask),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -57,6 +58,11 @@ impl OpusProperties {
|
|||
self.channels
|
||||
}
|
||||
|
||||
/// Channel mask
|
||||
pub fn channel_mask(&self) -> ChannelMask {
|
||||
self.channel_mask
|
||||
}
|
||||
|
||||
/// Opus version
|
||||
pub fn version(&self) -> u8 {
|
||||
self.version
|
||||
|
@ -103,6 +109,9 @@ where
|
|||
decode_err!(@BAIL Opus, "Invalid channel count for mapping family");
|
||||
}
|
||||
|
||||
properties.channel_mask =
|
||||
ChannelMask::from_opus_channels(properties.channels).expect("Channel count is valid");
|
||||
|
||||
let last_page = find_last_page(data);
|
||||
let file_length = data.seek(SeekFrom::End(0))?;
|
||||
|
||||
|
|
|
@ -66,11 +66,59 @@ impl ChannelMask {
|
|||
Self(Self::FRONT_LEFT.0 | Self::FRONT_RIGHT.0)
|
||||
}
|
||||
|
||||
/// Front left+right+center channels
|
||||
#[must_use]
|
||||
pub const fn linear_surround() -> Self {
|
||||
Self(Self::FRONT_LEFT.0 | Self::FRONT_RIGHT.0 | Self::FRONT_CENTER.0)
|
||||
}
|
||||
|
||||
/// The bit mask
|
||||
#[must_use]
|
||||
pub const fn bits(self) -> u32 {
|
||||
self.0
|
||||
}
|
||||
|
||||
/// Create a channel mask from the number of channels in an Opus file
|
||||
///
|
||||
/// See <https://datatracker.ietf.org/doc/html/rfc7845#section-5.1.1.2> for the mapping.
|
||||
pub const fn from_opus_channels(channels: u8) -> Option<Self> {
|
||||
match channels {
|
||||
1 => Some(Self::mono()),
|
||||
2 => Some(Self::stereo()),
|
||||
3 => Some(Self::linear_surround()),
|
||||
4 => Some(Self(
|
||||
Self::FRONT_LEFT.bits()
|
||||
| Self::FRONT_RIGHT.bits()
|
||||
| Self::BACK_LEFT.bits()
|
||||
| Self::BACK_RIGHT.bits(),
|
||||
)),
|
||||
5 => Some(Self(
|
||||
Self::linear_surround().bits() | Self::BACK_LEFT.bits() | Self::BACK_RIGHT.bits(),
|
||||
)),
|
||||
6 => Some(Self(
|
||||
Self::linear_surround().bits()
|
||||
| Self::BACK_LEFT.bits()
|
||||
| Self::BACK_RIGHT.bits()
|
||||
| Self::LOW_FREQUENCY.bits(),
|
||||
)),
|
||||
7 => Some(Self(
|
||||
Self::linear_surround().bits()
|
||||
| Self::SIDE_LEFT.bits()
|
||||
| Self::SIDE_RIGHT.bits()
|
||||
| Self::BACK_CENTER.bits()
|
||||
| Self::LOW_FREQUENCY.bits(),
|
||||
)),
|
||||
8 => {
|
||||
Some(Self(
|
||||
Self::linear_surround().bits()
|
||||
| Self::SIDE_LEFT.bits() | Self::SIDE_RIGHT.bits()
|
||||
| Self::BACK_LEFT.bits() | Self::BACK_RIGHT.bits()
|
||||
| Self::LOW_FREQUENCY.bits(),
|
||||
))
|
||||
},
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl BitOr for ChannelMask {
|
||||
|
|
|
@ -229,6 +229,7 @@ const OPUS_PROPERTIES: OpusProperties = OpusProperties {
|
|||
overall_bitrate: 120,
|
||||
audio_bitrate: 120,
|
||||
channels: 2,
|
||||
channel_mask: ChannelMask::stereo(),
|
||||
version: 1,
|
||||
input_sample_rate: 48000,
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue