1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
//! Some basic event dispatching.
use super::Voice;
use super::VoiceAssignerHelper;

/// A simple voice state
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub enum SimpleVoiceState<Identifier>
where
    Identifier: Copy + Eq,
{
    /// The voice is idle (in other words: doing nothing).
    Idle,
    /// The voice has received a signal to stop, but is still rendering audio (e.g. some reverb
    /// after the end of the audio).
    ///
    /// The `VoiceIdentifier` indicates what it is still rendering.
    Releasing(Identifier),
    /// The voice has not yet received a signal to stop and is still rendering audio.
    Active(Identifier),
}

/// A simple event dispatcher.
///
/// Voice assignment is done in a very simple way.
/// A new voice is assigned in the following way:
/// * if there is an idle voice, the first idle voice is used
/// * otherwise, if there is a voice releasing, the first releasing voice is used,
/// * otherwise, the first voice is used.
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub struct SimpleEventDispatcher;

impl<V, Identifier> VoiceAssignerHelper<V, Identifier> for SimpleEventDispatcher
where
    V: Voice<SimpleVoiceState<Identifier>>,
    Identifier: Copy + Eq,
{
    fn find_active_voice(&mut self, identifier: Identifier, voices: &mut [V]) -> Option<usize> {
        voices
            .iter()
            .position(|voice| voice.state() == SimpleVoiceState::Active(identifier))
    }

    fn find_new_voice(&mut self, identifier: Identifier, voices: &mut [V]) -> usize {
        let mut second_best = None;
        let mut third_best = 0;
        for (index, voice) in voices.iter().enumerate() {
            match voice.state() {
                SimpleVoiceState::Idle => {
                    return index;
                }
                SimpleVoiceState::Releasing(i) => {
                    if i == identifier {
                        second_best = Some(index);
                    } else {
                        third_best = index;
                    }
                }
                SimpleVoiceState::Active(_) => {}
            }
        }
        second_best.unwrap_or(third_best)
    }
}