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::{
|
||||
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
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue