add symphonia codec support for opening and exporting encoded files (not bendable since that would lead to data corruption)

This commit is contained in:
Breval Ferrari 2025-03-17 00:33:38 -04:00
parent 2733cd9345
commit 4d80833bbd
No known key found for this signature in database
GPG key ID: F71E304D6400AB8E

View file

@ -1,31 +1,40 @@
use std::io;
use std::io::{self, Read};
use derive_new::new;
use symphonia::{
core::{
audio::{RawSample, RawSampleBuffer},
audio::Signal,
codecs::Decoder,
conv::FromSample,
errors::Error,
formats::FormatReader,
io::MediaSourceStream,
probe::Hint,
sample::Sample,
sample::{i24, u24},
},
default,
};
use crate::TryFromDataBytes;
use crate::{IntoDataBytes, TryFromDataBytes};
pub struct Audio<S>(RawSampleBuffer<S>)
where
S: Sample + RawSample;
use super::{RawSamples, Sample};
impl<S> TryFromDataBytes for Audio<S>
where
S: Sample + RawSample,
{
type Error = symphonia::core::errors::Error;
/// The new hot thing: this represents audio in any format. You can open any file and make this thing with the file's bytes.
/// You can then modify its bytes and see what it gives. Maybe it won't work anymore.
/// You can also decode it to raw samples and play with it freely without corrupting anything.
#[derive(new)]
pub struct Audio {
reader: Box<dyn FormatReader>,
decoder: Box<dyn Decoder>,
}
impl TryFromDataBytes for Audio {
type Error = Error;
type Format = Hint;
fn try_from_data_bytes(
bytes: crate::Bytes,
format: Self::Format,
crop: crate::Crop,
_crop: crate::Crop,
) -> Result<Self, Self::Error>
where
Self: Sized,
@ -37,6 +46,84 @@ where
let reader = probe
.format(&format, mss, &Default::default(), &Default::default())?
.format;
todo!()
let decoder = registry.make(&Default::default(), &Default::default())?;
Ok(Audio::new(reader, decoder))
}
}
impl IntoDataBytes for Audio {
fn into_data_bytes(self) -> crate::Bytes {
self.reader.into_inner().bytes().flatten().collect()
}
}
macro_rules! dynamic_map(
($dynimage: expr, $image: pat => $action: expr) => ({
match $dynimage {
symphonia::core::audio::AudioBufferRef::U8($image) => symphonia::core::audio::AudioBufferRef::U8($action),
symphonia::core::audio::AudioBufferRef::U16($image) => symphonia::core::audio::AudioBufferRef::U16($action),
symphonia::core::audio::AudioBufferRef::U24($image) => symphonia::core::audio::AudioBufferRef::U24($action),
symphonia::core::audio::AudioBufferRef::U32($image) => symphonia::core::audio::AudioBufferRef::U32($action),
symphonia::core::audio::AudioBufferRef::S8($image) => symphonia::core::audio::AudioBufferRef::S8($action),
symphonia::core::audio::AudioBufferRef::S16($image) => symphonia::core::audio::AudioBufferRef::S16($action),
symphonia::core::audio::AudioBufferRef::S24($image) => symphonia::core::audio::AudioBufferRef::S24($action),
symphonia::core::audio::AudioBufferRef::S32($image) => symphonia::core::audio::AudioBufferRef::S32($action),
symphonia::core::audio::AudioBufferRef::F32($image) => symphonia::core::audio::AudioBufferRef::F32($action),
symphonia::core::audio::AudioBufferRef::F64($image) => symphonia::core::audio::AudioBufferRef::F64($action),
}
});
($dynimage: expr, $image:pat_param, $action: expr) => (
match $dynimage {
symphonia::core::audio::AudioBufferRef::U8($image) => $action,
symphonia::core::audio::AudioBufferRef::U16($image) => $action,
symphonia::core::audio::AudioBufferRef::U24($image) => $action,
symphonia::core::audio::AudioBufferRef::U32($image) => $action,
symphonia::core::audio::AudioBufferRef::S8($image) => $action,
symphonia::core::audio::AudioBufferRef::S16($image) => $action,
symphonia::core::audio::AudioBufferRef::S24($image) => $action,
symphonia::core::audio::AudioBufferRef::S32($image) => $action,
symphonia::core::audio::AudioBufferRef::F32($image) => $action,
symphonia::core::audio::AudioBufferRef::F64($image) => $action,
}
);
);
impl<S> From<Audio> for RawSamples<S>
where
S: Sample
+ FromSample<u8>
+ FromSample<u16>
+ FromSample<u24>
+ FromSample<u32>
+ FromSample<i8>
+ FromSample<i16>
+ FromSample<i24>
+ FromSample<i32>
+ FromSample<f32>
+ FromSample<f64>,
{
fn from(mut value: Audio) -> Self {
RawSamples::from({
let mut result = Vec::new();
while let Ok(packet) = value.reader.next_packet() {
if let Ok(src) = value.decoder.decode(&packet) {
dynamic_map!(
src,
ref audio_buffer,
result.append(
&mut (0usize..src.spec().channels.count())
.flat_map(|ch| audio_buffer
.chan(ch)
.iter()
.map(|s| S::from_sample(s.clone()))
.collect::<Vec<S>>())
.collect::<Vec<S>>()
)
)
}
}
result
})
}
}