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
use euphony_units::coordinates::Polar;

use crate::{BoxProcessor, Buffers, Inputs, Node, Output};

pub trait Sink: 'static + Send + Sized {
    #[inline]
    fn spawn(self) -> BoxProcessor {
        Wrapper::spawn(self)
    }

    fn write<S: Iterator<Item = (f64, Polar<f64>)>>(&mut self, samples: S);
}

#[repr(u8)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum SampleType {
    Pcm = 0,
    /// The azimuth (or azimuthal angle) is the signed angle measured from
    /// the azimuth reference direction to the orthogonal projection of the
    /// line segment OP on the reference plane.
    Azimuth = 1,
    /// The inclination (or polar angle) is the angle between the zenith
    /// direction and the line segment OP.
    Inclination = 2,
    /// The radius or radial distance is the Euclidean distance from the
    /// origin O to P.
    Radius = 3,
}

#[derive(Clone, Debug, Default)]
struct Wrapper<Inner: Sink> {
    inner: Inner,
}

impl<Inner: Sink> Wrapper<Inner> {
    fn spawn(inner: Inner) -> BoxProcessor {
        crate::spawn(Self { inner })
    }
}

impl<Inner: Sink> Node<4, 0> for Wrapper<Inner> {
    const DEFAULTS: [f64; 4] = [0.0, 0.0, 0.0, 0.0];

    #[inline]
    fn process(&mut self, inputs: Inputs<4>, _buffer: Buffers<0>, samples: &mut [f64]) {
        let pcm = inputs.get(0);
        let pcm = pcm.iter().take(samples.len());
        let azimuth = inputs.get(1);
        let azimuth = azimuth.iter().take(samples.len());
        let inclination = inputs.get(2);
        let inclination = inclination.iter().take(samples.len());
        let radius = inputs.get(3);
        let radius = radius.iter().take(samples.len());

        let coord = azimuth
            .zip(inclination)
            .zip(radius)
            .map(|((azimuth, inclination), radius)| Polar {
                azimuth,
                inclination,
                radius,
            });

        let samples = pcm.zip(coord);

        self.inner.write(samples)
    }

    #[inline]
    fn process_full(&mut self, inputs: Inputs<4>, _buffer: Buffers<0>, _samples: &mut Output) {
        let pcm = inputs.get(0);
        let pcm = pcm.iter();
        let azimuth = inputs.get(1);
        let azimuth = azimuth.iter();
        let inclination = inputs.get(2);
        let inclination = inclination.iter();
        let radius = inputs.get(3);
        let radius = radius.iter();

        let coord = azimuth
            .zip(inclination)
            .zip(radius)
            .map(|((azimuth, inclination), radius)| Polar {
                azimuth,
                inclination,
                radius,
            });

        let samples = pcm.zip(coord);

        self.inner.write(samples)
    }
}