Skip to content

Commit 38fb04f

Browse files
afq984Chromeos LUCI
authored and
Chromeos LUCI
committed
audio_processor: Use PipelineBuilder in offline-pipeline
BUG=b:340157092 TEST=bazel test //... TEST=sox -n -L -e signed-integer -b 16 -r 48000 -c 1 a.wav synth 11 whitenoise gain -10 TEST=offline-pipeline /run/imageloader/nc-ap-dlc/package/root/libdenoiser.so a.wav b.wav Change-Id: I1cff9a447a7fd1f7e4b2516fdae13450e3b30f67 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/adhd/+/5624519 Reviewed-by: Chih-Yang Hsia <[email protected]> Commit-Queue: Li-Yu Yu <[email protected]> Tested-by: [email protected] <[email protected]>
1 parent d69a916 commit 38fb04f

File tree

2 files changed

+71
-73
lines changed

2 files changed

+71
-73
lines changed

audio_processor/src/bin/offline-pipeline.rs

Lines changed: 59 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,17 @@
44

55
use std::num::ParseFloatError;
66
use std::path::PathBuf;
7+
use std::sync::mpsc::channel;
78
use std::time::Duration;
89

10+
use audio_processor::config::PipelineBuilder;
11+
use audio_processor::config::Processor;
912
use audio_processor::processors::profile;
1013
use audio_processor::processors::profile::Measurements;
1114
use audio_processor::processors::CheckShape;
12-
use audio_processor::processors::DynamicPluginProcessor;
13-
use audio_processor::processors::WavSink;
1415
use audio_processor::processors::WavSource;
1516
use audio_processor::AudioProcessor;
16-
use audio_processor::ByteProcessor;
1717
use audio_processor::Error;
18-
use audio_processor::Format;
1918
use audio_processor::MultiBuffer;
2019
use audio_processor::Shape;
2120
use clap::Parser;
@@ -24,7 +23,7 @@ use serde::Serialize;
2423
#[derive(Parser, Debug)]
2524
struct Command {
2625
/// Path to the plugin library (.so)
27-
plugin: String,
26+
plugin: PathBuf,
2827

2928
/// Path of input WAVE file
3029
input: PathBuf,
@@ -126,50 +125,37 @@ fn run(command: Command) {
126125
eprintln!("{:?}", command);
127126
let reader = hound::WavReader::open(command.input.clone()).expect("cannot open input file");
128127
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");
139128

140129
let block_size = command.compute_block_size(spec.sample_rate as usize);
141130
eprintln!("block size: {}", block_size);
131+
142132
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());
162134

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();
165153

166154
let mut buf = MultiBuffer::new(Shape {
167155
channels: 0,
168156
frames: 0,
169157
});
170158
'outer: loop {
171-
let mut slices = buf.as_multi_slice();
172-
173159
if let Some(dur) = command.sleep_duration {
174160
if dur.is_zero() {
175161
std::thread::yield_now();
@@ -178,40 +164,45 @@ fn run(command: Command) {
178164
}
179165
}
180166

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();
208168
if slices.min_len() == 0 {
209169
break;
210170
}
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();
211197
}
212198

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);
215206
eprintln!("cpu: {:?}", result.cpu);
216207
eprintln!("wall: {:?}", result.wall);
217208

@@ -258,7 +249,7 @@ mod tests {
258249
drop(writer);
259250

260251
super::run(crate::Command {
261-
plugin: env::var("LIBTEST_PLUGINS_SO").unwrap(),
252+
plugin: env::var("LIBTEST_PLUGINS_SO").unwrap().into(),
262253
input: in_wav_path,
263254
output: out_wav_path.clone(),
264255
sleep_duration: None,

audio_processor/src/processors/profile.rs

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,12 @@ pub struct Profile<T: AudioProcessor> {
1717
sender: Option<Sender<ProfileStats>>,
1818
}
1919

20-
#[derive(Default, Clone)]
20+
#[derive(Clone)]
2121
pub struct ProfileStats {
2222
// Human readable text describing the profiled processor.
2323
pub key: String,
24-
pub frames_processed: usize,
24+
pub output_format: Format,
25+
pub frames_generated: usize,
2526
pub measurements: Measurements,
2627
}
2728

@@ -42,7 +43,7 @@ impl<T: AudioProcessor> AudioProcessor for Profile<T> {
4243
let wall_time = Instant::elapsed(&wall);
4344
self.stats.measurements.cpu_time.add(cpu_time);
4445
self.stats.measurements.wall_time.add(wall_time);
45-
self.stats.frames_processed += output.min_len();
46+
self.stats.frames_generated += output.min_len();
4647

4748
Ok(output)
4849
}
@@ -54,9 +55,15 @@ impl<T: AudioProcessor> AudioProcessor for Profile<T> {
5455

5556
impl<T: AudioProcessor> Profile<T> {
5657
pub fn new(processor: T) -> Self {
58+
let output_format = processor.get_output_format();
5759
Self {
5860
inner: processor,
59-
stats: Default::default(),
61+
stats: ProfileStats {
62+
key: String::new(),
63+
output_format,
64+
frames_generated: 0,
65+
measurements: Measurements::default(),
66+
},
6067
sender: None,
6168
}
6269
}
@@ -261,7 +268,7 @@ mod tests {
261268
let cpu_all = cpu_time() - cpu_start;
262269
let wall_all = Instant::elapsed(&wall_start);
263270

264-
assert_eq!(p.stats.frames_processed, 8);
271+
assert_eq!(p.stats.frames_generated, 8);
265272

266273
let m = &p.stats.measurements;
267274
assert!(m.cpu_time.min <= m.cpu_time.max);

0 commit comments

Comments
 (0)