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
158
159
160
161
//! Structures related to `Bubble`

use crate::format::{BubbleField, BubbleFieldSize, Color};
use crate::format::oao::Floaout;
use crate::format::wav::{Wav, WavBlock};
use std::convert::{TryFrom, TryInto};

/// Details of the Bubble file.
#[derive(Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct Bubble {
    /// This is the number of `Bubble` version.
    pub version: u8,
    /// This includes length, width and height.
    pub bub_field_size: BubbleFieldSize,
    /// This includes red, green, blue.
    pub color: Color,
    // Format
    /// This is number of block.
    pub blocks: u64,
    /// Sampling Rate
    pub sampling_rate: u32,
    /// Bits Per Sample
    pub bits_per_sample: u16,
    /// Bubble Name Size
    pub name_size: u8,
    /// Name of Bubble
    pub name: String,
    /// Overall of Bubble field
    pub overall: BubbleField
}

impl Bubble {
    /// This method casts Bubble field size and bits per sample to `Bubble`.
    /// 
    /// # Examples
    /// ```
    /// use floaout::format::bub::Bubble;
    /// 
    /// let bub = Bubble::from_bub_field_size_and_bits_per_sample((0u8, 0u8, 0u8).into(), 32);
    /// 
    /// assert_eq!(
    ///     bub,
    ///     Bubble {
    ///         bub_field_size: (0u8, 0u8, 0u8).into(),
    ///         bits_per_sample: 32,
    ///         ..Default::default()
    ///     }
    /// );
    /// ```
    pub fn from_bub_field_size_and_bits_per_sample(bub_field_size: BubbleFieldSize, bits_per_sample: u16) -> Self {
        Self {
            bub_field_size,
            bits_per_sample,
            ..Default::default()
        }
    }
}

impl From<Floaout> for Bubble {
    fn from(oao: Floaout) -> Self {
        Self {
            bub_field_size: oao.bub_field_size,
            blocks: oao.blocks,
            sampling_rate: oao.sampling_rate,
            bits_per_sample: oao.bits_per_sample,
            ..Default::default()
        }
    }
}

impl TryFrom<Wav> for Bubble {
    type Error = &'static str;

    fn try_from(wav: Wav) -> Result<Self, Self::Error> {
        if wav.channels == 1 {
            Ok(
                Self {
                    blocks: (wav.data_size / wav.data_block_size as u32) as u64,
                    sampling_rate: wav.sampling_rate,
                    bits_per_sample: wav.bits_per_sample,
                    ..Default::default()
                }
            )
        } else {
            Err("Bubble only accepts 1 channel.")
        }
    }
}

impl TryInto<Wav> for Bubble {
    type Error = &'static str;

    fn try_into(self) -> Result<Wav, Self::Error> {
        let bytes_per_sample = self.bits_per_sample / 8;
        let riff_size = 1 * bytes_per_sample as u64 * self.blocks + 36;
        if riff_size > u32::max_value() as u64 {
            Err("Wav riff size only accepts no more than the largest value of u32.")
        } else {
            Ok(
                Wav {
                    riff_size: riff_size as u32,
                    format_size: 16,
                    format_tag: 3,
                    channels: 1,
                    sampling_rate: self.sampling_rate,
                    data_rate: self.sampling_rate * (bytes_per_sample * 1) as u32,
                    data_block_size: bytes_per_sample * 1,
                    bits_per_sample: self.bits_per_sample,
                    data_size: (riff_size - 36) as u32,
                    other_size: 0
                }
            )
        }
    }
}

/// Block of Bubble
#[derive(Clone, Debug, PartialEq, PartialOrd)]
pub struct BubbleBlock {
    /// Block of Wav
    pub wav_block: WavBlock,
    /// Bubble field
    pub bub_field: BubbleField
}

impl BubbleBlock {
    /// This method casts `WavBlock` and `BubbleField` to `Bubble`.
    /// 
    /// # Examples
    /// ```
    /// use floaout::format::BubbleField;
    /// use floaout::format::bub::{Bubble, BubbleBlock};
    /// use floaout::format::wav::WavBlock;
    /// 
    /// let bub_field: BubbleField = vec![vec![vec![0], vec![2]], vec![vec![1], vec![3]]].into();
    /// 
    /// let bub_block = BubbleBlock::from_wav_block_and_bub_field(1.0.into(), bub_field);
    /// ```
    pub fn from_wav_block_and_bub_field(wav_block: WavBlock, bub_field: BubbleField) -> Self {
        Self {
            wav_block,
            bub_field
        }
    }
}

/// Blocks of Bubble
#[derive(Clone, Debug, PartialEq, PartialOrd)]
pub struct BubbleBlocks(pub Box<[BubbleBlock]>);

impl From<Box<[BubbleBlock]>> for BubbleBlocks {
    fn from(buf: Box<[BubbleBlock]>) -> Self {
        BubbleBlocks(buf)
    }
}

impl Into<Box<[BubbleBlock]>> for BubbleBlocks {
    fn into(self) -> Box<[BubbleBlock]> {
        self.0
    }
}