1use crate::{
2 check_init, ffi,
3 vec::{CVec, FVecMut},
4 AsNativeStr, Error, Result, Smpl, Status,
5};
6
7use std::{
8 fmt::{Display, Formatter, Result as FmtResult},
9 str::FromStr,
10};
11
12pub trait SpecMethod: AsNativeStr {}
16
17#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
25pub enum SpecShape {
26 Centroid,
34
35 Spread,
43
44 Skewness,
52
53 Kurtosis,
61
62 Slope,
68
69 Decrease,
75
76 Rolloff,
82}
83
84impl SpecMethod for SpecShape {}
85
86impl AsNativeStr for SpecShape {
87 fn as_native_str(&self) -> &'static str {
88 use self::SpecShape::*;
89
90 match self {
91 Centroid => "centroid\0",
92 Spread => "spread\0",
93 Skewness => "skewness\0",
94 Kurtosis => "kurtosis\0",
95 Slope => "slope\0",
96 Decrease => "decrease\0",
97 Rolloff => "rolloff\0",
98 }
99 }
100}
101
102impl AsRef<str> for SpecShape {
103 fn as_ref(&self) -> &str {
104 self.as_rust_str()
105 }
106}
107
108impl Display for SpecShape {
109 fn fmt(&self, f: &mut Formatter) -> FmtResult {
110 self.as_ref().fmt(f)
111 }
112}
113
114impl FromStr for SpecShape {
115 type Err = Error;
116
117 fn from_str(src: &str) -> Result<Self> {
118 use self::SpecShape::*;
119
120 Ok(match src {
121 "centroid" => Centroid,
122 "spread" => Spread,
123 "skewness" => Skewness,
124 "kurtosis" => Kurtosis,
125 "slope" => Slope,
126 "decrease" => Decrease,
127 "rolloff" => Rolloff,
128 _ => return Err(Error::InvalidArg),
129 })
130 }
131}
132
133pub struct SpecDesc {
137 specdesc: *mut ffi::aubio_specdesc_t,
138}
139
140impl Drop for SpecDesc {
141 fn drop(&mut self) {
142 unsafe { ffi::del_aubio_specdesc(self.specdesc) }
143 }
144}
145
146impl SpecDesc {
147 pub fn new(method: impl SpecMethod, buf_size: usize) -> Result<Self> {
154 let specdesc =
155 unsafe { ffi::new_aubio_specdesc(method.as_native_cstr(), buf_size as ffi::uint_t) };
156
157 check_init(specdesc)?;
158
159 Ok(Self { specdesc })
160 }
161
162 pub fn do_<'i, 'o, I, O>(&mut self, fftgrain: I, desc: O) -> Status
168 where
169 I: Into<CVec<'i>>,
170 O: Into<FVecMut<'o>>,
171 {
172 let fftgrain = fftgrain.into();
173 let mut desc = desc.into();
174
175 desc.check_size(1)?;
176
177 unsafe {
178 ffi::aubio_specdesc_do(self.specdesc, fftgrain.as_ptr(), desc.as_mut_ptr());
179 }
180 Ok(())
181 }
182
183 pub fn do_result<'i, I>(&mut self, fftgrain: I) -> Result<Smpl>
189 where
190 I: Into<CVec<'i>>,
191 {
192 let mut desc = [0.; 1];
193 self.do_(fftgrain, &mut desc)?;
194 Ok(desc[0])
195 }
196}
197
198#[cfg(test)]
199mod test {
200 use crate::*;
201
202 #[test]
203 fn test() {
204 const WIN: usize = 1024; let in_ = carr!(WIN); let mut out = farr!(1); let mut o = SpecDesc::new(OnsetMode::Energy, WIN).unwrap();
210 o.do_(in_.as_ref(), out.as_mut()).unwrap();
211
212 let mut o = SpecDesc::new(OnsetMode::Hfc, WIN).unwrap();
213 o.do_(in_.as_ref(), out.as_mut()).unwrap();
214
215 let mut o = SpecDesc::new(OnsetMode::Complex, WIN).unwrap();
216 o.do_(in_.as_ref(), out.as_mut()).unwrap();
217
218 let mut o = SpecDesc::new(OnsetMode::Phase, WIN).unwrap();
219 o.do_(in_.as_ref(), out.as_mut()).unwrap();
220
221 let mut o = SpecDesc::new(OnsetMode::Kl, WIN).unwrap();
222 o.do_(in_.as_ref(), out.as_mut()).unwrap();
223
224 let mut o = SpecDesc::new(OnsetMode::Mkl, WIN).unwrap();
225 o.do_(in_.as_ref(), out.as_mut()).unwrap();
226
227 let mut o = SpecDesc::new(SpecShape::Centroid, WIN).unwrap();
228 o.do_(in_.as_ref(), out.as_mut()).unwrap();
229
230 let mut o = SpecDesc::new(SpecShape::Spread, WIN).unwrap();
231 o.do_(in_.as_ref(), out.as_mut()).unwrap();
232
233 let mut o = SpecDesc::new(SpecShape::Skewness, WIN).unwrap();
234 o.do_(in_.as_ref(), out.as_mut()).unwrap();
235
236 let mut o = SpecDesc::new(SpecShape::Kurtosis, WIN).unwrap();
237 o.do_(in_.as_ref(), out.as_mut()).unwrap();
238
239 let mut o = SpecDesc::new(SpecShape::Slope, WIN).unwrap();
240 o.do_(in_.as_ref(), out.as_mut()).unwrap();
241
242 let mut o = SpecDesc::new(SpecShape::Decrease, WIN).unwrap();
243 o.do_(in_.as_ref(), out.as_mut()).unwrap();
244
245 let mut o = SpecDesc::new(SpecShape::Rolloff, WIN).unwrap();
246 o.do_(in_.as_ref(), out.as_mut()).unwrap();
247 }
248}