add symphonia codec support for opening and exporting encoded files (not bendable since that would lead to data corruption)
This commit is contained in:
parent
2733cd9345
commit
4d80833bbd
1 changed files with 101 additions and 14 deletions
|
@ -1,31 +1,40 @@
|
||||||
use std::io;
|
use std::io::{self, Read};
|
||||||
|
|
||||||
|
use derive_new::new;
|
||||||
use symphonia::{
|
use symphonia::{
|
||||||
core::{
|
core::{
|
||||||
audio::{RawSample, RawSampleBuffer},
|
audio::Signal,
|
||||||
|
codecs::Decoder,
|
||||||
|
conv::FromSample,
|
||||||
|
errors::Error,
|
||||||
|
formats::FormatReader,
|
||||||
io::MediaSourceStream,
|
io::MediaSourceStream,
|
||||||
probe::Hint,
|
probe::Hint,
|
||||||
sample::Sample,
|
sample::{i24, u24},
|
||||||
},
|
},
|
||||||
default,
|
default,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::TryFromDataBytes;
|
use crate::{IntoDataBytes, TryFromDataBytes};
|
||||||
|
|
||||||
pub struct Audio<S>(RawSampleBuffer<S>)
|
use super::{RawSamples, Sample};
|
||||||
where
|
|
||||||
S: Sample + RawSample;
|
|
||||||
|
|
||||||
impl<S> TryFromDataBytes for Audio<S>
|
/// The new hot thing: this represents audio in any format. You can open any file and make this thing with the file's bytes.
|
||||||
where
|
/// You can then modify its bytes and see what it gives. Maybe it won't work anymore.
|
||||||
S: Sample + RawSample,
|
/// You can also decode it to raw samples and play with it freely without corrupting anything.
|
||||||
{
|
#[derive(new)]
|
||||||
type Error = symphonia::core::errors::Error;
|
pub struct Audio {
|
||||||
|
reader: Box<dyn FormatReader>,
|
||||||
|
decoder: Box<dyn Decoder>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFromDataBytes for Audio {
|
||||||
|
type Error = Error;
|
||||||
type Format = Hint;
|
type Format = Hint;
|
||||||
fn try_from_data_bytes(
|
fn try_from_data_bytes(
|
||||||
bytes: crate::Bytes,
|
bytes: crate::Bytes,
|
||||||
format: Self::Format,
|
format: Self::Format,
|
||||||
crop: crate::Crop,
|
_crop: crate::Crop,
|
||||||
) -> Result<Self, Self::Error>
|
) -> Result<Self, Self::Error>
|
||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
|
@ -37,6 +46,84 @@ where
|
||||||
let reader = probe
|
let reader = probe
|
||||||
.format(&format, mss, &Default::default(), &Default::default())?
|
.format(&format, mss, &Default::default(), &Default::default())?
|
||||||
.format;
|
.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
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue