sapi_lite/tts/speech/
types.rs

1use std::fmt::Display;
2use std::hash::Hash;
3
4/// Provides a hint about how to pronounce the associated content.
5#[derive(Debug, Hash, PartialEq, Eq, Clone, Copy)]
6pub enum SayAs<'s> {
7    /// Pronounce a sequence of numbers as a date, e.g. "03/08/2000" as "march eighth two thousand".
8    DateMDY,
9    /// Pronounce a sequence of numbers as a date, e.g. "03/08/2000" as "august third two thousand".
10    DateDMY,
11    /// Pronounce a sequence of numbers as a date, e.g. "2000/08/03" as "march eighth two thousand".
12    DateYMD,
13    /// Pronounce a sequence of numbers as a year and month, e.g. "2000/03" as "march two thousand".
14    DateYM,
15    /// Pronounce a sequence of numbers as a month and year, e.g. "03/2000" as "march two thousand".
16    DateMY,
17    /// Pronounce a sequence of numbers as a day and month, e.g. "03/08" as "march eighth".
18    DateDM,
19    /// Pronounce a sequence of numbers as a month and day, e.g. "03/08" as "august third".
20    DateMD,
21    /// Pronounce a number as a year, e.g. "1979" as "nineteen seventy-nine".
22    DateYear,
23    /// Pronounce a sequence of numbers as a time, e.g. "10:24" as "ten twenty-four".
24    Time,
25    /// Pronounce a number as a cardinal number, e.g. "1024" as "one thousand twenty-four".
26    NumberCardinal,
27    /// Pronounce a number as a sequence of digits, e.g. "1024" as "one zero two four".
28    NumberDigit,
29    /// Pronounce a number as a fraction, e.g. "3/8" as "three eighths".
30    NumberFraction,
31    /// Pronounce a number as a fraction, e.g. "10.24" as "ten point two four".
32    NumberDecimal,
33    /// Pronounce a sequence of numbers as a telephone, e.g. "(206) 555-1234" as "two zero six five
34    /// five five one two three four".
35    PhoneNumber,
36    /// A custom pronunciation hint supported by the engine.
37    Custom(&'s str),
38}
39
40impl<'s> SayAs<'s> {
41    pub(super) fn sapi_id(&self) -> &str {
42        match self {
43            Self::DateMDY => "date_mdy",
44            Self::DateDMY => "date_dmy",
45            Self::DateYMD => "date_ymd",
46            Self::DateYM => "date_ym",
47            Self::DateMY => "date_my",
48            Self::DateDM => "date_dm",
49            Self::DateMD => "date_md",
50            Self::DateYear => "date_year",
51            Self::Time => "time",
52            Self::NumberCardinal => "number_cardinal",
53            Self::NumberDigit => "number_digit",
54            Self::NumberFraction => "number_fraction",
55            Self::NumberDecimal => "number_decimal",
56            Self::PhoneNumber => "phone_number",
57            Self::Custom(s) => s,
58        }
59    }
60}
61
62macro_rules! decl_clamped_int {
63    {$(#[$meta:meta])* $name:ident($base:ty) in $min:literal..$max:literal} => {
64        $(#[$meta])*
65        #[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
66        pub struct $name($base);
67
68        impl $name {
69            /// Clamps the given value to the interval
70            #[doc = concat!("[", stringify!($min), ", ", stringify!($max), "]")]
71            /// and constructs a new instance from it.
72            pub fn new(value: $base) -> Self {
73                Self(value.clamp($min, $max))
74            }
75
76            /// Returns the value encapsulated by this instance.
77            pub fn value(&self) -> $base {
78                self.0
79            }
80        }
81
82        impl From<$base> for $name {
83            fn from(source: $base) -> Self {
84                Self::new(source)
85            }
86        }
87
88        impl From<$name> for $base {
89            fn from(source: $name) -> Self {
90                source.0
91            }
92        }
93
94        impl Display for $name {
95            fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
96                write!(f, "{}", self.0)
97            }
98        }
99    };
100}
101
102decl_clamped_int! {
103    /// Voice pitch, represented as a value in the interval [-10, 10], with 0 being normal pitch.
104    Pitch(i32) in -10..10
105}
106
107decl_clamped_int! {
108    /// Speech rate, represented as a value in the interval [-10, 10], with 0 being normal speed.
109    Rate(i32) in -10..10
110}
111
112decl_clamped_int! {
113    /// Voice volume, represented as a value in the interval [0, 100], with 100 being full volume.
114    Volume(u32) in 0..100
115}
116
117impl Volume {
118    pub(crate) fn from_sapi(source: u16) -> Self {
119        Self::new(source as _)
120    }
121
122    pub(crate) fn sapi_value(&self) -> u16 {
123        self.0 as _
124    }
125}