use objc2_core_audio_types::AudioStreamBasicDescription;
use super::audio_format::AudioFormat;
use super::audio_format::LinearPcmFlags;
use super::SampleFormat;
use crate::error::{self, Error};
#[derive(Copy, Clone, Debug)]
pub struct StreamFormat {
pub sample_rate: f64,
pub sample_format: SampleFormat,
pub flags: super::audio_format::LinearPcmFlags,
pub channels: u32,
}
impl StreamFormat {
#[allow(non_snake_case)]
pub fn from_asbd(asbd: AudioStreamBasicDescription) -> Result<StreamFormat, Error> {
const NOT_SUPPORTED: Error = Error::AudioUnit(error::audio_unit::Error::FormatNotSupported);
let AudioStreamBasicDescription {
mSampleRate,
mFormatID,
mFormatFlags,
mBytesPerFrame: _,
mChannelsPerFrame,
mBitsPerChannel,
..
} = asbd;
let flags = match AudioFormat::from_format_and_flag(mFormatID, Some(mFormatFlags)) {
Some(AudioFormat::LinearPCM(flags)) => flags,
_ => return Err(NOT_SUPPORTED),
};
let sample_format =
match SampleFormat::from_flags_and_bits_per_sample(flags, mBitsPerChannel) {
Some(sample_format) => sample_format,
None => return Err(NOT_SUPPORTED),
};
let channels = mChannelsPerFrame;
Ok(StreamFormat {
sample_rate: mSampleRate,
flags,
sample_format,
channels,
})
}
pub fn to_asbd(self) -> AudioStreamBasicDescription {
let StreamFormat {
sample_rate,
flags,
sample_format,
channels,
} = self;
let (format, maybe_flag) =
AudioFormat::LinearPCM(flags | LinearPcmFlags::IS_PACKED).as_format_and_flag();
let flag = maybe_flag.unwrap_or(u32::MAX - 2147483647);
let non_interleaved = flags.contains(LinearPcmFlags::IS_NON_INTERLEAVED);
let bytes_per_frame = if non_interleaved {
sample_format.size_in_bytes() as u32
} else {
sample_format.size_in_bytes() as u32 * channels
};
const FRAMES_PER_PACKET: u32 = 1;
let bytes_per_packet = bytes_per_frame * FRAMES_PER_PACKET;
let bits_per_channel = sample_format.size_in_bits();
AudioStreamBasicDescription {
mSampleRate: sample_rate,
mFormatID: format,
mFormatFlags: flag,
mBytesPerPacket: bytes_per_packet,
mFramesPerPacket: FRAMES_PER_PACKET,
mBytesPerFrame: bytes_per_frame,
mChannelsPerFrame: channels,
mBitsPerChannel: bits_per_channel,
mReserved: 0,
}
}
}