aubio_rs/
tempo.rs

1use crate::{
2    check_init, ffi,
3    vec::{FVec, FVecMut},
4    AsNativeStr, OnsetMode, Result, Smpl, Status,
5};
6
7/**
8 * Tempo detection object
9 */
10pub struct Tempo {
11    tempo: *mut ffi::aubio_tempo_t,
12    hop_size: usize,
13}
14
15impl Drop for Tempo {
16    fn drop(&mut self) {
17        unsafe { ffi::del_aubio_tempo(self.tempo) }
18    }
19}
20
21impl Tempo {
22    /**
23     * Create tempo detection object
24     *
25     * - `method` Beat tracking method
26     * - `buf_size` Length of FFT
27     * - `hop_size` Number of frames between two consecutive runs
28     * - `sample_rate` Sampling rate of the signal to analyze
29     */
30    pub fn new(
31        method: OnsetMode,
32        buf_size: usize,
33        hop_size: usize,
34        sample_rate: u32,
35    ) -> Result<Self> {
36        // TODO: Use `SpecFlux` as default method for Tempo
37        let tempo = unsafe {
38            ffi::new_aubio_tempo(
39                method.as_native_cstr(),
40                buf_size as ffi::uint_t,
41                hop_size as ffi::uint_t,
42                sample_rate as ffi::uint_t,
43            )
44        };
45
46        check_init(tempo)?;
47
48        Ok(Self { tempo, hop_size })
49    }
50
51    /**
52     * Set tempo detection silence threshold
53     */
54    pub fn with_silence(mut self, silence: Smpl) -> Self {
55        self.set_silence(silence);
56        self
57    }
58
59    /**
60     * Set tempo detection peak picking threshold
61     */
62    pub fn with_threshold(mut self, threshold: Smpl) -> Self {
63        self.set_threshold(threshold);
64        self
65    }
66
67    /**
68     * Set current delay in samples
69     */
70    pub fn with_delay(mut self, delay: isize) -> Self {
71        self.set_delay(delay);
72        self
73    }
74
75    /**
76     * Set current delay in seconds
77     */
78    pub fn with_delay_s(mut self, delay: Smpl) -> Self {
79        self.set_delay_s(delay);
80        self
81    }
82
83    /**
84     * Set current delay in milliseconds
85     */
86    pub fn with_delay_ms(mut self, delay: Smpl) -> Self {
87        self.set_delay_ms(delay);
88        self
89    }
90
91    /**
92     * Get hop size
93     */
94    pub fn get_hop(&self) -> usize {
95        self.hop_size
96    }
97
98    /**
99     * Execute tempo detection
100     */
101    pub fn do_<'i, 'o, I, O>(&mut self, input: I, output: O) -> Status
102    where
103        I: Into<FVec<'i>>,
104        O: Into<FVecMut<'o>>,
105    {
106        let input = input.into();
107        let mut output = output.into();
108
109        input.check_size(self.get_hop())?;
110        output.check_size(1)?;
111
112        unsafe {
113            ffi::aubio_tempo_do(self.tempo, input.as_ptr(), output.as_mut_ptr());
114        }
115        Ok(())
116    }
117
118    /**
119     * Execute tempo detection
120     */
121    pub fn do_result<'i, I>(&mut self, input: I) -> Result<Smpl>
122    where
123        I: Into<FVec<'i>>,
124    {
125        let mut output = [0.; 1];
126        self.do_(input, &mut output)?;
127        Ok(output[0])
128    }
129
130    /**
131     * Get the time of the latest beat detected, in samples
132     */
133    pub fn get_last(&self) -> usize {
134        (unsafe { ffi::aubio_tempo_get_last(self.tempo) }) as usize
135    }
136
137    /**
138     * Get the time of the latest beat detected, in seconds
139     */
140    pub fn get_last_s(&self) -> Smpl {
141        unsafe { ffi::aubio_tempo_get_last_s(self.tempo) }
142    }
143
144    /**
145     * Get the time of the latest beat detected, in milliseconds
146     */
147    pub fn get_last_ms(&self) -> Smpl {
148        unsafe { ffi::aubio_tempo_get_last_ms(self.tempo) }
149    }
150
151    /**
152     * Set tempo detection silence threshold
153     */
154    pub fn set_silence(&mut self, silence: Smpl) {
155        unsafe {
156            ffi::aubio_tempo_set_silence(self.tempo, silence);
157        }
158    }
159
160    /**
161     * Get tempo detection silence threshold
162     */
163    pub fn get_silence(&self) -> Smpl {
164        unsafe { ffi::aubio_tempo_get_silence(self.tempo) }
165    }
166
167    /**
168     * Set tempo detection peak picking threshold
169     */
170    pub fn set_threshold(&mut self, threshold: Smpl) {
171        unsafe {
172            ffi::aubio_tempo_set_threshold(self.tempo, threshold);
173        }
174    }
175
176    /**
177     * Get tempo peak picking threshold
178     */
179    pub fn get_threshold(&self) -> Smpl {
180        unsafe { ffi::aubio_tempo_get_threshold(self.tempo) }
181    }
182
183    /**
184     * Get the current beat period in samples
185     */
186    pub fn get_period(&self) -> usize {
187        (unsafe { ffi::aubio_tempo_get_period(self.tempo) }) as usize
188    }
189
190    /**
191     * Get the current beat period in seconds
192     */
193    pub fn get_period_s(&self) -> Smpl {
194        unsafe { ffi::aubio_tempo_get_period_s(self.tempo) }
195    }
196
197    /**
198     * Get the current tempo
199     */
200    pub fn get_bpm(&self) -> Smpl {
201        unsafe { ffi::aubio_tempo_get_bpm(self.tempo) }
202    }
203
204    /**
205     * Get the current tempo confidence
206     */
207    pub fn get_confidence(&self) -> Smpl {
208        unsafe { ffi::aubio_tempo_get_confidence(self.tempo) }
209    }
210
211    /**
212     * Set number of tatum per beat
213     */
214    pub fn set_tatum_signature(&mut self, signature: u32) {
215        unsafe {
216            ffi::aubio_tempo_set_tatum_signature(self.tempo, signature);
217        }
218    }
219
220    /**
221     * Check whether a tatum was detected in the current frame
222     */
223    pub fn was_tatum(&self) -> u32 {
224        unsafe { ffi::aubio_tempo_was_tatum(self.tempo) }
225    }
226
227    /**
228     * Get position of last tatum in samples
229     */
230    pub fn get_last_tatum(&self) -> Smpl {
231        unsafe { ffi::aubio_tempo_get_last_tatum(self.tempo) }
232    }
233
234    /**
235     * Set current delay in samples
236     */
237    pub fn set_delay(&mut self, delay: isize) {
238        unsafe {
239            ffi::aubio_tempo_set_delay(self.tempo, delay as ffi::sint_t);
240        }
241    }
242
243    /**
244     * Get current delay in samples
245     */
246    pub fn get_delay(&self) -> usize {
247        (unsafe { ffi::aubio_tempo_get_delay(self.tempo) }) as usize
248    }
249
250    /**
251     * Set current delay in seconds
252     */
253    pub fn set_delay_s(&mut self, delay: Smpl) {
254        unsafe {
255            ffi::aubio_tempo_set_delay_s(self.tempo, delay);
256        }
257    }
258
259    /**
260     * Get current delay in seconds
261     */
262    pub fn get_delay_s(&self) -> Smpl {
263        unsafe { ffi::aubio_tempo_get_delay_s(self.tempo) }
264    }
265
266    /**
267     * Set current delay in milliseconds
268     */
269    pub fn set_delay_ms(&mut self, delay: Smpl) {
270        unsafe {
271            ffi::aubio_tempo_set_delay_ms(self.tempo, delay);
272        }
273    }
274
275    /**
276     * Get current delay in milliseconds
277     */
278    pub fn get_delay_ms(&self) -> Smpl {
279        unsafe { ffi::aubio_tempo_get_delay_ms(self.tempo) }
280    }
281}