我正在编写一个简单的 Rust 程序,它将足够响亮的音频输入传输到输出设备。
我通过使用ringbuf获得输入和输出回调来共享状态,其方式深受此代码的启发。
但是,当我尝试在函数中使用我的结构之一的可变引用时,我遇到了此错误:
error[E0525]: expected a closure that implements the `FnMut` trait, but this closure only implements `FnOnce`
--> src/main.rs:72:25
|
72 | ...et input_data_fn = move |data: &[f32], _: &cpal::InputCallbackInfo| {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this closure implements `FnOnce`, not `FnMut`
...
77 | ... clipper.ingest(Chunk::new(samples, input_sample_rate));
| ------- closure is `FnOnce` because it moves the variable `clipper` out of its environment
...
124 | ...et input_stream = input.build_input_stream(&config, input_data_fn, err_f...
| ------------------ ------------- the requirement to implement `FnMut` derives from here
| |
| required by a bound introduced by this call
|
note: required by a bound in `build_input_stream`
--> C:\Users\info\.cargo\registry\src\index.crates.io-6f17d22bba15001f\cpal-0.15.3\src\traits.rs:134:12
|
125 | fn build_input_stream<T, D, E>(
| ------------------ required by a bound in this associated function
...
134 | D: FnMut(&[T], &InputCallbackInfo) + Send + 'static,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `DeviceTrait::build_input_stream`
我想不出解决办法,但想必编写
ringbuf
库的人找到了这个问题的解决方案。我注意到被调用的 函数包含一个 unsafe
块,但我相信这更多地与边界检查有关,而不是所有权。这是相关代码(如果有人感兴趣,还有
整个文件):
let mut sin_osc = SineOscillator::new(SIN_OSC_AMP, SIN_OSC_FREQ, output_sample_rate);
let mut clipper = LoudClipCollector::new(IN_TRIGGER_ADB, MIN_CLIP_SECS, output_sample_rate);
let input_data_fn = move |data: &[f32], _: &cpal::InputCallbackInfo| {
let mut output_fell_behind = false;
let mut samples: Vec<f32> = vec![];
samples.clone_from_slice(data);
clipper.ingest(Chunk::new(samples, input_sample_rate));
match clipper.next() {
Some(samples) => {
for sample in samples {
if producer.try_push(sample).is_err() {
output_fell_behind = true;
}
}
},
None => {
for i in 0..data.len() {
if producer.try_push(sin_osc.next().unwrap()).is_err() {
output_fell_behind = true;
}
}
},
};
if output_fell_behind {
eprintln!("output stream fell behind: try increasing latency");
}
};
try_push
fn try_push(&mut self, elem: Self::Item) -> Result<(), Self::Item> {
它使用 &mut
——可变引用。我的代码无法编译的原因是我在没有任何引用的情况下使用了
mut
,表示移动而不是借用。
pub fn ingest(mut self, chunk: Chunk) {
解决办法是添加一个字符
pub fn ingest(&mut self, chunk: Chunk) {