Skip to content

Commit 4b8aa41

Browse files
afq984Chromeos LUCI
authored and
Chromeos LUCI
committed
Move PluginLoader to audio_processor
So it can be used in offline-pipeline. BUG=b:340217962 TEST=bazel test //... Change-Id: If5ff5cd82cd3b3474b9f2309d1b9d46874a108df Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/adhd/+/5534472 Tested-by: Li-Yu Yu <[email protected]> Reviewed-by: Chih-Yang Hsia <[email protected]> Commit-Queue: Li-Yu Yu <[email protected]> Tested-by: [email protected] <[email protected]>
1 parent bbd7ee8 commit 4b8aa41

File tree

3 files changed

+94
-82
lines changed

3 files changed

+94
-82
lines changed
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
// Copyright 2024 The ChromiumOS Authors
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
use anyhow::anyhow;
6+
use anyhow::Context;
7+
8+
use crate::processors::ChunkWrapper;
9+
use crate::processors::DynamicPluginProcessor;
10+
use crate::processors::SpeexResampler;
11+
use crate::AudioProcessor;
12+
use crate::ProcessorVec;
13+
use crate::Shape;
14+
15+
// TODO(aaronyu): This is the wrong abstraction. We should have an API to
16+
// chain processors with incompatible shapes and rates easily instead,
17+
// when we have something that looks more like a graph.
18+
pub struct PluginLoader<'a> {
19+
pub path: &'a str,
20+
pub constructor: &'a str,
21+
pub channels: usize,
22+
pub outer_rate: usize,
23+
pub inner_rate: usize,
24+
pub outer_block_size: usize,
25+
pub inner_block_size: usize,
26+
pub allow_chunk_wrapper: bool,
27+
}
28+
29+
impl<'a> PluginLoader<'a> {
30+
pub fn load_and_wrap(self) -> anyhow::Result<ProcessorVec> {
31+
let processor = DynamicPluginProcessor::new(
32+
self.path,
33+
self.constructor,
34+
self.inner_block_size,
35+
self.channels,
36+
self.inner_rate,
37+
)
38+
.with_context(|| "DynamicPluginProcessor::new failed")?;
39+
40+
let maybe_wrapped_processor: Box<dyn AudioProcessor<I = f32, O = f32> + Send> = if self
41+
.outer_block_size
42+
* self.inner_rate
43+
!= self.inner_block_size * self.outer_rate
44+
{
45+
// The block size after resampling needs wrapping.
46+
if !self.allow_chunk_wrapper {
47+
return Err(anyhow!("ChunkWrapper is not allowed but required: outer rate={}, block_size={}; inner rate={}, block_size={}", self.outer_rate, self.outer_block_size, self.inner_rate, self.inner_block_size));
48+
}
49+
Box::new(ChunkWrapper::new(
50+
processor,
51+
self.inner_block_size,
52+
self.channels,
53+
self.channels,
54+
))
55+
} else {
56+
Box::new(processor)
57+
};
58+
59+
let processors = if self.outer_rate == self.inner_rate {
60+
vec![maybe_wrapped_processor]
61+
} else {
62+
vec![
63+
Box::new(
64+
SpeexResampler::new(
65+
Shape {
66+
channels: self.channels,
67+
frames: self.outer_block_size,
68+
},
69+
self.outer_rate,
70+
self.inner_rate,
71+
)
72+
.with_context(|| "failed to create 1st wrapping resampler")?,
73+
),
74+
maybe_wrapped_processor,
75+
Box::new(
76+
SpeexResampler::new(
77+
Shape {
78+
channels: self.channels,
79+
frames: self.outer_block_size * self.inner_rate / self.outer_rate,
80+
},
81+
self.inner_rate,
82+
self.outer_rate,
83+
)
84+
.with_context(|| "failed to create 2nd wrapping resampler")?,
85+
),
86+
]
87+
};
88+
89+
Ok(processors)
90+
}
91+
}

audio_processor/src/processors/plugin/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,5 @@ mod export;
1212
pub use export::export_plugin;
1313
mod processor;
1414
pub use processor::*;
15+
mod loader;
16+
pub use loader::*;

cras/src/server/rust/src/cras_processor.rs

Lines changed: 1 addition & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,15 @@ use std::ptr::NonNull;
88
use std::sync::atomic::AtomicUsize;
99
use std::sync::atomic::Ordering;
1010

11-
use anyhow::anyhow;
1211
use anyhow::bail;
1312
use anyhow::Context;
1413
use audio_processor::processors::binding::plugin_processor;
1514
use audio_processor::processors::export_plugin;
1615
use audio_processor::processors::CheckShape;
17-
use audio_processor::processors::ChunkWrapper;
18-
use audio_processor::processors::DynamicPluginProcessor;
1916
use audio_processor::processors::NegateAudioProcessor;
17+
use audio_processor::processors::PluginLoader;
2018
use audio_processor::processors::PluginProcessor;
2119
use audio_processor::processors::ShuffleChannels;
22-
use audio_processor::processors::SpeexResampler;
2320
use audio_processor::processors::ThreadedProcessor;
2421
use audio_processor::AudioProcessor;
2522
use audio_processor::Pipeline;
@@ -304,84 +301,6 @@ impl CrasProcessor {
304301
}
305302
}
306303

307-
// TODO(aaronyu): This is the wrong abstraction. We should have an API to
308-
// chain processors with incompatible shapes and rates easily instead,
309-
// when we have something that looks more like a graph.
310-
struct PluginLoader<'a> {
311-
path: &'a str,
312-
constructor: &'a str,
313-
channels: usize,
314-
outer_rate: usize,
315-
inner_rate: usize,
316-
outer_block_size: usize,
317-
inner_block_size: usize,
318-
allow_chunk_wrapper: bool,
319-
}
320-
321-
impl<'a> PluginLoader<'a> {
322-
fn load_and_wrap(self) -> anyhow::Result<ProcessorVec> {
323-
let processor = DynamicPluginProcessor::new(
324-
self.path,
325-
self.constructor,
326-
self.inner_block_size,
327-
self.channels,
328-
self.inner_rate,
329-
)
330-
.with_context(|| "DynamicPluginProcessor::new failed")?;
331-
332-
let maybe_wrapped_processor: Box<dyn AudioProcessor<I = f32, O = f32> + Send> = if self
333-
.outer_block_size
334-
* self.inner_rate
335-
!= self.inner_block_size * self.outer_rate
336-
{
337-
// The block size after resampling needs wrapping.
338-
if !self.allow_chunk_wrapper {
339-
return Err(anyhow!("ChunkWrapper is not allowed but required: outer rate={}, block_size={}; inner rate={}, block_size={}", self.outer_rate, self.outer_block_size, self.inner_rate, self.inner_block_size));
340-
}
341-
Box::new(ChunkWrapper::new(
342-
processor,
343-
self.inner_block_size,
344-
self.channels,
345-
self.channels,
346-
))
347-
} else {
348-
Box::new(processor)
349-
};
350-
351-
let processors = if self.outer_rate == self.inner_rate {
352-
vec![maybe_wrapped_processor]
353-
} else {
354-
vec![
355-
Box::new(
356-
SpeexResampler::new(
357-
Shape {
358-
channels: self.channels,
359-
frames: self.outer_block_size,
360-
},
361-
self.outer_rate,
362-
self.inner_rate,
363-
)
364-
.with_context(|| "failed to create 1st wrapping resampler")?,
365-
),
366-
maybe_wrapped_processor,
367-
Box::new(
368-
SpeexResampler::new(
369-
Shape {
370-
channels: self.channels,
371-
frames: self.outer_block_size * self.inner_rate / self.outer_rate,
372-
},
373-
self.inner_rate,
374-
self.outer_rate,
375-
)
376-
.with_context(|| "failed to create 2nd wrapping resampler")?,
377-
),
378-
]
379-
};
380-
381-
Ok(processors)
382-
}
383-
}
384-
385304
impl Drop for CrasProcessor {
386305
fn drop(&mut self) {
387306
log::info!("CrasProcessor #{} dropped", self.id);

0 commit comments

Comments
 (0)