1use serde::{Deserialize, Serialize};
2
3use symphonia::core::codecs::audio::{AudioCodecId, well_known::{CODEC_ID_AAC, CODEC_ID_AC4, CODEC_ID_ADPCM_G722, CODEC_ID_ADPCM_G726, CODEC_ID_ADPCM_G726LE, CODEC_ID_ADPCM_IMA_QT, CODEC_ID_ADPCM_IMA_WAV, CODEC_ID_ADPCM_MS, CODEC_ID_ALAC, CODEC_ID_ATRAC1, CODEC_ID_ATRAC3, CODEC_ID_ATRAC9, CODEC_ID_ATRAC3PLUS, CODEC_ID_DCA, CODEC_ID_EAC3, CODEC_ID_FLAC, CODEC_ID_MONKEYS_AUDIO, CODEC_ID_MP1, CODEC_ID_MP2, CODEC_ID_MP3, CODEC_ID_MUSEPACK, CODEC_ID_OPUS, CODEC_ID_PCM_ALAW, CODEC_ID_PCM_F32BE, CODEC_ID_PCM_F32BE_PLANAR, CODEC_ID_PCM_F32LE, CODEC_ID_PCM_F32LE_PLANAR, CODEC_ID_PCM_F64BE, CODEC_ID_PCM_F64BE_PLANAR, CODEC_ID_PCM_F64LE, CODEC_ID_PCM_F64LE_PLANAR, CODEC_ID_PCM_MULAW, CODEC_ID_PCM_S8, CODEC_ID_PCM_S8_PLANAR, CODEC_ID_PCM_S16BE, CODEC_ID_PCM_S16BE_PLANAR, CODEC_ID_PCM_S16LE, CODEC_ID_PCM_S16LE_PLANAR, CODEC_ID_PCM_S24BE, CODEC_ID_PCM_S24BE_PLANAR, CODEC_ID_PCM_S24LE, CODEC_ID_PCM_S24LE_PLANAR, CODEC_ID_PCM_S32BE, CODEC_ID_PCM_S32BE_PLANAR, CODEC_ID_PCM_S32LE, CODEC_ID_PCM_S32LE_PLANAR, CODEC_ID_PCM_U8, CODEC_ID_PCM_U8_PLANAR, CODEC_ID_PCM_U16BE, CODEC_ID_PCM_U16BE_PLANAR, CODEC_ID_PCM_U16LE, CODEC_ID_PCM_U16LE_PLANAR, CODEC_ID_PCM_U24BE, CODEC_ID_PCM_U24BE_PLANAR, CODEC_ID_PCM_U24LE, CODEC_ID_PCM_U24LE_PLANAR, CODEC_ID_PCM_U32BE, CODEC_ID_PCM_U32BE_PLANAR, CODEC_ID_PCM_U32LE, CODEC_ID_PCM_U32LE_PLANAR, CODEC_ID_SPEEX, CODEC_ID_TTA, CODEC_ID_VORBIS, CODEC_ID_WAVPACK, CODEC_ID_WMA}};
4use thiserror::Error;
5
6#[derive(Debug, Error)]
7pub enum CodecError {
8 #[error("Unknown or unsupported codec: {0}")]
9 Unknown(String),
10
11 #[error("Codec '{0:?}' is missing an encoder")]
12 NoEncoder(Codec),
13
14 #[error("A codec is missing a symphonia decoder")]
15 NoDecoder,
16
17 #[error("Codec '{0:?}' is an unsupported codec")]
18 UnsupportedCodec(Codec),
19}
20
21#[derive(Debug, PartialEq, Eq, Copy, Clone, Serialize, Deserialize)]
23pub enum Codec {
24 Aac,
25 Ac4,
26 AdpcmG722,
27 AdpcmG726,
28 AdpcmG726Le,
29 AdpcmImaQt,
30 AdpcmImaWav,
31 AdpcmMs,
32 Alac,
33 Atrac1,
34 Atrac3,
35 Atrac9,
36 Atrac3Plus,
37 Dca,
38 Eac3,
39 Flac,
40 MonkeysAudio,
41 Mp1,
42 Mp2,
43 Mp3,
44 Musepack,
45 Opus,
46 PcmAlaw,
47 PcmF32Be,
48 PcmF32BePlanar,
49 PcmF32Le,
50 PcmF32LePlanar,
51 PcmF64Be,
52 PcmF64BePlanar,
53 PcmF64Le,
54 PcmF64LePlanar,
55 PcmMulaw,
56 PcmS8,
57 PcmS8Planar,
58 PcmS16Be,
59 PcmS16BePlanar,
60 PcmS16Le,
61 PcmS16LePlanar,
62 PcmS24Be,
63 PcmS24BePlanar,
64 PcmS24Le,
65 PcmS24LePlanar,
66 PcmS32Be,
67 PcmS32BePlanar,
68 PcmS32Le,
69 PcmS32LePlanar,
70 PcmU8,
71 PcmU8Planar,
72 PcmU16Be,
73 PcmU16BePlanar,
74 PcmU16Le,
75 PcmU16LePlanar,
76 PcmU24Be,
77 PcmU24BePlanar,
78 PcmU24Le,
79 PcmU24LePlanar,
80 PcmU32Be,
81 PcmU32BePlanar,
82 PcmU32Le,
83 PcmU32LePlanar,
84 Speex,
85 Tta,
86 Vorbis,
87 WavPack,
88 Wma,
89}
90
91impl Codec {
92 #[must_use]
93 pub fn is_pcm(&self) -> bool {
94 matches!(
95 self,
96 Codec::PcmAlaw
97 | Codec::PcmF32Be
98 | Codec::PcmF32BePlanar
99 | Codec::PcmF32Le
100 | Codec::PcmF32LePlanar
101 | Codec::PcmF64Be
102 | Codec::PcmF64BePlanar
103 | Codec::PcmF64Le
104 | Codec::PcmF64LePlanar
105 | Codec::PcmMulaw
106 | Codec::PcmS8
107 | Codec::PcmS8Planar
108 | Codec::PcmS16Be
109 | Codec::PcmS16BePlanar
110 | Codec::PcmS16Le
111 | Codec::PcmS16LePlanar
112 | Codec::PcmS24Be
113 | Codec::PcmS24BePlanar
114 | Codec::PcmS24Le
115 | Codec::PcmS24LePlanar
116 | Codec::PcmS32Be
117 | Codec::PcmS32BePlanar
118 | Codec::PcmS32Le
119 | Codec::PcmS32LePlanar
120 | Codec::PcmU8
121 | Codec::PcmU8Planar
122 | Codec::PcmU16Be
123 | Codec::PcmU16BePlanar
124 | Codec::PcmU16Le
125 | Codec::PcmU16LePlanar
126 | Codec::PcmU24Be
127 | Codec::PcmU24BePlanar
128 | Codec::PcmU24Le
129 | Codec::PcmU24LePlanar
130 | Codec::PcmU32Be
131 | Codec::PcmU32BePlanar
132 | Codec::PcmU32Le
133 | Codec::PcmU32LePlanar
134 | Codec::Tta
135 | Codec::WavPack
136 )
137 }
138
139 #[must_use]
140 pub fn is_lossless(&self) -> bool {
141 matches!(
142 self,
143 Codec::Alac
144 | Codec::Flac
145 | Codec::MonkeysAudio
146 | Codec::PcmF32Be
147 | Codec::PcmF32BePlanar
148 | Codec::PcmF32Le
149 | Codec::PcmF32LePlanar
150 | Codec::PcmF64Be
151 | Codec::PcmF64BePlanar
152 | Codec::PcmF64Le
153 | Codec::PcmF64LePlanar
154 | Codec::PcmS8
155 | Codec::PcmS8Planar
156 | Codec::PcmS16Be
157 | Codec::PcmS16BePlanar
158 | Codec::PcmS16Le
159 | Codec::PcmS16LePlanar
160 | Codec::PcmS24Be
161 | Codec::PcmS24BePlanar
162 | Codec::PcmS24Le
163 | Codec::PcmS24LePlanar
164 | Codec::PcmS32Be
165 | Codec::PcmS32BePlanar
166 | Codec::PcmS32Le
167 | Codec::PcmS32LePlanar
168 | Codec::PcmU8
169 | Codec::PcmU8Planar
170 | Codec::PcmU16Be
171 | Codec::PcmU16BePlanar
172 | Codec::PcmU16Le
173 | Codec::PcmU16LePlanar
174 | Codec::PcmU24Be
175 | Codec::PcmU24BePlanar
176 | Codec::PcmU24Le
177 | Codec::PcmU24LePlanar
178 | Codec::PcmU32Be
179 | Codec::PcmU32BePlanar
180 | Codec::PcmU32Le
181 | Codec::PcmU32LePlanar
182 )
183 }
184
185 #[must_use]
186 pub fn is_flac(&self) -> bool {
187 matches!(self, Self::Flac)
188 }
189
190 #[must_use]
191 pub fn is_mp3(&self) -> bool {
192 matches!(self, Self::Mp3)
193 }
194
195 #[must_use]
196 pub fn is_opus(&self) -> bool {
197 matches!(self, Self::Opus)
198 }
199
200 #[must_use]
201 pub fn is_vorbis(&self) -> bool {
202 matches!(self, Self::Vorbis)
203 }
204
205 #[must_use]
206 pub(crate) fn is_ape(&self) -> bool {
207 matches!(self, Self::MonkeysAudio)
208 }
209}
210
211impl TryFrom<AudioCodecId> for Codec {
212 type Error = CodecError;
213
214 fn try_from(value: AudioCodecId) -> Result<Codec, CodecError> {
215 let codec = match value {
216 CODEC_ID_AAC => Codec::Aac,
217 CODEC_ID_AC4 => Codec::Ac4,
218 CODEC_ID_ADPCM_G722 => Codec::AdpcmG722,
219 CODEC_ID_ADPCM_G726 => Codec::AdpcmG726,
220 CODEC_ID_ADPCM_G726LE => Codec::AdpcmG726Le,
221 CODEC_ID_ADPCM_IMA_QT => Codec::AdpcmImaQt,
222 CODEC_ID_ADPCM_IMA_WAV => Codec::AdpcmImaWav,
223 CODEC_ID_ADPCM_MS => Codec::AdpcmMs,
224 CODEC_ID_ALAC => Codec::Alac,
225 CODEC_ID_ATRAC1 => Codec::Atrac1,
226 CODEC_ID_ATRAC3 => Codec::Atrac3,
227 CODEC_ID_ATRAC9 => Codec::Atrac9,
228 CODEC_ID_ATRAC3PLUS => Codec::Atrac3Plus,
229 CODEC_ID_DCA => Codec::Dca,
230 CODEC_ID_EAC3 => Codec::Eac3,
231 CODEC_ID_FLAC => Codec::Flac,
232 CODEC_ID_MONKEYS_AUDIO => Codec::MonkeysAudio,
233 CODEC_ID_MP1 => Codec::Mp1,
234 CODEC_ID_MP2 => Codec::Mp2,
235 CODEC_ID_MP3 => Codec::Mp3,
236 CODEC_ID_MUSEPACK => Codec::Musepack,
237 CODEC_ID_OPUS => Codec::Opus,
238 CODEC_ID_PCM_ALAW => Codec::PcmAlaw,
239 CODEC_ID_PCM_F32BE => Codec::PcmF32Be,
240 CODEC_ID_PCM_F32BE_PLANAR => Codec::PcmF32BePlanar,
241 CODEC_ID_PCM_F32LE => Codec::PcmF32Le,
242 CODEC_ID_PCM_F32LE_PLANAR => Codec::PcmF32LePlanar,
243 CODEC_ID_PCM_F64BE => Codec::PcmF64Be,
244 CODEC_ID_PCM_F64BE_PLANAR => Codec::PcmF64BePlanar,
245 CODEC_ID_PCM_F64LE => Codec::PcmF64Le,
246 CODEC_ID_PCM_F64LE_PLANAR => Codec::PcmF64LePlanar,
247 CODEC_ID_PCM_MULAW => Codec::PcmMulaw,
248 CODEC_ID_PCM_S8 => Codec::PcmS8,
249 CODEC_ID_PCM_S8_PLANAR => Codec::PcmS8Planar,
250 CODEC_ID_PCM_S16BE => Codec::PcmS16Be,
251 CODEC_ID_PCM_S16BE_PLANAR => Codec::PcmS16BePlanar,
252 CODEC_ID_PCM_S16LE => Codec::PcmS16Le,
253 CODEC_ID_PCM_S16LE_PLANAR => Codec::PcmS16LePlanar,
254 CODEC_ID_PCM_S24BE => Codec::PcmS24Be,
255 CODEC_ID_PCM_S24BE_PLANAR => Codec::PcmS24BePlanar,
256 CODEC_ID_PCM_S24LE => Codec::PcmS24Le,
257 CODEC_ID_PCM_S24LE_PLANAR => Codec::PcmS24LePlanar,
258 CODEC_ID_PCM_S32BE => Codec::PcmS32Be,
259 CODEC_ID_PCM_S32BE_PLANAR => Codec::PcmS32BePlanar,
260 CODEC_ID_PCM_S32LE => Codec::PcmS32Le,
261 CODEC_ID_PCM_S32LE_PLANAR => Codec::PcmS32LePlanar,
262 CODEC_ID_PCM_U8 => Codec::PcmU8,
263 CODEC_ID_PCM_U8_PLANAR => Codec::PcmU8Planar,
264 CODEC_ID_PCM_U16BE => Codec::PcmU16Be,
265 CODEC_ID_PCM_U16BE_PLANAR => Codec::PcmU16BePlanar,
266 CODEC_ID_PCM_U16LE => Codec::PcmU16Le,
267 CODEC_ID_PCM_U16LE_PLANAR => Codec::PcmU16LePlanar,
268 CODEC_ID_PCM_U24BE => Codec::PcmU24Be,
269 CODEC_ID_PCM_U24BE_PLANAR => Codec::PcmU24BePlanar,
270 CODEC_ID_PCM_U24LE => Codec::PcmU24Le,
271 CODEC_ID_PCM_U24LE_PLANAR => Codec::PcmU24LePlanar,
272 CODEC_ID_PCM_U32BE => Codec::PcmU32Be,
273 CODEC_ID_PCM_U32BE_PLANAR => Codec::PcmU32BePlanar,
274 CODEC_ID_PCM_U32LE => Codec::PcmU32Le,
275 CODEC_ID_PCM_U32LE_PLANAR => Codec::PcmU32LePlanar,
276 CODEC_ID_SPEEX => Codec::Speex,
277 CODEC_ID_TTA => Codec::Tta,
278 CODEC_ID_VORBIS => Codec::Vorbis,
279 CODEC_ID_WAVPACK => Codec::WavPack,
280 CODEC_ID_WMA => Codec::Wma,
281 other => return Err(CodecError::Unknown(other.to_string())),
282 };
283 Ok(codec)
284 }
285}