x_media/
audio.rs

1use std::{
2    iter,
3    num::{NonZeroU32, NonZeroU8},
4};
5
6use crate::{
7    base::time,
8    media_frame::{MemoryPlanes, PlaneInformation},
9};
10
11pub const SAMPLE_RATE_TELEPHONE: u32 = 8000;
12pub const SAMPLE_RATE_VOIP: u32 = 16000;
13pub const SAMPLE_RATE_CD: u32 = 44100;
14pub const SAMPLE_RATE_DVD: u32 = 48000;
15pub const SAMPLE_RATE_HIGH: u32 = 96000;
16pub const SAMPLE_RATE_ULTRA_HIGH: u32 = 192000;
17
18#[derive(Clone, Copy, Debug, PartialEq)]
19pub enum AudioFormat {
20    U8 = 0, // unsigned 8 bits
21    S16,    // signed 16 bits
22    S32,    // signed 32 bits
23    F32,    // float 32 bits
24    F64,    // float 64 bits
25    U8P,    // unsigned 8 bits, planar
26    S16P,   // signed 16 bits, planar
27    S32P,   // signed 32 bits, planar
28    F32P,   // float 32 bits, planar
29    F64P,   // float 64 bits, planar
30    MAX,
31}
32
33#[derive(Clone, Debug, PartialEq)]
34pub struct AudioFrameDescription {
35    pub format: AudioFormat,
36    pub channels: NonZeroU8,
37    pub samples: NonZeroU32,
38    pub sample_rate: NonZeroU32,
39}
40
41impl AudioFrameDescription {
42    pub fn new(format: AudioFormat, channels: NonZeroU8, samples: NonZeroU32, sample_rate: NonZeroU32) -> Self {
43        Self {
44            format,
45            channels,
46            samples,
47            sample_rate,
48        }
49    }
50
51    pub fn duration_equal(&self, other: &AudioFrameDescription) -> bool {
52        let duration1 = self.samples.get() as u64 * time::MSEC_PER_SEC / self.sample_rate.get() as u64;
53        let duration2 = other.samples.get() as u64 * time::MSEC_PER_SEC / other.sample_rate.get() as u64;
54        duration1 == duration2
55    }
56}
57
58struct AudioFormatInfo {
59    pub bits: u8,
60    pub is_planar: bool,
61}
62
63static AUDIO_FORMAT_INFO: [AudioFormatInfo; AudioFormat::MAX as usize] = [
64    // U8
65    AudioFormatInfo {
66        bits: 8,
67        is_planar: false,
68    },
69    // S16
70    AudioFormatInfo {
71        bits: 16,
72        is_planar: false,
73    },
74    // S32
75    AudioFormatInfo {
76        bits: 32,
77        is_planar: false,
78    },
79    // F32
80    AudioFormatInfo {
81        bits: 32,
82        is_planar: false,
83    },
84    // F64
85    AudioFormatInfo {
86        bits: 64,
87        is_planar: false,
88    },
89    // U8P
90    AudioFormatInfo {
91        bits: 8,
92        is_planar: true,
93    },
94    // S16P
95    AudioFormatInfo {
96        bits: 16,
97        is_planar: true,
98    },
99    // S32P
100    AudioFormatInfo {
101        bits: 32,
102        is_planar: true,
103    },
104    // F32P
105    AudioFormatInfo {
106        bits: 32,
107        is_planar: true,
108    },
109    // F64P
110    AudioFormatInfo {
111        bits: 64,
112        is_planar: true,
113    },
114];
115
116impl AudioFormat {
117    pub fn bits(&self) -> u8 {
118        AUDIO_FORMAT_INFO[*self as usize].bits
119    }
120
121    pub fn bytes(&self) -> u8 {
122        self.bits() >> 3
123    }
124
125    pub fn data_calc(&self, channels: u8, samples: u32) -> (u32, MemoryPlanes) {
126        let mut size = 0;
127        let mut planes = MemoryPlanes::new();
128        let stride = self.stride(channels, samples);
129
130        if self.is_planar() {
131            planes.extend(iter::repeat(PlaneInformation::Audio(stride)).take(channels as usize));
132            size += stride * channels as u32;
133        } else {
134            planes.push(PlaneInformation::Audio(stride));
135            size = stride;
136        }
137
138        (size, planes)
139    }
140
141    pub fn is_planar(&self) -> bool {
142        AUDIO_FORMAT_INFO[*self as usize].is_planar
143    }
144
145    pub fn stride(&self, channels: u8, samples: u32) -> u32 {
146        if self.is_planar() {
147            self.bytes() as u32 * samples
148        } else {
149            self.bytes() as u32 * channels as u32 * samples
150        }
151    }
152}