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

use rodio::{decoder::Decoder, Source};
use std::{io::Cursor, io::Read, sync::Arc};

/// Stores the raw data of an audio file.

///

/// To play the clip construct a [`ClipPlayer`] using a [`ClipPlayerBuilder`].

///

/// # Example

/// ```

/// # use riddle_audio::*; fn main() -> Result<(), AudioError> {

/// let clip_bytes = include_bytes!("../../example_assets/boop.wav");

/// let clip = Clip::new(&clip_bytes[..])?;

/// # Ok(()) }

/// ```

#[derive(Clone)]
pub struct Clip {
    pub(crate) data: ClipData,
    duration: Option<std::time::Duration>,
}

impl Clip {
    /// Reads the entirety of the data reader in to memory.

    ///

    /// An [`AudioError::ClipDecodeError`] value will be returned if the data isn't a known format.

    pub fn new<R>(mut data: R) -> Result<Clip>
    where
        R: Read,
    {
        let mut owned_data: Vec<u8> = vec![];
        data.read_to_end(&mut owned_data)
            .map_err(|e| CommonError::IOError(e))?;

        let source = Decoder::new(Cursor::new(owned_data.clone()))
            .map_err(|_| AudioError::ClipDecodeError)?;
        let duration = source.total_duration();

        Ok(Self {
            data: ClipData::new(owned_data),
            duration,
        })
    }

    /// Get the run time of the clip, if it can be determined.

    ///

    /// # Example

    ///

    /// ```

    /// # use riddle_audio::*; fn main() -> Result<(), AudioError> {

    /// let clip_bytes = include_bytes!("../../example_assets/boop.wav");

    /// let clip = Clip::new(&clip_bytes[..])?;

    ///

    /// assert!(clip.duration().unwrap() > std::time::Duration::from_secs(0));

    /// # Ok(()) }

    /// ```

    pub fn duration(&self) -> Option<std::time::Duration> {
        self.duration
    }
}

#[derive(Clone)]
pub(crate) struct ClipData {
    data: Arc<Vec<u8>>,
}

impl ClipData {
    fn new(data: Vec<u8>) -> Self {
        Self { data: data.into() }
    }
}

impl AsRef<[u8]> for ClipData {
    fn as_ref(&self) -> &[u8] {
        Arc::as_ref(&self.data).as_ref()
    }
}