AAC: Create a ChannelMask for AacProperties

This commit is contained in:
Serial 2024-04-09 20:29:25 -04:00
parent 1ff1f8a441
commit c9738c84fd
No known key found for this signature in database
GPG key ID: DA95198DC17C4568
3 changed files with 55 additions and 2 deletions

View file

@ -1,7 +1,7 @@
use crate::aac::header::ADTSHeader;
use crate::mp4::AudioObjectType;
use crate::mpeg::header::MpegVersion;
use crate::properties::FileProperties;
use crate::properties::{ChannelMask, FileProperties};
use std::time::Duration;
@ -15,6 +15,7 @@ pub struct AACProperties {
pub(crate) audio_bitrate: u32,
pub(crate) sample_rate: u32,
pub(crate) channels: u8,
pub(crate) channel_mask: Option<ChannelMask>,
pub(crate) copyright: bool,
pub(crate) original: bool,
}
@ -67,6 +68,11 @@ impl AACProperties {
self.channels
}
/// Channel mask
pub fn channel_mask(&self) -> Option<ChannelMask> {
self.channel_mask
}
/// Whether the audio is copyrighted
pub fn copyright(&self) -> bool {
self.copyright
@ -87,7 +93,7 @@ impl From<AACProperties> for FileProperties {
sample_rate: Some(input.sample_rate),
bit_depth: None,
channels: Some(input.channels),
channel_mask: None,
channel_mask: input.channel_mask,
}
}
}
@ -101,6 +107,17 @@ pub(super) fn read_properties(
properties.audio_object_type = first_frame.audio_object_ty;
properties.sample_rate = first_frame.sample_rate;
properties.channels = first_frame.channels;
match ChannelMask::from_mp4_channels(properties.channels) {
Some(mask) => properties.channel_mask = Some(mask),
None => {
log::warn!(
"Unable to create channel mask, invalid channel count: {}",
properties.channels
);
},
}
properties.copyright = first_frame.copyright;
properties.original = first_frame.original;

View file

@ -119,6 +119,41 @@ impl ChannelMask {
_ => None,
}
}
/// Create a channel mask from the number of channels in an MP4 file
///
/// See <https://wiki.multimedia.cx/index.php/MPEG-4_Audio#Channel_Configurations> for the mapping.
pub const fn from_mp4_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_LEFT.bits() | Self::BACK_RIGHT.bits()
| Self::LOW_FREQUENCY.bits(),
))
},
_ => None,
}
}
}
impl BitOr for ChannelMask {

View file

@ -32,6 +32,7 @@ const AAC_PROPERTIES: AACProperties = AACProperties {
audio_bitrate: 117, // 9 less than FFmpeg reports
sample_rate: 48000,
channels: 2,
channel_mask: Some(ChannelMask::stereo()),
copyright: false,
original: false,
};