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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
use crate::{stream, Buffer};
use dasp_sample::Sample;
use std;

/// A `sound::Requester` for converting backend audio requests into requests for buffers of a fixed
/// size called from a separate thread.
///
/// The `Requester` works by calling `fill_buffer` with the requested buffer and sample rate from
/// the audio backend each time the callback is invoked.
pub struct Requester<S> {
    samples: Vec<S>,
    num_frames: usize,
    // `Some` if part of `frames` has not yet been written to output.
    pending_range: Option<std::ops::Range<usize>>,
}

impl<S> Requester<S>
where
    S: Sample,
{
    /// Construct a new `sound::Requester`.
    ///
    /// `num_frames` must be greater than `0`.
    pub fn new(num_frames: usize, num_channels: usize) -> Self {
        // We can't make any progress filling buffers of `0` frames.
        assert!(num_frames > 0);
        let num_samples = num_frames + num_channels;
        Requester {
            samples: vec![S::EQUILIBRIUM; num_samples],
            num_frames: num_frames,
            pending_range: None,
        }
    }

    /// Fill the given `output` buffer with samples requested from the model.
    ///
    /// `Panic!`s if `sample_rate` is not greater than `0` or if the output buffer's length is not
    /// a multiple of the given number of channels.
    pub fn fill_buffer<M, FR>(
        &mut self,
        mut model: M,
        render: &FR,
        output: &mut [S],
        channels: usize,
        sample_rate: u32,
    ) -> M
    where
        FR: stream::output::RenderFn<M, S>,
    {
        let Requester {
            ref mut samples,
            num_frames,
            ref mut pending_range,
        } = *self;

        // Ensure that the buffer length makes sense given the number of channels.
        assert_eq!(output.len() % channels, 0);

        // Determine the number of samples in the buffer.
        let num_samples = num_frames * channels;

        // if `output` is empty, there's nothing to fill.
        if output.is_empty() {
            return model;
        }

        // Fill the given buffer with silence.
        fn silence<S: Sample>(buffer: &mut [S]) {
            for sample in buffer {
                *sample = S::EQUILIBRIUM;
            }
        }

        // Zero the buffer before doing anything else.
        silence(output);

        // Have to have a positive sample_rate or nothing will happen!
        assert!(sample_rate > 0);

        // The starting index of the output slice we'll write to.
        let mut start = 0;

        // Write the contents of b to a.
        fn write<S: Copy>(a: &mut [S], b: &[S]) {
            for (a_sample, b_sample) in a.iter_mut().zip(b) {
                *a_sample = *b_sample;
            }
        }

        // If there is some un-read range of `samples`, read those first.
        if let Some(range) = pending_range.take() {
            // If the pending range would not fill the output, write what we can before going on to
            // request more frames.
            if range.len() < output.len() {
                start = range.len();
                write(&mut output[..range.len()], &samples[range]);

            // If we have the exact number of frames as output, write them and return.
            } else if range.len() == output.len() {
                write(output, &samples[range]);
                return model;
            } else {
                let end = range.start + output.len();
                write(output, &samples[range.start..end]);
                *pending_range = Some(end..range.end);
                return model;
            }
        }

        // Ensure that our buffer has `num_frames` `frames`.
        samples.resize(num_samples, S::EQUILIBRIUM);

        // Loop until the given `output` is filled.
        loop {
            // See how many frames are left to fill.
            let num_samples_remaining = output.len() - start;

            // The number of frames to write to output on this iteration.
            let num_samples_to_fill = std::cmp::min(samples.len(), num_samples_remaining);

            // Zero the `samples` buffer ready for summing.
            silence(samples);

            // Render the state of the model to the samples buffer.
            let interleaved_samples = std::mem::replace(samples, Vec::new()).into_boxed_slice();
            let mut buffer = Buffer {
                interleaved_samples,
                channels,
                sample_rate,
            };
            render(&mut model, &mut buffer);
            let mut new_samples = buffer.interleaved_samples.into_vec();
            std::mem::swap(samples, &mut new_samples);

            // Write the `frames` to output.
            let end = start + num_samples_to_fill;
            let range = start..end;
            write(&mut output[range.clone()], &samples[..range.len()]);

            // If this was the last frame, break from the loop.
            if end == output.len() {
                // If this is the last iteration and not all of `frames` were read, store the
                // `pending_range` to be read next time this method is called.
                if range.len() < samples.len() {
                    *pending_range = Some(range.len()..samples.len());
                }

                break;
            }

            // Continue looping through the next frames.
            start = end;
        }

        model
    }
}