Je suis le sine example dans le répertoire des exemples rust-portaudio (qui utilise l'API non bloquante), et j'essaie d'obtenir run()
avec un trait tapez argument au lieu de calculer les échantillons dans run()
lui-même.Utilisation des types de caractères avec port-rouille en mode non-bloquant
Le trait que je l'ai défini est assez simple:
pub trait Evaluatable {
fn evaluate(&mut self) -> (f32, f32);
}
J'ai changé la signature de la fonction run()
à ce qui suit pour accepter mon trait:
fn run<E: Evaluatable + 'static>(mut generator: E) -> Result<(), pa::Error>
et upated la fonction de rappel pour appeler le evaluate()
sur le type de trait au lieu de générer lui-même des échantillons:
let callback = move |pa::OutputStreamCallbackArgs { buffer, frames, .. }| {
let mut idx = 0;
for _ in 0..frames {
let samples = generator.evaluate();
buffer[idx] = samples.0;
buffer[idx+1] = samples.1;
idx += 2;
}
pa::Continue
};
E
doit être 'static
en raison de ce rappel (voir open_non_blocking_stream()
), qui est la principale source de ma frustration ...
En main
, je peux créer un type Evaluatable
et passer en très bien (à part: Je suis surpris que cela fonctionne, les objets ne se main
vie 'static
?):
fn main() {
// Implements Evaluatable
// arguments are: sample rate, frequency, amplitude
let mut sine_generator = SineGenerator::new(44100.0, 200.0, 0.3);
run(sine_generator).unwrap()
}
Mais je veux être en mesure de combiner des signaux, donc je fait une struct qui peut les combiner:
use evaluatable::Evaluatable;
pub struct Combine<'a> {
first: &'a mut (Evaluatable + 'a),
second: &'a mut (Evaluatable + 'a),
}
impl<'a> Combine<'a> {
pub fn new(first: &'a mut Evaluatable, second: &'a mut Evaluatable) -> Combine<'a> {
Combine {first, second}
}
}
impl<'a> Evaluatable for Combine<'a> {
fn evaluate(&mut self) -> (f32, f32) {
let first_output = self.first.evaluate();
let second_output = self.second.evaluate();
(first_output.0 + second_output.0, first_output.1 + second_output.1)
}
}
et a essayé de l'utiliser dans main()
:
fn main() {
let mut sine_generator1 = SineGenerator::new(44100.0, 200.0, 0.3);
let mut sine_generator2 = SineGenerator::new(44100.0, 250.0, 0.3);
let combine = Combine::new(&mut sine_generator1, &mut sine_generator2);
run(combine).unwrap()
}
Maintenant, Rust semble avoir un problème avec la durée de vie ne pas être 'static
:
Error[E0597]: `sine_generator1` does not live long enough
--> src/main.rs:27:37
|
27 | let combine = Combine::new(&mut sine_generator1, &mut sine_generator2);
| ^^^^^^^^^^^^^^^ does not live long enough
28 | run(combine).unwrap()
29 | }
| - borrowed value only lives until here
|
= note: borrowed value must be valid for the static lifetime...
- Pourquoi wa s Rust en mesure de me permettre d'utiliser
SineGenerator
demain()
, mais ne me laisse pas utiliserCombine
qui prend les mêmes objets (avec, je suppose, les mêmes durées de vie)? - Existe-t-il une meilleure façon de mettre en œuvre
Combine
qui me permettra de faire ce que je veux faire ici? J'ai dû prendre des références parce que les types de caractères n'ont pas de taille définie lors de la compilation.
A travaillé impeccablement, merci! On dirait que j'ai encore beaucoup à apprendre avec Rust. – crs