-
Notifications
You must be signed in to change notification settings - Fork 6
Expand file tree
/
Copy pathstretch_example.rs
More file actions
135 lines (128 loc) · 5.63 KB
/
Copy pathstretch_example.rs
File metadata and controls
135 lines (128 loc) · 5.63 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
//! Example usage of SignalsmithStretch for time-stretching and pitch-shifting
use cute_dsp::stretch::SignalsmithStretch;
use std::f32::consts::PI;
fn main() {
mono_ramp_demo();
stereo_demo();
sine_wave_demo();
formant_demo();
custom_map_demo();
}
fn mono_ramp_demo() {
println!("=== Mono ramp time-stretch & pitch-shift ===");
let sample_rate = 48000.0_f32;
let channels = 1;
let block_samples = 1024;
let interval_samples = 256;
let input_len = 2048;
let mut input: Vec<Vec<f32>> = vec![vec![0.0; input_len]; channels];
for i in 0..input_len {
input[0][i] = (i as f32 / input_len as f32) * 2.0 - 1.0;
}
let output_len = (input_len as f32 * 1.5) as usize;
let mut output: Vec<Vec<f32>> = vec![vec![0.0; output_len]; channels];
let mut stretch = SignalsmithStretch::<f32>::new();
stretch.configure(channels, block_samples, interval_samples, false);
stretch.set_transpose_semitones(3.0, 0.0);
stretch.set_formant_semitones(1.0, false);
stretch.process(&input, input_len, &mut output, output_len);
println!("Input (first 10): {:?}", &input[0][..10]);
println!("Output (first 10): {:?}", &output[0][..10]);
println!("Output (last 10): {:?}\n", &output[0][output_len-10..]);
}
fn stereo_demo() {
println!("=== Stereo time-stretch & pitch-shift ===");
let sample_rate = 48000.0_f32;
let channels = 2;
let block_samples = 1024;
let interval_samples = 256;
let input_len = 2048;
let mut input: Vec<Vec<f32>> = vec![vec![0.0; input_len]; channels];
for i in 0..input_len {
input[0][i] = ((i as f32 / input_len as f32) * 2.0 - 1.0) * 0.8; // left
input[1][i] = (((input_len - i) as f32 / input_len as f32) * 2.0 - 1.0) * 0.5; // right
}
let output_len = (input_len as f32 * 0.75) as usize;
let mut output: Vec<Vec<f32>> = vec![vec![0.0; output_len]; channels];
let mut stretch = SignalsmithStretch::<f32>::new();
stretch.configure(channels, block_samples, interval_samples, false);
stretch.set_transpose_semitones(-5.0, 0.0); // pitch down
stretch.process(&input, input_len, &mut output, output_len);
println!("Stereo input L (first 10): {:?}", &input[0][..10]);
println!("Stereo input R (first 10): {:?}", &input[1][..10]);
println!("Stereo output L (first 10): {:?}", &output[0][..10]);
println!("Stereo output R (first 10): {:?}\n", &output[1][..10]);
}
fn sine_wave_demo() {
println!("=== Sine wave pitch-shifting ===");
let sample_rate = 48000.0_f32;
let freq = 440.0;
let block_samples = 1024;
let interval_samples = 256;
let input_len = 1024;
let mut input: Vec<Vec<f32>> = vec![vec![0.0; input_len]];
for i in 0..input_len {
input[0][i] = (2.0 * PI * freq * (i as f32) / sample_rate).sin();
}
let output_len = input_len;
let mut output: Vec<Vec<f32>> = vec![vec![0.0; output_len]];
let mut stretch = SignalsmithStretch::<f32>::new();
stretch.configure(1, block_samples, interval_samples, false);
stretch.set_transpose_semitones(12.0, 0.0); // up one octave
stretch.process(&input, input_len, &mut output, output_len);
println!("Sine input (first 10): {:?}", &input[0][..10]);
println!("Sine output (first 10): {:?}\n", &output[0][..10]);
}
fn formant_demo() {
println!("=== Formant preservation demo ===");
let sample_rate = 48000.0_f32;
let block_samples = 1024;
let interval_samples = 256;
let input_len = 1024;
let mut input: Vec<Vec<f32>> = vec![vec![0.0; input_len]];
// Simulate a "vowel" with two sine waves (formants)
let f1 = 700.0;
let f2 = 1200.0;
for i in 0..input_len {
input[0][i] = 0.6 * (2.0 * PI * f1 * (i as f32) / sample_rate).sin()
+ 0.4 * (2.0 * PI * f2 * (i as f32) / sample_rate).sin();
}
let output_len = input_len;
let mut output_no_formant: Vec<Vec<f32>> = vec![vec![0.0; output_len]];
let mut output_with_formant: Vec<Vec<f32>> = vec![vec![0.0; output_len]];
let mut stretch = SignalsmithStretch::<f32>::new();
stretch.configure(1, block_samples, interval_samples, false);
stretch.set_transpose_semitones(7.0, 0.0); // up a fifth
// No formant preservation
stretch.set_formant_semitones(0.0, false);
stretch.process(&input, input_len, &mut output_no_formant, output_len);
// With formant preservation
stretch.set_formant_semitones(-7.0, true); // compensate pitch shift
stretch.process(&input, input_len, &mut output_with_formant, output_len);
println!("Formant input (first 10): {:?}", &input[0][..10]);
println!("Output w/o formant (first 10): {:?}", &output_no_formant[0][..10]);
println!("Output w/ formant (first 10): {:?}\n", &output_with_formant[0][..10]);
}
fn custom_map_demo() {
println!("=== Custom frequency map demo ===");
let sample_rate = 48000.0_f32;
let block_samples = 1024;
let interval_samples = 256;
let input_len = 1024;
let mut input: Vec<Vec<f32>> = vec![vec![0.0; input_len]];
for i in 0..input_len {
input[0][i] = (2.0 * PI * (i as f32) / 32.0).sin();
}
let output_len = input_len;
let mut output: Vec<Vec<f32>> = vec![vec![0.0; output_len]];
let mut stretch = SignalsmithStretch::<f32>::new();
stretch.configure(1, block_samples, interval_samples, false);
// Custom frequency map: invert spectrum (for demonstration)
stretch.set_freq_map(move |freq| {
let max_freq = sample_rate / 2.0;
max_freq - freq
});
stretch.process(&input, input_len, &mut output, output_len);
println!("Custom map input (first 10): {:?}", &input[0][..10]);
println!("Custom map output (first 10): {:?}", &output[0][..10]);
}