Fully implement CommonSampleRates

This commit is contained in:
JasonLG1979 2023-06-29 16:35:54 -05:00
parent 1ab5bac786
commit 15e2b441aa
2 changed files with 132 additions and 3 deletions

View file

@ -2,7 +2,7 @@ use super::{Open, Sink, SinkAsBytes, SinkError, SinkResult};
use crate::config::{AudioFormat, SampleRate};
use crate::convert::Converter;
use crate::decoder::AudioPacket;
use crate::{COMMON_SAMPLE_RATES, NUM_CHANNELS, SAMPLE_RATE as DECODER_SAMPLE_RATE};
use crate::{CommonSampleRates, NUM_CHANNELS, SAMPLE_RATE as DECODER_SAMPLE_RATE};
use alsa::device_name::HintIter;
use alsa::pcm::{Access, Format, Frames, HwParams, PCM};
use alsa::{Direction, ValueOr};
@ -35,7 +35,7 @@ enum AlsaError {
UnsupportedSampleRate {
device: String,
samplerate: u32,
supported_rates: Vec<u32>,
supported_rates: Vec<String>,
e: alsa::Error,
},
@ -382,9 +382,21 @@ impl AlsaSink {
hwp.set_rate(self.sample_rate, ValueOr::Nearest)
.map_err(|e| {
let common_sample_rates = CommonSampleRates::default();
let supported_rates = (hwp.get_rate_min().unwrap_or_default()
..=hwp.get_rate_max().unwrap_or_default())
.filter(|r| COMMON_SAMPLE_RATES.contains(r) && hwp.test_rate(*r).is_ok())
.filter_map(|r| {
if common_sample_rates.contains(r) && hwp.test_rate(r).is_ok() {
Some(
CommonSampleRates::try_from(r)
.unwrap_or_default()
.to_string(),
)
} else {
None
}
})
.collect();
AlsaError::UnsupportedSampleRate {

View file

@ -1,3 +1,6 @@
use std::convert::TryFrom;
use std::fmt;
#[macro_use]
extern crate log;
@ -39,3 +42,117 @@ pub fn db_to_ratio(db: f64) -> f64 {
pub fn ratio_to_db(ratio: f64) -> f64 {
ratio.log10() * DB_VOLTAGE_RATIO
}
// not used by all backends
#[allow(dead_code)]
#[derive(Copy, Clone, Debug, Default)]
pub enum CommonSampleRates {
#[default]
Hz8000,
Hz11025,
Hz16000,
Hz22050,
Hz44100,
Hz48000,
Hz88200,
Hz96000,
Hz176400,
Hz192000,
Hz352800,
Hz384000,
Hz705600,
Hz768000,
}
impl TryFrom<u32> for CommonSampleRates {
type Error = ();
fn try_from(value: u32) -> Result<Self, Self::Error> {
use CommonSampleRates::*;
match value {
8000 => Ok(Hz8000),
11025 => Ok(Hz11025),
16000 => Ok(Hz16000),
22050 => Ok(Hz22050),
44100 => Ok(Hz44100),
48000 => Ok(Hz48000),
88200 => Ok(Hz88200),
96000 => Ok(Hz96000),
176400 => Ok(Hz176400),
192000 => Ok(Hz192000),
352800 => Ok(Hz352800),
384000 => Ok(Hz384000),
705600 => Ok(Hz705600),
768000 => Ok(Hz768000),
_ => Err(()),
}
}
}
impl fmt::Display for CommonSampleRates {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use CommonSampleRates::*;
let rate_str = match self {
Hz8000 => "8kHz",
Hz11025 => "11.025kHz",
Hz16000 => "16kHz",
Hz22050 => "22.05kHz",
Hz44100 => "44.1kHz",
Hz48000 => "48kHz",
Hz88200 => "88.2kHz",
Hz96000 => "96kHz",
Hz176400 => "176.4kHz",
Hz192000 => "192kHz",
Hz352800 => "352.8kHz",
Hz384000 => "384kHz",
Hz705600 => "705.6kHz",
Hz768000 => "768kHz",
};
write!(f, "{}", rate_str)
}
}
impl IntoIterator for CommonSampleRates {
type Item = CommonSampleRates;
type IntoIter = std::vec::IntoIter<Self::Item>;
fn into_iter(self) -> Self::IntoIter {
use CommonSampleRates::*;
vec![
Hz8000, Hz11025, Hz16000, Hz22050, Hz44100, Hz48000, Hz88200, Hz96000, Hz176400,
Hz192000, Hz352800, Hz384000, Hz705600, Hz768000,
]
.into_iter()
}
}
impl CommonSampleRates {
pub fn as_u32(&self) -> u32 {
use CommonSampleRates::*;
match self {
Hz8000 => 8000,
Hz11025 => 11025,
Hz16000 => 16000,
Hz22050 => 22050,
Hz44100 => 44100,
Hz48000 => 48000,
Hz88200 => 88200,
Hz96000 => 96000,
Hz176400 => 176400,
Hz192000 => 192000,
Hz352800 => 352800,
Hz384000 => 384000,
Hz705600 => 705600,
Hz768000 => 768000,
}
}
pub fn contains(&self, rate: u32) -> bool {
self.into_iter().any(|r| r.as_u32() == rate)
}
}