4
4
5
5
use std:: num:: ParseFloatError ;
6
6
use std:: path:: PathBuf ;
7
+ use std:: sync:: mpsc:: channel;
7
8
use std:: time:: Duration ;
8
9
10
+ use audio_processor:: config:: PipelineBuilder ;
11
+ use audio_processor:: config:: Processor ;
9
12
use audio_processor:: processors:: profile;
10
13
use audio_processor:: processors:: profile:: Measurements ;
11
14
use audio_processor:: processors:: CheckShape ;
12
- use audio_processor:: processors:: DynamicPluginProcessor ;
13
- use audio_processor:: processors:: WavSink ;
14
15
use audio_processor:: processors:: WavSource ;
15
16
use audio_processor:: AudioProcessor ;
16
- use audio_processor:: ByteProcessor ;
17
17
use audio_processor:: Error ;
18
- use audio_processor:: Format ;
19
18
use audio_processor:: MultiBuffer ;
20
19
use audio_processor:: Shape ;
21
20
use clap:: Parser ;
@@ -24,7 +23,7 @@ use serde::Serialize;
24
23
#[ derive( Parser , Debug ) ]
25
24
struct Command {
26
25
/// Path to the plugin library (.so)
27
- plugin : String ,
26
+ plugin : PathBuf ,
28
27
29
28
/// Path of input WAVE file
30
29
input : PathBuf ,
@@ -126,50 +125,37 @@ fn run(command: Command) {
126
125
eprintln ! ( "{:?}" , command) ;
127
126
let reader = hound:: WavReader :: open ( command. input . clone ( ) ) . expect ( "cannot open input file" ) ;
128
127
let spec = reader. spec ( ) ;
129
- let writer = hound:: WavWriter :: create (
130
- command. output . clone ( ) ,
131
- hound:: WavSpec {
132
- channels : command. output_channels . unwrap_or ( spec. channels ) ,
133
- sample_rate : spec. sample_rate ,
134
- bits_per_sample : 32 ,
135
- sample_format : hound:: SampleFormat :: Float ,
136
- } ,
137
- )
138
- . expect ( "cannot create output file" ) ;
139
128
140
129
let block_size = command. compute_block_size ( spec. sample_rate as usize ) ;
141
130
eprintln ! ( "block size: {}" , block_size) ;
131
+
142
132
let mut source = WavSource :: new ( reader, block_size) ;
143
- let frame_rate =
144
- usize:: try_from ( spec. sample_rate ) . expect ( "Sample rate failed to fit into usize" ) ;
145
- let mut check_shape = CheckShape :: < f32 > :: new ( Format {
146
- channels : spec. channels as usize ,
147
- block_size,
148
- frame_rate,
149
- } ) ;
150
- let ext = DynamicPluginProcessor :: new (
151
- & command. plugin ,
152
- & command. plugin_name ,
153
- Format {
154
- channels : spec. channels as usize ,
155
- block_size,
156
- frame_rate : spec. sample_rate as usize ,
157
- } ,
158
- )
159
- . expect ( "Cannot load plugin" ) ;
160
- let mut profile = profile:: Profile :: new ( ext) ;
161
- let mut sink = WavSink :: new ( writer, profile. get_output_format ( ) . block_size ) ;
133
+ let mut check_shape = CheckShape :: < f32 > :: new ( source. get_output_format ( ) ) ;
162
134
163
- let mut pipeline: Vec < & mut dyn ByteProcessor > =
164
- vec ! [ & mut source, & mut check_shape, & mut profile, & mut sink] ;
135
+ let pipeline_decl = vec ! [
136
+ Processor :: Plugin {
137
+ path: command. plugin,
138
+ constructor: command. plugin_name,
139
+ } ,
140
+ Processor :: WavSink {
141
+ path: command. output,
142
+ } ,
143
+ ] ;
144
+ eprintln ! ( "pipeline config: {pipeline_decl:?}" ) ;
145
+
146
+ let ( profile_sender, profile_receiver) = channel ( ) ;
147
+ let mut pipeline = PipelineBuilder :: new ( check_shape. get_output_format ( ) )
148
+ . with_profile_sender ( profile_sender)
149
+ . build ( Processor :: Pipeline {
150
+ processors : pipeline_decl,
151
+ } )
152
+ . unwrap ( ) ;
165
153
166
154
let mut buf = MultiBuffer :: new ( Shape {
167
155
channels : 0 ,
168
156
frames : 0 ,
169
157
} ) ;
170
158
' outer: loop {
171
- let mut slices = buf. as_multi_slice ( ) ;
172
-
173
159
if let Some ( dur) = command. sleep_duration {
174
160
if dur. is_zero ( ) {
175
161
std:: thread:: yield_now ( ) ;
@@ -178,40 +164,45 @@ fn run(command: Command) {
178
164
}
179
165
}
180
166
181
- for processor in pipeline. iter_mut ( ) {
182
- slices = match processor. process_bytes ( slices) {
183
- Ok ( output) => output,
184
- Err ( error) => match error {
185
- Error :: InvalidShape {
186
- want_frames,
187
- got_frames,
188
- want_channels,
189
- got_channels,
190
- } => {
191
- assert_eq ! (
192
- want_channels, got_channels,
193
- "WavSource returned invalid channels: want {} got {}" ,
194
- want_channels, got_channels,
195
- ) ;
196
- if got_frames > 0 {
197
- eprintln ! (
198
- "dropped last {} frames which do not fit into a {}-frame block" ,
199
- got_frames, want_frames,
200
- ) ;
201
- }
202
- break ' outer;
203
- }
204
- _ => panic ! ( "{}" , error) ,
205
- } ,
206
- }
207
- }
167
+ let slices = source. process ( buf. as_multi_slice ( ) ) . unwrap ( ) ;
208
168
if slices. min_len ( ) == 0 {
209
169
break ;
210
170
}
171
+ let slices = match check_shape. process ( slices) {
172
+ Ok ( output) => output,
173
+ Err ( error) => match error {
174
+ Error :: InvalidShape {
175
+ want_frames,
176
+ got_frames,
177
+ want_channels,
178
+ got_channels,
179
+ } => {
180
+ assert_eq ! (
181
+ want_channels, got_channels,
182
+ "WavSource returned invalid channels: want {} got {}" ,
183
+ want_channels, got_channels,
184
+ ) ;
185
+ if got_frames > 0 {
186
+ eprintln ! (
187
+ "dropped last {} frames which do not fit into a {}-frame block" ,
188
+ got_frames, want_frames,
189
+ ) ;
190
+ }
191
+ break ' outer;
192
+ }
193
+ _ => panic ! ( "{}" , error) ,
194
+ } ,
195
+ } ;
196
+ pipeline. process ( slices) . unwrap ( ) ;
211
197
}
212
198
213
- let clip_duration = profile. stats . frames_processed as f64 / spec. sample_rate as f64 ;
214
- let result = ProfileResult :: new ( & profile. stats . measurements , clip_duration) ;
199
+ // Drop pipeline to flush profile.
200
+ drop ( pipeline) ;
201
+ // Receive the first stat.
202
+ let stats = profile_receiver. recv ( ) . unwrap ( ) ;
203
+
204
+ let clip_duration = stats. frames_generated as f64 / stats. output_format . frame_rate as f64 ;
205
+ let result = ProfileResult :: new ( & stats. measurements , clip_duration) ;
215
206
eprintln ! ( "cpu: {:?}" , result. cpu) ;
216
207
eprintln ! ( "wall: {:?}" , result. wall) ;
217
208
@@ -258,7 +249,7 @@ mod tests {
258
249
drop ( writer) ;
259
250
260
251
super :: run ( crate :: Command {
261
- plugin : env:: var ( "LIBTEST_PLUGINS_SO" ) . unwrap ( ) ,
252
+ plugin : env:: var ( "LIBTEST_PLUGINS_SO" ) . unwrap ( ) . into ( ) ,
262
253
input : in_wav_path,
263
254
output : out_wav_path. clone ( ) ,
264
255
sleep_duration : None ,
0 commit comments