1
- use rustfft:: FFTplanner ;
2
1
use num_complex:: Complex ;
2
+ use rustfft:: FFTplanner ;
3
3
4
4
use crate :: float:: Float ;
5
- use crate :: utils:: buffer:: ComplexComponent ;
6
- use crate :: utils:: buffer:: copy_real_to_complex;
7
5
use crate :: utils:: buffer:: copy_complex_to_real;
8
- use crate :: utils:: buffer:: new_real_buffer ;
6
+ use crate :: utils:: buffer:: copy_real_to_complex ;
9
7
use crate :: utils:: buffer:: new_complex_buffer;
10
- use crate :: utils:: peak :: PeakCorrection ;
11
- use crate :: utils:: peak :: detect_peaks ;
8
+ use crate :: utils:: buffer :: new_real_buffer ;
9
+ use crate :: utils:: buffer :: ComplexComponent ;
12
10
use crate :: utils:: peak:: choose_peak;
13
11
use crate :: utils:: peak:: correct_peak;
12
+ use crate :: utils:: peak:: detect_peaks;
13
+ use crate :: utils:: peak:: PeakCorrection ;
14
14
15
15
pub struct Pitch < T >
16
- where T : Float
16
+ where
17
+ T : Float ,
17
18
{
18
19
pub frequency : T ,
19
- pub clarity : T
20
+ pub clarity : T ,
20
21
}
21
22
22
23
pub struct DetectorInternals < T >
23
- where T : Float
24
+ where
25
+ T : Float ,
24
26
{
25
27
pub size : usize ,
26
28
pub padding : usize ,
27
29
pub real_buffers : Vec < Vec < T > > ,
28
- pub complex_buffers : Vec < Vec < Complex < T > > >
30
+ pub complex_buffers : Vec < Vec < Complex < T > > > ,
29
31
}
30
32
31
33
impl < T > DetectorInternals < T >
32
- where T : Float
34
+ where
35
+ T : Float ,
33
36
{
34
- pub fn new ( n_real_buffers : usize , n_complex_buffers : usize , size : usize , padding : usize ) -> Self {
37
+ pub fn new (
38
+ n_real_buffers : usize ,
39
+ n_complex_buffers : usize ,
40
+ size : usize ,
41
+ padding : usize ,
42
+ ) -> Self {
35
43
let mut real_buffers: Vec < Vec < T > > = Vec :: new ( ) ;
36
44
let mut complex_buffers: Vec < Vec < Complex < T > > > = Vec :: new ( ) ;
37
45
@@ -49,98 +57,92 @@ impl<T> DetectorInternals<T>
49
57
size,
50
58
padding,
51
59
real_buffers,
52
- complex_buffers
60
+ complex_buffers,
53
61
}
54
62
}
55
63
}
56
64
57
- pub fn autocorrelation < T > ( signal : & [ T ] , signal_complex : & mut [ Complex < T > ] , scratch : & mut [ Complex < T > ] , result : & mut [ T ] )
58
- where T : Float
65
+ pub fn autocorrelation < T > (
66
+ signal : & [ T ] ,
67
+ signal_complex : & mut [ Complex < T > ] ,
68
+ scratch : & mut [ Complex < T > ] ,
69
+ result : & mut [ T ] ,
70
+ ) where
71
+ T : Float ,
59
72
{
60
73
copy_real_to_complex ( signal, signal_complex, ComplexComponent :: Re ) ;
61
74
let mut planner = FFTplanner :: new ( false ) ;
62
75
let fft = planner. plan_fft ( signal_complex. len ( ) ) ;
63
76
fft. process ( signal_complex, scratch) ;
64
- for i in 0 .. scratch. len ( ) {
65
- scratch [ i ] . re = scratch [ i ] . re * scratch [ i ] . re + scratch [ i ] . im * scratch [ i ] . im ;
66
- scratch [ i ] . im = T :: zero ( ) ;
67
- }
77
+ scratch. iter_mut ( ) . for_each ( |s| {
78
+ s . re = s . re * s . re + s . im * s . im ;
79
+ s . im = T :: zero ( ) ;
80
+ } ) ;
68
81
let mut planner = FFTplanner :: new ( true ) ;
69
82
let inv_fft = planner. plan_fft ( signal_complex. len ( ) ) ;
70
83
inv_fft. process ( scratch, signal_complex) ;
71
84
copy_complex_to_real ( signal_complex, result, ComplexComponent :: Re ) ;
72
85
}
73
86
74
- pub fn pitch_from_peaks < T > ( input : & [ T ] , sample_rate : usize , clarity_threshold : T , correction : PeakCorrection ) -> Option < Pitch < T > >
75
- where T : Float
87
+ pub fn pitch_from_peaks < T > (
88
+ input : & [ T ] ,
89
+ sample_rate : usize ,
90
+ clarity_threshold : T ,
91
+ correction : PeakCorrection ,
92
+ ) -> Option < Pitch < T > >
93
+ where
94
+ T : Float ,
76
95
{
77
96
let peaks = detect_peaks ( input) ;
78
- let chosen_peak = choose_peak ( & peaks, clarity_threshold) ;
79
- let chosen_peak = match chosen_peak {
80
- Some ( peak) => {
81
- Some ( correct_peak ( peak, input, correction) )
82
- } ,
83
- None => {
84
- None
85
- }
86
- } ;
87
-
88
- let pitch = match chosen_peak {
89
- Some ( peak) => {
97
+ choose_peak ( peaks, clarity_threshold)
98
+ . map ( |peak| correct_peak ( peak, input, correction) )
99
+ . map ( |peak| {
90
100
let frequency = T :: from_usize ( sample_rate) . unwrap ( ) / peak. 0 ;
91
101
let clarity = peak. 1 / input[ 0 ] ;
92
- Some ( Pitch { frequency, clarity } )
93
- } ,
94
- None => {
95
- None
96
- }
97
- } ;
98
- pitch
102
+ Pitch { frequency, clarity }
103
+ } )
99
104
}
100
105
101
106
pub fn get_power_level < T > ( signal : & [ T ] ) -> T
102
- where T : Float
107
+ where
108
+ T : Float + std:: iter:: Sum ,
103
109
{
104
- let mut power = T :: zero ( ) ;
105
- for i in 0 ..signal. len ( ) {
106
- power = power + signal[ i] * signal[ i] ;
107
- }
108
- power
110
+ signal. iter ( ) . map ( |s| * s * * s) . sum :: < T > ( )
109
111
}
110
112
111
113
fn m_of_tau < T > ( signal : & [ T ] , signal_square_sum : Option < T > , result : & mut [ T ] )
112
- where T : Float
114
+ where
115
+ T : Float + std:: iter:: Sum ,
113
116
{
114
117
assert ! ( result. len( ) >= signal. len( ) ) ;
115
118
116
- let signal_square_sum = match signal_square_sum {
117
- Some ( val) => val,
118
- None => {
119
- let mut val = T :: zero ( ) ;
120
- for i in 0 ..signal. len ( ) {
121
- val = val + signal[ i] * signal[ i] ;
122
- }
123
- val
124
- }
125
- } ;
119
+ let signal_square_sum =
120
+ signal_square_sum. unwrap_or_else ( || signal. iter ( ) . map ( |s| * s * * s) . sum :: < T > ( ) ) ;
126
121
127
122
result[ 0 ] = T :: from_usize ( 2 ) . unwrap ( ) * signal_square_sum;
128
- for i in 1 ..signal . len ( ) {
129
- result [ i ] = result [ i - 1 ] - signal [ i - 1 ] * signal [ i - 1 ] ;
130
- }
131
-
132
- // Signal has no padding, but result does
133
- for i in signal . len ( ) ..result . len ( ) {
134
- result [ i ] = result [ i - 1 ] ;
135
- }
123
+ let last = result [ 1 ..] . iter_mut ( ) . zip ( signal ) . fold (
124
+ T :: from_usize ( 2 ) . unwrap ( ) * signal_square_sum ,
125
+ |old , ( r , s ) | {
126
+ * r = old - * s * * s ;
127
+ * r
128
+ } ,
129
+ ) ;
130
+ result [ signal . len ( ) .. ] . iter_mut ( ) . for_each ( |r| * r = last ) ;
136
131
}
137
132
138
- pub fn normalized_square_difference < T > ( signal : & [ T ] , scratch0 : & mut [ Complex < T > ] , scratch1 : & mut [ Complex < T > ] , scratch2 : & mut [ T ] , result : & mut [ T ] )
139
- where T : Float
133
+ pub fn normalized_square_difference < T > (
134
+ signal : & [ T ] ,
135
+ scratch0 : & mut [ Complex < T > ] ,
136
+ scratch1 : & mut [ Complex < T > ] ,
137
+ scratch2 : & mut [ T ] ,
138
+ result : & mut [ T ] ,
139
+ ) where
140
+ T : Float + std:: iter:: Sum ,
140
141
{
141
142
autocorrelation ( signal, scratch0, scratch1, result) ;
142
143
m_of_tau ( signal, Some ( result[ 0 ] ) , scratch2) ;
143
- for i in 0 ..result. len ( ) {
144
- result[ i] = T :: from_usize ( 2 ) . unwrap ( ) * result[ i] / scratch2[ i] ;
145
- }
144
+ result
145
+ . iter_mut ( )
146
+ . zip ( scratch2)
147
+ . for_each ( |( r, s) | * r = T :: from_usize ( 2 ) . unwrap ( ) * * r / * s)
146
148
}
0 commit comments