audio: Add Nellymoser support

This commit is contained in:
relrelb 2020-12-05 22:42:57 +02:00 committed by Mike Welsh
parent 2c2a9367ae
commit 074731e1a4
6 changed files with 163 additions and 30 deletions

122
Cargo.lock generated
View File

@ -260,9 +260,9 @@ checksum = "39092a32794787acd8525ee150305ff051b0aa6cc2abaf193924f5ab05425f39"
[[package]] [[package]]
name = "bumpalo" name = "bumpalo"
version = "3.4.0" version = "3.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2e8c087f005730276d1096a652e92a8bacee2e2472bcc9715a74d2bec38b5820" checksum = "099e596ef14349721d9016f6b80dd3419ea1bf289ab9b44df8e4dfd3a005d5d9"
[[package]] [[package]]
name = "bytemuck" name = "bytemuck"
@ -534,7 +534,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "784ad0fbab4f3e9cef09f20e0aea6000ae08d2cb98ac4c0abc53df18803d702f" checksum = "784ad0fbab4f3e9cef09f20e0aea6000ae08d2cb98ac4c0abc53df18803d702f"
dependencies = [ dependencies = [
"percent-encoding", "percent-encoding",
"time 0.2.24", "time 0.2.25",
"version_check", "version_check",
] ]
@ -550,7 +550,7 @@ dependencies = [
"publicsuffix", "publicsuffix",
"serde", "serde",
"serde_json", "serde_json",
"time 0.2.24", "time 0.2.25",
"url", "url",
] ]
@ -985,9 +985,9 @@ dependencies = [
[[package]] [[package]]
name = "derivative" name = "derivative"
version = "2.1.3" version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eaed5874effa6cde088c644ddcdcb4ffd1511391c5be4fdd7a5ccd02c7e4a183" checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -1426,7 +1426,7 @@ dependencies = [
"cfg-if 1.0.0", "cfg-if 1.0.0",
"js-sys", "js-sys",
"libc", "libc",
"wasi 0.10.1+wasi-snapshot-preview1", "wasi 0.10.2+wasi-snapshot-preview1",
"wasm-bindgen", "wasm-bindgen",
] ]
@ -1745,9 +1745,9 @@ dependencies = [
[[package]] [[package]]
name = "inplace_it" name = "inplace_it"
version = "0.3.2" version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd01a2a73f2f399df96b22dc88ea687ef4d76226284e7531ae3c7ee1dc5cb534" checksum = "90953f308a79fe6d62a4643e51f848fbfddcd05975a38e69fdf4ab86a7baf7ca"
[[package]] [[package]]
name = "instant" name = "instant"
@ -1900,9 +1900,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.82" version = "0.2.84"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "89203f3fba0a3795506acaad8ebce3c80c0af93f994d5a1d7a0b1eeb23271929" checksum = "1cca32fa0182e8c0989459524dc356b8f2b5c10f1b9eb521b7d182c03cf8c5ff"
[[package]] [[package]]
name = "libflate" name = "libflate"
@ -2249,6 +2249,15 @@ version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c44922cb3dbb1c70b5e5f443d63b64363a898564d739ba5198e3a9138442868d" checksum = "c44922cb3dbb1c70b5e5f443d63b64363a898564d739ba5198e3a9138442868d"
[[package]]
name = "nellymoser-rs"
version = "0.1.0"
source = "git+https://github.com/ruffle-rs/nellymoser?branch=main#6cc9051aee2de649dcaeee4d66d14d0b14c8c0f6"
dependencies = [
"bitstream-io 1.0.0",
"rustdct",
]
[[package]] [[package]]
name = "net2" name = "net2"
version = "0.2.37" version = "0.2.37"
@ -2297,14 +2306,23 @@ dependencies = [
[[package]] [[package]]
name = "nom" name = "nom"
version = "6.0.1" version = "6.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "88034cfd6b4a0d54dd14f4a507eceee36c0b70e5a02236c4e4df571102be17f0" checksum = "ab6f70b46d6325aa300f1c7bb3d470127dfc27806d8ea6bf294ee0ce643ce2b1"
dependencies = [ dependencies = [
"memchr", "memchr",
"version_check", "version_check",
] ]
[[package]]
name = "num-complex"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "747d632c0c558b87dbabbe6a82f3b4ae03720d0646ac5b7b4dae89394be5f2c5"
dependencies = [
"num-traits",
]
[[package]] [[package]]
name = "num-derive" name = "num-derive"
version = "0.3.3" version = "0.3.3"
@ -2681,6 +2699,15 @@ dependencies = [
"output_vt100", "output_vt100",
] ]
[[package]]
name = "primal-check"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "01419cee72c1a1ca944554e23d83e483e1bccf378753344e881de28b5487511d"
dependencies = [
"num-integer",
]
[[package]] [[package]]
name = "proc-macro-crate" name = "proc-macro-crate"
version = "0.1.5" version = "0.1.5"
@ -2961,6 +2988,7 @@ dependencies = [
"json", "json",
"log", "log",
"minimp3", "minimp3",
"nellymoser-rs",
"num-traits", "num-traits",
"num_enum 0.5.1", "num_enum 0.5.1",
"percent-encoding", "percent-encoding",
@ -3156,6 +3184,29 @@ dependencies = [
"semver", "semver",
] ]
[[package]]
name = "rustdct"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fadcb505b98aa64da1dadb1498b912e3642aae4606623cb3ae952cd8da33f80d"
dependencies = [
"rustfft",
]
[[package]]
name = "rustfft"
version = "5.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2af893d9cfb30d3d2f2ac4bd2a071232143558e06e791dc768179f0089f68f8"
dependencies = [
"num-complex",
"num-integer",
"num-traits",
"primal-check",
"strength_reduce",
"transpose",
]
[[package]] [[package]]
name = "rustls" name = "rustls"
version = "0.19.0" version = "0.19.0"
@ -3478,6 +3529,12 @@ dependencies = [
"lock_api", "lock_api",
] ]
[[package]]
name = "strength_reduce"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a3ff2f71c82567c565ba4b3009a9350a96a7269eaa4001ebedae926230bc2254"
[[package]] [[package]]
name = "strsim" name = "strsim"
version = "0.9.3" version = "0.9.3"
@ -3539,13 +3596,12 @@ dependencies = [
[[package]] [[package]]
name = "tar" name = "tar"
version = "0.4.30" version = "0.4.32"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "489997b7557e9a43e192c527face4feacc78bfbe6eed67fd55c4c9e381cba290" checksum = "0313546c01d59e29be4f09687bcb4fb6690cec931cc3607b6aec7a0e417f4cc6"
dependencies = [ dependencies = [
"filetime", "filetime",
"libc", "libc",
"redox_syscall 0.1.57",
"xattr", "xattr",
] ]
@ -3599,11 +3655,11 @@ dependencies = [
[[package]] [[package]]
name = "thread_local" name = "thread_local"
version = "1.1.0" version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb9bc092d0d51e76b2b19d9d85534ffc9ec2db959a2523cdae0697e2972cd447" checksum = "d8208a331e1cb318dd5bd76951d2b8fc48ca38a69f5f4e4af1b6a9f8c6236915"
dependencies = [ dependencies = [
"lazy_static", "once_cell",
] ]
[[package]] [[package]]
@ -3635,9 +3691,9 @@ dependencies = [
[[package]] [[package]]
name = "time" name = "time"
version = "0.2.24" version = "0.2.25"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "273d3ed44dca264b0d6b3665e8d48fb515042d42466fad93d2a45b90ec4058f7" checksum = "1195b046942c221454c2539395f85413b33383a067449d78aab2b7b052a142f7"
dependencies = [ dependencies = [
"const_fn", "const_fn",
"libc", "libc",
@ -3682,9 +3738,9 @@ dependencies = [
[[package]] [[package]]
name = "tinyvec" name = "tinyvec"
version = "1.1.0" version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ccf8dbc19eb42fba10e8feaaec282fb50e2c14b2726d6301dbfeed0f73306a6f" checksum = "317cca572a0e89c3ce0ca1f1bdc9369547fe318a683418e42ac8f59d14701023"
dependencies = [ dependencies = [
"tinyvec_macros", "tinyvec_macros",
] ]
@ -3747,6 +3803,16 @@ dependencies = [
"tracing", "tracing",
] ]
[[package]]
name = "transpose"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3311ef71dea6a1fd6bf5bfc10ec5b4bef6174048f6b481dbc6ce915ff48c0a0"
dependencies = [
"num-integer",
"strength_reduce",
]
[[package]] [[package]]
name = "ttf-parser" name = "ttf-parser"
version = "0.6.2" version = "0.6.2"
@ -3910,9 +3976,9 @@ checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
[[package]] [[package]]
name = "wasi" name = "wasi"
version = "0.10.1+wasi-snapshot-preview1" version = "0.10.2+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93c6c3420963c5c64bca373b25e77acb562081b9bb4dd5bb864187742186cea9" checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
[[package]] [[package]]
name = "wasm-bindgen" name = "wasm-bindgen"
@ -4127,9 +4193,9 @@ dependencies = [
[[package]] [[package]]
name = "weezl" name = "weezl"
version = "0.1.3" version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3e2bb9fc8309084dd7cd651336673844c1d47f8ef6d2091ec160b27f5c4aa277" checksum = "4a32b378380f4e9869b22f0b5177c68a5519f03b3454fde0b291455ddbae266c"
[[package]] [[package]]
name = "wgpu" name = "wgpu"
@ -4344,7 +4410,7 @@ version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3a9a231574ae78801646617cefd13bfe94be907c0e4fa979cfd8b770aa3c5d08" checksum = "3a9a231574ae78801646617cefd13bfe94be907c0e4fa979cfd8b770aa3c5d08"
dependencies = [ dependencies = [
"nom 6.0.1", "nom 6.1.0",
] ]
[[package]] [[package]]

View File

@ -36,6 +36,7 @@ instant = "0.1"
encoding_rs = "0.8.26" encoding_rs = "0.8.26"
rand = { version = "0.8.3", features = ["std", "small_rng"], default-features = false } rand = { version = "0.8.3", features = ["std", "small_rng"], default-features = false }
serde = { version = "1.0.123", features = ["derive"], optional = true } serde = { version = "1.0.123", features = ["derive"], optional = true }
nellymoser-rs = { git = "https://github.com/ruffle-rs/nellymoser", branch = "main" }
[dependencies.jpeg-decoder] [dependencies.jpeg-decoder]
version = "0.1.22" version = "0.1.22"

View File

@ -2,10 +2,12 @@
mod adpcm; mod adpcm;
mod mp3; mod mp3;
mod nellymoser;
mod pcm; mod pcm;
pub use adpcm::AdpcmDecoder; pub use adpcm::AdpcmDecoder;
pub use mp3::Mp3Decoder; pub use mp3::Mp3Decoder;
pub use nellymoser::NellymoserDecoder;
pub use pcm::PcmDecoder; pub use pcm::PcmDecoder;
use crate::tag_utils::SwfSlice; use crate::tag_utils::SwfSlice;
@ -56,6 +58,9 @@ pub fn make_decoder<'a, R: 'a + Send + Read>(
format.sample_rate.into(), format.sample_rate.into(),
data, data,
)), )),
AudioCompression::Nellymoser => {
Box::new(NellymoserDecoder::new(data, format.sample_rate.into()))
}
_ => { _ => {
let msg = format!( let msg = format!(
"make_decoder: Unhandled audio compression {:?}", "make_decoder: Unhandled audio compression {:?}",

View File

@ -0,0 +1,42 @@
use super::{Decoder, SeekableDecoder};
use std::io::{Cursor, Read};
pub struct NellymoserDecoder<R: Read> {
decoder: nellymoser_rs::Decoder<R>,
}
impl<R: Read> NellymoserDecoder<R> {
pub fn new(reader: R, sample_rate: u32) -> Self {
Self {
decoder: nellymoser_rs::Decoder::new(reader, sample_rate),
}
}
}
impl<R: Read> Iterator for NellymoserDecoder<R> {
type Item = [i16; 2];
fn next(&mut self) -> Option<Self::Item> {
let sample = self.decoder.next()? as i16;
Some([sample, sample])
}
}
impl<R: Read> Decoder for NellymoserDecoder<R> {
#[inline]
fn num_channels(&self) -> u8 {
1
}
#[inline]
fn sample_rate(&self) -> u16 {
self.decoder.sample_rate() as u16
}
}
impl<R: AsRef<[u8]>> SeekableDecoder for NellymoserDecoder<Cursor<R>> {
#[inline]
fn reset(&mut self) {
self.decoder.reset();
}
}

View File

@ -1,7 +1,7 @@
use cpal::traits::{DeviceTrait, HostTrait, StreamTrait}; use cpal::traits::{DeviceTrait, HostTrait, StreamTrait};
use generational_arena::Arena; use generational_arena::Arena;
use ruffle_core::backend::audio::decoders::{ use ruffle_core::backend::audio::decoders::{
self, AdpcmDecoder, Mp3Decoder, PcmDecoder, SeekableDecoder, self, AdpcmDecoder, Mp3Decoder, NellymoserDecoder, PcmDecoder, SeekableDecoder,
}; };
use ruffle_core::backend::audio::{ use ruffle_core::backend::audio::{
swf, AudioBackend, SoundHandle, SoundInstanceHandle, SoundTransform, swf, AudioBackend, SoundHandle, SoundInstanceHandle, SoundTransform,
@ -167,6 +167,9 @@ impl CpalAudioBackend {
format.sample_rate.into(), format.sample_rate.into(),
data, data,
)), )),
AudioCompression::Nellymoser => {
Box::new(NellymoserDecoder::new(data, format.sample_rate.into()))
}
_ => { _ => {
let msg = format!( let msg = format!(
"start_stream: Unhandled audio compression {:?}", "start_stream: Unhandled audio compression {:?}",

View File

@ -1,7 +1,7 @@
use fnv::FnvHashMap; use fnv::FnvHashMap;
use generational_arena::Arena; use generational_arena::Arena;
use ruffle_core::backend::audio::{ use ruffle_core::backend::audio::{
decoders::{AdpcmDecoder, Mp3Decoder}, decoders::{AdpcmDecoder, Mp3Decoder, NellymoserDecoder},
swf::{self, AudioCompression}, swf::{self, AudioCompression},
AudioBackend, PreloadStreamHandle, SoundHandle, SoundInstanceHandle, SoundTransform, AudioBackend, PreloadStreamHandle, SoundHandle, SoundInstanceHandle, SoundTransform,
}; };
@ -452,6 +452,10 @@ impl WebAudioBackend {
sound.format.sample_rate.into(), sound.format.sample_rate.into(),
std::io::Cursor::new(audio_data.to_vec()), //&sound.data[..] std::io::Cursor::new(audio_data.to_vec()), //&sound.data[..]
)), )),
AudioCompression::Nellymoser => Box::new(NellymoserDecoder::new(
std::io::Cursor::new(audio_data.to_vec()),
sound.format.sample_rate.into(),
)),
compression => { compression => {
return Err(format!("Unimplemented codec: {:?}", compression).into()) return Err(format!("Unimplemented codec: {:?}", compression).into())
} }
@ -633,6 +637,14 @@ impl WebAudioBackend {
} }
} }
} }
AudioCompression::Nellymoser => {
let decoder = NellymoserDecoder::new(audio_data, format.sample_rate.into());
for frame in decoder {
let (l, r) = (frame[0], frame[1]);
self.left_samples.push(f32::from(l) / 32767.0);
self.right_samples.push(f32::from(r) / 32767.0);
}
}
compression => return Err(format!("Unimplemented codec: {:?}", compression).into()), compression => return Err(format!("Unimplemented codec: {:?}", compression).into()),
} }
@ -873,6 +885,10 @@ impl AudioBackend for WebAudioBackend {
stream.adpcm_block_offsets.push(stream.audio_data.len()); stream.adpcm_block_offsets.push(stream.audio_data.len());
stream.audio_data.extend_from_slice(audio_data); stream.audio_data.extend_from_slice(audio_data);
} }
AudioCompression::Nellymoser => {
stream.num_sample_frames += stream.samples_per_block;
stream.audio_data.extend_from_slice(audio_data);
}
_ => { _ => {
// TODO: This is a guess and will vary slightly from block to block! // TODO: This is a guess and will vary slightly from block to block!
stream.num_sample_frames += stream.samples_per_block; stream.num_sample_frames += stream.samples_per_block;