core: Add symphonia as optional MP3 decoder
Add symphonia_mp3 feature to enable symphonia as an MP3 decoder. This is a pure Rust MP3 decoder that could be used on web.
This commit is contained in:
parent
94d02fa653
commit
483995823f
|
@ -106,6 +106,12 @@ dependencies = [
|
|||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "arrayvec"
|
||||
version = "0.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "269d0f5e68353a7cab87f81e7c736adc008d279a36ebc6a05dfe01193a89f0c9"
|
||||
|
||||
[[package]]
|
||||
name = "ash"
|
||||
version = "0.32.1"
|
||||
|
@ -1482,7 +1488,7 @@ version = "0.9.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f9e453baf3aaef2b0c354ce0b3d63d76402e406a59b64b7182d123cfa6635ae"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"arrayvec 0.5.2",
|
||||
"bitflags",
|
||||
"gfx-auxil",
|
||||
"gfx-hal",
|
||||
|
@ -1505,7 +1511,7 @@ version = "0.9.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "21506399f64a3c4d389182a89a30073856ae33eb712315456b4fd8f39ee7682a"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"arrayvec 0.5.2",
|
||||
"bit-set",
|
||||
"bitflags",
|
||||
"d3d12",
|
||||
|
@ -1539,7 +1545,7 @@ version = "0.9.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6bae057fc3a0ab23ecf97ae51d4017d27d5ddf0aab16ee6dcb58981af88c3152"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"arrayvec 0.5.2",
|
||||
"bitflags",
|
||||
"fxhash",
|
||||
"gfx-hal",
|
||||
|
@ -1561,7 +1567,7 @@ version = "0.9.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0de85808e2a98994c6af925253f8a9593bc57180ef1ea137deab6d35cc949517"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"arrayvec 0.5.2",
|
||||
"bitflags",
|
||||
"block",
|
||||
"cocoa-foundation",
|
||||
|
@ -1587,7 +1593,7 @@ version = "0.9.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a9861ec855acbbc65c0e4f966d761224886e811dc2c6d413a4776e9293d0e5c0"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"arrayvec 0.5.2",
|
||||
"ash",
|
||||
"byteorder",
|
||||
"core-graphics-types",
|
||||
|
@ -1963,7 +1969,7 @@ version = "0.7.6"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6607c62aa161d23d17a9072cc5da0be67cdfc89d3afb1e8d9c842bebc2525ffe"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"arrayvec 0.5.2",
|
||||
"bitflags",
|
||||
"cfg-if 1.0.0",
|
||||
"ryu",
|
||||
|
@ -2083,7 +2089,7 @@ version = "0.17.4"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f1e79ed83352715656b6e73bd9c1b54736f22d0c6ad9b1809ad20d585b943f4a"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"arrayvec 0.5.2",
|
||||
"euclid",
|
||||
"num-traits",
|
||||
]
|
||||
|
@ -2103,7 +2109,7 @@ version = "0.17.8"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6c76c657e6eadab8fc258b0570226d88f186d2a462105a62dc015471f56fe761"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"arrayvec 0.5.2",
|
||||
"float_next_after",
|
||||
"lyon_path",
|
||||
"sid",
|
||||
|
@ -3065,6 +3071,7 @@ dependencies = [
|
|||
"serde",
|
||||
"smallvec",
|
||||
"swf",
|
||||
"symphonia",
|
||||
"thiserror",
|
||||
"url",
|
||||
"weak-table",
|
||||
|
@ -3494,6 +3501,56 @@ dependencies = [
|
|||
"smallvec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "symphonia"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9fae959d5ea7b4cd0cd8db3b899ec4f549b0d8a298694826a36ae7e5f19d4aa6"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"symphonia-bundle-mp3",
|
||||
"symphonia-core",
|
||||
"symphonia-metadata",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "symphonia-bundle-mp3"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b9f596fe16d2ae06e9404558644b61e27e2dcfee6c511f559be4699c403283fa"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"lazy_static",
|
||||
"log",
|
||||
"symphonia-core",
|
||||
"symphonia-metadata",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "symphonia-core"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c1742e06f50b4a7ed7abee53433231e050a248b498cd0ae2c639c8a70b115001"
|
||||
dependencies = [
|
||||
"arrayvec 0.6.1",
|
||||
"bitflags",
|
||||
"byteorder",
|
||||
"lazy_static",
|
||||
"log",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "symphonia-metadata"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "db5e36e38a7400f968569135e7ac0f8647de42e93905ad41c79d583aaeae565c"
|
||||
dependencies = [
|
||||
"encoding_rs",
|
||||
"lazy_static",
|
||||
"log",
|
||||
"symphonia-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.76"
|
||||
|
@ -4001,7 +4058,7 @@ version = "0.9.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bd247f8b26fd3d42ef2f320d378025cd6e84d782ef749fab45cc3b981fbe3275"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"arrayvec 0.5.2",
|
||||
"js-sys",
|
||||
"log",
|
||||
"naga",
|
||||
|
@ -4022,7 +4079,7 @@ version = "0.9.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "958a8a5e418492723ab4e7933bf6dbdf06f5dc87274ba2ae0e4f9c891aac579c"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"arrayvec 0.5.2",
|
||||
"bitflags",
|
||||
"cfg_aliases",
|
||||
"copyless",
|
||||
|
|
|
@ -43,6 +43,7 @@ flash-lso = { git = "https://github.com/ruffle-rs/rust-flash-lso", rev = "19fecd
|
|||
json = "0.12.4"
|
||||
lzma-rs = {version = "0.2.0", optional = true }
|
||||
dasp = { git = "https://github.com/RustAudio/dasp", rev = "f05a703", features = ["interpolate", "interpolate-linear", "signal"] }
|
||||
symphonia = { version = "0.3.0", default-features = false, features = ["mp3"], optional = true }
|
||||
|
||||
[dependencies.jpeg-decoder]
|
||||
version = "0.1.22"
|
||||
|
|
|
@ -1,14 +1,16 @@
|
|||
//! Audio decoders.
|
||||
|
||||
mod adpcm;
|
||||
#[cfg(feature = "minimp3")]
|
||||
#[cfg(any(feature = "minimp3", feature = "symphonia"))]
|
||||
mod mp3;
|
||||
mod nellymoser;
|
||||
mod pcm;
|
||||
|
||||
pub use adpcm::AdpcmDecoder;
|
||||
#[cfg(feature = "minimp3")]
|
||||
pub use mp3::Mp3Decoder;
|
||||
pub use mp3::minimp3::Mp3Decoder;
|
||||
#[cfg(all(feature = "symphonia", not(feature = "minimp3")))]
|
||||
pub use mp3::symphonia::Mp3Decoder;
|
||||
pub use nellymoser::NellymoserDecoder;
|
||||
pub use pcm::PcmDecoder;
|
||||
|
||||
|
@ -29,11 +31,11 @@ pub trait Decoder: Iterator<Item = [i16; 2]> {
|
|||
}
|
||||
|
||||
/// Instantiate a decoder for the compression that the sound data uses.
|
||||
pub fn make_decoder<'a, R: 'a + Send + Read>(
|
||||
pub fn make_decoder<R: 'static + Send + Read>(
|
||||
format: &SoundFormat,
|
||||
data: R,
|
||||
) -> Result<Box<dyn 'a + Send + Decoder>, Error> {
|
||||
let decoder: Box<dyn 'a + Send + Decoder> = match format.compression {
|
||||
) -> Result<Box<dyn Send + Decoder>, Error> {
|
||||
let decoder: Box<dyn Send + Decoder> = match format.compression {
|
||||
AudioCompression::UncompressedUnknownEndian => {
|
||||
// Cross fingers that it's little endian.
|
||||
log::warn!("make_decoder: PCM sound is unknown endian; assuming little endian");
|
||||
|
@ -55,7 +57,7 @@ pub fn make_decoder<'a, R: 'a + Send + Read>(
|
|||
format.is_stereo,
|
||||
format.sample_rate,
|
||||
)),
|
||||
#[cfg(feature = "minimp3")]
|
||||
#[cfg(any(feature = "minimp3", feature = "symphonia"))]
|
||||
AudioCompression::Mp3 => Box::new(Mp3Decoder::new(
|
||||
if format.is_stereo { 2 } else { 1 },
|
||||
format.sample_rate.into(),
|
||||
|
|
|
@ -1,95 +1,267 @@
|
|||
use super::{Decoder, SeekableDecoder};
|
||||
use std::io::{Cursor, Read};
|
||||
|
||||
#[cfg(feature = "minimp3")]
|
||||
pub struct Mp3Decoder<R: Read> {
|
||||
decoder: minimp3::Decoder<R>,
|
||||
sample_rate: u32,
|
||||
num_channels: u16,
|
||||
cur_frame: minimp3::Frame,
|
||||
cur_sample: usize,
|
||||
num_samples: usize,
|
||||
}
|
||||
pub mod minimp3 {
|
||||
use crate::backend::audio::decoders::{Decoder, SeekableDecoder};
|
||||
use std::io::{Cursor, Read};
|
||||
|
||||
#[cfg(feature = "minimp3")]
|
||||
impl<R: Read> Mp3Decoder<R> {
|
||||
pub fn new(num_channels: u16, sample_rate: u32, reader: R) -> Self {
|
||||
Mp3Decoder {
|
||||
decoder: minimp3::Decoder::new(reader),
|
||||
num_channels,
|
||||
sample_rate,
|
||||
cur_frame: minimp3::Frame {
|
||||
data: vec![],
|
||||
sample_rate: sample_rate as i32,
|
||||
channels: num_channels.into(),
|
||||
layer: 3,
|
||||
bitrate: 128,
|
||||
},
|
||||
cur_sample: 0,
|
||||
num_samples: 0,
|
||||
}
|
||||
pub struct Mp3Decoder<R: Read> {
|
||||
decoder: minimp3::Decoder<R>,
|
||||
sample_rate: u32,
|
||||
num_channels: u16,
|
||||
cur_frame: minimp3::Frame,
|
||||
cur_sample: usize,
|
||||
num_samples: usize,
|
||||
}
|
||||
|
||||
fn next_frame(&mut self) {
|
||||
if let Ok(frame) = self.decoder.next_frame() {
|
||||
self.num_samples = frame.data.len();
|
||||
self.cur_frame = frame;
|
||||
} else {
|
||||
self.num_samples = 0;
|
||||
}
|
||||
self.cur_sample = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "minimp3")]
|
||||
impl<R: Read> Iterator for Mp3Decoder<R> {
|
||||
type Item = [i16; 2];
|
||||
|
||||
#[inline]
|
||||
#[allow(unknown_lints, clippy::branches_sharing_code)]
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if self.cur_sample >= self.num_samples {
|
||||
self.next_frame();
|
||||
impl<R: Read> Mp3Decoder<R> {
|
||||
pub fn new(num_channels: u16, sample_rate: u32, reader: R) -> Self {
|
||||
Mp3Decoder {
|
||||
decoder: minimp3::Decoder::new(reader),
|
||||
num_channels,
|
||||
sample_rate,
|
||||
cur_frame: minimp3::Frame {
|
||||
data: vec![],
|
||||
sample_rate: sample_rate as i32,
|
||||
channels: num_channels.into(),
|
||||
layer: 3,
|
||||
bitrate: 128,
|
||||
},
|
||||
cur_sample: 0,
|
||||
num_samples: 0,
|
||||
}
|
||||
}
|
||||
|
||||
if self.num_samples > 0 {
|
||||
if self.num_channels == 2 {
|
||||
let left = self.cur_frame.data[self.cur_sample];
|
||||
let right = self.cur_frame.data[self.cur_sample + 1];
|
||||
self.cur_sample += 2;
|
||||
Some([left, right])
|
||||
fn next_frame(&mut self) {
|
||||
if let Ok(frame) = self.decoder.next_frame() {
|
||||
self.num_samples = frame.data.len();
|
||||
self.cur_frame = frame;
|
||||
} else {
|
||||
let sample = self.cur_frame.data[self.cur_sample];
|
||||
self.num_samples = 0;
|
||||
}
|
||||
self.cur_sample = 0;
|
||||
}
|
||||
}
|
||||
|
||||
impl<R: Read> Iterator for Mp3Decoder<R> {
|
||||
type Item = [i16; 2];
|
||||
|
||||
#[inline]
|
||||
#[allow(unknown_lints, clippy::branches_sharing_code)]
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if self.cur_sample >= self.num_samples {
|
||||
self.next_frame();
|
||||
}
|
||||
|
||||
if self.num_samples > 0 {
|
||||
if self.num_channels == 2 {
|
||||
let left = self.cur_frame.data[self.cur_sample];
|
||||
let right = self.cur_frame.data[self.cur_sample + 1];
|
||||
self.cur_sample += 2;
|
||||
Some([left, right])
|
||||
} else {
|
||||
let sample = self.cur_frame.data[self.cur_sample];
|
||||
self.cur_sample += 1;
|
||||
Some([sample, sample])
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<R: AsRef<[u8]> + Default> SeekableDecoder for Mp3Decoder<Cursor<R>> {
|
||||
#[inline]
|
||||
fn reset(&mut self) {
|
||||
// TODO: This is funky.
|
||||
// I want to reset the `BitStream` and `Cursor` to their initial positions,
|
||||
// but have to work around the borrowing rules of Rust.
|
||||
let mut cursor = std::mem::take(self.decoder.reader_mut());
|
||||
cursor.set_position(0);
|
||||
*self = Mp3Decoder::new(self.num_channels, self.sample_rate, cursor);
|
||||
}
|
||||
}
|
||||
|
||||
impl<R: Read> Decoder for Mp3Decoder<R> {
|
||||
#[inline]
|
||||
fn num_channels(&self) -> u8 {
|
||||
self.num_channels as u8
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn sample_rate(&self) -> u16 {
|
||||
self.sample_rate as u16
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "symphonia")]
|
||||
#[allow(dead_code)]
|
||||
pub mod symphonia {
|
||||
use crate::backend::audio::decoders::{Decoder, SeekableDecoder};
|
||||
use std::io::{Cursor, Read};
|
||||
use symphonia::{
|
||||
core::{
|
||||
self, audio, codecs, errors,
|
||||
formats::{self, FormatReader},
|
||||
io,
|
||||
},
|
||||
default::formats::Mp3Reader as SymphoniaMp3Reader,
|
||||
};
|
||||
|
||||
pub struct Mp3Decoder {
|
||||
reader: SymphoniaMp3Reader,
|
||||
decoder: Box<dyn codecs::Decoder>,
|
||||
codec_params: codecs::CodecParameters,
|
||||
sample_buf: audio::SampleBuffer<i16>,
|
||||
cur_sample: usize,
|
||||
sample_rate: u16,
|
||||
num_channels: u8,
|
||||
stream_ended: bool,
|
||||
}
|
||||
|
||||
impl Mp3Decoder {
|
||||
pub fn new<R: 'static + Read + Send>(
|
||||
num_channels: u16,
|
||||
sample_rate: u32,
|
||||
reader: R,
|
||||
) -> Self {
|
||||
let source = Box::new(io::ReadOnlySource::new(reader)) as Box<dyn io::MediaSource>;
|
||||
let source = io::MediaSourceStream::new(source, Default::default());
|
||||
let reader = SymphoniaMp3Reader::try_new(source, &Default::default()).unwrap();
|
||||
let track = reader.default_track().unwrap();
|
||||
let codec_params = track.codec_params.clone();
|
||||
let decoder = symphonia::default::get_codecs()
|
||||
.make(&codec_params, &Default::default())
|
||||
.unwrap();
|
||||
let sample_rate = codec_params
|
||||
.sample_rate
|
||||
.map_or(sample_rate as u16, |n| n as u16);
|
||||
let num_channels = codec_params
|
||||
.channels
|
||||
.map_or(num_channels as u8, |n| n.count() as u8);
|
||||
Mp3Decoder {
|
||||
reader,
|
||||
decoder,
|
||||
codec_params,
|
||||
sample_buf: audio::SampleBuffer::new(
|
||||
0,
|
||||
audio::SignalSpec::new(0, Default::default()),
|
||||
),
|
||||
cur_sample: 0,
|
||||
num_channels,
|
||||
sample_rate,
|
||||
stream_ended: false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_seekable<R: 'static + AsRef<[u8]> + Send>(
|
||||
num_channels: u16,
|
||||
sample_rate: u32,
|
||||
reader: Cursor<R>,
|
||||
) -> Self {
|
||||
let source = Box::new(reader) as Box<dyn io::MediaSource>;
|
||||
let source = io::MediaSourceStream::new(source, Default::default());
|
||||
let reader = SymphoniaMp3Reader::try_new(source, &Default::default()).unwrap();
|
||||
let track = reader.default_track().unwrap();
|
||||
let codec_params = track.codec_params.clone();
|
||||
let decoder = symphonia::default::get_codecs()
|
||||
.make(&codec_params, &Default::default())
|
||||
.unwrap();
|
||||
let sample_rate = codec_params
|
||||
.sample_rate
|
||||
.map_or(sample_rate as u16, |n| n as u16);
|
||||
let num_channels = codec_params
|
||||
.channels
|
||||
.map_or(num_channels as u8, |n| n.count() as u8);
|
||||
Mp3Decoder {
|
||||
reader,
|
||||
decoder,
|
||||
codec_params,
|
||||
sample_buf: audio::SampleBuffer::new(
|
||||
0,
|
||||
audio::SignalSpec::new(0, Default::default()),
|
||||
),
|
||||
cur_sample: 0,
|
||||
num_channels,
|
||||
sample_rate,
|
||||
stream_ended: false,
|
||||
}
|
||||
}
|
||||
|
||||
fn next_frame(&mut self) {
|
||||
if self.stream_ended {
|
||||
return;
|
||||
}
|
||||
|
||||
self.cur_sample = 0;
|
||||
while let Ok(packet) = self.reader.next_packet() {
|
||||
match self.decoder.decode(&packet) {
|
||||
Ok(decoded) => {
|
||||
if self.sample_buf.len() == 0 {
|
||||
self.sample_buf = audio::SampleBuffer::new(
|
||||
decoded.capacity() as core::units::Duration,
|
||||
*decoded.spec(),
|
||||
);
|
||||
}
|
||||
self.sample_buf.copy_interleaved_ref(decoded);
|
||||
return;
|
||||
}
|
||||
// Decode errors are not fatal.
|
||||
Err(errors::Error::DecodeError(_)) => (),
|
||||
Err(_) => break,
|
||||
}
|
||||
}
|
||||
// EOF reached.
|
||||
self.decoder.close();
|
||||
self.stream_ended = true;
|
||||
}
|
||||
}
|
||||
|
||||
impl Iterator for Mp3Decoder {
|
||||
type Item = [i16; 2];
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if self.cur_sample >= self.sample_buf.len() {
|
||||
self.next_frame();
|
||||
if self.stream_ended {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
|
||||
let sample_buf = self.sample_buf.samples();
|
||||
if self.num_channels == 2 {
|
||||
let samples: [i16; 2] =
|
||||
[sample_buf[self.cur_sample], sample_buf[self.cur_sample + 1]];
|
||||
self.cur_sample += 2;
|
||||
Some(samples)
|
||||
} else {
|
||||
let sample = sample_buf[self.cur_sample];
|
||||
self.cur_sample += 1;
|
||||
Some([sample, sample])
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl SeekableDecoder for Mp3Decoder {
|
||||
#[inline]
|
||||
fn reset(&mut self) {
|
||||
let _ = self.reader.seek(
|
||||
formats::SeekMode::Accurate,
|
||||
formats::SeekTo::TimeStamp { track_id: 0, ts: 0 },
|
||||
);
|
||||
self.cur_sample = self.sample_buf.len();
|
||||
}
|
||||
}
|
||||
|
||||
impl Decoder for Mp3Decoder {
|
||||
#[inline]
|
||||
fn num_channels(&self) -> u8 {
|
||||
self.num_channels
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn sample_rate(&self) -> u16 {
|
||||
self.sample_rate
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "minimp3")]
|
||||
impl<R: AsRef<[u8]> + Default> SeekableDecoder for Mp3Decoder<Cursor<R>> {
|
||||
#[inline]
|
||||
fn reset(&mut self) {
|
||||
// TODO: This is funky.
|
||||
// I want to reset the `BitStream` and `Cursor` to their initial positions,
|
||||
// but have to work around the borrowing rules of Rust.
|
||||
let mut cursor = std::mem::take(self.decoder.reader_mut());
|
||||
cursor.set_position(0);
|
||||
*self = Mp3Decoder::new(self.num_channels, self.sample_rate, cursor);
|
||||
}
|
||||
}
|
||||
|
||||
impl<R: Read> Decoder for Mp3Decoder<R> {
|
||||
#[inline]
|
||||
fn num_channels(&self) -> u8 {
|
||||
self.num_channels as u8
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn sample_rate(&self) -> u16 {
|
||||
self.sample_rate as u16
|
||||
}
|
||||
}
|
||||
|
|
|
@ -146,7 +146,7 @@ impl AudioMixer {
|
|||
format.sample_rate.into(),
|
||||
data,
|
||||
)),
|
||||
#[cfg(all(feature = "symphonia_mp3", not(feature = "minimp3")))]
|
||||
#[cfg(all(feature = "symphonia", not(feature = "minimp3")))]
|
||||
AudioCompression::Mp3 => Box::new(decoders::Mp3Decoder::new_seekable(
|
||||
if format.is_stereo { 2 } else { 1 },
|
||||
format.sample_rate.into(),
|
||||
|
|
Loading…
Reference in New Issue