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
use crate::Synth;

/// The trait which implements samples data buffer interface
pub trait IsSamples {
    fn write_samples(self, synth: &mut Synth);
}

#[cfg(feature = "i16-out")]
impl IsSamples for &mut [i16] {
    /// Write samples interleaved
    fn write_samples(self, synth: &mut Synth) {
        let len = self.len() / 2;
        unsafe {
            let ptr = self as *mut _;
            synth.write_i16(len, &mut *ptr, 0, 2, &mut *ptr, 1, 2)
        }
    }
}

#[cfg(feature = "i16-out")]
impl IsSamples for (&mut [i16], &mut [i16]) {
    /// Write samples non-interleaved
    fn write_samples(self, synth: &mut Synth) {
        let len = self.0.len().min(self.1.len());
        synth.write_i16(len, self.0, 0, 1, self.1, 0, 1)
    }
}

impl IsSamples for &mut [f32] {
    /// Write samples interleaved
    fn write_samples(self, synth: &mut Synth) {
        let len = self.len() / 2;
        synth.write_cb(len, 2, |id, l, r| {
            self[id] = l;
            self[id + 1] = r;
        });
    }
}

impl IsSamples for (&mut [f32], &mut [f32]) {
    /// Write samples non-interleaved
    fn write_samples(self, synth: &mut Synth) {
        let len = self.0.len().min(self.1.len());
        synth.write_cb(len, 1, |id, l, r| {
            self.0[id] = l;
            self.1[id] = r;
        });
    }
}

impl IsSamples for &mut [f64] {
    /// Write samples interleaved
    fn write_samples(self, synth: &mut Synth) {
        let len = self.len() / 2;
        synth.write_cb(len, 2, |id, l, r| {
            self[id] = l as f64;
            self[id + 1] = r as f64;
        });
    }
}

/**
Synthesizer plugin
 */
impl Synth {
    /**
    Write sound samples to the sample data buffer
     */
    pub fn write<S: IsSamples>(&mut self, samples: S) {
        samples.write_samples(self)
    }

    pub fn read_next(&mut self) -> (f32, f32) {
        self.core.read_next()
    }

    pub fn write_cb<F: FnMut(usize, f32, f32)>(&mut self, len: usize, incr: usize, cb: F) {
        self.core.write(len, incr, cb)
    }

    /**
    Write samples as 16-bit signed integers

    # Safety

    The `len` must corresponds to the lenghtes of buffers.
     */
    #[cfg(feature = "i16-out")]
    #[allow(clippy::too_many_arguments)]
    #[inline]
    pub fn write_i16(
        &mut self,
        len: usize,
        left_out: &mut [i16],
        loff: u32,
        lincr: u32,
        right_out: &mut [i16],
        roff: u32,
        rincr: u32,
    ) {
        self.handle.write_s16(
            len as _, left_out, loff as _, lincr as _, right_out, roff as _, rincr as _,
        )
    }

    /**
    Write samples as 32-bit floating-point numbers

    # Safety

    The `len` must corresponds to the lenghtes of buffers.
     */
    #[allow(clippy::too_many_arguments)]
    #[inline]
    pub fn write_f32(
        &mut self,
        len: usize,
        left_out: &mut [f32],
        loff: u32,
        lincr: u32,
        right_out: &mut [f32],
        roff: u32,
        rincr: u32,
    ) {
        self.core.write_f32(
            len as _, left_out, loff as _, lincr as _, right_out, roff as _, rincr as _,
        )
    }

    /**
    Write samples as 64-bit floating-point numbers

    # Safety

    The `len` must corresponds to the lenghtes of buffers.
     */
    #[allow(clippy::too_many_arguments)]
    #[inline]
    pub fn write_f64(
        &mut self,
        len: usize,
        left_out: &mut [f64],
        loff: u32,
        lincr: u32,
        right_out: &mut [f64],
        roff: u32,
        rincr: u32,
    ) {
        self.core.write_f64(
            len as _, left_out, loff as _, lincr as _, right_out, roff as _, rincr as _,
        )
    }
}