unity_asset_binary/audio/
decoder.rs1use super::formats::AudioCompressionFormat;
7use super::types::{AudioClip, DecodedAudio};
8use crate::error::{BinaryError, Result};
9
10pub struct AudioDecoder;
15
16impl AudioDecoder {
17 pub fn new() -> Self {
19 Self
20 }
21
22 #[cfg(feature = "symphonia")]
24 pub fn decode(&self, clip: &AudioClip) -> Result<DecodedAudio> {
25 use std::io::Cursor;
26 use symphonia::core::audio::{AudioBufferRef, Signal};
27 use symphonia::core::codecs::{CODEC_TYPE_NULL, DecoderOptions};
28 use symphonia::core::errors::Error as SymphoniaError;
29 use symphonia::core::formats::FormatOptions;
30 use symphonia::core::io::MediaSourceStream;
31 use symphonia::core::meta::MetadataOptions;
32 use symphonia::core::probe::Hint;
33
34 if clip.data.is_empty() {
35 return Err(BinaryError::invalid_data("No audio data to decode"));
36 }
37
38 let cursor = Cursor::new(clip.data.clone());
40 let media_source = MediaSourceStream::new(Box::new(cursor), Default::default());
41
42 let mut hint = Hint::new();
44 match clip.compression_format() {
45 AudioCompressionFormat::Vorbis => hint.with_extension("ogg"),
46 AudioCompressionFormat::MP3 => hint.with_extension("mp3"),
47 AudioCompressionFormat::AAC => hint.with_extension("aac"),
48 AudioCompressionFormat::PCM => hint.with_extension("wav"),
49 _ => &mut hint,
50 };
51
52 let meta_opts: MetadataOptions = Default::default();
54 let fmt_opts: FormatOptions = Default::default();
55
56 let probed = symphonia::default::get_probe()
58 .format(&hint, media_source, &fmt_opts, &meta_opts)
59 .map_err(|e| BinaryError::generic(format!("Failed to probe audio format: {}", e)))?;
60
61 let mut format = probed.format;
63
64 let track = format
66 .tracks()
67 .iter()
68 .find(|t| t.codec_params.codec != CODEC_TYPE_NULL)
69 .ok_or_else(|| BinaryError::generic("No supported audio tracks found"))?;
70
71 let dec_opts: DecoderOptions = Default::default();
73
74 let mut decoder = symphonia::default::get_codecs()
76 .make(&track.codec_params, &dec_opts)
77 .map_err(|e| BinaryError::generic(format!("Failed to create decoder: {}", e)))?;
78
79 let track_id = track.id;
81
82 let mut samples = Vec::new();
83 let mut sample_rate = 44100u32;
84 let mut channels = 2u32;
85
86 loop {
88 let packet = match format.next_packet() {
90 Ok(packet) => packet,
91 Err(SymphoniaError::ResetRequired) => {
92 break;
97 }
98 Err(SymphoniaError::IoError(_)) => {
99 break;
101 }
102 Err(err) => {
103 return Err(BinaryError::generic(format!("Decode error: {}", err)));
105 }
106 };
107
108 while !format.metadata().is_latest() {
110 format.metadata().pop();
112 }
113
114 if packet.track_id() != track_id {
116 continue;
117 }
118
119 match decoder.decode(&packet) {
121 Ok(decoded) => {
122 let spec = *decoded.spec();
124 sample_rate = spec.rate;
125 channels = spec.channels.count() as u32;
126
127 match decoded {
129 AudioBufferRef::F32(buf) => {
130 samples.extend_from_slice(buf.chan(0));
131 if channels > 1 {
132 for ch in 1..channels as usize {
133 if ch < buf.spec().channels.count() {
134 let channel_samples = buf.chan(ch);
135 for (i, &sample) in channel_samples.iter().enumerate() {
137 if i * channels as usize + ch < samples.len() {
138 samples.insert(i * channels as usize + ch, sample);
139 } else {
140 samples.push(sample);
141 }
142 }
143 }
144 }
145 }
146 }
147 AudioBufferRef::U8(buf) => {
148 for ch in 0..channels as usize {
149 if ch < buf.spec().channels.count() {
150 let channel_samples = buf.chan(ch);
151 for &sample in channel_samples {
152 let normalized = (sample as f32 - 128.0) / 128.0;
153 samples.push(normalized);
154 }
155 }
156 }
157 }
158 AudioBufferRef::U16(buf) => {
159 for ch in 0..channels as usize {
160 if ch < buf.spec().channels.count() {
161 let channel_samples = buf.chan(ch);
162 for &sample in channel_samples {
163 let normalized = (sample as f32 - 32768.0) / 32768.0;
164 samples.push(normalized);
165 }
166 }
167 }
168 }
169 AudioBufferRef::U32(buf) => {
170 for ch in 0..channels as usize {
171 if ch < buf.spec().channels.count() {
172 let channel_samples = buf.chan(ch);
173 for &sample in channel_samples {
174 let normalized =
175 (sample as f32 - 2147483648.0) / 2147483648.0;
176 samples.push(normalized);
177 }
178 }
179 }
180 }
181 AudioBufferRef::S8(buf) => {
182 for ch in 0..channels as usize {
183 if ch < buf.spec().channels.count() {
184 let channel_samples = buf.chan(ch);
185 for &sample in channel_samples {
186 let normalized = sample as f32 / 128.0;
187 samples.push(normalized);
188 }
189 }
190 }
191 }
192 AudioBufferRef::S16(buf) => {
193 for ch in 0..channels as usize {
194 if ch < buf.spec().channels.count() {
195 let channel_samples = buf.chan(ch);
196 for &sample in channel_samples {
197 let normalized = sample as f32 / 32768.0;
198 samples.push(normalized);
199 }
200 }
201 }
202 }
203 AudioBufferRef::S32(buf) => {
204 for ch in 0..channels as usize {
205 if ch < buf.spec().channels.count() {
206 let channel_samples = buf.chan(ch);
207 for &sample in channel_samples {
208 let normalized = sample as f32 / 2147483648.0;
209 samples.push(normalized);
210 }
211 }
212 }
213 }
214 AudioBufferRef::F64(buf) => {
215 for ch in 0..channels as usize {
216 if ch < buf.spec().channels.count() {
217 let channel_samples = buf.chan(ch);
218 for &sample in channel_samples {
219 samples.push(sample as f32);
220 }
221 }
222 }
223 }
224 AudioBufferRef::U24(buf) => {
225 for ch in 0..channels as usize {
226 if ch < buf.spec().channels.count() {
227 let channel_samples = buf.chan(ch);
228 for &sample in channel_samples {
229 let value = sample.inner() as i32;
230 let normalized = (value as f32 - 8388608.0) / 8388608.0;
231 samples.push(normalized);
232 }
233 }
234 }
235 }
236 AudioBufferRef::S24(buf) => {
237 for ch in 0..channels as usize {
238 if ch < buf.spec().channels.count() {
239 let channel_samples = buf.chan(ch);
240 for &sample in channel_samples {
241 let value = sample.inner();
242 let normalized = value as f32 / 8388608.0;
243 samples.push(normalized);
244 }
245 }
246 }
247 }
248 }
249 }
250 Err(SymphoniaError::IoError(_)) => {
251 break;
253 }
254 Err(SymphoniaError::DecodeError(_)) => {
255 continue;
257 }
258 Err(err) => {
259 return Err(BinaryError::generic(format!("Decode error: {}", err)));
261 }
262 }
263 }
264
265 if samples.is_empty() {
266 return Err(BinaryError::generic("No audio samples decoded"));
267 }
268
269 Ok(DecodedAudio::new(samples, sample_rate, channels))
270 }
271
272 #[cfg(not(feature = "symphonia"))]
274 pub fn decode(&self, _clip: &AudioClip) -> Result<DecodedAudio> {
275 Err(BinaryError::unsupported(
276 "Audio decoding requires symphonia feature",
277 ))
278 }
279
280 pub fn can_decode(&self, format: AudioCompressionFormat) -> bool {
282 #[cfg(feature = "symphonia")]
283 {
284 matches!(
285 format,
286 AudioCompressionFormat::PCM
287 | AudioCompressionFormat::Vorbis
288 | AudioCompressionFormat::MP3
289 | AudioCompressionFormat::AAC
290 | AudioCompressionFormat::ADPCM
291 )
292 }
293
294 #[cfg(not(feature = "symphonia"))]
295 {
296 false
297 }
298 }
299
300 pub fn supported_formats(&self) -> Vec<AudioCompressionFormat> {
302 #[cfg(feature = "symphonia")]
303 {
304 vec![
305 AudioCompressionFormat::PCM,
306 AudioCompressionFormat::Vorbis,
307 AudioCompressionFormat::MP3,
308 AudioCompressionFormat::AAC,
309 AudioCompressionFormat::ADPCM,
310 ]
311 }
312
313 #[cfg(not(feature = "symphonia"))]
314 {
315 vec![]
316 }
317 }
318}
319
320impl Default for AudioDecoder {
321 fn default() -> Self {
322 Self::new()
323 }
324}