gstreamer_audio/
audio_converter.rs

1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use std::ops;
4
5use glib::prelude::*;
6
7#[derive(Debug, Clone, PartialEq, Eq)]
8pub struct AudioConverterConfig(gst::Structure);
9
10impl ops::Deref for AudioConverterConfig {
11    type Target = gst::StructureRef;
12
13    #[inline]
14    fn deref(&self) -> &gst::StructureRef {
15        self.0.deref()
16    }
17}
18
19impl ops::DerefMut for AudioConverterConfig {
20    #[inline]
21    fn deref_mut(&mut self) -> &mut gst::StructureRef {
22        self.0.deref_mut()
23    }
24}
25
26impl AsRef<gst::StructureRef> for AudioConverterConfig {
27    #[inline]
28    fn as_ref(&self) -> &gst::StructureRef {
29        self.0.as_ref()
30    }
31}
32
33impl AsMut<gst::StructureRef> for AudioConverterConfig {
34    #[inline]
35    fn as_mut(&mut self) -> &mut gst::StructureRef {
36        self.0.as_mut()
37    }
38}
39
40impl Default for AudioConverterConfig {
41    #[inline]
42    fn default() -> Self {
43        Self::new()
44    }
45}
46
47impl TryFrom<gst::Structure> for AudioConverterConfig {
48    type Error = glib::BoolError;
49
50    fn try_from(v: gst::Structure) -> Result<Self, Self::Error> {
51        skip_assert_initialized!();
52        if v.name() == "GstAudioConverter" {
53            Ok(Self(v))
54        } else {
55            Err(glib::bool_error!("Structure is no AudioConverterConfig"))
56        }
57    }
58}
59
60impl<'a> TryFrom<&'a gst::StructureRef> for AudioConverterConfig {
61    type Error = glib::BoolError;
62
63    fn try_from(v: &'a gst::StructureRef) -> Result<Self, Self::Error> {
64        skip_assert_initialized!();
65        Self::try_from(v.to_owned())
66    }
67}
68
69impl From<AudioConverterConfig> for gst::Structure {
70    fn from(v: AudioConverterConfig) -> Self {
71        skip_assert_initialized!();
72        v.0
73    }
74}
75
76impl glib::value::ToValue for AudioConverterConfig {
77    fn to_value(&self) -> glib::Value {
78        self.0.to_value()
79    }
80
81    fn value_type(&self) -> glib::Type {
82        self.0.value_type()
83    }
84}
85
86impl glib::value::ToValueOptional for AudioConverterConfig {
87    fn to_value_optional(s: Option<&Self>) -> glib::Value {
88        skip_assert_initialized!();
89        s.map(|s| &s.0).to_value()
90    }
91}
92
93impl From<AudioConverterConfig> for glib::Value {
94    fn from(s: AudioConverterConfig) -> glib::Value {
95        skip_assert_initialized!();
96        s.0.into()
97    }
98}
99
100impl AudioConverterConfig {
101    pub fn new() -> Self {
102        Self(gst::Structure::new_empty("GstAudioConverter"))
103    }
104
105    pub fn set_dither_method(&mut self, v: crate::AudioDitherMethod) {
106        self.0
107            .set(glib::gstr!("GstAudioConverter.dither-method"), v);
108    }
109
110    #[doc(alias = "get_dither_method")]
111    pub fn dither_method(&self) -> crate::AudioDitherMethod {
112        self.0
113            .get_optional(glib::gstr!("GstAudioConverter.dither-method"))
114            .expect("Wrong type")
115            .unwrap_or(crate::AudioDitherMethod::None)
116    }
117
118    pub fn set_noise_shaping_method(&mut self, v: crate::AudioNoiseShapingMethod) {
119        self.0
120            .set(glib::gstr!("GstAudioConverter.noise-shaping-method"), v);
121    }
122
123    #[doc(alias = "get_noise_shaping_method")]
124    pub fn noise_shaping_method(&self) -> crate::AudioNoiseShapingMethod {
125        self.0
126            .get_optional(glib::gstr!("GstAudioConverter.noise-shaping-method"))
127            .expect("Wrong type")
128            .unwrap_or(crate::AudioNoiseShapingMethod::None)
129    }
130
131    pub fn set_quantization(&mut self, v: u32) {
132        self.0.set(glib::gstr!("GstAudioConverter.quantization"), v);
133    }
134
135    #[doc(alias = "get_quantization")]
136    pub fn quantization(&self) -> u32 {
137        self.0
138            .get_optional(glib::gstr!("GstAudioConverter.quantization"))
139            .expect("Wrong type")
140            .unwrap_or(1)
141    }
142
143    pub fn set_resampler_method(&mut self, v: crate::AudioResamplerMethod) {
144        self.0
145            .set(glib::gstr!("GstAudioConverter.resampler-method"), v);
146    }
147
148    #[doc(alias = "get_resampler_method")]
149    pub fn resampler_method(&self) -> crate::AudioResamplerMethod {
150        self.0
151            .get_optional(glib::gstr!("GstAudioConverter.resampler-method"))
152            .expect("Wrong type")
153            .unwrap_or(crate::AudioResamplerMethod::BlackmanNuttall)
154    }
155
156    pub fn set_mix_matrix(&mut self, v: &[impl AsRef<[f32]>]) {
157        let length = v.first().map(|v| v.as_ref().len()).unwrap_or(0);
158        let array = gst::Array::from_values(v.iter().map(|val| {
159            let val = val.as_ref();
160            assert_eq!(val.len(), length);
161            gst::Array::from_values(val.iter().map(|val| val.to_send_value())).to_send_value()
162        }));
163        self.0
164            .set(glib::gstr!("GstAudioConverter.mix-matrix"), array);
165    }
166
167    #[doc(alias = "get_mix_matrix")]
168    pub fn mix_matrix(&self) -> Vec<Vec<f32>> {
169        self.0
170            .get_optional::<gst::Array>(glib::gstr!("GstAudioConverter.mix-matrix"))
171            .expect("Wrong type")
172            .map(|array| {
173                array
174                    .as_slice()
175                    .iter()
176                    .map(|val| {
177                        let array = val.get::<gst::Array>().expect("Wrong type");
178
179                        array
180                            .as_slice()
181                            .iter()
182                            .map(|val| val.get::<f32>().expect("Wrong type"))
183                            .collect::<Vec<_>>()
184                    })
185                    .collect::<Vec<_>>()
186            })
187            .unwrap_or_default()
188    }
189
190    #[cfg(feature = "v1_22")]
191    #[cfg_attr(docsrs, doc(cfg(feature = "v1_22")))]
192    pub fn set_dither_threshold(&mut self, v: u32) {
193        self.0
194            .set(glib::gstr!("GstAudioConverter.dither-threshold"), v);
195    }
196
197    #[cfg(feature = "v1_22")]
198    #[cfg_attr(docsrs, doc(cfg(feature = "v1_22")))]
199    #[doc(alias = "get_dither_threshold")]
200    pub fn dither_threshold(&self) -> u32 {
201        self.0
202            .get_optional(glib::gstr!("GstAudioConverter.dither-threshold"))
203            .expect("Wrong type")
204            .unwrap_or(20)
205    }
206}
207
208#[cfg(test)]
209mod tests {
210    use super::*;
211
212    #[test]
213    fn test_mix_matrix() {
214        const MATRIX: &[&[f32]] = &[&[1.2, 0.3], &[0.2, 0.8]];
215
216        gst::init().unwrap();
217
218        let mut config = AudioConverterConfig::new();
219        config.set_mix_matrix(MATRIX);
220
221        let matrix = config.mix_matrix();
222        assert_eq!(matrix, MATRIX);
223
224        config.set_mix_matrix(&matrix);
225    }
226}