diff --git a/Cargo.lock b/Cargo.lock index 8a9d1497df45f4e9ebf6baa9e8d19c54f81ecbf7..e62167ed8c185a1e0cf588fd99b1eec85b25b9a7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -50,11 +50,11 @@ dependencies = [ [[package]] name = "audioipc" -version = "0.2.2" +version = "0.2.3" dependencies = [ "bincode 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "cubeb 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cubeb 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -71,10 +71,10 @@ dependencies = [ [[package]] name = "audioipc-client" -version = "0.3.0" +version = "0.4.0" dependencies = [ - "audioipc 0.2.2", - "cubeb-backend 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "audioipc 0.2.3", + "cubeb-backend 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "foreign-types 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -88,9 +88,9 @@ dependencies = [ name = "audioipc-server" version = "0.2.2" dependencies = [ - "audioipc 0.2.2", + "audioipc 0.2.3", "bytes 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "cubeb 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cubeb 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", "lazycell 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -406,34 +406,34 @@ dependencies = [ [[package]] name = "cubeb" -version = "0.4.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cubeb-core 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "cubeb-core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "cubeb-backend" -version = "0.4.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cubeb-core 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "cubeb-core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "cubeb-core" -version = "0.4.4" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "cubeb-sys 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cubeb-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "cubeb-pulse" -version = "0.1.1" +version = "0.2.0" dependencies = [ - "cubeb-backend 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cubeb-backend 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "pulse 0.2.0", "pulse-ffi 0.1.0", "semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -441,7 +441,7 @@ dependencies = [ [[package]] name = "cubeb-sys" -version = "0.4.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", @@ -724,11 +724,11 @@ dependencies = [ name = "gkrust-shared" version = "0.1.0" dependencies = [ - "audioipc-client 0.3.0", + "audioipc-client 0.4.0", "audioipc-server 0.2.2", "cose-c 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "cubeb-pulse 0.1.1", - "cubeb-sys 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cubeb-pulse 0.2.0", + "cubeb-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "encoding_c 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "encoding_glue 0.1.0", "geckoservo 0.0.1", @@ -2222,10 +2222,10 @@ dependencies = [ "checksum cssparser-macros 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "079adec4af52bb5275eadd004292028c79eb3c5f5b4ee8086a36d4197032f6df" "checksum cstr 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b6557bdb1dc9647eae1cf7f5601b14cd45fc3c7ccf2df618387416fe542da6ea" "checksum cstr-macros 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f9f316203d1ea36f4f18316822806f6999aa3dc5ed1adf51e35b77e3b3933d78" -"checksum cubeb 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ed237804b9799d1c29089e6cab3f4b7160186179981a61865feff13d55a902f8" -"checksum cubeb-backend 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4f6d8f189a1cf9cce9aec45eb0aeb1d221514d788b89a1cd6bc2b76110ee4d81" -"checksum cubeb-core 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "7dcedc8ffadc0481f1dfbdeb315e7d7ae9afe6a70815d22efcca8e0bd2ba89e0" -"checksum cubeb-sys 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fab28c0e152330f74bcbec1572c374397458957d5ad50605879352ec562f41aa" +"checksum cubeb 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7923bed2d5a1a64ba0c3e8b6badc360508ba488d1f2f59f16a688802e755bb85" +"checksum cubeb-backend 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fdcac95519416d9ec814db2dc40e6293e7da25b906023d93f48b87f0587ab138" +"checksum cubeb-core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "169d9a36f5daa60f9c4597905132aef056cf62693addd4a3421492853ccad565" +"checksum cubeb-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e405ad4dff2c1a7cbfa6998e5925e8ceafe900feeacfcad35a3e3790bea0f2aa" "checksum darling 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d3effd06d4057f275cb7858889f4952920bab78dd8ff0f6e7dfe0c8d2e67ed89" "checksum darling_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "167dd3e235c2f1da16a635c282630452cdf49191eb05711de1bcd1d3d5068c00" "checksum darling_macro 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c53edaba455f6073a10c27c72440860eb3f60444f8c8660a391032eeae744d82" diff --git a/third_party/rust/cubeb-backend/.cargo-checksum.json b/third_party/rust/cubeb-backend/.cargo-checksum.json index 6e43cad87faa90cac36b9878b429cae9e3a83080..edae3f1315a8b29d3a96904968e52ca1babefeb8 100644 --- a/third_party/rust/cubeb-backend/.cargo-checksum.json +++ b/third_party/rust/cubeb-backend/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"d3e2dd5ca6196dcab0d81eaa4971cb43dd0200fbaa7be17b46290a9b9405c3d8","LICENSE":"8c044baa5d883274736eeece0b955249076c2697b826e576fce59496235b2cf5","src/capi.rs":"a1f0b172d313459a4d44d3897a76cadc41be6485d8739660c0a421967a9bed80","src/lib.rs":"94b80747ae1037423a2281f2572fc6d15cd7702417974ae3730adccd71c7a300","src/log.rs":"af1d787754706e34d6b8f4ac88aa89078ae9a16970b168ad8dc17cc4180688c2","src/ops.rs":"0af019afdf8c79e27a6f56ecccf597a70f6fdfe3b3c26cdbb16808cd0c453602","src/traits.rs":"93b1499e767d9c279d60887d049d59d2f206938d397298bf0199a55b817a0441","tests/test_capi.rs":"2938826a8c4df04351cba5ac1da5d228329e307300ea40bf1e9f4bba1f2e5b2d"},"package":"4f6d8f189a1cf9cce9aec45eb0aeb1d221514d788b89a1cd6bc2b76110ee4d81"} \ No newline at end of file +{"files":{"Cargo.toml":"4bae03732c4f490b3c7dbc07d2eabccf5d0f6b5ab2c1c74d592cc7609c9d8d8e","LICENSE":"8c044baa5d883274736eeece0b955249076c2697b826e576fce59496235b2cf5","src/capi.rs":"300e76bd3901de540b21a2cfc8d15dbcd1b2940d5fbb517fc5fe568af2ec2775","src/lib.rs":"94b80747ae1037423a2281f2572fc6d15cd7702417974ae3730adccd71c7a300","src/log.rs":"af1d787754706e34d6b8f4ac88aa89078ae9a16970b168ad8dc17cc4180688c2","src/ops.rs":"55cbf9bdccdd854834eba72e8bde3e59a9a4193e65209769a1a6e0d8a320b8f6","src/traits.rs":"1a6e3401bb25088d355041704bd89099d62b51eda94da177e7e860646c52b955","tests/test_capi.rs":"9d949cbdb1c19e229ce4f652999a058c283cf7d5a882a669dbca08b71ac2fb62"},"package":"fdcac95519416d9ec814db2dc40e6293e7da25b906023d93f48b87f0587ab138"} \ No newline at end of file diff --git a/third_party/rust/cubeb-backend/Cargo.toml b/third_party/rust/cubeb-backend/Cargo.toml index d4eebb605f037c36c7dec1c4198beb8251db2a68..cb9ebe252fd15f464fa5dca4235a11ca99815d24 100644 --- a/third_party/rust/cubeb-backend/Cargo.toml +++ b/third_party/rust/cubeb-backend/Cargo.toml @@ -12,7 +12,7 @@ [package] name = "cubeb-backend" -version = "0.4.1" +version = "0.5.0" authors = ["Dan Glastonbury <dglastonbury@mozilla.com>"] description = "Bindings to libcubeb internals to facilitate implementing cubeb backends in rust.\n" homepage = "https://github.com/djg/cubeb-rs" @@ -21,7 +21,7 @@ categories = ["api-bindings"] license = "ISC" repository = "https://github.com/djg/cubeb-rs" [dependencies.cubeb-core] -version = "0.4.1" +version = "0.5.0" [features] gecko-in-tree = ["cubeb-core/gecko-in-tree"] diff --git a/third_party/rust/cubeb-backend/src/capi.rs b/third_party/rust/cubeb-backend/src/capi.rs index 190913f9681ca60be724406e4a3070d5070d0955..a827763d7500f27eaab760233602c5641daee506 100644 --- a/third_party/rust/cubeb-backend/src/capi.rs +++ b/third_party/rust/cubeb-backend/src/capi.rs @@ -38,8 +38,6 @@ macro_rules! capi_new( get_max_channel_count: Some($crate::capi::capi_get_max_channel_count::<$ctx>), get_min_latency: Some($crate::capi::capi_get_min_latency::<$ctx>), get_preferred_sample_rate: Some($crate::capi::capi_get_preferred_sample_rate::<$ctx>), - get_preferred_channel_layout: - Some($crate::capi::capi_get_preferred_channel_layout::<$ctx>), enumerate_devices: Some($crate::capi::capi_enumerate_devices::<$ctx>), device_collection_destroy: Some($crate::capi::capi_device_collection_destroy::<$ctx>), destroy: Some($crate::capi::capi_destroy::<$ctx>), @@ -109,16 +107,6 @@ pub unsafe extern "C" fn capi_get_preferred_sample_rate<CTX: ContextOps>( ffi::CUBEB_OK } -pub unsafe extern "C" fn capi_get_preferred_channel_layout<CTX: ContextOps>( - c: *mut ffi::cubeb, - layout: *mut ffi::cubeb_channel_layout, -) -> c_int { - let ctx = &mut *(c as *mut CTX); - - *layout = _try!(ctx.preferred_channel_layout()) as _; - ffi::CUBEB_OK -} - pub unsafe extern "C" fn capi_enumerate_devices<CTX: ContextOps>( c: *mut ffi::cubeb, devtype: ffi::cubeb_device_type, diff --git a/third_party/rust/cubeb-backend/src/ops.rs b/third_party/rust/cubeb-backend/src/ops.rs index c68e9b8ceef58dce3c603d31d083907acf7ae414..9d4193e652adfbccc95f1f80b6790bfafff736f1 100644 --- a/third_party/rust/cubeb-backend/src/ops.rs +++ b/third_party/rust/cubeb-backend/src/ops.rs @@ -25,10 +25,6 @@ pub struct Ops { >, pub get_preferred_sample_rate: Option<unsafe extern "C" fn(context: *mut ffi::cubeb, rate: *mut u32) -> c_int>, - pub get_preferred_channel_layout: Option< - unsafe extern "C" fn(context: *mut ffi::cubeb, layout: *mut ffi::cubeb_channel_layout) - -> c_int, - >, pub enumerate_devices: Option< unsafe extern "C" fn( context: *mut ffi::cubeb, diff --git a/third_party/rust/cubeb-backend/src/traits.rs b/third_party/rust/cubeb-backend/src/traits.rs index d33f584506243e230c60d5f4af1110bad8498d82..8f4e0cd8a763b5c868f41108f47fbf447bc9e12e 100644 --- a/third_party/rust/cubeb-backend/src/traits.rs +++ b/third_party/rust/cubeb-backend/src/traits.rs @@ -3,8 +3,8 @@ // This program is made available under an ISC-style license. See the // accompanying file LICENSE for details. -use cubeb_core::{ChannelLayout, Context, DeviceCollectionRef, DeviceId, DeviceRef, DeviceType, - Result, Stream, StreamParams, StreamParamsRef}; +use cubeb_core::{Context, DeviceCollectionRef, DeviceId, DeviceRef, DeviceType, Result, Stream, + StreamParams, StreamParamsRef}; use ffi; use std::ffi::CStr; use std::os::raw::c_void; @@ -15,7 +15,6 @@ pub trait ContextOps { fn max_channel_count(&mut self) -> Result<u32>; fn min_latency(&mut self, params: StreamParams) -> Result<u32>; fn preferred_sample_rate(&mut self) -> Result<u32>; - fn preferred_channel_layout(&mut self) -> Result<ChannelLayout>; fn enumerate_devices( &mut self, devtype: DeviceType, diff --git a/third_party/rust/cubeb-backend/tests/test_capi.rs b/third_party/rust/cubeb-backend/tests/test_capi.rs index 2b2f43bb5aade5c17aa69699fe17677acbc56871..deda864f618086d1f8cd7b0f3e3cd9090e93579e 100644 --- a/third_party/rust/cubeb-backend/tests/test_capi.rs +++ b/third_party/rust/cubeb-backend/tests/test_capi.rs @@ -8,9 +8,8 @@ #[macro_use] extern crate cubeb_backend; -use cubeb_backend::{ffi, ChannelLayout, Context, ContextOps, DeviceCollectionRef, DeviceId, - DeviceRef, DeviceType, Ops, Result, Stream, StreamOps, StreamParams, - StreamParamsRef}; +use cubeb_backend::{ffi, Context, ContextOps, DeviceCollectionRef, DeviceId, DeviceRef, + DeviceType, Ops, Result, Stream, StreamOps, StreamParams, StreamParamsRef}; use std::ffi::CStr; use std::os::raw::c_void; use std::ptr; @@ -41,9 +40,6 @@ impl ContextOps for TestContext { fn preferred_sample_rate(&mut self) -> Result<u32> { Ok(0u32) } - fn preferred_channel_layout(&mut self) -> Result<ChannelLayout> { - Ok(ChannelLayout::Mono as _) - } fn enumerate_devices( &mut self, _devtype: DeviceType, @@ -171,17 +167,6 @@ fn test_ops_context_preferred_sample_rate() { assert_eq!(rate, 0); } -#[test] -fn test_ops_context_preferred_channel_layout() { - let c: *mut ffi::cubeb = ptr::null_mut(); - let mut layout = ChannelLayout::Undefined; - assert_eq!( - unsafe { OPS.get_preferred_channel_layout.unwrap()(c, &mut layout as *mut _ as *mut _) }, - ffi::CUBEB_OK - ); - assert_eq!(layout, ChannelLayout::Mono); -} - #[test] fn test_ops_context_enumerate_devices() { let c: *mut ffi::cubeb = ptr::null_mut(); diff --git a/third_party/rust/cubeb-core/.cargo-checksum.json b/third_party/rust/cubeb-core/.cargo-checksum.json index b3cbb16c1de6d917509e681bbf856eca6c0f646b..eb67c4663bde6decaafc9b2d1416bfa26e6bc72e 100644 --- a/third_party/rust/cubeb-core/.cargo-checksum.json +++ b/third_party/rust/cubeb-core/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"f9beebeb032911cbb1856ad4278a61b2d58105e89e8a15971a2ec4ac69d8d367","LICENSE":"8c044baa5d883274736eeece0b955249076c2697b826e576fce59496235b2cf5","src/builders.rs":"f4f4764697c65c08bfbf156005c5f40a43bb8b9ae72a4986dc8b5252537de7ec","src/channel.rs":"bc1e970d9a32ffa9f51f285bce511c20f33c4dd56add27d0bb27273e6483aa90","src/context.rs":"39f643da2716c003c9a190a6138a7d5f8a99aca05df463a2dad00938c9cf4067","src/device.rs":"490d2e94ecae1e149476c2e8d9aa03c4163987c3efccc962b2d3123e4c09dedf","src/device_collection.rs":"f6d0c1628cc34b524f86b84a1e1c79971c3f64ebc4ac64eeb10a1330bbe8c238","src/error.rs":"855ff3d3597753f832ecea00e403c71129afd80db3d39456cf3e23cb9aeb91e7","src/ffi_types.rs":"d815d7a80895b5e86907e708dc0219fca4ac4668cde114afee434e7d702a145d","src/format.rs":"5513c537a72af1c222ee7c30b26d4de9d368a69772688b95d88b1a99f6892d5c","src/lib.rs":"6010a5e20b836b8e5c9fba382fde819e6f3c18c0ec2016e6e7e118eabedbcd51","src/log.rs":"c46bae3472043fd076df3229c3421d948a87fae8495c1524b41ab2d8608f612a","src/stream.rs":"28fce5a49384437f5106b0575aebfb09d7b1875e4adb53d57102d79666bbab43","src/try_call.rs":"231bfa3f3448f7531427bb228beb2bcd4fd711f0b13d2d8f412af013470f40c7","src/util.rs":"308cfbaacd615ff600e74415c52daeef007fff34a4a0648a73c0042f6067f84f"},"package":"7dcedc8ffadc0481f1dfbdeb315e7d7ae9afe6a70815d22efcca8e0bd2ba89e0"} \ No newline at end of file +{"files":{"Cargo.toml":"5cc2013bd01c4f844a0056af1b3a484f39c77b8aeac03c3f15e4598caf9625a9","LICENSE":"8c044baa5d883274736eeece0b955249076c2697b826e576fce59496235b2cf5","src/builders.rs":"ca97e3a3d1f3fc451c17851c8538964ec67f3964dfe29e902d904ee7445becca","src/channel.rs":"c8d5a76ef3ecdd96cd4de516e3d4d139bbb83c4690d1c3f5fd07fffc47be51f1","src/context.rs":"09625b75070ec88d566a907ab2e574e2d85df4c6df295f798b3372df2cdc8f7a","src/device.rs":"490d2e94ecae1e149476c2e8d9aa03c4163987c3efccc962b2d3123e4c09dedf","src/device_collection.rs":"f6d0c1628cc34b524f86b84a1e1c79971c3f64ebc4ac64eeb10a1330bbe8c238","src/error.rs":"855ff3d3597753f832ecea00e403c71129afd80db3d39456cf3e23cb9aeb91e7","src/ffi_types.rs":"d815d7a80895b5e86907e708dc0219fca4ac4668cde114afee434e7d702a145d","src/format.rs":"5513c537a72af1c222ee7c30b26d4de9d368a69772688b95d88b1a99f6892d5c","src/lib.rs":"6010a5e20b836b8e5c9fba382fde819e6f3c18c0ec2016e6e7e118eabedbcd51","src/log.rs":"c46bae3472043fd076df3229c3421d948a87fae8495c1524b41ab2d8608f612a","src/stream.rs":"cd8dccefe88c584264af908169f566b1f65fdab79792a9abf7e38342ca9b8e62","src/try_call.rs":"231bfa3f3448f7531427bb228beb2bcd4fd711f0b13d2d8f412af013470f40c7","src/util.rs":"308cfbaacd615ff600e74415c52daeef007fff34a4a0648a73c0042f6067f84f"},"package":"169d9a36f5daa60f9c4597905132aef056cf62693addd4a3421492853ccad565"} \ No newline at end of file diff --git a/third_party/rust/cubeb-core/Cargo.toml b/third_party/rust/cubeb-core/Cargo.toml index 340ef0505ea68bb85b34f4f988ba2df1adebce5c..ac35932895ab48668881fe54896d1288ea152a6d 100644 --- a/third_party/rust/cubeb-core/Cargo.toml +++ b/third_party/rust/cubeb-core/Cargo.toml @@ -12,7 +12,7 @@ [package] name = "cubeb-core" -version = "0.4.4" +version = "0.5.0" authors = ["Dan Glastonbury <dglastonbury@mozilla.com>"] description = "Common types and definitions for cubeb rust and C bindings. Not intended for direct use.\n" homepage = "https://github.com/djg/cubeb-rs" @@ -24,7 +24,7 @@ repository = "https://github.com/djg/cubeb-rs" version = "1.0" [dependencies.cubeb-sys] -version = "0.4.1" +version = "0.5.0" [features] gecko-in-tree = ["cubeb-sys/gecko-in-tree"] diff --git a/third_party/rust/cubeb-core/src/builders.rs b/third_party/rust/cubeb-core/src/builders.rs index e75babb5c7f2374fdb8258ba1d13207c12404a33..b3a1ab2e17d195b7461b55bde127541bf9a8ce13 100644 --- a/third_party/rust/cubeb-core/src/builders.rs +++ b/third_party/rust/cubeb-core/src/builders.rs @@ -117,24 +117,27 @@ mod tests { ) ); check!( - Undefined, - DualMono, - DualMonoLfe, - Mono, - MonoLfe, - Stereo, - StereoLfe, - Layout3F, - Layout3FLfe, - Layout2F1, - Layout2F1Lfe, - Layout3F1, - Layout3F1Lfe, - Layout2F2, - Layout2F2Lfe, - Layout3F2, - Layout3F3RLfe, - Layout3F4Lfe + UNDEFINED, + MONO, + MONO_LFE, + STEREO, + STEREO_LFE, + _3F, + _3F_LFE, + _2F1, + _2F1_LFE, + _3F1, + _3F1_LFE, + _2F2, + _2F2_LFE, + QUAD, + QUAD_LFE, + _3F2, + _3F2_LFE, + _3F2_BACK, + _3F2_LFE_BACK, + _3F3R_LFE, + _3F4_LFE ); } @@ -210,25 +213,27 @@ mod tests { )* ) ); - check!(Undefined => CUBEB_LAYOUT_UNDEFINED, - DualMono => CUBEB_LAYOUT_DUAL_MONO, - DualMonoLfe => CUBEB_LAYOUT_DUAL_MONO_LFE, - Mono => CUBEB_LAYOUT_MONO, - MonoLfe => CUBEB_LAYOUT_MONO_LFE, - Stereo => CUBEB_LAYOUT_STEREO, - StereoLfe => CUBEB_LAYOUT_STEREO_LFE, - Layout3F => CUBEB_LAYOUT_3F, - Layout3FLfe => CUBEB_LAYOUT_3F_LFE, - Layout2F1 => CUBEB_LAYOUT_2F1, - Layout2F1Lfe => CUBEB_LAYOUT_2F1_LFE, - Layout3F1 => CUBEB_LAYOUT_3F1, - Layout3F1Lfe => CUBEB_LAYOUT_3F1_LFE, - Layout2F2 => CUBEB_LAYOUT_2F2, - Layout2F2Lfe => CUBEB_LAYOUT_2F2_LFE, - Layout3F2 => CUBEB_LAYOUT_3F2, - Layout3F2Lfe => CUBEB_LAYOUT_3F2_LFE, - Layout3F3RLfe => CUBEB_LAYOUT_3F3R_LFE, - Layout3F4Lfe => CUBEB_LAYOUT_3F4_LFE); + check!(UNDEFINED => CUBEB_LAYOUT_UNDEFINED, + MONO => CUBEB_LAYOUT_MONO, + MONO_LFE => CUBEB_LAYOUT_MONO_LFE, + STEREO => CUBEB_LAYOUT_STEREO, + STEREO_LFE => CUBEB_LAYOUT_STEREO_LFE, + _3F => CUBEB_LAYOUT_3F, + _3F_LFE => CUBEB_LAYOUT_3F_LFE, + _2F1 => CUBEB_LAYOUT_2F1, + _2F1_LFE=> CUBEB_LAYOUT_2F1_LFE, + _3F1 => CUBEB_LAYOUT_3F1, + _3F1_LFE => CUBEB_LAYOUT_3F1_LFE, + _2F2 => CUBEB_LAYOUT_2F2, + _2F2_LFE => CUBEB_LAYOUT_2F2_LFE, + QUAD => CUBEB_LAYOUT_QUAD, + QUAD_LFE => CUBEB_LAYOUT_QUAD_LFE, + _3F2 => CUBEB_LAYOUT_3F2, + _3F2_LFE => CUBEB_LAYOUT_3F2_LFE, + _3F2_BACK => CUBEB_LAYOUT_3F2_BACK, + _3F2_LFE_BACK => CUBEB_LAYOUT_3F2_LFE_BACK, + _3F3R_LFE => CUBEB_LAYOUT_3F3R_LFE, + _3F4_LFE => CUBEB_LAYOUT_3F4_LFE); } #[test] diff --git a/third_party/rust/cubeb-core/src/channel.rs b/third_party/rust/cubeb-core/src/channel.rs index fc670387ba339b3db1ccaa8c06c262a8675e3c12..8602f4ce6fccf055f125da31865b539c40355d85 100644 --- a/third_party/rust/cubeb-core/src/channel.rs +++ b/third_party/rust/cubeb-core/src/channel.rs @@ -5,101 +5,147 @@ use ffi; -/// SMPTE channel layout (also known as wave order) -/// -/// --------------------------------------------------- -/// Name | Channels -/// --------------------------------------------------- -/// DUAL-MONO | L R -/// DUAL-MONO-LFE | L R LFE -/// MONO | M -/// MONO-LFE | M LFE -/// STEREO | L R -/// STEREO-LFE | L R LFE -/// 3F | L R C -/// 3F-LFE | L R C LFE -/// 2F1 | L R S -/// 2F1-LFE | L R LFE S -/// 3F1 | L R C S -/// 3F1-LFE | L R C LFE S -/// 2F2 | L R LS RS -/// 2F2-LFE | L R LFE LS RS -/// 3F2 | L R C LS RS -/// 3F2-LFE | L R C LFE LS RS -/// 3F3R-LFE | L R C LFE RC LS RS -/// 3F4-LFE | L R C LFE RLS RRS LS RS -/// --------------------------------------------------- -/// -/// The abbreviation of channel name is defined in following table: -/// --------------------------- -/// Abbr | Channel name -/// --------------------------- -/// M | Mono -/// L | Left -/// R | Right -/// C | Center -/// LS | Left Surround -/// RS | Right Surround -/// RLS | Rear Left Surround -/// RC | Rear Center -/// RRS | Rear Right Surround -/// LFE | Low Frequency Effects -/// --------------------------- -#[cfg_attr(target_env = "msvc", repr(i32))] -#[cfg_attr(not(target_env = "msvc"), repr(u32))] -#[derive(Clone, Copy, Debug, Eq, PartialEq)] -pub enum ChannelLayout { - Undefined = ffi::CUBEB_LAYOUT_UNDEFINED, - DualMono = ffi::CUBEB_LAYOUT_DUAL_MONO, - DualMonoLfe = ffi::CUBEB_LAYOUT_DUAL_MONO_LFE, - Mono = ffi::CUBEB_LAYOUT_MONO, - MonoLfe = ffi::CUBEB_LAYOUT_MONO_LFE, - Stereo = ffi::CUBEB_LAYOUT_STEREO, - StereoLfe = ffi::CUBEB_LAYOUT_STEREO_LFE, - Layout3F = ffi::CUBEB_LAYOUT_3F, - Layout3FLfe = ffi::CUBEB_LAYOUT_3F_LFE, - Layout2F1 = ffi::CUBEB_LAYOUT_2F1, - Layout2F1Lfe = ffi::CUBEB_LAYOUT_2F1_LFE, - Layout3F1 = ffi::CUBEB_LAYOUT_3F1, - Layout3F1Lfe = ffi::CUBEB_LAYOUT_3F1_LFE, - Layout2F2 = ffi::CUBEB_LAYOUT_2F2, - Layout2F2Lfe = ffi::CUBEB_LAYOUT_2F2_LFE, - Layout3F2 = ffi::CUBEB_LAYOUT_3F2, - Layout3F2Lfe = ffi::CUBEB_LAYOUT_3F2_LFE, - Layout3F3RLfe = ffi::CUBEB_LAYOUT_3F3R_LFE, - Layout3F4Lfe = ffi::CUBEB_LAYOUT_3F4_LFE, +bitflags! { + /// Some common layout definitions + pub struct ChannelLayout: ffi::cubeb_channel_layout { + /// + const FRONT_LEFT = ffi::CHANNEL_FRONT_LEFT; + const FRONT_RIGHT = ffi::CHANNEL_FRONT_RIGHT; + const FRONT_CENTER = ffi::CHANNEL_FRONT_CENTER; + const LOW_FREQUENCY = ffi::CHANNEL_LOW_FREQUENCY; + const BACK_LEFT = ffi::CHANNEL_BACK_LEFT; + const BACK_RIGHT = ffi::CHANNEL_BACK_RIGHT; + const FRONT_LEFT_OF_CENTER = ffi::CHANNEL_FRONT_LEFT_OF_CENTER; + const FRONT_RIGHT_OF_CENTER = ffi::CHANNEL_FRONT_RIGHT_OF_CENTER; + const BACK_CENTER = ffi::CHANNEL_BACK_CENTER; + const SIDE_LEFT = ffi::CHANNEL_SIDE_LEFT; + const SIDE_RIGHT = ffi::CHANNEL_SIDE_RIGHT; + const TOP_CENTER = ffi::CHANNEL_TOP_CENTER; + const TOP_FRONT_LEFT = ffi::CHANNEL_TOP_FRONT_LEFT; + const TOP_FRONT_CENTER = ffi::CHANNEL_TOP_FRONT_CENTER; + const TOP_FRONT_RIGHT = ffi::CHANNEL_TOP_FRONT_RIGHT; + const TOP_BACK_LEFT = ffi::CHANNEL_TOP_BACK_LEFT; + const TOP_BACK_CENTER = ffi::CHANNEL_TOP_BACK_CENTER; + const TOP_BACK_RIGHT = ffi::CHANNEL_TOP_BACK_RIGHT; + } +} + +macro_rules! bits { + ($($x:ident => $y:ident),*) => { + $(pub const $x: ChannelLayout = ChannelLayout { bits: ffi::$y };)* + } +} + +impl ChannelLayout { + bits!(UNDEFINED => CUBEB_LAYOUT_UNDEFINED, + MONO => CUBEB_LAYOUT_MONO, + MONO_LFE => CUBEB_LAYOUT_MONO_LFE, + STEREO => CUBEB_LAYOUT_STEREO, + STEREO_LFE => CUBEB_LAYOUT_STEREO_LFE, + _3F => CUBEB_LAYOUT_3F, + _3F_LFE => CUBEB_LAYOUT_3F_LFE, + _2F1 => CUBEB_LAYOUT_2F1, + _2F1_LFE => CUBEB_LAYOUT_2F1_LFE, + _3F1 => CUBEB_LAYOUT_3F1, + _3F1_LFE => CUBEB_LAYOUT_3F1_LFE, + _2F2 => CUBEB_LAYOUT_2F2, + _2F2_LFE => CUBEB_LAYOUT_2F2_LFE, + QUAD => CUBEB_LAYOUT_QUAD, + QUAD_LFE => CUBEB_LAYOUT_QUAD_LFE, + _3F2 => CUBEB_LAYOUT_3F2, + _3F2_LFE => CUBEB_LAYOUT_3F2_LFE, + _3F2_BACK => CUBEB_LAYOUT_3F2_BACK, + _3F2_LFE_BACK => CUBEB_LAYOUT_3F2_LFE_BACK, + _3F3R_LFE => CUBEB_LAYOUT_3F3R_LFE, + _3F4_LFE => CUBEB_LAYOUT_3F4_LFE + ); +} + +impl From<ffi::cubeb_channel> for ChannelLayout { + fn from(x: ffi::cubeb_channel) -> Self { + ChannelLayout::from_bits_truncate(x) + } } -impl From<ffi::cubeb_channel_layout> for ChannelLayout { - fn from(x: ffi::cubeb_channel_layout) -> ChannelLayout { - match x { - ffi::CUBEB_LAYOUT_DUAL_MONO => ChannelLayout::DualMono, - ffi::CUBEB_LAYOUT_DUAL_MONO_LFE => ChannelLayout::DualMonoLfe, - ffi::CUBEB_LAYOUT_MONO => ChannelLayout::Mono, - ffi::CUBEB_LAYOUT_MONO_LFE => ChannelLayout::MonoLfe, - ffi::CUBEB_LAYOUT_STEREO => ChannelLayout::Stereo, - ffi::CUBEB_LAYOUT_STEREO_LFE => ChannelLayout::StereoLfe, - ffi::CUBEB_LAYOUT_3F => ChannelLayout::Layout3F, - ffi::CUBEB_LAYOUT_3F_LFE => ChannelLayout::Layout3FLfe, - ffi::CUBEB_LAYOUT_2F1 => ChannelLayout::Layout2F1, - ffi::CUBEB_LAYOUT_2F1_LFE => ChannelLayout::Layout2F1Lfe, - ffi::CUBEB_LAYOUT_3F1 => ChannelLayout::Layout3F1, - ffi::CUBEB_LAYOUT_3F1_LFE => ChannelLayout::Layout3F1Lfe, - ffi::CUBEB_LAYOUT_2F2 => ChannelLayout::Layout2F2, - ffi::CUBEB_LAYOUT_2F2_LFE => ChannelLayout::Layout2F2Lfe, - ffi::CUBEB_LAYOUT_3F2 => ChannelLayout::Layout3F2, - ffi::CUBEB_LAYOUT_3F2_LFE => ChannelLayout::Layout3F2Lfe, - ffi::CUBEB_LAYOUT_3F3R_LFE => ChannelLayout::Layout3F3RLfe, - ffi::CUBEB_LAYOUT_3F4_LFE => ChannelLayout::Layout3F4Lfe, - // TODO: Implement TryFrom - // Everything else is just undefined. - _ => ChannelLayout::Undefined, - } +impl Into<ffi::cubeb_channel> for ChannelLayout { + fn into(self) -> ffi::cubeb_channel { + self.bits() } } -impl Into<ffi::cubeb_channel_layout> for ChannelLayout { - fn into(self) -> ffi::cubeb_channel_layout { - self as ffi::cubeb_channel_layout +impl ChannelLayout { + pub fn num_channels(&self) -> u32 { + let layout = *self; + unsafe { ffi::cubeb_channel_layout_nb_channels(layout.into()) } + } +} + +#[cfg(test)] +mod test { + use ffi; + + #[test] + fn channel_layout_from_raw() { + macro_rules! check( + ($($raw:ident => $real:ident),*) => ( + $(let x = super::ChannelLayout::from(ffi::$raw);; + assert_eq!(x, super::ChannelLayout::$real); + )* + ) ); + + check!(CUBEB_LAYOUT_UNDEFINED => UNDEFINED, + CUBEB_LAYOUT_MONO => MONO, + CUBEB_LAYOUT_MONO_LFE => MONO_LFE, + CUBEB_LAYOUT_STEREO => STEREO, + CUBEB_LAYOUT_STEREO_LFE => STEREO_LFE, + CUBEB_LAYOUT_3F => _3F, + CUBEB_LAYOUT_3F_LFE => _3F_LFE, + CUBEB_LAYOUT_2F1 => _2F1, + CUBEB_LAYOUT_2F1_LFE => _2F1_LFE, + CUBEB_LAYOUT_3F1 => _3F1, + CUBEB_LAYOUT_3F1_LFE => _3F1_LFE, + CUBEB_LAYOUT_2F2 => _2F2, + CUBEB_LAYOUT_2F2_LFE => _2F2_LFE, + CUBEB_LAYOUT_QUAD => QUAD, + CUBEB_LAYOUT_QUAD_LFE => QUAD_LFE, + CUBEB_LAYOUT_3F2 => _3F2, + CUBEB_LAYOUT_3F2_LFE => _3F2_LFE, + CUBEB_LAYOUT_3F2_BACK => _3F2_BACK, + CUBEB_LAYOUT_3F2_LFE_BACK => _3F2_LFE_BACK, + CUBEB_LAYOUT_3F3R_LFE => _3F3R_LFE, + CUBEB_LAYOUT_3F4_LFE => _3F4_LFE); + } + + #[test] + fn channel_layout_into_raw() { + macro_rules! check( + ($($real:ident => $raw:ident),*) => ( + $(let x = super::ChannelLayout::$real; + let x: ffi::cubeb_channel_layout = x.into(); + assert_eq!(x, ffi::$raw); + )* + ) ); + + check!(UNDEFINED => CUBEB_LAYOUT_UNDEFINED, + MONO => CUBEB_LAYOUT_MONO, + MONO_LFE => CUBEB_LAYOUT_MONO_LFE, + STEREO => CUBEB_LAYOUT_STEREO, + STEREO_LFE => CUBEB_LAYOUT_STEREO_LFE, + _3F => CUBEB_LAYOUT_3F, + _3F_LFE => CUBEB_LAYOUT_3F_LFE, + _2F1 => CUBEB_LAYOUT_2F1, + _2F1_LFE=> CUBEB_LAYOUT_2F1_LFE, + _3F1 => CUBEB_LAYOUT_3F1, + _3F1_LFE => CUBEB_LAYOUT_3F1_LFE, + _2F2 => CUBEB_LAYOUT_2F2, + _2F2_LFE => CUBEB_LAYOUT_2F2_LFE, + QUAD => CUBEB_LAYOUT_QUAD, + QUAD_LFE => CUBEB_LAYOUT_QUAD_LFE, + _3F2 => CUBEB_LAYOUT_3F2, + _3F2_LFE => CUBEB_LAYOUT_3F2_LFE, + _3F2_BACK => CUBEB_LAYOUT_3F2_BACK, + _3F2_LFE_BACK => CUBEB_LAYOUT_3F2_LFE_BACK, + _3F3R_LFE => CUBEB_LAYOUT_3F3R_LFE, + _3F4_LFE => CUBEB_LAYOUT_3F4_LFE); } } diff --git a/third_party/rust/cubeb-core/src/context.rs b/third_party/rust/cubeb-core/src/context.rs index eede5f2f1a7bf67e9d2c5fb224ed9d893dc202a0..a9fdcd1395698afda096cd1ed4d9ef426286ae17 100644 --- a/third_party/rust/cubeb-core/src/context.rs +++ b/third_party/rust/cubeb-core/src/context.rs @@ -3,7 +3,7 @@ // This program is made available under an ISC-style license. See the // accompanying file LICENSE for details. -use {ChannelLayout, DeviceCollection, DeviceId, DeviceType, Result, Stream, StreamParamsRef}; +use {DeviceCollection, DeviceId, DeviceType, Result, Stream, StreamParamsRef}; use ffi; use std::{ptr, str}; use std::ffi::CStr; @@ -76,17 +76,6 @@ impl ContextRef { Ok(rate) } - pub fn preferred_channel_layout(&self) -> Result<ChannelLayout> { - let mut layout: ffi::cubeb_channel_layout = ffi::CUBEB_LAYOUT_UNDEFINED; - unsafe { - let _ = try_call!(ffi::cubeb_get_preferred_channel_layout( - self.as_ptr(), - &mut layout - )); - } - Ok(ChannelLayout::from(layout)) - } - #[cfg_attr(feature = "cargo-clippy", allow(too_many_arguments))] pub unsafe fn stream_init( &self, diff --git a/third_party/rust/cubeb-core/src/stream.rs b/third_party/rust/cubeb-core/src/stream.rs index c2ff6f0ef95089d3beb45bef77d22aba6300788b..c26d59d80fbc90e71e464ceb2c77dcead38c9b7d 100644 --- a/third_party/rust/cubeb-core/src/stream.rs +++ b/third_party/rust/cubeb-core/src/stream.rs @@ -85,35 +85,7 @@ impl StreamParamsRef { } pub fn layout(&self) -> ChannelLayout { - macro_rules! check( ($($raw:ident => $real:ident),*) => {{ - let layout = self.get_ref().layout; - $(if layout == ffi::$raw { - ChannelLayout::$real - }) else * - else { - panic!("unknown channel layout: {}", layout) - } - }} ); - - check!(CUBEB_LAYOUT_UNDEFINED => Undefined, - CUBEB_LAYOUT_DUAL_MONO => DualMono, - CUBEB_LAYOUT_DUAL_MONO_LFE => DualMonoLfe, - CUBEB_LAYOUT_MONO => Mono, - CUBEB_LAYOUT_MONO_LFE => MonoLfe, - CUBEB_LAYOUT_STEREO => Stereo, - CUBEB_LAYOUT_STEREO_LFE => StereoLfe, - CUBEB_LAYOUT_3F => Layout3F, - CUBEB_LAYOUT_3F_LFE => Layout3FLfe, - CUBEB_LAYOUT_2F1 => Layout2F1, - CUBEB_LAYOUT_2F1_LFE => Layout2F1Lfe, - CUBEB_LAYOUT_3F1 => Layout3F1, - CUBEB_LAYOUT_3F1_LFE => Layout3F1Lfe, - CUBEB_LAYOUT_2F2 => Layout2F2, - CUBEB_LAYOUT_2F2_LFE => Layout2F2Lfe, - CUBEB_LAYOUT_3F2 => Layout3F2, - CUBEB_LAYOUT_3F2_LFE => Layout3F2Lfe, - CUBEB_LAYOUT_3F3R_LFE => Layout3F3RLfe, - CUBEB_LAYOUT_3F4_LFE => Layout3F4Lfe) + ChannelLayout::from(self.get_ref().layout) } pub fn prefs(&self) -> StreamPrefs { @@ -297,25 +269,27 @@ mod tests { )* ) ); - check!(CUBEB_LAYOUT_UNDEFINED => Undefined, - CUBEB_LAYOUT_DUAL_MONO => DualMono, - CUBEB_LAYOUT_DUAL_MONO_LFE => DualMonoLfe, - CUBEB_LAYOUT_MONO => Mono, - CUBEB_LAYOUT_MONO_LFE => MonoLfe, - CUBEB_LAYOUT_STEREO => Stereo, - CUBEB_LAYOUT_STEREO_LFE => StereoLfe, - CUBEB_LAYOUT_3F => Layout3F, - CUBEB_LAYOUT_3F_LFE => Layout3FLfe, - CUBEB_LAYOUT_2F1 => Layout2F1, - CUBEB_LAYOUT_2F1_LFE => Layout2F1Lfe, - CUBEB_LAYOUT_3F1 => Layout3F1, - CUBEB_LAYOUT_3F1_LFE => Layout3F1Lfe, - CUBEB_LAYOUT_2F2 => Layout2F2, - CUBEB_LAYOUT_2F2_LFE => Layout2F2Lfe, - CUBEB_LAYOUT_3F2 => Layout3F2, - CUBEB_LAYOUT_3F2_LFE => Layout3F2Lfe, - CUBEB_LAYOUT_3F3R_LFE => Layout3F3RLfe, - CUBEB_LAYOUT_3F4_LFE => Layout3F4Lfe); + check!(CUBEB_LAYOUT_UNDEFINED => UNDEFINED, + CUBEB_LAYOUT_MONO => MONO, + CUBEB_LAYOUT_MONO_LFE => MONO_LFE, + CUBEB_LAYOUT_STEREO => STEREO, + CUBEB_LAYOUT_STEREO_LFE => STEREO_LFE, + CUBEB_LAYOUT_3F => _3F, + CUBEB_LAYOUT_3F_LFE => _3F_LFE, + CUBEB_LAYOUT_2F1 => _2F1, + CUBEB_LAYOUT_2F1_LFE => _2F1_LFE, + CUBEB_LAYOUT_3F1 => _3F1, + CUBEB_LAYOUT_3F1_LFE => _3F1_LFE, + CUBEB_LAYOUT_2F2 => _2F2, + CUBEB_LAYOUT_2F2_LFE => _2F2_LFE, + CUBEB_LAYOUT_QUAD => QUAD, + CUBEB_LAYOUT_QUAD_LFE => QUAD_LFE, + CUBEB_LAYOUT_3F2 => _3F2, + CUBEB_LAYOUT_3F2_LFE => _3F2_LFE, + CUBEB_LAYOUT_3F2_BACK => _3F2_BACK, + CUBEB_LAYOUT_3F2_LFE_BACK => _3F2_LFE_BACK, + CUBEB_LAYOUT_3F3R_LFE => _3F3R_LFE, + CUBEB_LAYOUT_3F4_LFE => _3F4_LFE); } #[test] diff --git a/third_party/rust/cubeb-sys/.cargo-checksum.json b/third_party/rust/cubeb-sys/.cargo-checksum.json index bd8441d2ed1c12a514418c767d9f69b652cc5635..eab1e98e6b765d8353aea887578b17d975a53079 100644 --- a/third_party/rust/cubeb-sys/.cargo-checksum.json +++ b/third_party/rust/cubeb-sys/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"9c7435ec35196feeee3229e1f2ead5101d14e18a72956820464378e335bd9cf6","LICENSE":"8c044baa5d883274736eeece0b955249076c2697b826e576fce59496235b2cf5","build.rs":"49985a30631de0015517fc260321aa03a003eaf26d80650bebd928d55edc9444","libcubeb/.gitmodules":"6fe6fc18ff76ba8dd3dc749247d61a2f4a18c1e42b1890581e234ab8151d4c95","libcubeb/.travis.yml":"edb891b3c9edc375d8296d93a79bcbb8e5f884f695b3115a7c0d57cf45471823","libcubeb/AUTHORS":"829e45d138c7c8827799f302806fa4be8cd8bd4bad70a2fe26c3a27a5cf36948","libcubeb/CMakeLists.txt":"017e5e2a43ccaff30f4dc52070a31a0c4938b46714e9c4ae7558e5d3d53115ed","libcubeb/Config.cmake.in":"88019286c96ef3d5d3a673b183c8655dfc97ceede07d3eb6c18f0c51bb896388","libcubeb/INSTALL.md":"7a84cdfbe86e7d3180e2203603b88571df61b369421fa97ee86740ffd4d4db8e","libcubeb/LICENSE":"44c6b5ae5ec3fe2fbc608b00e6f4896f4d2d5c7e525fcbaa3eaa3cf2f3d5a983","libcubeb/README.md":"aa417156dc65069264901b75fc3c792c73021ec61c909de04e109bd4184c07ab","libcubeb/TODO":"6f8065136e005d2becee810e3d8697a94f2c755f8c79687adfac7136ad165e80","libcubeb/appveyor.yml":"9a87fdc18b76fca1167289ecb2ec3a210b76984c1d7e92268b2cd36f1e00f541","libcubeb/cmake/sanitizers-cmake/CMakeLists.txt":"89b282c19b3897ff666f7847d5e679ae928ca7e76ffd0d23f7c58c9464048b61","libcubeb/cmake/sanitizers-cmake/LICENSE":"4b67e7ae8c91e68e1a929eb1cbaa4c773c6d19aa91aaa12c390cf9560d1c9799","libcubeb/cmake/sanitizers-cmake/README.md":"30ab1524618ac828b75f9b83c665a0bd50b839b42ce61519a8048d73f401da6e","libcubeb/cmake/sanitizers-cmake/cmake/FindASan.cmake":"cba07ffe438c57bef0840ed6a2d2890676530b66509da3c616438c53018baa4f","libcubeb/cmake/sanitizers-cmake/cmake/FindMSan.cmake":"1303aac5028fe9f64d42be0afd47f1291e679d74f8280b3dc5271f20ebf4d7a4","libcubeb/cmake/sanitizers-cmake/cmake/FindSanitizers.cmake":"ce1971b943bbef08fb9aba958cf28e3cbdff075406c85a3cfed22e00c9f8d9a8","libcubeb/cmake/sanitizers-cmake/cmake/FindTSan.cmake":"edca39b287312e9a8fc718f6ec791d2520515900b37426091310fe1bd52dc6a1","libcubeb/cmake/sanitizers-cmake/cmake/FindUBSan.cmake":"5b9d3621f629c807a1345a7cb053677a8bf25782a079e345dda53d04aecdc4b7","libcubeb/cmake/sanitizers-cmake/cmake/asan-wrapper":"4e543936e6374e24b80a0f92135c07c2e2101c0d110e51bddaf0e70ae8ec391e","libcubeb/cmake/sanitizers-cmake/cmake/sanitize-helpers.cmake":"282620734c2a8062f1280d0dde3121b8b01af26e5ecaa7d4308e145f80ecd115","libcubeb/cmake/sanitizers-cmake/tests/CMakeLists.txt":"fb983bab7040be002847db59c2493abfd249f67ad06e3a9270fbceb9fabda11c","libcubeb/cmake/sanitizers-cmake/tests/asan_test.cpp":"8b351c7c8668b4a2438286df426f0ad322cade6d1c6199a74668ccbd1c5204a4","libcubeb/cmake/toolchain-cross-android.cmake":"59d2355845a71647b353fb8b18fca630db8ffee7bb8500143e2d6fbc409cec97","libcubeb/cmake/toolchain-cross-mingw.cmake":"b09dc261981c0d4a0f8430f05aae9c8fc545651cd9cbfacd09754277b776b532","libcubeb/cubeb.supp":"19f33e59f8dc91a327c923e44c2c3f9af0a043ce1d6a8cac275ba094b4bfe0da","libcubeb/docs/Doxyfile.in":"0815f19789cedd310652a133bab260c27b57e95f7a65458df2dfca38ea4f1041","libcubeb/googletest/CHANGES":"72c8a289bfe4dd9160074a3a2238c8067a5bc7ca49fd87f70a134c3f373932a4","libcubeb/googletest/CMakeLists.txt":"cdf938ce79ea066866dc614de3925bfaa48d9e19e04049db2ec8c5443abaaa9b","libcubeb/googletest/CONTRIBUTORS":"4d911cd5e6d71f3f4bbcb2788b2f916df4b0ce1e088752a159457a1d936ae0ce","libcubeb/googletest/COPYING":"9702de7e4117a8e2b20dafab11ffda58c198aede066406496bef670d40a22138","libcubeb/googletest/Makefile.am":"a795e5a18e82ba06fd97509d92d773b7fafd0dd7086db8a1211fbd151b503bac","libcubeb/googletest/README":"484b19654362942fac9734c8fab0ed3d99249b81c69027bdb7de46054abada6b","libcubeb/googletest/build-aux/.keep":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","libcubeb/googletest/cmake/internal_utils.cmake":"6f4670a5825cf8ae0415be9dd43d82a7f30316d75cab20a4c60afb6d9db2a01d","libcubeb/googletest/codegear/gtest.cbproj":"9fa07a66b8c01773256e508187775407c465ed9055651e93d390426d1888721a","libcubeb/googletest/codegear/gtest.groupproj":"76c001cb2ee0070e26d1570fb6db5250f2585179c707496c5ef6d12e582cf205","libcubeb/googletest/codegear/gtest_all.cc":"c8750dc2b7b3612edb60e8d23fc2f60ae264451916c4b15f81cbf60ea30eb75d","libcubeb/googletest/codegear/gtest_link.cc":"e5e47c086f932471e0ca748a62b3b1597e5e731f4d34fb8cb8b2ca2db7ba3ed0","libcubeb/googletest/codegear/gtest_main.cbproj":"056448ba7f41fae3f704b1001922d9f6e419cf8cbcf3a55bf0ecc59ece1fa9a1","libcubeb/googletest/codegear/gtest_unittest.cbproj":"2c48be90b0dbc3224a8bd6c4dc21f78dd1b08c81685e6bd4952bb6df6ee38701","libcubeb/googletest/configure.ac":"fadebffdaeaccebb60fbe4a501c1138c296e01348a5da45fabf5e4233248baa8","libcubeb/googletest/include/gtest/gtest-death-test.h":"fdd087f700cd04a3ce4bdd36f35769de52a44bfc0c5bae2dc9681d4cbcd3c44a","libcubeb/googletest/include/gtest/gtest-message.h":"eaf44df1284d94333507c47091c84eaaf43814e6a02a1b1c0061ca7b363e74d6","libcubeb/googletest/include/gtest/gtest-param-test.h":"f226f0a24c04cddbceaaa45d8a5e575ce18c3392349f9b8ba73317e37e62368d","libcubeb/googletest/include/gtest/gtest-param-test.h.pump":"17c65fd5cc5218279044a61f3873c9c952b0924a7ba5147d4999d400b122207f","libcubeb/googletest/include/gtest/gtest-printers.h":"7046f611398d63ee0f1c37bdb4fd08d9931979b2fedf13b781e6d85d4b3b5d60","libcubeb/googletest/include/gtest/gtest-spi.h":"560407dd45e8e57fa6927504c9e4a4cfdecf30f8cada975c1ffddce765e6a88a","libcubeb/googletest/include/gtest/gtest-test-part.h":"c4d6d840284728740c284646075e8ffc85b63b9f74f3ed488b18ef3c2c2b9005","libcubeb/googletest/include/gtest/gtest-typed-test.h":"1ec858bbb9ed8a8bb553232df016437c080b2670f00453b4de297c286eb78c21","libcubeb/googletest/include/gtest/gtest.h":"47433ca72a43bda7a380c34fe6d4ff451797c687e9bbd74d1f366bcdfa0cb013","libcubeb/googletest/include/gtest/gtest_pred_impl.h":"f03a3f77e3c231889c0ace6f63b2c4e410e4a9330287ea09443b23b9a3cf9092","libcubeb/googletest/include/gtest/gtest_prod.h":"4a99a3d986a45b4d6d9b3af54809f015c54aa98274793a4ae173f5010d0ad33c","libcubeb/googletest/include/gtest/internal/gtest-death-test-internal.h":"0b3abead866363f3e6b4201acc8d2763072e033826b22ae5ebffd790e1415235","libcubeb/googletest/include/gtest/internal/gtest-filepath.h":"638d2bb6c06a894513b03311a8e931ac835fc00afc4bd21fab3afc05732c23a0","libcubeb/googletest/include/gtest/internal/gtest-internal.h":"12c2c83df0a9dc5b46697ccd8271dfa34ee5f3d1972dcb56585bc1459d9583c9","libcubeb/googletest/include/gtest/internal/gtest-linked_ptr.h":"9bd319548dd073630dfd349c06a440c6a582feec47d4ff14f348ec32f8b4c1f3","libcubeb/googletest/include/gtest/internal/gtest-param-util-generated.h":"10db93fa7e98820192bae6f560664469dd33b265036fca64253c89b6801f96cb","libcubeb/googletest/include/gtest/internal/gtest-param-util-generated.h.pump":"abb72365d94d2811b34c195dc520fbf41c7dcb42aae5a1cfa0502cf619b21e70","libcubeb/googletest/include/gtest/internal/gtest-param-util.h":"7f9311f033ef6916217d87cef53b1db6c4e8733be930e4b48fe7e11d21b33da0","libcubeb/googletest/include/gtest/internal/gtest-port.h":"612932c2930a7cf2c3514d89a8d6b51a2c0030d251309b71765ed1c9954e20c5","libcubeb/googletest/include/gtest/internal/gtest-string.h":"a46aa36165c400d1e926f942be03fe04cd7ccb1e59f7a2a03b919c4eea05b997","libcubeb/googletest/include/gtest/internal/gtest-tuple.h":"43e7e3c92f8e4258cf3927a9204b214d4d03e6c796f88f3ad4e66b1ac20aa938","libcubeb/googletest/include/gtest/internal/gtest-tuple.h.pump":"16fa027ed3c5940699e0ac906815e66620993bcf75b0acaf826d4f09348d4b83","libcubeb/googletest/include/gtest/internal/gtest-type-util.h":"6d177af46a9b1e14b969972a8b886667f95e69037aba411433a44fb9b92e7037","libcubeb/googletest/include/gtest/internal/gtest-type-util.h.pump":"22092f44127af91651f57ce222e20914d5d32ae02f1c0964f6d5d7bc019af339","libcubeb/googletest/m4/acx_pthread.m4":"3326e3746b6b351d1671fe31f798269cda8de92c365b8a8305404ec0fa6c6b32","libcubeb/googletest/m4/gtest.m4":"d3c37ebd1aa792c967d4357755cc670bc6deb30091d9e6db498871d90a30ea4c","libcubeb/googletest/make/Makefile":"9b86e2a112dd55c6bf6a2b39e6f4078faf60cfecb8282ebf9b025167ed233420","libcubeb/googletest/msvc/gtest-md.sln":"0beab679b42cf0c431eaf4fe143bbf3b01fc064e20c74d9e33e7e437a70487d4","libcubeb/googletest/msvc/gtest-md.vcproj":"52e873e964daf9d5409b4e9bb471ddf2827be04985cd96c40620f9275d17a256","libcubeb/googletest/msvc/gtest.sln":"be21c2340650ec2259a2fbaeb8608ae6d3e982a0626a0f91128a771dc88e6bea","libcubeb/googletest/msvc/gtest.vcproj":"0064616c7d88a284c1b7c05baab038f239134ea9c6c563628f286f9600b3f921","libcubeb/googletest/msvc/gtest_main-md.vcproj":"f83a294a92b616bf34ccae6743ff916297bdba61d6125a9637a813d467a30372","libcubeb/googletest/msvc/gtest_main.vcproj":"9f03270a00896eab0c7015c6fb1a73818d024e462d3944ba1d3ceb313a051649","libcubeb/googletest/msvc/gtest_prod_test-md.vcproj":"7caa108733e2d5f140da004d2133e04a9a105811909c0e2d4ec06e2971983592","libcubeb/googletest/msvc/gtest_prod_test.vcproj":"cf5bfb7f3de9a59a0eba5535067845d12c33c3fd8fecc3d03aa702665db29578","libcubeb/googletest/msvc/gtest_unittest-md.vcproj":"e7949b21cf0418f2a7afe8aa94616e2c40e3ba0801c2f0826f3a3a3d2e6f48b0","libcubeb/googletest/msvc/gtest_unittest.vcproj":"5b097d596fbbc1c4090fd518008a0961b29661194e1c02d8a2d3daaa557e626f","libcubeb/googletest/samples/prime_tables.h":"2903df1d1e6643a5f624fe3ea3f931c3410eb1858ac347c5df278273c6c91ca4","libcubeb/googletest/samples/sample1.cc":"dc106c5940d87bb4bbef3d77815eab642ee173a3340b2b9c532b5c711c4c2d0e","libcubeb/googletest/samples/sample1.h":"7a7bf9a0fbd2401e8b2cb554bfcb9bd0ed228212f3b970675c1b1d38d4e188bb","libcubeb/googletest/samples/sample10_unittest.cc":"ccebb6393a5a8468399f7e511219b667a2233f82312ce59834a4bb0997d8700e","libcubeb/googletest/samples/sample1_unittest.cc":"904be0d4a095e74393515195392bd10e1e916bb2ca61f3f94b1bd6aebea29cb6","libcubeb/googletest/samples/sample2.cc":"f14b8a1e69d52eef1a70053fb256818c7eca64e8eda08de43cf46e896e57fcc2","libcubeb/googletest/samples/sample2.h":"df956ba520dafca068dbc1e28f36567db3cba36293e06762318af8cda6a12bd4","libcubeb/googletest/samples/sample2_unittest.cc":"abe7e0b253d328cb82ae67623fbe3c89eb94699102510c64a0b568eaca101e05","libcubeb/googletest/samples/sample3-inl.h":"3fe482bbd4f725f5820f5d6beab4d0d4a524be8addf4b344a9a470ec5aabc451","libcubeb/googletest/samples/sample3_unittest.cc":"252c06b4531dc35213ebdd7311700b9b4057bc1bdeeba0cd767b2bc86c456639","libcubeb/googletest/samples/sample4.cc":"b4260f5fa35d78ac114a9abb59fce12403faf0273df41f57e83c341ae7979222","libcubeb/googletest/samples/sample4.h":"604905cae7e5587805c3b884a36eda7a2bebdfedb53b24b0fd9a220eec0ef1a9","libcubeb/googletest/samples/sample4_unittest.cc":"6cfb4821d8cb1c77fbb5af4f8aec569948762d8ea314827e3ead967b5b6a223e","libcubeb/googletest/samples/sample5_unittest.cc":"73646d9038873a68bb2e56b12495d7f7b65b5c23901109701da446af454ba2ec","libcubeb/googletest/samples/sample6_unittest.cc":"833fee399954f908cf0f3b789832e505329787f4cf73607a7b31ca0f62f368d7","libcubeb/googletest/samples/sample7_unittest.cc":"8013ee68d61c181e4e936cdae3a9a635646274f8512033ef11bff7214e03e4a6","libcubeb/googletest/samples/sample8_unittest.cc":"7b7510fadf4955d2f934d23d652dbd35add832e50bdfcc98421fb9be4588d808","libcubeb/googletest/samples/sample9_unittest.cc":"8b827040dea37b460cbcaea0b255b98974a9840f6ef7bd82aaa7d4ad2c724335","libcubeb/googletest/scripts/fuse_gtest_files.py":"adecf64c6bab65b31740c321e568cf174f753d5617745aa5762d842339d68b53","libcubeb/googletest/scripts/gen_gtest_pred_impl.py":"78fb7e20a014c251d723186eb58040e4eb32405b73c9288d787ea0a0e4ff5183","libcubeb/googletest/scripts/gtest-config.in":"9a43978eeee88e188845d737c17f4d024d4e74feae09da7997e8fbe4ea6cc176","libcubeb/googletest/scripts/pump.py":"3856a3d7be37f78e0f214ee7d4f29d05f1ca14218b67539d67c9a16e992f670c","libcubeb/googletest/scripts/test/Makefile":"3576b257594a2d8e843b9e4de8c83353d837833bb86431fb1b4198022b1bcddc","libcubeb/googletest/scripts/upload.py":"f75d0712e3b13bebd8daa0a15e4eb32c9e3034a933f4fcccf65b1e999a7ae066","libcubeb/googletest/scripts/upload_gtest.py":"6e76fc0a7a3831c01cfffd18c220d44438073a66338d91ca61fc84b924021e61","libcubeb/googletest/src/gtest-all.cc":"568ac119f5e6418f1fbcfbdf185d724657d7f3539b47822da229ac5d015626b2","libcubeb/googletest/src/gtest-death-test.cc":"eec1b3c8252670c76acbbaf63483946897ce625139b53a566406b6313f023896","libcubeb/googletest/src/gtest-filepath.cc":"31b7fcda5d11346f8a487597c6a70ff057f1192e0cb11f27eb7841a9f3aa8b86","libcubeb/googletest/src/gtest-internal-inl.h":"c9d428a6b5990ace091e40c4ce8b7bf6c50c186a8314b1c4a4cdc988ca0ac1a4","libcubeb/googletest/src/gtest-port.cc":"95bcf473622d1b901c734e5c2aeb8efb058555ec924212a61bb04f049bb5a069","libcubeb/googletest/src/gtest-printers.cc":"6f191a7fc7f5a0a967fd11964057f2e2d2eaf2f37ccece16bd816531f52b3154","libcubeb/googletest/src/gtest-test-part.cc":"e489868b4cdc66f4fc33bc2326ac86bc1acc5808ab58bbb288c9dcfc330faddc","libcubeb/googletest/src/gtest-typed-test.cc":"ca9e819df728c25a6a1fc072806c22f3494e1dffe4bd0d48284f38dbdd3a0dd5","libcubeb/googletest/src/gtest.cc":"5cf9a3e897892c9f0e5c887f91d3c8c8c5665bd7348560441fc0b946c254873c","libcubeb/googletest/src/gtest_main.cc":"22fa1f77542b882d1798d7f696045c5895942a626e26200a175fa4382e1fa5b5","libcubeb/googletest/test/gtest-death-test_ex_test.cc":"613ccf50a3ff8f84c975a13e86ea01ea4e36933072388a3738b4acf9ed3ed7cf","libcubeb/googletest/test/gtest-death-test_test.cc":"df8384a847bdf889233c3d45d171f784991def7a9b6a08442138569fbae32b9d","libcubeb/googletest/test/gtest-filepath_test.cc":"49760f91723845b113bb60bb9b1a1426ed1da1f4ebfef2462128980ea5692cc9","libcubeb/googletest/test/gtest-linked_ptr_test.cc":"1b9cb4ff67475900db9de34ae9749b94193048a1f7a741091ba5a2dd7fc7a79b","libcubeb/googletest/test/gtest-listener_test.cc":"acf78f2c9a730525ea5adc93e9196a42de8fbfe488db1dfd02656bdbd477b2c0","libcubeb/googletest/test/gtest-message_test.cc":"b1fc68f8b75ce25fbd79b3f7d3c9c793381ef07b3203e1a2d9b610cb597542be","libcubeb/googletest/test/gtest-options_test.cc":"74e3ae0c310edb3139b0032266219d3ce7f386ded6feafa57fef03f4493ed7fa","libcubeb/googletest/test/gtest-param-test2_test.cc":"a0f1efbcab3f7e49df639383157626931f64756f7e738be081760f93f7308332","libcubeb/googletest/test/gtest-param-test_test.cc":"ef8bd344e959053f562b0c9e0d15e2fb6c1e534772a67aaf3f90bd6bad0bf99f","libcubeb/googletest/test/gtest-param-test_test.h":"9d7f47b79d54df7cc050aa6038b0464aa684dfca669a847bf70ea16e4a000628","libcubeb/googletest/test/gtest-port_test.cc":"1600f78ef0860a0f5b5525e5e5041ff32a216cc6ae948b1ea61fe04ec603f67d","libcubeb/googletest/test/gtest-printers_test.cc":"7898e4b4163ee0821fed248e1c75d9f4a0a511a2b4bbfad1ef2f4a11a099f6e7","libcubeb/googletest/test/gtest-test-part_test.cc":"62c8906bb0d12ea84d60217b3773cd8e1768db4aab934880db2316df7026cab8","libcubeb/googletest/test/gtest-tuple_test.cc":"2850dc1f73a3f8020d8a4d80688a28d9b736eae6d677222c3f871d8d33b25501","libcubeb/googletest/test/gtest-typed-test2_test.cc":"c52b65e7181610d6e577631cd50177399884913ff28d08aedfedc92f05185044","libcubeb/googletest/test/gtest-typed-test_test.cc":"c7daff5211028da79b3ca0473dca18ada9197f38e710f72d0493ad3332ce3ec9","libcubeb/googletest/test/gtest-typed-test_test.h":"3145698534d8869beb624c9c8ed114f75bead046b2eeb92ada5a724993ee7786","libcubeb/googletest/test/gtest-unittest-api_test.cc":"e3f54c28ef2849e8b12af666ed46aace50c3e047845072ee6f974ce4528bd297","libcubeb/googletest/test/gtest_all_test.cc":"db0c3c42b385570b1d517e3ee927671b8fad4e206247fca738ec477222ac3d97","libcubeb/googletest/test/gtest_break_on_failure_unittest.py":"11c91bc1c68cfdb913e2affb01261b55fb3b0c18773a45875e9c25cb330a4dcd","libcubeb/googletest/test/gtest_break_on_failure_unittest_.cc":"1da12e4bdda2a0bc7b59d4638fe34b2d3798134224fd9237eeebdd09c3326011","libcubeb/googletest/test/gtest_catch_exceptions_test.py":"305cef45c6dc034bdf72fd91aba1e89e1c6b5d222c3d6baffff5acdfd9b3873e","libcubeb/googletest/test/gtest_catch_exceptions_test_.cc":"b297a4f4d5bc0285ea9eb8869741631658305e49d4513bca904842aacb82128b","libcubeb/googletest/test/gtest_color_test.py":"c4cb006682a40f2d88759a4bcabf0d4be623720b135c71447f1788d17ea23d0f","libcubeb/googletest/test/gtest_color_test_.cc":"f263ba349afe58a558bf0fee98a98bb9207a648e7cd4f908a87799bd13d001ea","libcubeb/googletest/test/gtest_env_var_test.py":"79819598cd1e366eaa8f2a4fee2d638b6ef0686e490402fae792ccce58d876c0","libcubeb/googletest/test/gtest_env_var_test_.cc":"0eee5dfbb2a2598f4e76626346b921928ec1e052e38f254cc97c60d05611ab46","libcubeb/googletest/test/gtest_environment_test.cc":"a52a21ea29c2203b03fa93922733546d171f98d3b2fcd42972269e98fd124715","libcubeb/googletest/test/gtest_filter_unittest.py":"edc7d278803bba41626eacd050d91d7247f1c5999f9dceb99a8877e238bc73d6","libcubeb/googletest/test/gtest_filter_unittest_.cc":"996ac528ad75c293d8201ce28cf6acccee266286bd369b4cf43f05b8d67a4559","libcubeb/googletest/test/gtest_help_test.py":"b43ab690c08e4bffd84a47b361167496298697f9511bdf4a745bf305b5cfbdfc","libcubeb/googletest/test/gtest_help_test_.cc":"ff4b121098f0fe7cb4abf11fdd31f2fe7a477286ec9175482138bc038d61c807","libcubeb/googletest/test/gtest_list_tests_unittest.py":"7caebc175b44b3c727fc50420ada1a6a9500f3e4ce9e2839f69205437aa85e7a","libcubeb/googletest/test/gtest_list_tests_unittest_.cc":"d82d8b72914897232c2ff9fd091a7b0add68b7cf75f3f210d3a487ebeea84cfe","libcubeb/googletest/test/gtest_main_unittest.cc":"0f66f318809c88f0fbe034a340a75331720c4e33be5378022baffaf588ef1202","libcubeb/googletest/test/gtest_no_test_unittest.cc":"7cf487e07c3d27376c2cb8af33d02239b7966623875d37b7aa0259e927a9c2f6","libcubeb/googletest/test/gtest_output_test.py":"cf0dc1979572d94450a5e611b44f3fdb88d9cd980d669a723f0ed63057b5e2c4","libcubeb/googletest/test/gtest_output_test_.cc":"f69569374c2b3d06aa04a38ebc4f92ddc303e6af503f8b533cd8e6bf9f104899","libcubeb/googletest/test/gtest_output_test_golden_lin.txt":"4f3e49c10a524a99437cdcb5294e3335a7f3c07ea8462e65730f703a5fe4fec3","libcubeb/googletest/test/gtest_pred_impl_unittest.cc":"e406eccf75b6b58746a95d1c7ea7bc8e80ff974e438ef7c83074a46d4e62db9a","libcubeb/googletest/test/gtest_prod_test.cc":"b42ca1a6d0a1e43bc576b4ff7776c6d2c37234f6dc2a76f2735f261b4a47a526","libcubeb/googletest/test/gtest_repeat_test.cc":"e10abbb71595920aa3bb415029eed74106335fc9ea3d58c417ccfc7cba6a4cdb","libcubeb/googletest/test/gtest_shuffle_test.py":"12dd94eb5f30260ba37059fa74658bda57dffa821f3ba6a2a8b52ff14b1ad029","libcubeb/googletest/test/gtest_shuffle_test_.cc":"af1b2b01ae275f1a9fee7e7940c0f88f39ded063008994d585aad87e3ffadb39","libcubeb/googletest/test/gtest_sole_header_test.cc":"538414c27a593ab8dc34c37b5c877eb3a022d75d1b481ef14ceca00914929754","libcubeb/googletest/test/gtest_stress_test.cc":"0b02fc12f87944226915a999bdcc8a3eaafb34a1ea5bb0df128774abf8667f09","libcubeb/googletest/test/gtest_test_utils.py":"d4a76930aee6658ad8734981ca0c4ea14f34dbe8fdd31d5afe41f6d98f9779ee","libcubeb/googletest/test/gtest_throw_on_failure_ex_test.cc":"11ae790028da20bc7b7af1572eff3cfe8499be43ab64c110e18e1892612a183f","libcubeb/googletest/test/gtest_throw_on_failure_test.py":"ebe18ca0b07f90c53b9b3f9a54ed02df94facf8995cfa90dd41c6f5474537c13","libcubeb/googletest/test/gtest_throw_on_failure_test_.cc":"f8cbf75d8bf9e9ae068a17ff968434c3aec7b7f1137c994d8f14af1a84361aa9","libcubeb/googletest/test/gtest_uninitialized_test.py":"da8e6ce34930753e36fc1dfa2c3e20e48d02bda2a27d3d03a07364312c5f3bd9","libcubeb/googletest/test/gtest_uninitialized_test_.cc":"0b6a9d4983480f87352ca4da946089264b401f7a4a3b1282253fd6cc861bf483","libcubeb/googletest/test/gtest_unittest.cc":"c0c7d1f691ce1e10c3d1647ed5f7a66510725808ad58bb6da4bc03a7a08fb2fc","libcubeb/googletest/test/gtest_xml_outfile1_test_.cc":"29341d777a9c9d25f360d13ed966b30f0cbef1fc88aefe2f01bb88b82cf1ed93","libcubeb/googletest/test/gtest_xml_outfile2_test_.cc":"da7ab3cf0e9b2a293eceed7c5691233d6b61afb557e3c1176dfb75390f85be46","libcubeb/googletest/test/gtest_xml_outfiles_test.py":"b07927b43f44afbfd61761c2cc69f1b68c4fbdeddb992db03ff0c73052518cd4","libcubeb/googletest/test/gtest_xml_output_unittest.py":"b5ff0c0207238d01cada961b8f4656f2ec30a3e1e5bf9d22efdf1745af423031","libcubeb/googletest/test/gtest_xml_output_unittest_.cc":"ad0b9ebe63a146e386df3c5c51916869f6d4647b9832ceacc912fb1272d15f82","libcubeb/googletest/test/gtest_xml_test_utils.py":"ad89a39a6cd5b08e87082341f3e7800dbf1150ea0f1386e0b8cd374aa6832f00","libcubeb/googletest/test/production.cc":"56fef77c3a8e62073ec11653d740a8e534008a0d57925ab0877b843f4fdd6be8","libcubeb/googletest/test/production.h":"a36d10545d12ead5e93a3b0fdca6ff73405f29091cfe38164415e9038888ba8d","libcubeb/googletest/xcode/Config/DebugProject.xcconfig":"fb42302df29bd8e8b5237194c0c04941f0e578527037930d88469baeb7a7f62b","libcubeb/googletest/xcode/Config/FrameworkTarget.xcconfig":"9935ddabe221f074d2f3b969a137d12b0dc0f845a460f58b63232987cb0f37ff","libcubeb/googletest/xcode/Config/General.xcconfig":"0fb768924daba1048f8db28b3a1fbf915b6f788d49d9d37e85979aa4ee92e02d","libcubeb/googletest/xcode/Config/ReleaseProject.xcconfig":"a4878ddd1ed78fb411906623cb51bc0ab4aea1cc3feb5379d2ae2862d8bf3bf5","libcubeb/googletest/xcode/Config/StaticLibraryTarget.xcconfig":"5886291788b3e9d5aadcb979ff055fd26a2413be81016e7afffb813b627d177c","libcubeb/googletest/xcode/Config/TestTarget.xcconfig":"f074e6c2516a6063b253ec6b842d74f5c2abefc7bcf8d8da54097a7bfe016480","libcubeb/googletest/xcode/Resources/Info.plist":"5b7f78a6d5810ce5490649793175c8982d41e6b49af06bc0705bc061567cc9aa","libcubeb/googletest/xcode/Samples/FrameworkSample/Info.plist":"1c13d83e5eed45689d7fe4bf4681030366474bc40608e39e1623c1350513a0cd","libcubeb/googletest/xcode/Samples/FrameworkSample/WidgetFramework.xcodeproj/project.pbxproj":"1cf0e1b1abf84414372faf9c8bf634e01fe5750bb3ca769b1eb25fc530b21358","libcubeb/googletest/xcode/Samples/FrameworkSample/runtests.sh":"a587e5b00a8353dee0aca5a4c59b28301ccf7648dee8c79b62a9223f9fc3c8cf","libcubeb/googletest/xcode/Samples/FrameworkSample/widget.cc":"562a2bb615e93186012823c9b41761769638a11e38b54498ad5f699038c8fd32","libcubeb/googletest/xcode/Samples/FrameworkSample/widget.h":"0c7915e45cf7cb8d67db24e49cd0b277f23f967578f917f8e859a6adc4b156f9","libcubeb/googletest/xcode/Samples/FrameworkSample/widget_test.cc":"6a1a49d64912d9829ef3d991faf5a3f0e1e081126a1d8d387cdfa84fab70dc77","libcubeb/googletest/xcode/Scripts/runtests.sh":"1a0672a4151b16f3c797478ba26c534e82b2faa603f90b9aa14e785805f7683a","libcubeb/googletest/xcode/Scripts/versiongenerate.py":"4b9d5c0f4e1b556084109311d156bee6d781968dc5b1dfdc8702364508f1dd43","libcubeb/googletest/xcode/gtest.xcodeproj/project.pbxproj":"a1224decff058bfed01b8eefaee13cab0129492615548c6d0d878003a154f7ff","libcubeb/include/cubeb/cubeb.h":"b0eaa7d2af05c4f473762282d87ac1f0fa4dd1bef5d30bb839e9783268b3346e","libcubeb/scan-build-install.sh":"1ecf22aca367a4d02f810c4cb78db8636e08a12787e94e30c441ce439cf4a265","libcubeb/src/android/audiotrack_definitions.h":"0d5ec772f9ebf61333bc16e61a081a7e3b4cc02342ec4f8f417e220d032fbbc6","libcubeb/src/android/sles_definitions.h":"24e400ca2330ec16d3a37b69b74144697b51dce17f9ead763b1a6ffedc5633ac","libcubeb/src/cubeb-internal.h":"bcac7660194c5f3db59c71abfb8a7a312771234e8601d78eae3bff6f778adf96","libcubeb/src/cubeb-sles.h":"dc84a01ba4de9db1ff108609930b36ba442020ccc3e3d6f16528f429426c430c","libcubeb/src/cubeb-speex-resampler.h":"dbf543eee4cc6e40ba3531a39d327e2cec884c19e26c570aa7eae0647e5f7420","libcubeb/src/cubeb.c":"17d0e6d44f96703e04d326a0a3b7df2632332b1df0e47c136fab30d5f29e4917","libcubeb/src/cubeb_alsa.c":"5eec74a2d6136bc77f26cca98f5c7b2547bc9e78e438589f55f048860f776328","libcubeb/src/cubeb_array_queue.h":"5264ae02799c540ff73e8eb8efa55986772b22562a025ae227c2603b6b8d1036","libcubeb/src/cubeb_assert.h":"ab8ed4fe7070a3aed9419c5f9695fce2318c4dafd91213ae61cac476e64adaa7","libcubeb/src/cubeb_audiotrack.c":"10e55c09b445c078cf40d7e187f606ab2fcd0b86ffe60ceb8319b6e9aabf5a71","libcubeb/src/cubeb_audiounit.cpp":"00267798952785f70ec455a1a405b18991257f105700cd3eb38297ba7fc38f12","libcubeb/src/cubeb_jack.cpp":"54ad5f1238730894754dd2d4c1b74021db44172357f411f75aacaf6ca68b6935","libcubeb/src/cubeb_kai.c":"a71e1de94211ff0e5667a218d71588f1e74102ccf0140b80925c277949871095","libcubeb/src/cubeb_log.cpp":"74bdc0d92a31d6b4ce3c376c6d310db583b869d673e40e6bd0ea795a1e2f937a","libcubeb/src/cubeb_log.h":"ee05fd22ed9820bed79247b8603cdc64f67bcb145be47e78bf0a0e99fb6c0806","libcubeb/src/cubeb_mixer.cpp":"574b33c0026cf02aff39d61a3a2768163422484e1e81cb46b2eb718469244fa3","libcubeb/src/cubeb_mixer.h":"ada2bb1d3356bd2d4e4fb991e63cd2c1132b46e4a832b0fba9842cb836c6c9da","libcubeb/src/cubeb_opensl.c":"86ed3bb3a33b83082bd24ed5cd5f9d3707d18a7942983456709383ea08aace33","libcubeb/src/cubeb_osx_run_loop.cpp":"13c029f7ea04808597b8841b13f248c4476fb7425762f01a59bc6c944cab3a78","libcubeb/src/cubeb_osx_run_loop.h":"ffe80df60b8ea3d0341715b72cc60aae2e0df45141887c01117df543260a0ef8","libcubeb/src/cubeb_panner.cpp":"405a115ff0eb5f00dbab6bc8f2999b02ee4ea4792a87bad7ebd7218ee7980438","libcubeb/src/cubeb_panner.h":"5679df1b9d138c91f6ea642d51e6230cdf3163bdd65db156ad45906916cb74b0","libcubeb/src/cubeb_pulse.c":"5947b03784c22cb7cd5c457150722091566e630221e4250f8daf6b7657050a44","libcubeb/src/cubeb_resampler.cpp":"2d5f5f4ff242d61897b62b4aeaeee85633be54c1eb155c9e35a2c67d8d5b7043","libcubeb/src/cubeb_resampler.h":"ad9800a40c0272fb2a451c02367cc5a516a3067d4acf963d35eb31be367f9224","libcubeb/src/cubeb_resampler_internal.h":"4b4eb6aee343b9c1f73cf17b201329d3714ba44b06ecb1cebf950fdf93a9dfe6","libcubeb/src/cubeb_ring_array.h":"db8dec7a6d778a424045e5ac61c2bc3a3cec8c4fe8e4780f383db4b6f1b2438c","libcubeb/src/cubeb_ringbuffer.h":"2296255ca7835a3ace2fe1852054f43428b677f432b4174bd832ad0224a409eb","libcubeb/src/cubeb_sndio.c":"9bab520c5254f4861aceeaf31de7a1fb6e682191d5d7364f581c390a3f070977","libcubeb/src/cubeb_strings.c":"60f2b8c03a5a01925f9777eec0ab84b0e704b40c03e0d6b9c0e7a16246c81fde","libcubeb/src/cubeb_strings.h":"00e5dc97cf16e28cfb53aaae50ac0e3c0ae8a82aad0720ab6842ce5d9785c39f","libcubeb/src/cubeb_utils.h":"c8229a25741577dde1917375688c463cf671a1ce81b4b058ecea7309ecc260f8","libcubeb/src/cubeb_utils_unix.h":"2a48bd2aefa1b4e4e4968121512bcaaa6be3bca6597ea390b8203c338f5c49b5","libcubeb/src/cubeb_utils_win.h":"74658b6266a8a223c681b0fd06fcc9c891c7b0b95377635c6f1763b240c2ab27","libcubeb/src/cubeb_wasapi.cpp":"bde4016dcb93c5cd36f68c6d44c72b3f58c3794325e48907c0b466dbae66e5f6","libcubeb/src/cubeb_winmm.c":"d61a4f9c4c52ad79275af2e120de5fd35f54a8e7b50072b71dcaf64279d05665","libcubeb/src/speex/arch.h":"2300bce68c588270cdc684dc7f01377e5e251529f4545d93771e111c56d51b0f","libcubeb/src/speex/fixed_generic.h":"306ee7453677fa6067f16c79d358c6c90a9d3d008850b493cdaa59c07e6375c1","libcubeb/src/speex/resample.c":"9c3a1c64ecf3750af82c980d01ea73d3682f73c332a580465d1e787e5c54cd00","libcubeb/src/speex/resample_neon.h":"7d3fd7af9a1ddde22518b9c7b4419073b72b2dfa5be4c3bc8796992bc87b3da0","libcubeb/src/speex/resample_sse.h":"5a196d8e2d8ab5c956f5252f09f5ddc55aee1f99b1341af3fa54a1f4c2157924","libcubeb/src/speex/speex_config_types.h":"24e3ffbf29e5519611a48e5acb959645b01d166dcb4369380d5f776c3f53d4cd","libcubeb/src/speex/speex_resampler.h":"7e439ec0dd30c32216b3ced17135f8992e5aaf53389d3f5996a7d900c453e65f","libcubeb/src/speex/stack_alloc.h":"e8a2fc0874942d2c7177475fcc141fdd0c0156200b8a4e7656d4a20313e2e569","libcubeb/test/README.md":"1c11b038f87daf10ea78abc17bdbdd157940c241df548c24d5872d142a98c1af","libcubeb/test/common.h":"f29b051ef7f5ff8ef08f6b7cd51229381ad4f1cd7454563c3f96188db3e6ebaf","libcubeb/test/test_audio.cpp":"3be1f9d1f5c4f37f7743ffa4065241c746859b8a57a86e687890ceee5c69f957","libcubeb/test/test_deadlock.cpp":"c311519f30c05300715e91b529685a0c61b8e6b67161fa1f4aeb7030587d86f9","libcubeb/test/test_devices.cpp":"eec312a08667d053216a4266ef9e2b04dcdfa487cc4d34a811bb64cb33ed2937","libcubeb/test/test_duplex.cpp":"add22390fe2dbba09def4cece9a0a6a8e69b24a97f874312b931ece43b1ec4c3","libcubeb/test/test_latency.cpp":"0ace31644f499d69adcfa0aa3bad8c859ad51e97b622e2fa6d26374b8af12894","libcubeb/test/test_loopback.cpp":"05aa359587d0e8739889a15f3296cfe338f36352f55abfa0aee1674a23b762b9","libcubeb/test/test_mixer.cpp":"42dbda1b84c91185fccefd21e936b24e0beb0a8dcf0daa7e1418ef0ee031bcda","libcubeb/test/test_overload_callback.cpp":"8a05771e5bedfabf9f8a2e5a9266df90f5e964ead3b07782e2e435d7b69b0beb","libcubeb/test/test_record.cpp":"76d5b4f738ca7c30836ef6cc5851f3e04e396b21cf26511e0eeb7a616049fa04","libcubeb/test/test_resampler.cpp":"ca4bc0493ce0c3a5f02f389ac6e37bc2cdb9a752faad2b6fbc5af0a2223ef645","libcubeb/test/test_ring_array.cpp":"27836d716616abf8b020a710659c10ac5e1d4b64149d22cb89bd7a7a5a5669d1","libcubeb/test/test_ring_buffer.cpp":"f6e5a9f552f15808eb8ac3405559bf0ea61e7da4219cd14ac49fff3bfbf49ca7","libcubeb/test/test_sanity.cpp":"e54ab30e6d897c15fb997d7593bc118b87e9cc0ddbc58b951f509872e47ce524","libcubeb/test/test_tone.cpp":"3938250700c708c9c742ec8d0c9c2984f3e11860ff8dcacdf0ce785d4668f789","libcubeb/test/test_utils.cpp":"e8d7a02a9096dbc0fd15d71f9849415d52958d2ed82cbc7b8507d3228e08d382","src/callbacks.rs":"b4b4eb3f370475488d7c77b338b0bceee94ef59ede8ff41fa797a3d35ea98b5d","src/channel.rs":"a724887b18c796f070d94894e76cfa61d1c5572497bcda011e46504d887537f4","src/context.rs":"dfc04eaff022f377c1e3523a674f088f25b45845a4af4c48faca8ba29c7cc1b4","src/device.rs":"5b65e1c1fdd53fa5208f20bfb809475cbb3c434e02db7d0e4771d13c86f8e369","src/error.rs":"406e3b843ed2d263fe677c4b34fb96a6d780a68bcb56a6f85f041d20d70227bd","src/format.rs":"d4d27790c20eab0b16592f60d5e487425a45a268cf4c74cf843c10ac91bbff4c","src/internal.rs":"c3af5f53dc7957860bf3bc0cd9737d094fb8ac000e7b40c569304cfa76a43145","src/lib.rs":"cb49a3dd8782369172a2f8a61d5c74b4615bfb5fba3677af7d5c149e47d71815","src/log.rs":"6694178177775f2ce5449435d00609e9361c836e23119c07d04892000587dc55","src/macros.rs":"caef13f5d23f7a3ec1a54ec3ca2390ac4ad89d521893f1d0864daf70d57a20aa","src/mixer.rs":"485022afdf333c86d267ac45e54c9c7bacb1268459c6c2ab1ba5d5c0c3608081","src/panner.rs":"341af4b5a5331a3c1a4ab5396125a3600945e588ea33350431dfe6f1a9a0bd80","src/resampler.rs":"762070f8afde2256715b8764380cdfa1204a1a39d98a9da0b2efe88699792f2c","src/stream.rs":"ea3080b6225949938098e3ac38c42939c49a91b322b327ea66e959fe41f51763"},"package":"fab28c0e152330f74bcbec1572c374397458957d5ad50605879352ec562f41aa"} \ No newline at end of file +{"files":{"Cargo.toml":"3a9a9f86b409fd16755421048f3ba976501d321acd698601fe5930d7da8b1ada","LICENSE":"8c044baa5d883274736eeece0b955249076c2697b826e576fce59496235b2cf5","build.rs":"49985a30631de0015517fc260321aa03a003eaf26d80650bebd928d55edc9444","libcubeb/.gitmodules":"6fe6fc18ff76ba8dd3dc749247d61a2f4a18c1e42b1890581e234ab8151d4c95","libcubeb/.travis.yml":"edb891b3c9edc375d8296d93a79bcbb8e5f884f695b3115a7c0d57cf45471823","libcubeb/AUTHORS":"829e45d138c7c8827799f302806fa4be8cd8bd4bad70a2fe26c3a27a5cf36948","libcubeb/CMakeLists.txt":"381886472be5fc0f925aa42268fd2df9f17f5613ee7db489849af474189f0358","libcubeb/Config.cmake.in":"88019286c96ef3d5d3a673b183c8655dfc97ceede07d3eb6c18f0c51bb896388","libcubeb/INSTALL.md":"7a84cdfbe86e7d3180e2203603b88571df61b369421fa97ee86740ffd4d4db8e","libcubeb/LICENSE":"44c6b5ae5ec3fe2fbc608b00e6f4896f4d2d5c7e525fcbaa3eaa3cf2f3d5a983","libcubeb/README.md":"aa417156dc65069264901b75fc3c792c73021ec61c909de04e109bd4184c07ab","libcubeb/TODO":"6f8065136e005d2becee810e3d8697a94f2c755f8c79687adfac7136ad165e80","libcubeb/appveyor.yml":"9a87fdc18b76fca1167289ecb2ec3a210b76984c1d7e92268b2cd36f1e00f541","libcubeb/cmake/sanitizers-cmake/CMakeLists.txt":"89b282c19b3897ff666f7847d5e679ae928ca7e76ffd0d23f7c58c9464048b61","libcubeb/cmake/sanitizers-cmake/LICENSE":"4b67e7ae8c91e68e1a929eb1cbaa4c773c6d19aa91aaa12c390cf9560d1c9799","libcubeb/cmake/sanitizers-cmake/README.md":"30ab1524618ac828b75f9b83c665a0bd50b839b42ce61519a8048d73f401da6e","libcubeb/cmake/sanitizers-cmake/cmake/FindASan.cmake":"cba07ffe438c57bef0840ed6a2d2890676530b66509da3c616438c53018baa4f","libcubeb/cmake/sanitizers-cmake/cmake/FindMSan.cmake":"1303aac5028fe9f64d42be0afd47f1291e679d74f8280b3dc5271f20ebf4d7a4","libcubeb/cmake/sanitizers-cmake/cmake/FindSanitizers.cmake":"ce1971b943bbef08fb9aba958cf28e3cbdff075406c85a3cfed22e00c9f8d9a8","libcubeb/cmake/sanitizers-cmake/cmake/FindTSan.cmake":"edca39b287312e9a8fc718f6ec791d2520515900b37426091310fe1bd52dc6a1","libcubeb/cmake/sanitizers-cmake/cmake/FindUBSan.cmake":"5b9d3621f629c807a1345a7cb053677a8bf25782a079e345dda53d04aecdc4b7","libcubeb/cmake/sanitizers-cmake/cmake/asan-wrapper":"4e543936e6374e24b80a0f92135c07c2e2101c0d110e51bddaf0e70ae8ec391e","libcubeb/cmake/sanitizers-cmake/cmake/sanitize-helpers.cmake":"282620734c2a8062f1280d0dde3121b8b01af26e5ecaa7d4308e145f80ecd115","libcubeb/cmake/sanitizers-cmake/tests/CMakeLists.txt":"fb983bab7040be002847db59c2493abfd249f67ad06e3a9270fbceb9fabda11c","libcubeb/cmake/sanitizers-cmake/tests/asan_test.cpp":"8b351c7c8668b4a2438286df426f0ad322cade6d1c6199a74668ccbd1c5204a4","libcubeb/cmake/toolchain-cross-android.cmake":"59d2355845a71647b353fb8b18fca630db8ffee7bb8500143e2d6fbc409cec97","libcubeb/cmake/toolchain-cross-mingw.cmake":"b09dc261981c0d4a0f8430f05aae9c8fc545651cd9cbfacd09754277b776b532","libcubeb/cubeb.supp":"19f33e59f8dc91a327c923e44c2c3f9af0a043ce1d6a8cac275ba094b4bfe0da","libcubeb/docs/Doxyfile.in":"0815f19789cedd310652a133bab260c27b57e95f7a65458df2dfca38ea4f1041","libcubeb/googletest/CHANGES":"72c8a289bfe4dd9160074a3a2238c8067a5bc7ca49fd87f70a134c3f373932a4","libcubeb/googletest/CMakeLists.txt":"cdf938ce79ea066866dc614de3925bfaa48d9e19e04049db2ec8c5443abaaa9b","libcubeb/googletest/CONTRIBUTORS":"4d911cd5e6d71f3f4bbcb2788b2f916df4b0ce1e088752a159457a1d936ae0ce","libcubeb/googletest/COPYING":"9702de7e4117a8e2b20dafab11ffda58c198aede066406496bef670d40a22138","libcubeb/googletest/Makefile.am":"a795e5a18e82ba06fd97509d92d773b7fafd0dd7086db8a1211fbd151b503bac","libcubeb/googletest/README":"484b19654362942fac9734c8fab0ed3d99249b81c69027bdb7de46054abada6b","libcubeb/googletest/build-aux/.keep":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","libcubeb/googletest/cmake/internal_utils.cmake":"6f4670a5825cf8ae0415be9dd43d82a7f30316d75cab20a4c60afb6d9db2a01d","libcubeb/googletest/codegear/gtest.cbproj":"9fa07a66b8c01773256e508187775407c465ed9055651e93d390426d1888721a","libcubeb/googletest/codegear/gtest.groupproj":"76c001cb2ee0070e26d1570fb6db5250f2585179c707496c5ef6d12e582cf205","libcubeb/googletest/codegear/gtest_all.cc":"c8750dc2b7b3612edb60e8d23fc2f60ae264451916c4b15f81cbf60ea30eb75d","libcubeb/googletest/codegear/gtest_link.cc":"e5e47c086f932471e0ca748a62b3b1597e5e731f4d34fb8cb8b2ca2db7ba3ed0","libcubeb/googletest/codegear/gtest_main.cbproj":"056448ba7f41fae3f704b1001922d9f6e419cf8cbcf3a55bf0ecc59ece1fa9a1","libcubeb/googletest/codegear/gtest_unittest.cbproj":"2c48be90b0dbc3224a8bd6c4dc21f78dd1b08c81685e6bd4952bb6df6ee38701","libcubeb/googletest/configure.ac":"fadebffdaeaccebb60fbe4a501c1138c296e01348a5da45fabf5e4233248baa8","libcubeb/googletest/include/gtest/gtest-death-test.h":"fdd087f700cd04a3ce4bdd36f35769de52a44bfc0c5bae2dc9681d4cbcd3c44a","libcubeb/googletest/include/gtest/gtest-message.h":"eaf44df1284d94333507c47091c84eaaf43814e6a02a1b1c0061ca7b363e74d6","libcubeb/googletest/include/gtest/gtest-param-test.h":"f226f0a24c04cddbceaaa45d8a5e575ce18c3392349f9b8ba73317e37e62368d","libcubeb/googletest/include/gtest/gtest-param-test.h.pump":"17c65fd5cc5218279044a61f3873c9c952b0924a7ba5147d4999d400b122207f","libcubeb/googletest/include/gtest/gtest-printers.h":"7046f611398d63ee0f1c37bdb4fd08d9931979b2fedf13b781e6d85d4b3b5d60","libcubeb/googletest/include/gtest/gtest-spi.h":"560407dd45e8e57fa6927504c9e4a4cfdecf30f8cada975c1ffddce765e6a88a","libcubeb/googletest/include/gtest/gtest-test-part.h":"c4d6d840284728740c284646075e8ffc85b63b9f74f3ed488b18ef3c2c2b9005","libcubeb/googletest/include/gtest/gtest-typed-test.h":"1ec858bbb9ed8a8bb553232df016437c080b2670f00453b4de297c286eb78c21","libcubeb/googletest/include/gtest/gtest.h":"47433ca72a43bda7a380c34fe6d4ff451797c687e9bbd74d1f366bcdfa0cb013","libcubeb/googletest/include/gtest/gtest_pred_impl.h":"f03a3f77e3c231889c0ace6f63b2c4e410e4a9330287ea09443b23b9a3cf9092","libcubeb/googletest/include/gtest/gtest_prod.h":"4a99a3d986a45b4d6d9b3af54809f015c54aa98274793a4ae173f5010d0ad33c","libcubeb/googletest/include/gtest/internal/gtest-death-test-internal.h":"0b3abead866363f3e6b4201acc8d2763072e033826b22ae5ebffd790e1415235","libcubeb/googletest/include/gtest/internal/gtest-filepath.h":"638d2bb6c06a894513b03311a8e931ac835fc00afc4bd21fab3afc05732c23a0","libcubeb/googletest/include/gtest/internal/gtest-internal.h":"12c2c83df0a9dc5b46697ccd8271dfa34ee5f3d1972dcb56585bc1459d9583c9","libcubeb/googletest/include/gtest/internal/gtest-linked_ptr.h":"9bd319548dd073630dfd349c06a440c6a582feec47d4ff14f348ec32f8b4c1f3","libcubeb/googletest/include/gtest/internal/gtest-param-util-generated.h":"10db93fa7e98820192bae6f560664469dd33b265036fca64253c89b6801f96cb","libcubeb/googletest/include/gtest/internal/gtest-param-util-generated.h.pump":"abb72365d94d2811b34c195dc520fbf41c7dcb42aae5a1cfa0502cf619b21e70","libcubeb/googletest/include/gtest/internal/gtest-param-util.h":"7f9311f033ef6916217d87cef53b1db6c4e8733be930e4b48fe7e11d21b33da0","libcubeb/googletest/include/gtest/internal/gtest-port.h":"612932c2930a7cf2c3514d89a8d6b51a2c0030d251309b71765ed1c9954e20c5","libcubeb/googletest/include/gtest/internal/gtest-string.h":"a46aa36165c400d1e926f942be03fe04cd7ccb1e59f7a2a03b919c4eea05b997","libcubeb/googletest/include/gtest/internal/gtest-tuple.h":"43e7e3c92f8e4258cf3927a9204b214d4d03e6c796f88f3ad4e66b1ac20aa938","libcubeb/googletest/include/gtest/internal/gtest-tuple.h.pump":"16fa027ed3c5940699e0ac906815e66620993bcf75b0acaf826d4f09348d4b83","libcubeb/googletest/include/gtest/internal/gtest-type-util.h":"6d177af46a9b1e14b969972a8b886667f95e69037aba411433a44fb9b92e7037","libcubeb/googletest/include/gtest/internal/gtest-type-util.h.pump":"22092f44127af91651f57ce222e20914d5d32ae02f1c0964f6d5d7bc019af339","libcubeb/googletest/m4/acx_pthread.m4":"3326e3746b6b351d1671fe31f798269cda8de92c365b8a8305404ec0fa6c6b32","libcubeb/googletest/m4/gtest.m4":"d3c37ebd1aa792c967d4357755cc670bc6deb30091d9e6db498871d90a30ea4c","libcubeb/googletest/make/Makefile":"9b86e2a112dd55c6bf6a2b39e6f4078faf60cfecb8282ebf9b025167ed233420","libcubeb/googletest/msvc/gtest-md.sln":"0beab679b42cf0c431eaf4fe143bbf3b01fc064e20c74d9e33e7e437a70487d4","libcubeb/googletest/msvc/gtest-md.vcproj":"52e873e964daf9d5409b4e9bb471ddf2827be04985cd96c40620f9275d17a256","libcubeb/googletest/msvc/gtest.sln":"be21c2340650ec2259a2fbaeb8608ae6d3e982a0626a0f91128a771dc88e6bea","libcubeb/googletest/msvc/gtest.vcproj":"0064616c7d88a284c1b7c05baab038f239134ea9c6c563628f286f9600b3f921","libcubeb/googletest/msvc/gtest_main-md.vcproj":"f83a294a92b616bf34ccae6743ff916297bdba61d6125a9637a813d467a30372","libcubeb/googletest/msvc/gtest_main.vcproj":"9f03270a00896eab0c7015c6fb1a73818d024e462d3944ba1d3ceb313a051649","libcubeb/googletest/msvc/gtest_prod_test-md.vcproj":"7caa108733e2d5f140da004d2133e04a9a105811909c0e2d4ec06e2971983592","libcubeb/googletest/msvc/gtest_prod_test.vcproj":"cf5bfb7f3de9a59a0eba5535067845d12c33c3fd8fecc3d03aa702665db29578","libcubeb/googletest/msvc/gtest_unittest-md.vcproj":"e7949b21cf0418f2a7afe8aa94616e2c40e3ba0801c2f0826f3a3a3d2e6f48b0","libcubeb/googletest/msvc/gtest_unittest.vcproj":"5b097d596fbbc1c4090fd518008a0961b29661194e1c02d8a2d3daaa557e626f","libcubeb/googletest/samples/prime_tables.h":"2903df1d1e6643a5f624fe3ea3f931c3410eb1858ac347c5df278273c6c91ca4","libcubeb/googletest/samples/sample1.cc":"dc106c5940d87bb4bbef3d77815eab642ee173a3340b2b9c532b5c711c4c2d0e","libcubeb/googletest/samples/sample1.h":"7a7bf9a0fbd2401e8b2cb554bfcb9bd0ed228212f3b970675c1b1d38d4e188bb","libcubeb/googletest/samples/sample10_unittest.cc":"ccebb6393a5a8468399f7e511219b667a2233f82312ce59834a4bb0997d8700e","libcubeb/googletest/samples/sample1_unittest.cc":"904be0d4a095e74393515195392bd10e1e916bb2ca61f3f94b1bd6aebea29cb6","libcubeb/googletest/samples/sample2.cc":"f14b8a1e69d52eef1a70053fb256818c7eca64e8eda08de43cf46e896e57fcc2","libcubeb/googletest/samples/sample2.h":"df956ba520dafca068dbc1e28f36567db3cba36293e06762318af8cda6a12bd4","libcubeb/googletest/samples/sample2_unittest.cc":"abe7e0b253d328cb82ae67623fbe3c89eb94699102510c64a0b568eaca101e05","libcubeb/googletest/samples/sample3-inl.h":"3fe482bbd4f725f5820f5d6beab4d0d4a524be8addf4b344a9a470ec5aabc451","libcubeb/googletest/samples/sample3_unittest.cc":"252c06b4531dc35213ebdd7311700b9b4057bc1bdeeba0cd767b2bc86c456639","libcubeb/googletest/samples/sample4.cc":"b4260f5fa35d78ac114a9abb59fce12403faf0273df41f57e83c341ae7979222","libcubeb/googletest/samples/sample4.h":"604905cae7e5587805c3b884a36eda7a2bebdfedb53b24b0fd9a220eec0ef1a9","libcubeb/googletest/samples/sample4_unittest.cc":"6cfb4821d8cb1c77fbb5af4f8aec569948762d8ea314827e3ead967b5b6a223e","libcubeb/googletest/samples/sample5_unittest.cc":"73646d9038873a68bb2e56b12495d7f7b65b5c23901109701da446af454ba2ec","libcubeb/googletest/samples/sample6_unittest.cc":"833fee399954f908cf0f3b789832e505329787f4cf73607a7b31ca0f62f368d7","libcubeb/googletest/samples/sample7_unittest.cc":"8013ee68d61c181e4e936cdae3a9a635646274f8512033ef11bff7214e03e4a6","libcubeb/googletest/samples/sample8_unittest.cc":"7b7510fadf4955d2f934d23d652dbd35add832e50bdfcc98421fb9be4588d808","libcubeb/googletest/samples/sample9_unittest.cc":"8b827040dea37b460cbcaea0b255b98974a9840f6ef7bd82aaa7d4ad2c724335","libcubeb/googletest/scripts/fuse_gtest_files.py":"adecf64c6bab65b31740c321e568cf174f753d5617745aa5762d842339d68b53","libcubeb/googletest/scripts/gen_gtest_pred_impl.py":"78fb7e20a014c251d723186eb58040e4eb32405b73c9288d787ea0a0e4ff5183","libcubeb/googletest/scripts/gtest-config.in":"9a43978eeee88e188845d737c17f4d024d4e74feae09da7997e8fbe4ea6cc176","libcubeb/googletest/scripts/pump.py":"3856a3d7be37f78e0f214ee7d4f29d05f1ca14218b67539d67c9a16e992f670c","libcubeb/googletest/scripts/test/Makefile":"3576b257594a2d8e843b9e4de8c83353d837833bb86431fb1b4198022b1bcddc","libcubeb/googletest/scripts/upload.py":"f75d0712e3b13bebd8daa0a15e4eb32c9e3034a933f4fcccf65b1e999a7ae066","libcubeb/googletest/scripts/upload_gtest.py":"6e76fc0a7a3831c01cfffd18c220d44438073a66338d91ca61fc84b924021e61","libcubeb/googletest/src/gtest-all.cc":"568ac119f5e6418f1fbcfbdf185d724657d7f3539b47822da229ac5d015626b2","libcubeb/googletest/src/gtest-death-test.cc":"eec1b3c8252670c76acbbaf63483946897ce625139b53a566406b6313f023896","libcubeb/googletest/src/gtest-filepath.cc":"31b7fcda5d11346f8a487597c6a70ff057f1192e0cb11f27eb7841a9f3aa8b86","libcubeb/googletest/src/gtest-internal-inl.h":"c9d428a6b5990ace091e40c4ce8b7bf6c50c186a8314b1c4a4cdc988ca0ac1a4","libcubeb/googletest/src/gtest-port.cc":"95bcf473622d1b901c734e5c2aeb8efb058555ec924212a61bb04f049bb5a069","libcubeb/googletest/src/gtest-printers.cc":"6f191a7fc7f5a0a967fd11964057f2e2d2eaf2f37ccece16bd816531f52b3154","libcubeb/googletest/src/gtest-test-part.cc":"e489868b4cdc66f4fc33bc2326ac86bc1acc5808ab58bbb288c9dcfc330faddc","libcubeb/googletest/src/gtest-typed-test.cc":"ca9e819df728c25a6a1fc072806c22f3494e1dffe4bd0d48284f38dbdd3a0dd5","libcubeb/googletest/src/gtest.cc":"5cf9a3e897892c9f0e5c887f91d3c8c8c5665bd7348560441fc0b946c254873c","libcubeb/googletest/src/gtest_main.cc":"22fa1f77542b882d1798d7f696045c5895942a626e26200a175fa4382e1fa5b5","libcubeb/googletest/test/gtest-death-test_ex_test.cc":"613ccf50a3ff8f84c975a13e86ea01ea4e36933072388a3738b4acf9ed3ed7cf","libcubeb/googletest/test/gtest-death-test_test.cc":"df8384a847bdf889233c3d45d171f784991def7a9b6a08442138569fbae32b9d","libcubeb/googletest/test/gtest-filepath_test.cc":"49760f91723845b113bb60bb9b1a1426ed1da1f4ebfef2462128980ea5692cc9","libcubeb/googletest/test/gtest-linked_ptr_test.cc":"1b9cb4ff67475900db9de34ae9749b94193048a1f7a741091ba5a2dd7fc7a79b","libcubeb/googletest/test/gtest-listener_test.cc":"acf78f2c9a730525ea5adc93e9196a42de8fbfe488db1dfd02656bdbd477b2c0","libcubeb/googletest/test/gtest-message_test.cc":"b1fc68f8b75ce25fbd79b3f7d3c9c793381ef07b3203e1a2d9b610cb597542be","libcubeb/googletest/test/gtest-options_test.cc":"74e3ae0c310edb3139b0032266219d3ce7f386ded6feafa57fef03f4493ed7fa","libcubeb/googletest/test/gtest-param-test2_test.cc":"a0f1efbcab3f7e49df639383157626931f64756f7e738be081760f93f7308332","libcubeb/googletest/test/gtest-param-test_test.cc":"ef8bd344e959053f562b0c9e0d15e2fb6c1e534772a67aaf3f90bd6bad0bf99f","libcubeb/googletest/test/gtest-param-test_test.h":"9d7f47b79d54df7cc050aa6038b0464aa684dfca669a847bf70ea16e4a000628","libcubeb/googletest/test/gtest-port_test.cc":"1600f78ef0860a0f5b5525e5e5041ff32a216cc6ae948b1ea61fe04ec603f67d","libcubeb/googletest/test/gtest-printers_test.cc":"7898e4b4163ee0821fed248e1c75d9f4a0a511a2b4bbfad1ef2f4a11a099f6e7","libcubeb/googletest/test/gtest-test-part_test.cc":"62c8906bb0d12ea84d60217b3773cd8e1768db4aab934880db2316df7026cab8","libcubeb/googletest/test/gtest-tuple_test.cc":"2850dc1f73a3f8020d8a4d80688a28d9b736eae6d677222c3f871d8d33b25501","libcubeb/googletest/test/gtest-typed-test2_test.cc":"c52b65e7181610d6e577631cd50177399884913ff28d08aedfedc92f05185044","libcubeb/googletest/test/gtest-typed-test_test.cc":"c7daff5211028da79b3ca0473dca18ada9197f38e710f72d0493ad3332ce3ec9","libcubeb/googletest/test/gtest-typed-test_test.h":"3145698534d8869beb624c9c8ed114f75bead046b2eeb92ada5a724993ee7786","libcubeb/googletest/test/gtest-unittest-api_test.cc":"e3f54c28ef2849e8b12af666ed46aace50c3e047845072ee6f974ce4528bd297","libcubeb/googletest/test/gtest_all_test.cc":"db0c3c42b385570b1d517e3ee927671b8fad4e206247fca738ec477222ac3d97","libcubeb/googletest/test/gtest_break_on_failure_unittest.py":"11c91bc1c68cfdb913e2affb01261b55fb3b0c18773a45875e9c25cb330a4dcd","libcubeb/googletest/test/gtest_break_on_failure_unittest_.cc":"1da12e4bdda2a0bc7b59d4638fe34b2d3798134224fd9237eeebdd09c3326011","libcubeb/googletest/test/gtest_catch_exceptions_test.py":"305cef45c6dc034bdf72fd91aba1e89e1c6b5d222c3d6baffff5acdfd9b3873e","libcubeb/googletest/test/gtest_catch_exceptions_test_.cc":"b297a4f4d5bc0285ea9eb8869741631658305e49d4513bca904842aacb82128b","libcubeb/googletest/test/gtest_color_test.py":"c4cb006682a40f2d88759a4bcabf0d4be623720b135c71447f1788d17ea23d0f","libcubeb/googletest/test/gtest_color_test_.cc":"f263ba349afe58a558bf0fee98a98bb9207a648e7cd4f908a87799bd13d001ea","libcubeb/googletest/test/gtest_env_var_test.py":"79819598cd1e366eaa8f2a4fee2d638b6ef0686e490402fae792ccce58d876c0","libcubeb/googletest/test/gtest_env_var_test_.cc":"0eee5dfbb2a2598f4e76626346b921928ec1e052e38f254cc97c60d05611ab46","libcubeb/googletest/test/gtest_environment_test.cc":"a52a21ea29c2203b03fa93922733546d171f98d3b2fcd42972269e98fd124715","libcubeb/googletest/test/gtest_filter_unittest.py":"edc7d278803bba41626eacd050d91d7247f1c5999f9dceb99a8877e238bc73d6","libcubeb/googletest/test/gtest_filter_unittest_.cc":"996ac528ad75c293d8201ce28cf6acccee266286bd369b4cf43f05b8d67a4559","libcubeb/googletest/test/gtest_help_test.py":"b43ab690c08e4bffd84a47b361167496298697f9511bdf4a745bf305b5cfbdfc","libcubeb/googletest/test/gtest_help_test_.cc":"ff4b121098f0fe7cb4abf11fdd31f2fe7a477286ec9175482138bc038d61c807","libcubeb/googletest/test/gtest_list_tests_unittest.py":"7caebc175b44b3c727fc50420ada1a6a9500f3e4ce9e2839f69205437aa85e7a","libcubeb/googletest/test/gtest_list_tests_unittest_.cc":"d82d8b72914897232c2ff9fd091a7b0add68b7cf75f3f210d3a487ebeea84cfe","libcubeb/googletest/test/gtest_main_unittest.cc":"0f66f318809c88f0fbe034a340a75331720c4e33be5378022baffaf588ef1202","libcubeb/googletest/test/gtest_no_test_unittest.cc":"7cf487e07c3d27376c2cb8af33d02239b7966623875d37b7aa0259e927a9c2f6","libcubeb/googletest/test/gtest_output_test.py":"cf0dc1979572d94450a5e611b44f3fdb88d9cd980d669a723f0ed63057b5e2c4","libcubeb/googletest/test/gtest_output_test_.cc":"f69569374c2b3d06aa04a38ebc4f92ddc303e6af503f8b533cd8e6bf9f104899","libcubeb/googletest/test/gtest_output_test_golden_lin.txt":"4f3e49c10a524a99437cdcb5294e3335a7f3c07ea8462e65730f703a5fe4fec3","libcubeb/googletest/test/gtest_pred_impl_unittest.cc":"e406eccf75b6b58746a95d1c7ea7bc8e80ff974e438ef7c83074a46d4e62db9a","libcubeb/googletest/test/gtest_prod_test.cc":"b42ca1a6d0a1e43bc576b4ff7776c6d2c37234f6dc2a76f2735f261b4a47a526","libcubeb/googletest/test/gtest_repeat_test.cc":"e10abbb71595920aa3bb415029eed74106335fc9ea3d58c417ccfc7cba6a4cdb","libcubeb/googletest/test/gtest_shuffle_test.py":"12dd94eb5f30260ba37059fa74658bda57dffa821f3ba6a2a8b52ff14b1ad029","libcubeb/googletest/test/gtest_shuffle_test_.cc":"af1b2b01ae275f1a9fee7e7940c0f88f39ded063008994d585aad87e3ffadb39","libcubeb/googletest/test/gtest_sole_header_test.cc":"538414c27a593ab8dc34c37b5c877eb3a022d75d1b481ef14ceca00914929754","libcubeb/googletest/test/gtest_stress_test.cc":"0b02fc12f87944226915a999bdcc8a3eaafb34a1ea5bb0df128774abf8667f09","libcubeb/googletest/test/gtest_test_utils.py":"d4a76930aee6658ad8734981ca0c4ea14f34dbe8fdd31d5afe41f6d98f9779ee","libcubeb/googletest/test/gtest_throw_on_failure_ex_test.cc":"11ae790028da20bc7b7af1572eff3cfe8499be43ab64c110e18e1892612a183f","libcubeb/googletest/test/gtest_throw_on_failure_test.py":"ebe18ca0b07f90c53b9b3f9a54ed02df94facf8995cfa90dd41c6f5474537c13","libcubeb/googletest/test/gtest_throw_on_failure_test_.cc":"f8cbf75d8bf9e9ae068a17ff968434c3aec7b7f1137c994d8f14af1a84361aa9","libcubeb/googletest/test/gtest_uninitialized_test.py":"da8e6ce34930753e36fc1dfa2c3e20e48d02bda2a27d3d03a07364312c5f3bd9","libcubeb/googletest/test/gtest_uninitialized_test_.cc":"0b6a9d4983480f87352ca4da946089264b401f7a4a3b1282253fd6cc861bf483","libcubeb/googletest/test/gtest_unittest.cc":"c0c7d1f691ce1e10c3d1647ed5f7a66510725808ad58bb6da4bc03a7a08fb2fc","libcubeb/googletest/test/gtest_xml_outfile1_test_.cc":"29341d777a9c9d25f360d13ed966b30f0cbef1fc88aefe2f01bb88b82cf1ed93","libcubeb/googletest/test/gtest_xml_outfile2_test_.cc":"da7ab3cf0e9b2a293eceed7c5691233d6b61afb557e3c1176dfb75390f85be46","libcubeb/googletest/test/gtest_xml_outfiles_test.py":"b07927b43f44afbfd61761c2cc69f1b68c4fbdeddb992db03ff0c73052518cd4","libcubeb/googletest/test/gtest_xml_output_unittest.py":"b5ff0c0207238d01cada961b8f4656f2ec30a3e1e5bf9d22efdf1745af423031","libcubeb/googletest/test/gtest_xml_output_unittest_.cc":"ad0b9ebe63a146e386df3c5c51916869f6d4647b9832ceacc912fb1272d15f82","libcubeb/googletest/test/gtest_xml_test_utils.py":"ad89a39a6cd5b08e87082341f3e7800dbf1150ea0f1386e0b8cd374aa6832f00","libcubeb/googletest/test/production.cc":"56fef77c3a8e62073ec11653d740a8e534008a0d57925ab0877b843f4fdd6be8","libcubeb/googletest/test/production.h":"a36d10545d12ead5e93a3b0fdca6ff73405f29091cfe38164415e9038888ba8d","libcubeb/googletest/xcode/Config/DebugProject.xcconfig":"fb42302df29bd8e8b5237194c0c04941f0e578527037930d88469baeb7a7f62b","libcubeb/googletest/xcode/Config/FrameworkTarget.xcconfig":"9935ddabe221f074d2f3b969a137d12b0dc0f845a460f58b63232987cb0f37ff","libcubeb/googletest/xcode/Config/General.xcconfig":"0fb768924daba1048f8db28b3a1fbf915b6f788d49d9d37e85979aa4ee92e02d","libcubeb/googletest/xcode/Config/ReleaseProject.xcconfig":"a4878ddd1ed78fb411906623cb51bc0ab4aea1cc3feb5379d2ae2862d8bf3bf5","libcubeb/googletest/xcode/Config/StaticLibraryTarget.xcconfig":"5886291788b3e9d5aadcb979ff055fd26a2413be81016e7afffb813b627d177c","libcubeb/googletest/xcode/Config/TestTarget.xcconfig":"f074e6c2516a6063b253ec6b842d74f5c2abefc7bcf8d8da54097a7bfe016480","libcubeb/googletest/xcode/Resources/Info.plist":"5b7f78a6d5810ce5490649793175c8982d41e6b49af06bc0705bc061567cc9aa","libcubeb/googletest/xcode/Samples/FrameworkSample/Info.plist":"1c13d83e5eed45689d7fe4bf4681030366474bc40608e39e1623c1350513a0cd","libcubeb/googletest/xcode/Samples/FrameworkSample/WidgetFramework.xcodeproj/project.pbxproj":"1cf0e1b1abf84414372faf9c8bf634e01fe5750bb3ca769b1eb25fc530b21358","libcubeb/googletest/xcode/Samples/FrameworkSample/runtests.sh":"a587e5b00a8353dee0aca5a4c59b28301ccf7648dee8c79b62a9223f9fc3c8cf","libcubeb/googletest/xcode/Samples/FrameworkSample/widget.cc":"562a2bb615e93186012823c9b41761769638a11e38b54498ad5f699038c8fd32","libcubeb/googletest/xcode/Samples/FrameworkSample/widget.h":"0c7915e45cf7cb8d67db24e49cd0b277f23f967578f917f8e859a6adc4b156f9","libcubeb/googletest/xcode/Samples/FrameworkSample/widget_test.cc":"6a1a49d64912d9829ef3d991faf5a3f0e1e081126a1d8d387cdfa84fab70dc77","libcubeb/googletest/xcode/Scripts/runtests.sh":"1a0672a4151b16f3c797478ba26c534e82b2faa603f90b9aa14e785805f7683a","libcubeb/googletest/xcode/Scripts/versiongenerate.py":"4b9d5c0f4e1b556084109311d156bee6d781968dc5b1dfdc8702364508f1dd43","libcubeb/googletest/xcode/gtest.xcodeproj/project.pbxproj":"a1224decff058bfed01b8eefaee13cab0129492615548c6d0d878003a154f7ff","libcubeb/include/cubeb/cubeb.h":"a73748e7fafc73122a81f0639e9148179ca29b6582f225000a60283bf68417ab","libcubeb/scan-build-install.sh":"1ecf22aca367a4d02f810c4cb78db8636e08a12787e94e30c441ce439cf4a265","libcubeb/src/android/audiotrack_definitions.h":"0d5ec772f9ebf61333bc16e61a081a7e3b4cc02342ec4f8f417e220d032fbbc6","libcubeb/src/android/cubeb-output-latency.h":"000fb7bec38105f54b9d40fc436440c637d63390b219775d335216d29d767226","libcubeb/src/android/cubeb_media_library.h":"f67965fb2ea38f0023eb4c76024341ba9563ac1a135507b6f12a9aabd85e30a9","libcubeb/src/android/sles_definitions.h":"24e400ca2330ec16d3a37b69b74144697b51dce17f9ead763b1a6ffedc5633ac","libcubeb/src/cubeb-internal.h":"ef7e7e19c40f743c814a39b8a47b9f03df054894018ad88b49129ffad2564bfa","libcubeb/src/cubeb-jni-instances.h":"8195554372bf60dea569873c9e5fb1106a2cf5dedc66a13d2bc967da0ff48a12","libcubeb/src/cubeb-jni.cpp":"81f001720c41c69b5927e32bd19b9e8e7176d7c33d63c2a58bd0d695dace4fd2","libcubeb/src/cubeb-jni.h":"73f810a32087a6062fd49ba89542655a7e19cecac6f40f8411e1d77ce42a45d1","libcubeb/src/cubeb-sles.h":"dc84a01ba4de9db1ff108609930b36ba442020ccc3e3d6f16528f429426c430c","libcubeb/src/cubeb-speex-resampler.h":"dbf543eee4cc6e40ba3531a39d327e2cec884c19e26c570aa7eae0647e5f7420","libcubeb/src/cubeb.c":"2de6d02fefd308dcc755dc9009cdb42d2d60f900237b4eda305ddcaa180f13db","libcubeb/src/cubeb_alsa.c":"6c833e379eea5d64a65a209f8e60c2aa2d6e038ea855554cd3f2664c463abbcd","libcubeb/src/cubeb_array_queue.h":"5264ae02799c540ff73e8eb8efa55986772b22562a025ae227c2603b6b8d1036","libcubeb/src/cubeb_assert.h":"ab8ed4fe7070a3aed9419c5f9695fce2318c4dafd91213ae61cac476e64adaa7","libcubeb/src/cubeb_audiotrack.c":"fe66d36dfecbfaad164ee8c871b39fd6e708a2f8f1f8524a5c0148ab86bab467","libcubeb/src/cubeb_audiounit.cpp":"8c127f884bb773e3856cc7c1f74b85210d1c589b199b61a6d6322a9c0bc1fbd0","libcubeb/src/cubeb_jack.cpp":"129c011feb01e8c6d573862218c31a8bf90522539a28a5ece8bcf87867be9daf","libcubeb/src/cubeb_kai.c":"a71e1de94211ff0e5667a218d71588f1e74102ccf0140b80925c277949871095","libcubeb/src/cubeb_log.cpp":"74bdc0d92a31d6b4ce3c376c6d310db583b869d673e40e6bd0ea795a1e2f937a","libcubeb/src/cubeb_log.h":"ee05fd22ed9820bed79247b8603cdc64f67bcb145be47e78bf0a0e99fb6c0806","libcubeb/src/cubeb_mixer.cpp":"5ed48f4ff41100ed46292d45253a0fa52573c64022317c3311f9d586b98d4c6a","libcubeb/src/cubeb_mixer.h":"541846b5f3fb5ff5ed1cb97d25b5a9e733500faa9f8e1e76bb5e7ba25991ae7e","libcubeb/src/cubeb_opensl.c":"d10d2d35667a48c8fc31f0ecdd47a8c62d7988bc83fb53d4186d0f37c0fc2ad3","libcubeb/src/cubeb_osx_run_loop.cpp":"13c029f7ea04808597b8841b13f248c4476fb7425762f01a59bc6c944cab3a78","libcubeb/src/cubeb_osx_run_loop.h":"ffe80df60b8ea3d0341715b72cc60aae2e0df45141887c01117df543260a0ef8","libcubeb/src/cubeb_panner.cpp":"405a115ff0eb5f00dbab6bc8f2999b02ee4ea4792a87bad7ebd7218ee7980438","libcubeb/src/cubeb_panner.h":"5679df1b9d138c91f6ea642d51e6230cdf3163bdd65db156ad45906916cb74b0","libcubeb/src/cubeb_pulse.c":"f64e466cc704a569df9a7480062f5dee1c1ba1094762b6689d9941aa50bda208","libcubeb/src/cubeb_resampler.cpp":"2d5f5f4ff242d61897b62b4aeaeee85633be54c1eb155c9e35a2c67d8d5b7043","libcubeb/src/cubeb_resampler.h":"ad9800a40c0272fb2a451c02367cc5a516a3067d4acf963d35eb31be367f9224","libcubeb/src/cubeb_resampler_internal.h":"4b4eb6aee343b9c1f73cf17b201329d3714ba44b06ecb1cebf950fdf93a9dfe6","libcubeb/src/cubeb_ring_array.h":"db8dec7a6d778a424045e5ac61c2bc3a3cec8c4fe8e4780f383db4b6f1b2438c","libcubeb/src/cubeb_ringbuffer.h":"2296255ca7835a3ace2fe1852054f43428b677f432b4174bd832ad0224a409eb","libcubeb/src/cubeb_sndio.c":"d64d6ed34987d89a3041988274834a8346c3af6f08e3dd641a0cef2c71eab6c3","libcubeb/src/cubeb_strings.c":"60f2b8c03a5a01925f9777eec0ab84b0e704b40c03e0d6b9c0e7a16246c81fde","libcubeb/src/cubeb_strings.h":"00e5dc97cf16e28cfb53aaae50ac0e3c0ae8a82aad0720ab6842ce5d9785c39f","libcubeb/src/cubeb_utils.cpp":"5bd7de8bbf7bbdc3a275525edd92bad590fb90fb4d35e77017fdd5d25a5769e6","libcubeb/src/cubeb_utils.h":"27baa42747771bf9232741382b83722f5c731e5dcd4dc2e9b595aca91c5647a5","libcubeb/src/cubeb_utils_unix.h":"2a48bd2aefa1b4e4e4968121512bcaaa6be3bca6597ea390b8203c338f5c49b5","libcubeb/src/cubeb_utils_win.h":"74658b6266a8a223c681b0fd06fcc9c891c7b0b95377635c6f1763b240c2ab27","libcubeb/src/cubeb_wasapi.cpp":"1d476782be50c0944ed0ef4b24f8c64b17e315e1051941aed21b79d7bd06aeb0","libcubeb/src/cubeb_winmm.c":"3f59675847c8ff899d34898616d813b12bd3b6c925cb32fb43f6f9357d0cced5","libcubeb/src/speex/arch.h":"2300bce68c588270cdc684dc7f01377e5e251529f4545d93771e111c56d51b0f","libcubeb/src/speex/fixed_generic.h":"306ee7453677fa6067f16c79d358c6c90a9d3d008850b493cdaa59c07e6375c1","libcubeb/src/speex/resample.c":"9c3a1c64ecf3750af82c980d01ea73d3682f73c332a580465d1e787e5c54cd00","libcubeb/src/speex/resample_neon.h":"7d3fd7af9a1ddde22518b9c7b4419073b72b2dfa5be4c3bc8796992bc87b3da0","libcubeb/src/speex/resample_sse.h":"5a196d8e2d8ab5c956f5252f09f5ddc55aee1f99b1341af3fa54a1f4c2157924","libcubeb/src/speex/speex_config_types.h":"24e3ffbf29e5519611a48e5acb959645b01d166dcb4369380d5f776c3f53d4cd","libcubeb/src/speex/speex_resampler.h":"7e439ec0dd30c32216b3ced17135f8992e5aaf53389d3f5996a7d900c453e65f","libcubeb/src/speex/stack_alloc.h":"e8a2fc0874942d2c7177475fcc141fdd0c0156200b8a4e7656d4a20313e2e569","libcubeb/test/README.md":"1c11b038f87daf10ea78abc17bdbdd157940c241df548c24d5872d142a98c1af","libcubeb/test/common.h":"45eccf0f0c506f2f424149bc434180e296f85ed682b3ffca78cd53f91487d210","libcubeb/test/test_audio.cpp":"c10a9f438d8667153cde2ca13e4b2eebda22d0db93a045299fdbd8c924c44c6c","libcubeb/test/test_callback_ret.cpp":"fdcd25f6da30f2e1dba147d2a790994737d61afbaa30e0e0e9bf41dd5fa41953","libcubeb/test/test_deadlock.cpp":"c311519f30c05300715e91b529685a0c61b8e6b67161fa1f4aeb7030587d86f9","libcubeb/test/test_devices.cpp":"eec312a08667d053216a4266ef9e2b04dcdfa487cc4d34a811bb64cb33ed2937","libcubeb/test/test_duplex.cpp":"add22390fe2dbba09def4cece9a0a6a8e69b24a97f874312b931ece43b1ec4c3","libcubeb/test/test_latency.cpp":"0ace31644f499d69adcfa0aa3bad8c859ad51e97b622e2fa6d26374b8af12894","libcubeb/test/test_loopback.cpp":"e5dfcd868b25468a43dd4d8482702b9494e807db05c041b6fdcb295c59f1f01c","libcubeb/test/test_overload_callback.cpp":"8a05771e5bedfabf9f8a2e5a9266df90f5e964ead3b07782e2e435d7b69b0beb","libcubeb/test/test_record.cpp":"76d5b4f738ca7c30836ef6cc5851f3e04e396b21cf26511e0eeb7a616049fa04","libcubeb/test/test_resampler.cpp":"ca4bc0493ce0c3a5f02f389ac6e37bc2cdb9a752faad2b6fbc5af0a2223ef645","libcubeb/test/test_ring_array.cpp":"27836d716616abf8b020a710659c10ac5e1d4b64149d22cb89bd7a7a5a5669d1","libcubeb/test/test_ring_buffer.cpp":"f6e5a9f552f15808eb8ac3405559bf0ea61e7da4219cd14ac49fff3bfbf49ca7","libcubeb/test/test_sanity.cpp":"f978de12e7046518fbf848fcb5dbb2b5033c7624d5f4b59c0f3e02e7155c3884","libcubeb/test/test_tone.cpp":"3938250700c708c9c742ec8d0c9c2984f3e11860ff8dcacdf0ce785d4668f789","libcubeb/test/test_utils.cpp":"e8d7a02a9096dbc0fd15d71f9849415d52958d2ed82cbc7b8507d3228e08d382","src/callbacks.rs":"b4b4eb3f370475488d7c77b338b0bceee94ef59ede8ff41fa797a3d35ea98b5d","src/channel.rs":"1ae3c22ccc848d6d7b5d312e5a6e64b41871d5bb611d34192651356b57c253c2","src/context.rs":"96bf3442b1dd40262d3088dbb6c473f5451fd91320cef93c522b40f284599803","src/device.rs":"5b65e1c1fdd53fa5208f20bfb809475cbb3c434e02db7d0e4771d13c86f8e369","src/error.rs":"406e3b843ed2d263fe677c4b34fb96a6d780a68bcb56a6f85f041d20d70227bd","src/format.rs":"d4d27790c20eab0b16592f60d5e487425a45a268cf4c74cf843c10ac91bbff4c","src/internal.rs":"c3af5f53dc7957860bf3bc0cd9737d094fb8ac000e7b40c569304cfa76a43145","src/lib.rs":"cb49a3dd8782369172a2f8a61d5c74b4615bfb5fba3677af7d5c149e47d71815","src/log.rs":"6694178177775f2ce5449435d00609e9361c836e23119c07d04892000587dc55","src/macros.rs":"caef13f5d23f7a3ec1a54ec3ca2390ac4ad89d521893f1d0864daf70d57a20aa","src/mixer.rs":"1eb1c8eca9f3f94d7b9a179acca31faee6193d7177d502d5300fcb956430772f","src/panner.rs":"341af4b5a5331a3c1a4ab5396125a3600945e588ea33350431dfe6f1a9a0bd80","src/resampler.rs":"762070f8afde2256715b8764380cdfa1204a1a39d98a9da0b2efe88699792f2c","src/stream.rs":"ea3080b6225949938098e3ac38c42939c49a91b322b327ea66e959fe41f51763"},"package":"e405ad4dff2c1a7cbfa6998e5925e8ceafe900feeacfcad35a3e3790bea0f2aa"} \ No newline at end of file diff --git a/third_party/rust/cubeb-sys/Cargo.toml b/third_party/rust/cubeb-sys/Cargo.toml index 6e50a06ca36bbcbbc18e8da11f0c4fbe1df554ff..cd9f02ff45b6dae4976168767c4f9cc43438b917 100644 --- a/third_party/rust/cubeb-sys/Cargo.toml +++ b/third_party/rust/cubeb-sys/Cargo.toml @@ -12,7 +12,7 @@ [package] name = "cubeb-sys" -version = "0.4.1" +version = "0.5.0" authors = ["Dan Glastonbury <dglastonbury@mozilla.com>"] build = "build.rs" links = "cubeb" diff --git a/third_party/rust/cubeb-sys/libcubeb/CMakeLists.txt b/third_party/rust/cubeb-sys/libcubeb/CMakeLists.txt index 4fac1b8f0754d844f98d5843954ef2a96860dc24..cdb00f9106f9b931a4324bbba4daba8c9f1d8d1a 100644 --- a/third_party/rust/cubeb-sys/libcubeb/CMakeLists.txt +++ b/third_party/rust/cubeb-sys/libcubeb/CMakeLists.txt @@ -59,6 +59,7 @@ add_library(cubeb src/cubeb_panner.cpp src/cubeb_log.cpp src/cubeb_strings.c + src/cubeb_utils.cpp $<TARGET_OBJECTS:speex>) target_include_directories(cubeb PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> $<INSTALL_INTERFACE:include> @@ -181,7 +182,8 @@ endif() check_include_files(SLES/OpenSLES.h USE_OPENSL) if(USE_OPENSL) target_sources(cubeb PRIVATE - src/cubeb_opensl.c) + src/cubeb_opensl.c + src/cubeb-jni.cpp) target_compile_definitions(cubeb PRIVATE USE_OPENSL) target_link_libraries(cubeb PRIVATE OpenSLES) endif() @@ -237,6 +239,7 @@ if(BUILD_TESTS) cubeb_add_test(audio) cubeb_add_test(record) cubeb_add_test(devices) + cubeb_add_test(callback_ret) add_executable(test_resampler test/test_resampler.cpp src/cubeb_resampler.cpp $<TARGET_OBJECTS:speex>) target_include_directories(test_resampler PRIVATE ${gtest_SOURCE_DIR}/include) @@ -260,27 +263,6 @@ if(BUILD_TESTS) cubeb_add_test(latency test_latency) cubeb_add_test(ring_array) - add_executable(test_mixer test/test_mixer.cpp src/cubeb_mixer.cpp) - if(USE_AUDIOUNIT) - target_compile_definitions(test_mixer PRIVATE USE_AUDIOUNIT) - endif() - target_include_directories(test_mixer PRIVATE ${gtest_SOURCE_DIR}/include) - target_include_directories(test_mixer PRIVATE src) - target_link_libraries(test_mixer PRIVATE cubeb gtest_main) - add_test(mixer test_mixer) - add_sanitizers(test_mixer) - install(TARGETS test_mixer DESTINATION ${CMAKE_INSTALL_PREFIX}) - cubeb_add_test(utils) cubeb_add_test(ring_buffer) - - if(USE_AUDIOUNIT) - add_executable(test_deadlock test/test_deadlock.cpp) - target_include_directories(test_deadlock PRIVATE ${gtest_SOURCE_DIR}/include) - target_include_directories(test_deadlock PRIVATE src) - target_link_libraries(test_deadlock PRIVATE cubeb gtest_main) - add_test(deadlock test_deadlock) - add_sanitizers(test_deadlock) - install(TARGETS test_deadlock DESTINATION ${CMAKE_INSTALL_PREFIX}) - endif() endif() diff --git a/third_party/rust/cubeb-sys/libcubeb/include/cubeb/cubeb.h b/third_party/rust/cubeb-sys/libcubeb/include/cubeb/cubeb.h index b7dc86260c9a33620eae6d6cd0e4dbb0086ccfad..afca25597f0afc9536bd81b1fcfb43d07aa29176 100644 --- a/third_party/rust/cubeb-sys/libcubeb/include/cubeb/cubeb.h +++ b/third_party/rust/cubeb-sys/libcubeb/include/cubeb/cubeb.h @@ -157,63 +157,66 @@ typedef enum { CUBEB_LOG_VERBOSE = 2, /**< Verbose logging of callbacks, can have performance implications. */ } cubeb_log_level; -/** SMPTE channel layout (also known as wave order) - * DUAL-MONO L R - * DUAL-MONO-LFE L R LFE - * MONO M - * MONO-LFE M LFE - * STEREO L R - * STEREO-LFE L R LFE - * 3F L R C - * 3F-LFE L R C LFE - * 2F1 L R RC - * 2F1-LFE L R LFE RC - * 3F1 L R C RC - * 3F1-LFE L R C LFE RC - * 2F2 L R LS RS - * 2F2-LFE L R LFE LS RS - * 3F2 L R C LS RS - * 3F2-LFE L R C LFE LS RS - * 3F3R-LFE L R C LFE RC LS RS - * 3F4-LFE L R C LFE RLS RRS LS RS - * - * The abbreviation of channel name is defined in following table: - * Abbr Channel name - * --------------------------- - * M Mono - * L Left - * R Right - * C Center - * LS Left Surround - * RS Right Surround - * RLS Rear Left Surround - * RC Rear Center - * RRS Rear Right Surround - * LFE Low Frequency Effects - */ - typedef enum { - CUBEB_LAYOUT_UNDEFINED, // Indicate the speaker's layout is undefined. - CUBEB_LAYOUT_DUAL_MONO, - CUBEB_LAYOUT_DUAL_MONO_LFE, - CUBEB_LAYOUT_MONO, - CUBEB_LAYOUT_MONO_LFE, - CUBEB_LAYOUT_STEREO, - CUBEB_LAYOUT_STEREO_LFE, - CUBEB_LAYOUT_3F, - CUBEB_LAYOUT_3F_LFE, - CUBEB_LAYOUT_2F1, - CUBEB_LAYOUT_2F1_LFE, - CUBEB_LAYOUT_3F1, - CUBEB_LAYOUT_3F1_LFE, - CUBEB_LAYOUT_2F2, - CUBEB_LAYOUT_2F2_LFE, - CUBEB_LAYOUT_3F2, - CUBEB_LAYOUT_3F2_LFE, - CUBEB_LAYOUT_3F3R_LFE, - CUBEB_LAYOUT_3F4_LFE, - CUBEB_LAYOUT_MAX -} cubeb_channel_layout; + CHANNEL_UNKNOWN = 0, + CHANNEL_FRONT_LEFT = 1 << 0, + CHANNEL_FRONT_RIGHT = 1 << 1, + CHANNEL_FRONT_CENTER = 1 << 2, + CHANNEL_LOW_FREQUENCY = 1 << 3, + CHANNEL_BACK_LEFT = 1 << 4, + CHANNEL_BACK_RIGHT = 1 << 5, + CHANNEL_FRONT_LEFT_OF_CENTER = 1 << 6, + CHANNEL_FRONT_RIGHT_OF_CENTER = 1 << 7, + CHANNEL_BACK_CENTER = 1 << 8, + CHANNEL_SIDE_LEFT = 1 << 9, + CHANNEL_SIDE_RIGHT = 1 << 10, + CHANNEL_TOP_CENTER = 1 << 11, + CHANNEL_TOP_FRONT_LEFT = 1 << 12, + CHANNEL_TOP_FRONT_CENTER = 1 << 13, + CHANNEL_TOP_FRONT_RIGHT = 1 << 14, + CHANNEL_TOP_BACK_LEFT = 1 << 15, + CHANNEL_TOP_BACK_CENTER = 1 << 16, + CHANNEL_TOP_BACK_RIGHT = 1 << 17 +} cubeb_channel; + +typedef uint32_t cubeb_channel_layout; +// Some common layout definitions. +enum { + CUBEB_LAYOUT_UNDEFINED = 0, // Indicate the speaker's layout is undefined. + CUBEB_LAYOUT_MONO = CHANNEL_FRONT_CENTER, + CUBEB_LAYOUT_MONO_LFE = CUBEB_LAYOUT_MONO | CHANNEL_LOW_FREQUENCY, + CUBEB_LAYOUT_STEREO = CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT, + CUBEB_LAYOUT_STEREO_LFE = CUBEB_LAYOUT_STEREO | CHANNEL_LOW_FREQUENCY, + CUBEB_LAYOUT_3F = + CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT | CHANNEL_FRONT_CENTER, + CUBEB_LAYOUT_3F_LFE = CUBEB_LAYOUT_3F | CHANNEL_LOW_FREQUENCY, + CUBEB_LAYOUT_2F1 = + CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT | CHANNEL_BACK_CENTER, + CUBEB_LAYOUT_2F1_LFE = CUBEB_LAYOUT_2F1 | CHANNEL_LOW_FREQUENCY, + CUBEB_LAYOUT_3F1 = CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT | + CHANNEL_FRONT_CENTER | CHANNEL_BACK_CENTER, + CUBEB_LAYOUT_3F1_LFE = CUBEB_LAYOUT_3F1 | CHANNEL_LOW_FREQUENCY, + CUBEB_LAYOUT_2F2 = CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT | + CHANNEL_SIDE_LEFT | CHANNEL_SIDE_RIGHT, + CUBEB_LAYOUT_2F2_LFE = CUBEB_LAYOUT_2F2 | CHANNEL_LOW_FREQUENCY, + CUBEB_LAYOUT_QUAD = CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT | + CHANNEL_BACK_LEFT | CHANNEL_BACK_RIGHT, + CUBEB_LAYOUT_QUAD_LFE = CUBEB_LAYOUT_QUAD | CHANNEL_LOW_FREQUENCY, + CUBEB_LAYOUT_3F2 = CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT | + CHANNEL_FRONT_CENTER | CHANNEL_SIDE_LEFT | + CHANNEL_SIDE_RIGHT, + CUBEB_LAYOUT_3F2_LFE = CUBEB_LAYOUT_3F2 | CHANNEL_LOW_FREQUENCY, + CUBEB_LAYOUT_3F2_BACK = CUBEB_LAYOUT_QUAD | CHANNEL_FRONT_CENTER, + CUBEB_LAYOUT_3F2_LFE_BACK = CUBEB_LAYOUT_3F2_BACK | CHANNEL_LOW_FREQUENCY, + CUBEB_LAYOUT_3F3R_LFE = CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT | + CHANNEL_FRONT_CENTER | CHANNEL_LOW_FREQUENCY | + CHANNEL_BACK_CENTER | CHANNEL_SIDE_LEFT | + CHANNEL_SIDE_RIGHT, + CUBEB_LAYOUT_3F4_LFE = CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT | + CHANNEL_FRONT_CENTER | CHANNEL_LOW_FREQUENCY | + CHANNEL_BACK_LEFT | CHANNEL_BACK_RIGHT | + CHANNEL_SIDE_LEFT | CHANNEL_SIDE_RIGHT, +}; /** Miscellaneous stream preferences. */ typedef enum { @@ -230,7 +233,7 @@ typedef struct { #cubeb_sample_format. */ uint32_t rate; /**< Requested sample rate. Valid range is [1000, 192000]. */ uint32_t channels; /**< Requested channel count. Valid range is [1, 8]. */ - cubeb_channel_layout layout; /**< Requested channel layout. This must be consistent with the provided channels. */ + cubeb_channel_layout layout; /**< Requested channel layout. This must be consistent with the provided channels. CUBEB_LAYOUT_UNDEFINED if unknown */ cubeb_stream_prefs prefs; /**< Requested preferences. */ } cubeb_stream_params; @@ -366,8 +369,12 @@ typedef struct { @param output_buffer A pointer to a buffer to be filled with audio samples, or nullptr if this is an input-only stream. @param nframes The number of frames of the two buffer. - @retval Number of frames written to the output buffer. If this number is - less than nframes, then the stream will start to drain. + @retval If the stream has output, this is the number of frames written to + the output buffer. In this case, if this number is less than + nframes then the stream will start to drain. If the stream is + input only, then returning nframes indicates data has been read. + In this case, a value less than nframes will result in the stream + being stopped. @retval CUBEB_ERROR on error, in which case the data callback will stop and the stream will enter a shutdown state. */ typedef long (* cubeb_data_callback)(cubeb_stream * stream, @@ -401,6 +408,10 @@ typedef void (* cubeb_log_callback)(char const * fmt, ...); /** Initialize an application context. This will perform any library or application scoped initialization. + + Note: On Windows platforms, COM must be initialized in MTA mode on + any thread that will call the cubeb API. + @param context A out param where an opaque pointer to the application context will be returned. @param context_name A name for the context. Depending on the platform this @@ -454,15 +465,6 @@ CUBEB_EXPORT int cubeb_get_min_latency(cubeb * context, @retval CUBEB_ERROR_NOT_SUPPORTED */ CUBEB_EXPORT int cubeb_get_preferred_sample_rate(cubeb * context, uint32_t * rate); -/** Get the preferred layout for this backend: this is hardware and - platform dependent. - @param context A pointer to the cubeb context. - @param layout The layout of the current speaker configuration. - @retval CUBEB_OK - @retval CUBEB_ERROR_INVALID_PARAMETER - @retval CUBEB_ERROR_NOT_SUPPORTED */ -CUBEB_EXPORT int cubeb_get_preferred_channel_layout(cubeb * context, cubeb_channel_layout * layout); - /** Destroy an application context. This must be called after all stream have * been destroyed. @param context A pointer to the cubeb context.*/ diff --git a/third_party/rust/cubeb-sys/libcubeb/src/android/cubeb-output-latency.h b/third_party/rust/cubeb-sys/libcubeb/src/android/cubeb-output-latency.h new file mode 100644 index 0000000000000000000000000000000000000000..a824fc1c2453d4b05c7d849087c171a6061182de --- /dev/null +++ b/third_party/rust/cubeb-sys/libcubeb/src/android/cubeb-output-latency.h @@ -0,0 +1,76 @@ +#ifndef _CUBEB_OUTPUT_LATENCY_H_ +#define _CUBEB_OUTPUT_LATENCY_H_ + +#include <stdbool.h> +#include "cubeb_media_library.h" +#include "../cubeb-jni.h" + +struct output_latency_function { + media_lib * from_lib; + cubeb_jni * from_jni; + int version; +}; + +typedef struct output_latency_function output_latency_function; + +const int ANDROID_JELLY_BEAN_MR1_4_2 = 17; + +output_latency_function * +cubeb_output_latency_load_method(int version) +{ + output_latency_function * ol = NULL; + ol = calloc(1, sizeof(output_latency_function)); + + ol->version = version; + + if (ol->version > ANDROID_JELLY_BEAN_MR1_4_2){ + ol->from_jni = cubeb_jni_init(); + return ol; + } + + ol->from_lib = cubeb_load_media_library(); + return ol; +} + +bool +cubeb_output_latency_method_is_loaded(output_latency_function * ol) +{ + assert(ol && (ol->from_jni || ol->from_lib)); + if (ol->version > ANDROID_JELLY_BEAN_MR1_4_2){ + return !!ol->from_jni; + } + + return !!ol->from_lib; +} + +void +cubeb_output_latency_unload_method(output_latency_function * ol) +{ + if (!ol) { + return; + } + + if (ol->version > ANDROID_JELLY_BEAN_MR1_4_2 && ol->from_jni) { + cubeb_jni_destroy(ol->from_jni); + } + + if (ol->version <= ANDROID_JELLY_BEAN_MR1_4_2 && ol->from_lib) { + cubeb_close_media_library(ol->from_lib); + } + + free(ol); +} + +uint32_t +cubeb_get_output_latency(output_latency_function * ol) +{ + assert(cubeb_output_latency_method_is_loaded(ol)); + + if (ol->version > ANDROID_JELLY_BEAN_MR1_4_2){ + return cubeb_get_output_latency_from_jni(ol->from_jni); + } + + return cubeb_get_output_latency_from_media_library(ol->from_lib); +} + +#endif // _CUBEB_OUTPUT_LATENCY_H_ diff --git a/third_party/rust/cubeb-sys/libcubeb/src/android/cubeb_media_library.h b/third_party/rust/cubeb-sys/libcubeb/src/android/cubeb_media_library.h new file mode 100644 index 0000000000000000000000000000000000000000..ab21b779dfad4f6a7534d2c6db221289a11c8255 --- /dev/null +++ b/third_party/rust/cubeb-sys/libcubeb/src/android/cubeb_media_library.h @@ -0,0 +1,62 @@ +#ifndef _CUBEB_MEDIA_LIBRARY_H_ +#define _CUBEB_MEDIA_LIBRARY_H_ + +struct media_lib { + void * libmedia; + int32_t (* get_output_latency)(uint32_t * latency, int stream_type); +}; + +typedef struct media_lib media_lib; + +media_lib * +cubeb_load_media_library() +{ + media_lib ml = {0}; + ml.libmedia = dlopen("libmedia.so", RTLD_LAZY); + if (!ml.libmedia) { + return NULL; + } + + // Get the latency, in ms, from AudioFlinger. First, try the most recent signature. + // status_t AudioSystem::getOutputLatency(uint32_t* latency, audio_stream_type_t streamType) + ml.get_output_latency = + dlsym(ml.libmedia, "_ZN7android11AudioSystem16getOutputLatencyEPj19audio_stream_type_t"); + if (!ml.get_output_latency) { + // In case of failure, try the signature from legacy version. + // status_t AudioSystem::getOutputLatency(uint32_t* latency, int streamType) + ml.get_output_latency = + dlsym(ml.libmedia, "_ZN7android11AudioSystem16getOutputLatencyEPji"); + if (!ml.get_output_latency) { + return NULL; + } + } + + media_lib * rv = NULL; + rv = calloc(1, sizeof(media_lib)); + assert(rv); + *rv = ml; + return rv; +} + +void +cubeb_close_media_library(media_lib * ml) +{ + dlclose(ml->libmedia); + ml->libmedia = NULL; + ml->get_output_latency = NULL; + free(ml); +} + +uint32_t +cubeb_get_output_latency_from_media_library(media_lib * ml) +{ + uint32_t latency = 0; + const int audio_stream_type_music = 3; + int32_t r = ml->get_output_latency(&latency, audio_stream_type_music); + if (r) { + return 0; + } + return latency; +} + +#endif // _CUBEB_MEDIA_LIBRARY_H_ diff --git a/third_party/rust/cubeb-sys/libcubeb/src/cubeb-internal.h b/third_party/rust/cubeb-sys/libcubeb/src/cubeb-internal.h index 25bad3a1d0f9948afbc4a7e1cbe39b706ab537fc..9b6199c2efb2eb8ac5aa09513cf4cd4992765832 100644 --- a/third_party/rust/cubeb-sys/libcubeb/src/cubeb-internal.h +++ b/third_party/rust/cubeb-sys/libcubeb/src/cubeb-internal.h @@ -33,14 +33,6 @@ extern "C" { } #endif -typedef struct { - char const * name; - unsigned int const channels; - cubeb_channel_layout const layout; -} cubeb_layout_map; - -extern cubeb_layout_map const CUBEB_CHANNEL_LAYOUT_MAPS[CUBEB_LAYOUT_MAX]; - struct cubeb_ops { int (* init)(cubeb ** context, char const * context_name); char const * (* get_backend_id)(cubeb * context); @@ -49,7 +41,6 @@ struct cubeb_ops { cubeb_stream_params params, uint32_t * latency_ms); int (* get_preferred_sample_rate)(cubeb * context, uint32_t * rate); - int (* get_preferred_channel_layout)(cubeb * context, cubeb_channel_layout * layout); int (* enumerate_devices)(cubeb * context, cubeb_device_type type, cubeb_device_collection * collection); int (* device_collection_destroy)(cubeb * context, diff --git a/third_party/rust/cubeb-sys/libcubeb/src/cubeb-jni-instances.h b/third_party/rust/cubeb-sys/libcubeb/src/cubeb-jni-instances.h new file mode 100644 index 0000000000000000000000000000000000000000..4fed046592132b49c1036f2157db87d309398af2 --- /dev/null +++ b/third_party/rust/cubeb-sys/libcubeb/src/cubeb-jni-instances.h @@ -0,0 +1,30 @@ +#ifndef _CUBEB_JNI_INSTANCES_H_ +#define _CUBEB_JNI_INSTANCES_H_ + +/* + * The methods in this file offer a way to pass in the required + * JNI instances in the cubeb library. By default they return NULL. + * In this case part of the cubeb API that depends on JNI + * will return CUBEB_ERROR_NOT_SUPPORTED. Currently only one + * method depends on that: + * + * cubeb_stream_get_position() + * + * Users that want to use that cubeb API method must "override" + * the methods bellow to return a valid instance of JavaVM + * and application's Context object. + * */ + +JNIEnv * +cubeb_get_jni_env_for_thread() +{ + return nullptr; +} + +jobject +cubeb_jni_get_context_instance() +{ + return nullptr; +} + +#endif //_CUBEB_JNI_INSTANCES_H_ diff --git a/third_party/rust/cubeb-sys/libcubeb/src/cubeb-jni.cpp b/third_party/rust/cubeb-sys/libcubeb/src/cubeb-jni.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a5066967af22ef763983019fafee796029671abc --- /dev/null +++ b/third_party/rust/cubeb-sys/libcubeb/src/cubeb-jni.cpp @@ -0,0 +1,68 @@ +#include "jni.h" +#include <assert.h> +#include "cubeb-jni-instances.h" + +#define AUDIO_STREAM_TYPE_MUSIC 3 + +struct cubeb_jni { + jobject s_audio_manager_obj = nullptr; + jclass s_audio_manager_class = nullptr; + jmethodID s_get_output_latency_id = nullptr; +}; + +extern "C" +cubeb_jni * +cubeb_jni_init() +{ + jobject ctx_obj = cubeb_jni_get_context_instance(); + JNIEnv * jni_env = cubeb_get_jni_env_for_thread(); + if (!jni_env || !ctx_obj) { + return nullptr; + } + + cubeb_jni * cubeb_jni_ptr = new cubeb_jni; + assert(cubeb_jni_ptr); + + // Find the audio manager object and make it global to call it from another method + jclass context_class = jni_env->FindClass("android/content/Context"); + jfieldID audio_service_field = jni_env->GetStaticFieldID(context_class, "AUDIO_SERVICE", "Ljava/lang/String;"); + jstring jstr = (jstring)jni_env->GetStaticObjectField(context_class, audio_service_field); + jmethodID get_system_service_id = jni_env->GetMethodID(context_class, "getSystemService", "(Ljava/lang/String;)Ljava/lang/Object;"); + jobject audio_manager_obj = jni_env->CallObjectMethod(ctx_obj, get_system_service_id, jstr); + cubeb_jni_ptr->s_audio_manager_obj = reinterpret_cast<jobject>(jni_env->NewGlobalRef(audio_manager_obj)); + + // Make the audio manager class a global reference in order to preserve method id + jclass audio_manager_class = jni_env->FindClass("android/media/AudioManager"); + cubeb_jni_ptr->s_audio_manager_class = reinterpret_cast<jclass>(jni_env->NewGlobalRef(audio_manager_class)); + cubeb_jni_ptr->s_get_output_latency_id = jni_env->GetMethodID (audio_manager_class, "getOutputLatency", "(I)I"); + + jni_env->DeleteLocalRef(ctx_obj); + jni_env->DeleteLocalRef(context_class); + jni_env->DeleteLocalRef(jstr); + jni_env->DeleteLocalRef(audio_manager_obj); + jni_env->DeleteLocalRef(audio_manager_class); + + return cubeb_jni_ptr; +} + +extern "C" +int cubeb_get_output_latency_from_jni(cubeb_jni * cubeb_jni_ptr) +{ + assert(cubeb_jni_ptr); + JNIEnv * jni_env = cubeb_get_jni_env_for_thread(); + return jni_env->CallIntMethod(cubeb_jni_ptr->s_audio_manager_obj, cubeb_jni_ptr->s_get_output_latency_id, AUDIO_STREAM_TYPE_MUSIC); //param: AudioManager.STREAM_MUSIC +} + +extern "C" +void cubeb_jni_destroy(cubeb_jni * cubeb_jni_ptr) +{ + assert(cubeb_jni_ptr); + + JNIEnv * jni_env = cubeb_get_jni_env_for_thread(); + assert(jni_env); + + jni_env->DeleteGlobalRef(cubeb_jni_ptr->s_audio_manager_obj); + jni_env->DeleteGlobalRef(cubeb_jni_ptr->s_audio_manager_class); + + delete cubeb_jni_ptr; +} diff --git a/third_party/rust/cubeb-sys/libcubeb/src/cubeb-jni.h b/third_party/rust/cubeb-sys/libcubeb/src/cubeb-jni.h new file mode 100644 index 0000000000000000000000000000000000000000..8c7ddb6acf4d5bb9acbdb214b367bcecaaa98489 --- /dev/null +++ b/third_party/rust/cubeb-sys/libcubeb/src/cubeb-jni.h @@ -0,0 +1,10 @@ +#ifndef _CUBEB_JNI_H_ +#define _CUBEB_JNI_H_ + +typedef struct cubeb_jni cubeb_jni; + +cubeb_jni * cubeb_jni_init(); +int cubeb_get_output_latency_from_jni(cubeb_jni * cubeb_jni_ptr); +void cubeb_jni_destroy(cubeb_jni * cubeb_jni_ptr); + +#endif // _CUBEB_JNI_H_ diff --git a/third_party/rust/cubeb-sys/libcubeb/src/cubeb.c b/third_party/rust/cubeb-sys/libcubeb/src/cubeb.c index f9bfdd35628db369bcf0be70a7db21bdd662ae51..ebb2170ceef5cd9e0f83a30030eacb03e36ffe9c 100644 --- a/third_party/rust/cubeb-sys/libcubeb/src/cubeb.c +++ b/third_party/rust/cubeb-sys/libcubeb/src/cubeb.c @@ -277,20 +277,6 @@ cubeb_get_preferred_sample_rate(cubeb * context, uint32_t * rate) return context->ops->get_preferred_sample_rate(context, rate); } -int -cubeb_get_preferred_channel_layout(cubeb * context, cubeb_channel_layout * layout) -{ - if (!context || !layout) { - return CUBEB_ERROR_INVALID_PARAMETER; - } - - if (!context->ops->get_preferred_channel_layout) { - return CUBEB_ERROR_NOT_SUPPORTED; - } - - return context->ops->get_preferred_channel_layout(context, layout); -} - void cubeb_destroy(cubeb * context) { diff --git a/third_party/rust/cubeb-sys/libcubeb/src/cubeb_alsa.c b/third_party/rust/cubeb-sys/libcubeb/src/cubeb_alsa.c index b38ab66cb08a486d290092222fd06740aa699730..bfd4d8f199d415cda8981c9fd9ed1e7468aa1bf2 100644 --- a/third_party/rust/cubeb-sys/libcubeb/src/cubeb_alsa.c +++ b/third_party/rust/cubeb-sys/libcubeb/src/cubeb_alsa.c @@ -1358,7 +1358,6 @@ static struct cubeb_ops const alsa_ops = { .get_max_channel_count = alsa_get_max_channel_count, .get_min_latency = alsa_get_min_latency, .get_preferred_sample_rate = alsa_get_preferred_sample_rate, - .get_preferred_channel_layout = NULL, .enumerate_devices = alsa_enumerate_devices, .device_collection_destroy = alsa_device_collection_destroy, .destroy = alsa_destroy, diff --git a/third_party/rust/cubeb-sys/libcubeb/src/cubeb_audiotrack.c b/third_party/rust/cubeb-sys/libcubeb/src/cubeb_audiotrack.c index 98d0bd96ce6c58a46a4bc59210113bc88115721c..0f4dfbbc8faa520bf1265e61da187327c144abcc 100644 --- a/third_party/rust/cubeb-sys/libcubeb/src/cubeb_audiotrack.c +++ b/third_party/rust/cubeb-sys/libcubeb/src/cubeb_audiotrack.c @@ -423,7 +423,6 @@ static struct cubeb_ops const audiotrack_ops = { .get_max_channel_count = audiotrack_get_max_channel_count, .get_min_latency = audiotrack_get_min_latency, .get_preferred_sample_rate = audiotrack_get_preferred_sample_rate, - .get_preferred_channel_layout = NULL, .enumerate_devices = NULL, .device_collection_destroy = NULL, .destroy = audiotrack_destroy, diff --git a/third_party/rust/cubeb-sys/libcubeb/src/cubeb_audiounit.cpp b/third_party/rust/cubeb-sys/libcubeb/src/cubeb_audiounit.cpp index ac71022169dffd2847c26371ca1a75387941db62..e11bb493c8997167eb526b4a295eea84ba2dea64 100644 --- a/third_party/rust/cubeb-sys/libcubeb/src/cubeb_audiounit.cpp +++ b/third_party/rust/cubeb-sys/libcubeb/src/cubeb_audiounit.cpp @@ -87,6 +87,7 @@ struct cubeb { dispatch_queue_t serial_queue = dispatch_queue_create(DISPATCH_QUEUE_LABEL, DISPATCH_QUEUE_SERIAL); // Current used channel layout atomic<cubeb_channel_layout> layout{ CUBEB_LAYOUT_UNDEFINED }; + uint32_t channels = 0; }; static unique_ptr<AudioChannelLayout, decltype(&free)> @@ -188,6 +189,10 @@ struct cubeb_stream { AudioObjectID plugin_id = 0; // used to create aggregate device /* Mixer interface */ unique_ptr<cubeb_mixer, decltype(&cubeb_mixer_destroy)> mixer; + /* Buffer where remixing/resampling will occur when upmixing is required */ + /* Only accessed from callback thread */ + unique_ptr<uint8_t[]> temp_buffer; + size_t temp_buffer_size = 0; // size in bytes. }; bool has_input(cubeb_stream * stm) @@ -204,18 +209,44 @@ cubeb_channel channel_label_to_cubeb_channel(UInt32 label) { switch (label) { - case kAudioChannelLabel_Mono: return CHANNEL_MONO; - case kAudioChannelLabel_Left: return CHANNEL_LEFT; - case kAudioChannelLabel_Right: return CHANNEL_RIGHT; - case kAudioChannelLabel_Center: return CHANNEL_CENTER; - case kAudioChannelLabel_LFEScreen: return CHANNEL_LFE; - case kAudioChannelLabel_LeftSurround: return CHANNEL_LS; - case kAudioChannelLabel_RightSurround: return CHANNEL_RS; - case kAudioChannelLabel_RearSurroundLeft: return CHANNEL_RLS; - case kAudioChannelLabel_RearSurroundRight: return CHANNEL_RRS; - case kAudioChannelLabel_CenterSurround: return CHANNEL_RCENTER; - case kAudioChannelLabel_Unknown: return CHANNEL_UNMAPPED; - default: return CHANNEL_INVALID; + case kAudioChannelLabel_Left: + return CHANNEL_FRONT_LEFT; + case kAudioChannelLabel_Right: + return CHANNEL_FRONT_RIGHT; + case kAudioChannelLabel_Center: + return CHANNEL_FRONT_CENTER; + case kAudioChannelLabel_LFEScreen: + return CHANNEL_LOW_FREQUENCY; + case kAudioChannelLabel_LeftSurround: + return CHANNEL_BACK_LEFT; + case kAudioChannelLabel_RightSurround: + return CHANNEL_BACK_RIGHT; + case kAudioChannelLabel_LeftCenter: + return CHANNEL_FRONT_LEFT_OF_CENTER; + case kAudioChannelLabel_RightCenter: + return CHANNEL_FRONT_RIGHT_OF_CENTER; + case kAudioChannelLabel_CenterSurround: + return CHANNEL_BACK_CENTER; + case kAudioChannelLabel_LeftSurroundDirect: + return CHANNEL_SIDE_LEFT; + case kAudioChannelLabel_RightSurroundDirect: + return CHANNEL_SIDE_RIGHT; + case kAudioChannelLabel_TopCenterSurround: + return CHANNEL_TOP_CENTER; + case kAudioChannelLabel_VerticalHeightLeft: + return CHANNEL_TOP_FRONT_LEFT; + case kAudioChannelLabel_VerticalHeightCenter: + return CHANNEL_TOP_FRONT_CENTER; + case kAudioChannelLabel_VerticalHeightRight: + return CHANNEL_TOP_FRONT_RIGHT; + case kAudioChannelLabel_TopBackLeft: + return CHANNEL_TOP_BACK_LEFT; + case kAudioChannelLabel_TopBackCenter: + return CHANNEL_TOP_BACK_CENTER; + case kAudioChannelLabel_TopBackRight: + return CHANNEL_TOP_BACK_RIGHT; + default: + return CHANNEL_UNKNOWN; } } @@ -223,18 +254,44 @@ AudioChannelLabel cubeb_channel_to_channel_label(cubeb_channel channel) { switch (channel) { - case CHANNEL_MONO: return kAudioChannelLabel_Mono; - case CHANNEL_LEFT: return kAudioChannelLabel_Left; - case CHANNEL_RIGHT: return kAudioChannelLabel_Right; - case CHANNEL_CENTER: return kAudioChannelLabel_Center; - case CHANNEL_LFE: return kAudioChannelLabel_LFEScreen; - case CHANNEL_LS: return kAudioChannelLabel_LeftSurround; - case CHANNEL_RS: return kAudioChannelLabel_RightSurround; - case CHANNEL_RLS: return kAudioChannelLabel_RearSurroundLeft; - case CHANNEL_RRS: return kAudioChannelLabel_RearSurroundRight; - case CHANNEL_RCENTER: return kAudioChannelLabel_CenterSurround; - case CHANNEL_UNMAPPED: return kAudioChannelLabel_Unknown; - default: return kAudioChannelLabel_Unknown; + case CHANNEL_FRONT_LEFT: + return kAudioChannelLabel_Left; + case CHANNEL_FRONT_RIGHT: + return kAudioChannelLabel_Right; + case CHANNEL_FRONT_CENTER: + return kAudioChannelLabel_Center; + case CHANNEL_LOW_FREQUENCY: + return kAudioChannelLabel_LFEScreen; + case CHANNEL_BACK_LEFT: + return kAudioChannelLabel_LeftSurround; + case CHANNEL_BACK_RIGHT: + return kAudioChannelLabel_RightSurround; + case CHANNEL_FRONT_LEFT_OF_CENTER: + return kAudioChannelLabel_LeftCenter; + case CHANNEL_FRONT_RIGHT_OF_CENTER: + return kAudioChannelLabel_RightCenter; + case CHANNEL_BACK_CENTER: + return kAudioChannelLabel_CenterSurround; + case CHANNEL_SIDE_LEFT: + return kAudioChannelLabel_LeftSurroundDirect; + case CHANNEL_SIDE_RIGHT: + return kAudioChannelLabel_RightSurroundDirect; + case CHANNEL_TOP_CENTER: + return kAudioChannelLabel_TopCenterSurround; + case CHANNEL_TOP_FRONT_LEFT: + return kAudioChannelLabel_VerticalHeightLeft; + case CHANNEL_TOP_FRONT_CENTER: + return kAudioChannelLabel_VerticalHeightCenter; + case CHANNEL_TOP_FRONT_RIGHT: + return kAudioChannelLabel_VerticalHeightRight; + case CHANNEL_TOP_BACK_LEFT: + return kAudioChannelLabel_TopBackLeft; + case CHANNEL_TOP_BACK_CENTER: + return kAudioChannelLabel_TopBackCenter; + case CHANNEL_TOP_BACK_RIGHT: + return kAudioChannelLabel_TopBackRight; + default: + return CHANNEL_UNKNOWN; } } @@ -382,6 +439,12 @@ audiounit_input_callback(void * user_ptr, &total_input_frames, NULL, 0); + if (outframes < total_input_frames) { + OSStatus r = AudioOutputUnitStop(stm->input_unit); + assert(r == 0); + stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_DRAINED); + return noErr; + } assert(outframes >= 0); // Reset input buffer @@ -411,24 +474,26 @@ is_extra_input_needed(cubeb_stream * stm) static void audiounit_mix_output_buffer(cubeb_stream * stm, - long output_frames, + size_t output_frames, + void * input_buffer, + size_t input_buffer_size, void * output_buffer, - unsigned long output_buffer_length) -{ - cubeb_stream_params output_mixer_params = { - stm->output_stream_params.format, - stm->output_stream_params.rate, - CUBEB_CHANNEL_LAYOUT_MAPS[stm->context->layout].channels, - stm->context->layout, - CUBEB_STREAM_PREF_NONE - }; + size_t output_buffer_size) +{ + assert(input_buffer_size >= + cubeb_sample_size(stm->output_stream_params.format) * + stm->output_stream_params.channels * output_frames); + assert(output_buffer_size >= stm->output_desc.mBytesPerFrame * output_frames); - // The downmixing(from 5.1) supports in-place conversion, so we can use - // the same buffer for both input and output of the mixer. - cubeb_mixer_mix(stm->mixer.get(), output_frames, - output_buffer, output_buffer_length, - output_buffer, output_buffer_length, - &stm->output_stream_params, &output_mixer_params); + int r = cubeb_mixer_mix(stm->mixer.get(), + output_frames, + input_buffer, + input_buffer_size, + output_buffer, + output_buffer_size); + if (r != 0) { + LOG("Remix error = %d", r); + } } static OSStatus @@ -473,8 +538,22 @@ audiounit_output_callback(void * user_ptr, audiounit_make_silent(&outBufferList->mBuffers[0]); return noErr; } + /* Get output buffer. */ - output_buffer = outBufferList->mBuffers[0].mData; + if (stm->mixer) { + // If remixing needs to occur, we can't directly work in our final + // destination buffer as data may be overwritten or too small to start with. + size_t size_needed = output_frames * stm->output_stream_params.channels * + cubeb_sample_size(stm->output_stream_params.format); + if (stm->temp_buffer_size < size_needed) { + stm->temp_buffer.reset(new uint8_t[size_needed]); + stm->temp_buffer_size = size_needed; + } + output_buffer = stm->temp_buffer.get(); + } else { + output_buffer = outBufferList->mBuffers[0].mData; + } + /* If Full duplex get also input buffer */ if (stm->input_unit != NULL) { if (is_extra_input_needed(stm)) { @@ -525,7 +604,6 @@ audiounit_output_callback(void * user_ptr, return noErr; } - size_t outbpf = stm->output_desc.mBytesPerFrame; stm->draining = (UInt32) outframes < output_frames; stm->frames_played = stm->frames_queued; stm->frames_queued += outframes; @@ -536,22 +614,29 @@ audiounit_output_callback(void * user_ptr, /* Post process output samples. */ if (stm->draining) { + size_t outbpf = cubeb_sample_size(stm->output_stream_params.format); /* Clear missing frames (silence) */ memset((uint8_t*)output_buffer + outframes * outbpf, 0, (output_frames - outframes) * outbpf); } - /* Pan stereo. */ - if (panning != 0.0f) { - if (outaff & kAudioFormatFlagIsFloat) { - cubeb_pan_stereo_buffer_float((float*)output_buffer, outframes, panning); - } else if (outaff & kAudioFormatFlagIsSignedInteger) { - cubeb_pan_stereo_buffer_int((short*)output_buffer, outframes, panning); - } - } /* Mixing */ - if (stm->output_stream_params.layout != CUBEB_LAYOUT_UNDEFINED) { - unsigned long output_buffer_length = outBufferList->mBuffers[0].mDataByteSize; - audiounit_mix_output_buffer(stm, output_frames, output_buffer, output_buffer_length); + if (stm->mixer) { + audiounit_mix_output_buffer(stm, + output_frames, + output_buffer, + stm->temp_buffer_size, + outBufferList->mBuffers[0].mData, + outBufferList->mBuffers[0].mDataByteSize); + } else { + /* Pan stereo. */ + if (panning != 0.0f) { + if (outaff & kAudioFormatFlagIsFloat) { + cubeb_pan_stereo_buffer_float( + (float*)output_buffer, outframes, panning); + } else if (outaff & kAudioFormatFlagIsSignedInteger) { + cubeb_pan_stereo_buffer_int((short*)output_buffer, outframes, panning); + } + } } return noErr; @@ -1120,6 +1205,15 @@ audiounit_get_preferred_sample_rate(cubeb * /* ctx */, uint32_t * rate) static cubeb_channel_layout audiounit_convert_channel_layout(AudioChannelLayout * layout) { + // When having on or two channel, force mono or stereo. Some devices (namely, + // Bose QC35, mark 1 and 2), expose a single channel mapped to the right for + // some reason. + if (layout->mNumberChannelDescriptions == 1) { + return CUBEB_LAYOUT_MONO; + } else if (layout->mNumberChannelDescriptions == 2) { + return CUBEB_LAYOUT_STEREO; + } + if (layout->mChannelLayoutTag != kAudioChannelLayoutTag_UseChannelDescriptions) { // kAudioChannelLayoutTag_UseChannelBitmap // kAudioChannelLayoutTag_Mono @@ -1129,19 +1223,13 @@ audiounit_convert_channel_layout(AudioChannelLayout * layout) return CUBEB_LAYOUT_UNDEFINED; } - // This devices has more channels that we can support, bail out. - if (layout->mNumberChannelDescriptions >= CHANNEL_MAX) { - LOG("Audio device has more than %d channels, bailing out.", CHANNEL_MAX); - return CUBEB_LAYOUT_UNDEFINED; - } - - cubeb_channel_map cm; - cm.channels = layout->mNumberChannelDescriptions; + cubeb_channel_layout cl = 0; for (UInt32 i = 0; i < layout->mNumberChannelDescriptions; ++i) { - cm.map[i] = channel_label_to_cubeb_channel(layout->mChannelDescriptions[i].mChannelLabel); + cl |= channel_label_to_cubeb_channel( + layout->mChannelDescriptions[i].mChannelLabel); } - return cubeb_channel_map_to_layout(&cm); + return cl; } static cubeb_channel_layout @@ -1176,76 +1264,8 @@ audiounit_get_current_channel_layout(AudioUnit output_unit) return audiounit_convert_channel_layout(layout.get()); } -static cubeb_channel_layout -audiounit_get_preferred_channel_layout() -{ - OSStatus rv = noErr; - UInt32 size = 0; - AudioDeviceID id; - - id = audiounit_get_default_device_id(CUBEB_DEVICE_TYPE_OUTPUT); - if (id == kAudioObjectUnknown) { - return CUBEB_LAYOUT_UNDEFINED; - } - - AudioObjectPropertyAddress adr = { kAudioDevicePropertyPreferredChannelLayout, - kAudioDevicePropertyScopeOutput, - kAudioObjectPropertyElementMaster }; - rv = AudioObjectGetPropertyDataSize(id, &adr, 0, NULL, &size); - if (rv != noErr) { - return CUBEB_LAYOUT_UNDEFINED; - } - assert(size > 0); - - auto layout = make_sized_audio_channel_layout(size); - rv = AudioObjectGetPropertyData(id, &adr, 0, NULL, &size, layout.get()); - if (rv != noErr) { - return CUBEB_LAYOUT_UNDEFINED; - } - - return audiounit_convert_channel_layout(layout.get()); -} - static int audiounit_create_unit(AudioUnit * unit, device_info * device); -static int -audiounit_get_preferred_channel_layout(cubeb * ctx, cubeb_channel_layout * layout) -{ - // The preferred layout is only returned when the connected sound device - // (e.g. ASUS Xonar U7), has preferred layout setting. - // For default output on Mac, there is no preferred channel layout, - // so it might return UNDEFINED. - *layout = audiounit_get_preferred_channel_layout(); - - // If the preferred channel layout is UNDEFINED, then we try to access the - // current applied channel layout. - if (*layout == CUBEB_LAYOUT_UNDEFINED) { - // If we already have at least one cubeb stream, then the current channel - // layout must be updated. We can return it directly. - if (ctx->active_streams) { - *layout = ctx->layout; - return CUBEB_OK; - } - - // If there is no existed stream, then we create a default ouput unit and - // use it to get the current used channel layout. - AudioUnit output_unit = nullptr; - device_info default_out_device; - default_out_device.id = audiounit_get_default_device_id(CUBEB_DEVICE_TYPE_OUTPUT); - default_out_device.flags = (DEV_OUTPUT | DEV_SYSTEM_DEFAULT); - if (default_out_device.id != kAudioObjectUnknown) { - audiounit_create_unit(&output_unit, &default_out_device); - *layout = audiounit_get_current_channel_layout(output_unit); - } - } - - if (*layout == CUBEB_LAYOUT_UNDEFINED) { - return CUBEB_ERROR; - } - - return CUBEB_OK; -} - static OSStatus audiounit_remove_device_listener(cubeb * context); static void @@ -1314,80 +1334,60 @@ audio_stream_desc_init(AudioStreamBasicDescription * ss, void audiounit_init_mixer(cubeb_stream * stm) { - // We only handle downmixing for now. - // The audio rendering mechanism on OS X will drop the extra channels beyond - // the channels that audio device can provide, so we need to downmix the + // We can't rely on macOS' AudioUnit to properly downmix (or upmix) the audio + // data, it silently drop the channels so we need to remix the // audio data by ourselves to keep all the information. stm->mixer.reset(cubeb_mixer_create(stm->output_stream_params.format, - CUBEB_MIXER_DIRECTION_DOWNMIX)); + stm->output_stream_params.channels, + stm->output_stream_params.layout, + stm->context->channels, + stm->context->layout)); + assert(stm->mixer); } static int audiounit_set_channel_layout(AudioUnit unit, io_side side, - const cubeb_stream_params * stream_params) + cubeb_channel_layout layout) { if (side != OUTPUT) { return CUBEB_ERROR; } - assert(stream_params->layout != CUBEB_LAYOUT_UNDEFINED); - assert(stream_params->channels == CUBEB_CHANNEL_LAYOUT_MAPS[stream_params->layout].channels); - - OSStatus r; - size_t size = sizeof(AudioChannelLayout); - auto layout = make_sized_audio_channel_layout(size); - - switch (stream_params->layout) { - case CUBEB_LAYOUT_DUAL_MONO: - case CUBEB_LAYOUT_STEREO: - layout->mChannelLayoutTag = kAudioChannelLayoutTag_Stereo; - break; - case CUBEB_LAYOUT_MONO: - layout->mChannelLayoutTag = kAudioChannelLayoutTag_Mono; - break; - case CUBEB_LAYOUT_3F: - layout->mChannelLayoutTag = kAudioChannelLayoutTag_ITU_3_0; - break; - case CUBEB_LAYOUT_2F1: - layout->mChannelLayoutTag = kAudioChannelLayoutTag_ITU_2_1; - break; - case CUBEB_LAYOUT_3F1: - layout->mChannelLayoutTag = kAudioChannelLayoutTag_ITU_3_1; - break; - case CUBEB_LAYOUT_2F2: - layout->mChannelLayoutTag = kAudioChannelLayoutTag_ITU_2_2; - break; - case CUBEB_LAYOUT_3F2: - layout->mChannelLayoutTag = kAudioChannelLayoutTag_ITU_3_2; - break; - case CUBEB_LAYOUT_3F2_LFE: - layout->mChannelLayoutTag = kAudioChannelLayoutTag_AudioUnit_5_1; - break; - default: - layout->mChannelLayoutTag = kAudioChannelLayoutTag_Unknown; - break; + if (layout == CUBEB_LAYOUT_UNDEFINED) { + // We leave everything as-is... + return CUBEB_OK; } - // For those layouts that can't be matched to coreaudio's predefined layout, - // we use customized layout. - if (layout->mChannelLayoutTag == kAudioChannelLayoutTag_Unknown) { - size = offsetof(AudioChannelLayout, mChannelDescriptions[stream_params->channels]); - layout = make_sized_audio_channel_layout(size); - layout->mChannelLayoutTag = kAudioChannelLayoutTag_UseChannelDescriptions; - layout->mNumberChannelDescriptions = stream_params->channels; - for (UInt32 i = 0 ; i < stream_params->channels ; ++i) { - layout->mChannelDescriptions[i].mChannelLabel = - cubeb_channel_to_channel_label(CHANNEL_INDEX_TO_ORDER[stream_params->layout][i]); - layout->mChannelDescriptions[i].mChannelFlags = kAudioChannelFlags_AllOff; - } + + OSStatus r; + int channels = cubeb_channel_layout_nb_channels(layout); + + // We do not use CoreAudio standard layout for lack of documentation on what + // the actual channel orders are. So we set a custom layout. + size_t size = offsetof(AudioChannelLayout, mChannelDescriptions[channels]); + auto au_layout = make_sized_audio_channel_layout(size); + au_layout->mChannelLayoutTag = kAudioChannelLayoutTag_UseChannelDescriptions; + au_layout->mNumberChannelDescriptions = channels; + cubeb_channel_layout channelMap = layout; + int i = 0; + while (channelMap != 0) { + XASSERT(i < channels); + uint32_t channel = (channelMap & 1) << i; + if (channel != 0) { + au_layout->mChannelDescriptions[i].mChannelLabel = + cubeb_channel_to_channel_label(static_cast<cubeb_channel>(channel)); + au_layout->mChannelDescriptions[i].mChannelFlags = kAudioChannelFlags_AllOff; + i += 1; + } + channelMap = channelMap >> 1; } r = AudioUnitSetProperty(unit, kAudioUnitProperty_AudioChannelLayout, kAudioUnitScope_Input, AU_OUT_BUS, - layout.get(), + au_layout.get(), size); if (r != noErr) { LOG("AudioUnitSetProperty/%s/kAudioUnitProperty_AudioChannelLayout rv=%d", to_string(side), r); @@ -1405,14 +1405,9 @@ audiounit_layout_init(cubeb_stream * stm, io_side side) return; } - audiounit_set_channel_layout(stm->output_unit, OUTPUT, &stm->output_stream_params); - - // Update the current used channel layout for the cubeb context. - // Notice that this channel layout may be different from the layout we set above, - // because OSX doesn't return error when the output device can NOT provide - // our desired layout. Thus, we update the layout evertime when the cubeb_stream - // is created and use it when we need to mix audio data. stm->context->layout = audiounit_get_current_channel_layout(stm->output_unit); + + audiounit_set_channel_layout(stm->output_unit, OUTPUT, stm->context->layout); } static vector<AudioObjectID> @@ -2310,6 +2305,25 @@ audiounit_configure_output(cubeb_stream * stm) } stm->output_hw_rate = output_hw_desc.mSampleRate; LOG("(%p) Output device sampling rate: %.2f", stm, output_hw_desc.mSampleRate); + stm->context->channels = output_hw_desc.mChannelsPerFrame; + + // Set the input layout to match the output device layout. + audiounit_layout_init(stm, OUTPUT); + if (stm->context->channels != stm->output_stream_params.channels || + stm->context->layout != stm->output_stream_params.layout) { + LOG("Incompatible channel layouts detected, setting up remixer"); + audiounit_init_mixer(stm); + // We will be remixing the data before it reaches the output device. + // We need to adjust the number of channels and other + // AudioStreamDescription details. + stm->output_desc.mChannelsPerFrame = stm->context->channels; + stm->output_desc.mBytesPerFrame = (stm->output_desc.mBitsPerChannel / 8) * + stm->output_desc.mChannelsPerFrame; + stm->output_desc.mBytesPerPacket = + stm->output_desc.mBytesPerFrame * stm->output_desc.mFramesPerPacket; + } else { + stm->mixer = nullptr; + } r = AudioUnitSetProperty(stm->output_unit, kAudioUnitProperty_StreamFormat, @@ -2353,10 +2367,6 @@ audiounit_configure_output(cubeb_stream * stm) return CUBEB_ERROR; } - if (stm->output_stream_params.layout != CUBEB_LAYOUT_UNDEFINED) { - audiounit_layout_init(stm, OUTPUT); - audiounit_init_mixer(stm); - } LOG("(%p) Output audiounit init successfully.", stm); return CUBEB_OK; } @@ -3468,7 +3478,6 @@ cubeb_ops const audiounit_ops = { /*.get_max_channel_count =*/ audiounit_get_max_channel_count, /*.get_min_latency =*/ audiounit_get_min_latency, /*.get_preferred_sample_rate =*/ audiounit_get_preferred_sample_rate, - /*.get_preferred_channel_layout =*/ audiounit_get_preferred_channel_layout, /*.enumerate_devices =*/ audiounit_enumerate_devices, /*.device_collection_destroy =*/ audiounit_device_collection_destroy, /*.destroy =*/ audiounit_destroy, diff --git a/third_party/rust/cubeb-sys/libcubeb/src/cubeb_jack.cpp b/third_party/rust/cubeb-sys/libcubeb/src/cubeb_jack.cpp index 5f4128d39970170540e47a0eb6ec5cb6cdefc070..3632da5221f318381ecfc4be00bc22afed30cdc9 100644 --- a/third_party/rust/cubeb-sys/libcubeb/src/cubeb_jack.cpp +++ b/third_party/rust/cubeb-sys/libcubeb/src/cubeb_jack.cpp @@ -119,7 +119,6 @@ static struct cubeb_ops const cbjack_ops = { .get_max_channel_count = cbjack_get_max_channel_count, .get_min_latency = cbjack_get_min_latency, .get_preferred_sample_rate = cbjack_get_preferred_sample_rate, - .get_preferred_channel_layout = NULL, .enumerate_devices = cbjack_enumerate_devices, .device_collection_destroy = cbjack_device_collection_destroy, .destroy = cbjack_destroy, diff --git a/third_party/rust/cubeb-sys/libcubeb/src/cubeb_mixer.cpp b/third_party/rust/cubeb-sys/libcubeb/src/cubeb_mixer.cpp index 62ce867961db97a32c8ddb9b52b10296638e8616..1a8cf99d30d2df736518550268f9fbef957f1961 100644 --- a/third_party/rust/cubeb-sys/libcubeb/src/cubeb_mixer.cpp +++ b/third_party/rust/cubeb-sys/libcubeb/src/cubeb_mixer.cpp @@ -3,555 +3,645 @@ * * This program is made available under an ISC-style license. See the * accompanying file LICENSE for details. + * + * Adapted from code based on libswresample's rematrix.c */ +#define NOMINMAX + +#include <algorithm> #include <cassert> +#include <climits> +#include <cmath> +#include <cstdlib> +#ifdef _MSC_VER +#include <intrin.h> +#endif +#include <memory> +#include <type_traits> #include "cubeb-internal.h" #include "cubeb_mixer.h" +#include "cubeb_utils.h" + +#ifndef FF_ARRAY_ELEMS +#define FF_ARRAY_ELEMS(a) (sizeof(a) / sizeof((a)[0])) +#endif + +#define CHANNELS_MAX 32 +#define FRONT_LEFT 0 +#define FRONT_RIGHT 1 +#define FRONT_CENTER 2 +#define LOW_FREQUENCY 3 +#define BACK_LEFT 4 +#define BACK_RIGHT 5 +#define FRONT_LEFT_OF_CENTER 6 +#define FRONT_RIGHT_OF_CENTER 7 +#define BACK_CENTER 8 +#define SIDE_LEFT 9 +#define SIDE_RIGHT 10 +#define TOP_CENTER 11 +#define TOP_FRONT_LEFT 12 +#define TOP_FRONT_CENTER 13 +#define TOP_FRONT_RIGHT 14 +#define TOP_BACK_LEFT 15 +#define TOP_BACK_CENTER 16 +#define TOP_BACK_RIGHT 17 +#define NUM_NAMED_CHANNELS 18 + +#ifndef M_SQRT1_2 +#define M_SQRT1_2 0.70710678118654752440 /* 1/sqrt(2) */ +#endif +#ifndef M_SQRT2 +#define M_SQRT2 1.41421356237309504880 /* sqrt(2) */ +#endif +#define SQRT3_2 1.22474487139158904909 /* sqrt(3/2) */ -// DUAL_MONO(_LFE) is same as STEREO(_LFE). -#define MASK_MONO (1 << CHANNEL_MONO) -#define MASK_MONO_LFE (MASK_MONO | (1 << CHANNEL_LFE)) -#define MASK_STEREO ((1 << CHANNEL_LEFT) | (1 << CHANNEL_RIGHT)) -#define MASK_STEREO_LFE (MASK_STEREO | (1 << CHANNEL_LFE)) -#define MASK_3F (MASK_STEREO | (1 << CHANNEL_CENTER)) -#define MASK_3F_LFE (MASK_3F | (1 << CHANNEL_LFE)) -#define MASK_2F1 (MASK_STEREO | (1 << CHANNEL_RCENTER)) -#define MASK_2F1_LFE (MASK_2F1 | (1 << CHANNEL_LFE)) -#define MASK_3F1 (MASK_3F | (1 << CHANNEL_RCENTER)) -#define MASK_3F1_LFE (MASK_3F1 | (1 << CHANNEL_LFE)) -#define MASK_2F2 (MASK_STEREO | (1 << CHANNEL_LS) | (1 << CHANNEL_RS)) -#define MASK_2F2_LFE (MASK_2F2 | (1 << CHANNEL_LFE)) -#define MASK_3F2 (MASK_2F2 | (1 << CHANNEL_CENTER)) -#define MASK_3F2_LFE (MASK_3F2 | (1 << CHANNEL_LFE)) -#define MASK_3F3R_LFE (MASK_3F2_LFE | (1 << CHANNEL_RCENTER)) -#define MASK_3F4_LFE (MASK_3F2_LFE | (1 << CHANNEL_RLS) | (1 << CHANNEL_RRS)) - -cubeb_channel_layout cubeb_channel_map_to_layout(cubeb_channel_map const * channel_map) +#define C30DB M_SQRT2 +#define C15DB 1.189207115 +#define C__0DB 1.0 +#define C_15DB 0.840896415 +#define C_30DB M_SQRT1_2 +#define C_45DB 0.594603558 +#define C_60DB 0.5 + +unsigned int cubeb_channel_layout_nb_channels(cubeb_channel_layout x) { - uint32_t channel_mask = 0; - for (uint8_t i = 0 ; i < channel_map->channels ; ++i) { - if (channel_map->map[i] == CHANNEL_INVALID || - channel_map->map[i] == CHANNEL_UNMAPPED) { - return CUBEB_LAYOUT_UNDEFINED; +#if __GNUC__ || __clang__ + return __builtin_popcount (x); +#elif _MSC_VER + return __popcnt(x); +#else + x -= (x >> 1) & 0x55555555; + x = (x & 0x33333333) + ((x >> 2) & 0x33333333); + x = (x + (x >> 4)) & 0x0F0F0F0F; + x += x >> 8; + return (x + (x >> 16)) & 0x3F; +#endif +} +struct MixerContext { + MixerContext(cubeb_sample_format f, + uint32_t in_channels, + cubeb_channel_layout in, + uint32_t out_channels, + cubeb_channel_layout out) + : _format(f) + , _in_ch_layout(in == CUBEB_LAYOUT_UNDEFINED + ? (in_channels == 1 + ? CUBEB_LAYOUT_MONO + : (in_channels == 2 ? CUBEB_LAYOUT_STEREO + : CUBEB_LAYOUT_UNDEFINED)) + : in) + , _out_ch_layout( + (out == CUBEB_LAYOUT_UNDEFINED + ? (out_channels == 1 ? CUBEB_LAYOUT_MONO + : (out_channels == 2 ? CUBEB_LAYOUT_STEREO + : CUBEB_LAYOUT_UNDEFINED)) + : out)) + , _in_ch_count(in_channels) + , _out_ch_count(out_channels) + { + if (in_channels != cubeb_channel_layout_nb_channels(in) || + out_channels != cubeb_channel_layout_nb_channels(out)) { + // Mismatch between channels and layout, aborting. + return; } - channel_mask |= 1 << channel_map->map[i]; + _valid = init() >= 0; } - switch(channel_mask) { - case MASK_MONO: return CUBEB_LAYOUT_MONO; - case MASK_MONO_LFE: return CUBEB_LAYOUT_MONO_LFE; - case MASK_STEREO: return CUBEB_LAYOUT_STEREO; - case MASK_STEREO_LFE: return CUBEB_LAYOUT_STEREO_LFE; - case MASK_3F: return CUBEB_LAYOUT_3F; - case MASK_3F_LFE: return CUBEB_LAYOUT_3F_LFE; - case MASK_2F1: return CUBEB_LAYOUT_2F1; - case MASK_2F1_LFE: return CUBEB_LAYOUT_2F1_LFE; - case MASK_3F1: return CUBEB_LAYOUT_3F1; - case MASK_3F1_LFE: return CUBEB_LAYOUT_3F1_LFE; - case MASK_2F2: return CUBEB_LAYOUT_2F2; - case MASK_2F2_LFE: return CUBEB_LAYOUT_2F2_LFE; - case MASK_3F2: return CUBEB_LAYOUT_3F2; - case MASK_3F2_LFE: return CUBEB_LAYOUT_3F2_LFE; - case MASK_3F3R_LFE: return CUBEB_LAYOUT_3F3R_LFE; - case MASK_3F4_LFE: return CUBEB_LAYOUT_3F4_LFE; - default: return CUBEB_LAYOUT_UNDEFINED; + static bool even(cubeb_channel_layout layout) + { + if (!layout) { + return true; + } + if (layout & (layout - 1)) { + return true; + } + return false; } -} -cubeb_layout_map const CUBEB_CHANNEL_LAYOUT_MAPS[CUBEB_LAYOUT_MAX] = { - { "undefined", 0, CUBEB_LAYOUT_UNDEFINED }, - { "dual mono", 2, CUBEB_LAYOUT_DUAL_MONO }, - { "dual mono lfe", 3, CUBEB_LAYOUT_DUAL_MONO_LFE }, - { "mono", 1, CUBEB_LAYOUT_MONO }, - { "mono lfe", 2, CUBEB_LAYOUT_MONO_LFE }, - { "stereo", 2, CUBEB_LAYOUT_STEREO }, - { "stereo lfe", 3, CUBEB_LAYOUT_STEREO_LFE }, - { "3f", 3, CUBEB_LAYOUT_3F }, - { "3f lfe", 4, CUBEB_LAYOUT_3F_LFE }, - { "2f1", 3, CUBEB_LAYOUT_2F1 }, - { "2f1 lfe", 4, CUBEB_LAYOUT_2F1_LFE }, - { "3f1", 4, CUBEB_LAYOUT_3F1 }, - { "3f1 lfe", 5, CUBEB_LAYOUT_3F1_LFE }, - { "2f2", 4, CUBEB_LAYOUT_2F2 }, - { "2f2 lfe", 5, CUBEB_LAYOUT_2F2_LFE }, - { "3f2", 5, CUBEB_LAYOUT_3F2 }, - { "3f2 lfe", 6, CUBEB_LAYOUT_3F2_LFE }, - { "3f3r lfe", 7, CUBEB_LAYOUT_3F3R_LFE }, - { "3f4 lfe", 8, CUBEB_LAYOUT_3F4_LFE } -}; + // Ensure that the layout is sane (that is have symmetrical left/right + // channels), if not, layout will be treated as mono. + static cubeb_channel_layout clean_layout(cubeb_channel_layout layout) + { + if (layout && layout != CHANNEL_FRONT_LEFT && !(layout & (layout - 1))) { + LOG("Treating layout as mono"); + return CHANNEL_FRONT_CENTER; + } -static int const CHANNEL_ORDER_TO_INDEX[CUBEB_LAYOUT_MAX][CHANNEL_MAX] = { -// M | L | R | C | LS | RS | RLS | RC | RRS | LFE - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, // UNDEFINED - { -1, 0, 1, -1, -1, -1, -1, -1, -1, -1 }, // DUAL_MONO - { -1, 0, 1, -1, -1, -1, -1, -1, -1, 2 }, // DUAL_MONO_LFE - { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, // MONO - { 0, -1, -1, -1, -1, -1, -1, -1, -1, 1 }, // MONO_LFE - { -1, 0, 1, -1, -1, -1, -1, -1, -1, -1 }, // STEREO - { -1, 0, 1, -1, -1, -1, -1, -1, -1, 2 }, // STEREO_LFE - { -1, 0, 1, 2, -1, -1, -1, -1, -1, -1 }, // 3F - { -1, 0, 1, 2, -1, -1, -1, -1, -1, 3 }, // 3F_LFE - { -1, 0, 1, -1, -1, -1, -1, 2, -1, -1 }, // 2F1 - { -1, 0, 1, -1, -1, -1, -1, 3, -1, 2 }, // 2F1_LFE - { -1, 0, 1, 2, -1, -1, -1, 3, -1, -1 }, // 3F1 - { -1, 0, 1, 2, -1, -1, -1, 4, -1, 3 }, // 3F1_LFE - { -1, 0, 1, -1, 2, 3, -1, -1, -1, -1 }, // 2F2 - { -1, 0, 1, -1, 3, 4, -1, -1, -1, 2 }, // 2F2_LFE - { -1, 0, 1, 2, 3, 4, -1, -1, -1, -1 }, // 3F2 - { -1, 0, 1, 2, 4, 5, -1, -1, -1, 3 }, // 3F2_LFE - { -1, 0, 1, 2, 5, 6, -1, 4, -1, 3 }, // 3F3R_LFE - { -1, 0, 1, 2, 6, 7, 4, -1, 5, 3 }, // 3F4_LFE -}; + return layout; + } -// The downmix matrix from TABLE 2 in the ITU-R BS.775-3[1] defines a way to -// convert 3F2 input data to 1F, 2F, 3F, 2F1, 3F1, 2F2 output data. We extend it -// to convert 3F2-LFE input data to 1F, 2F, 3F, 2F1, 3F1, 2F2 and their LFEs -// output data. -// [1] https://www.itu.int/dms_pubrec/itu-r/rec/bs/R-REC-BS.775-3-201208-I!!PDF-E.pdf - -// Number of converted layouts: 1F, 2F, 3F, 2F1, 3F1, 2F2 and their LFEs. -unsigned int const SUPPORTED_LAYOUT_NUM = 12; -// Number of input channel for downmix conversion. -unsigned int const INPUT_CHANNEL_NUM = 6; // 3F2-LFE -// Max number of possible output channels. -unsigned int const MAX_OUTPUT_CHANNEL_NUM = 5; // 2F2-LFE or 3F1-LFE -float const INV_SQRT_2 = 0.707106f; // 1/sqrt(2) -// Each array contains coefficients that will be multiplied with -// { L, R, C, LFE, LS, RS } channels respectively. -static float const DOWNMIX_MATRIX_3F2_LFE[SUPPORTED_LAYOUT_NUM][MAX_OUTPUT_CHANNEL_NUM][INPUT_CHANNEL_NUM] = -{ -// 1F Mono - { - { INV_SQRT_2, INV_SQRT_2, 1, 0, 0.5, 0.5 }, // M - }, -// 1F Mono-LFE - { - { INV_SQRT_2, INV_SQRT_2, 1, 0, 0.5, 0.5 }, // M - { 0, 0, 0, 1, 0, 0 } // LFE - }, -// 2F Stereo - { - { 1, 0, INV_SQRT_2, 0, INV_SQRT_2, 0 }, // L - { 0, 1, INV_SQRT_2, 0, 0, INV_SQRT_2 } // R - }, -// 2F Stereo-LFE - { - { 1, 0, INV_SQRT_2, 0, INV_SQRT_2, 0 }, // L - { 0, 1, INV_SQRT_2, 0, 0, INV_SQRT_2 }, // R - { 0, 0, 0, 1, 0, 0 } // LFE - }, -// 3F - { - { 1, 0, 0, 0, INV_SQRT_2, 0 }, // L - { 0, 1, 0, 0, 0, INV_SQRT_2 }, // R - { 0, 0, 1, 0, 0, 0 } // C - }, -// 3F-LFE - { - { 1, 0, 0, 0, INV_SQRT_2, 0 }, // L - { 0, 1, 0, 0, 0, INV_SQRT_2 }, // R - { 0, 0, 1, 0, 0, 0 }, // C - { 0, 0, 0, 1, 0, 0 } // LFE - }, -// 2F1 - { - { 1, 0, INV_SQRT_2, 0, 0, 0 }, // L - { 0, 1, INV_SQRT_2, 0, 0, 0 }, // R - { 0, 0, 0, 0, INV_SQRT_2, INV_SQRT_2 } // S - }, -// 2F1-LFE + static bool sane_layout(cubeb_channel_layout layout) { - { 1, 0, INV_SQRT_2, 0, 0, 0 }, // L - { 0, 1, INV_SQRT_2, 0, 0, 0 }, // R - { 0, 0, 0, 1, 0, 0 }, // LFE - { 0, 0, 0, 0, INV_SQRT_2, INV_SQRT_2 } // S - }, -// 3F1 - { - { 1, 0, 0, 0, 0, 0 }, // L - { 0, 1, 0, 0, 0, 0 }, // R - { 0, 0, 1, 0, 0, 0 }, // C - { 0, 0, 0, 0, INV_SQRT_2, INV_SQRT_2 } // S - }, -// 3F1-LFE - { - { 1, 0, 0, 0, 0, 0 }, // L - { 0, 1, 0, 0, 0, 0 }, // R - { 0, 0, 1, 0, 0, 0 }, // C - { 0, 0, 0, 1, 0, 0 }, // LFE - { 0, 0, 0, 0, INV_SQRT_2, INV_SQRT_2 } // S - }, -// 2F2 - { - { 1, 0, INV_SQRT_2, 0, 0, 0 }, // L - { 0, 1, INV_SQRT_2, 0, 0, 0 }, // R - { 0, 0, 0, 0, 1, 0 }, // LS - { 0, 0, 0, 0, 0, 1 } // RS - }, -// 2F2-LFE - { - { 1, 0, INV_SQRT_2, 0, 0, 0 }, // L - { 0, 1, INV_SQRT_2, 0, 0, 0 }, // R - { 0, 0, 0, 1, 0, 0 }, // LFE - { 0, 0, 0, 0, 1, 0 }, // LS - { 0, 0, 0, 0, 0, 1 } // RS + if (!(layout & CUBEB_LAYOUT_3F)) { // at least 1 front speaker + return false; + } + if (!even(layout & (CHANNEL_FRONT_LEFT | + CHANNEL_FRONT_RIGHT))) { // no asymetric front + return false; + } + if (!even(layout & + (CHANNEL_SIDE_LEFT | CHANNEL_SIDE_RIGHT))) { // no asymetric side + return false; + } + if (!even(layout & (CHANNEL_BACK_LEFT | CHANNEL_BACK_RIGHT))) { + return false; + } + if (!even(layout & + (CHANNEL_FRONT_LEFT_OF_CENTER | CHANNEL_FRONT_RIGHT_OF_CENTER))) { + return false; + } + if (cubeb_channel_layout_nb_channels(layout) >= CHANNELS_MAX) { + return false; + } + return true; } + + int auto_matrix(); + int init(); + + const cubeb_sample_format _format; + const cubeb_channel_layout _in_ch_layout; ///< input channel layout + const cubeb_channel_layout _out_ch_layout; ///< output channel layout + const uint32_t _in_ch_count; ///< input channel count + const uint32_t _out_ch_count; ///< output channel count + const float _surround_mix_level = C_30DB; ///< surround mixing level + const float _center_mix_level = C_30DB; ///< center mixing level + const float _lfe_mix_level = 1; ///< LFE mixing level + double _matrix[CHANNELS_MAX][CHANNELS_MAX] = {{ 0 }}; ///< floating point rematrixing coefficients + float _matrix_flt[CHANNELS_MAX][CHANNELS_MAX] = {{ 0 }}; ///< single precision floating point rematrixing coefficients + int32_t _matrix32[CHANNELS_MAX][CHANNELS_MAX] = {{ 0 }}; ///< 17.15 fixed point rematrixing coefficients + uint8_t _matrix_ch[CHANNELS_MAX][CHANNELS_MAX+1] = {{ 0 }}; ///< Lists of input channels per output channel that have non zero rematrixing coefficients + bool _clipping = false; ///< Set to true if clipping detection is required + bool _valid = false; ///< Set to true if context is valid. }; -// Convert audio data from 3F2(-LFE) to 1F, 2F, 3F, 2F1, 3F1, 2F2 and their LFEs. -// -// ITU-R BS.775-3[1] provides spec for downmixing 3F2 data to 1F, 2F, 3F, 2F1, -// 3F1, 2F2 data. We simply add LFE to its defined matrix. If both the input -// and output have LFE channel, then we pass it's data. If only input or output -// has LFE, then we either drop it or append 0 to the LFE channel. -// -// Fig. 1: -// |<-------------- 1 -------------->|<-------------- 2 -------------->| -// +----+----+----+------+-----+-----+----+----+----+------+-----+-----+ -// | L0 | R0 | C0 | LFE0 | LS0 | RS0 | L1 | R1 | C1 | LFE1 | LS1 | RS1 | ... -// +----+----+----+------+-----+-----+----+----+----+------+-----+-----+ -// -// Fig. 2: -// |<-- 1 -->|<-- 2 -->| -// +----+----+----+----+ -// | L0 | R0 | L1 | R1 | ... -// +----+----+----+----+ -// -// The figures above shows an example for downmixing from 3F2-LFE(Fig. 1) to -// to stereo(Fig. 2), where L0 = L0 + 0.707 * (C0 + LS0), -// R0 = R0 + 0.707 * (C0 + RS0), L1 = L1 + 0.707 * (C1 + LS1), -// R1 = R1 + 0.707 * (C1 + RS1), ... -// -// Nevertheless, the downmixing method is a little bit different on OSX. -// The audio rendering mechanism on OS X will drop the extra channels beyond -// the channels that audio device can provide. The trick here is that OSX allows -// us to set the layout containing other channels that the output device can -// NOT provide. For example, setting 3F2-LFE layout to a stereo device is fine. -// Therefore, OSX expects we fill the buffer for playing sound by the defined -// layout, so there are some will-be-dropped data in the buffer: -// -// +---+---+---+-----+----+----+ -// | L | R | C | LFE | LS | RS | ... -// +---+---+---+-----+----+----+ -// ^ ^ ^ ^ -// The data for these four channels will be dropped! -// -// To keep all the information, we need to downmix the data before it's dropped. -// The figure below shows an example for downmixing from 3F2-LFE(Fig. 1) -// to stereo(Fig. 3) on OSX, where the LO, R0, L1, R0 are same as above. -// -// Fig. 3: -// |<---------- 1 ---------->|<---------- 2 ---------->| -// +----+----+---+---+---+---+----+----+---+---+---+---+ -// | L0 | R0 | x | x | x | x | L1 | R1 | x | x | x | x | ... -// +----+----+---+---+---+---+----+----+---+---+---+---+ -// |<-- dummy -->| |<-- dummy -->| -template<typename T> -bool -downmix_3f2(unsigned long inframes, - T const * const in, unsigned long in_len, - T * out, unsigned long out_len, - cubeb_channel_layout in_layout, cubeb_channel_layout out_layout) +int MixerContext::auto_matrix() { - if ((in_layout != CUBEB_LAYOUT_3F2 && in_layout != CUBEB_LAYOUT_3F2_LFE) || - out_layout < CUBEB_LAYOUT_MONO || out_layout > CUBEB_LAYOUT_2F2_LFE) { - return false; + double matrix[NUM_NAMED_CHANNELS][NUM_NAMED_CHANNELS] = { { 0 } }; + double maxcoef = 0; + float maxval; + + cubeb_channel_layout in_ch_layout = clean_layout(_in_ch_layout); + cubeb_channel_layout out_ch_layout = clean_layout(_out_ch_layout); + + if (!sane_layout(in_ch_layout)) { + // Channel Not Supported + LOG("Input Layout %x is not supported", _in_ch_layout); + return -1; } - unsigned int in_channels = CUBEB_CHANNEL_LAYOUT_MAPS[in_layout].channels; - unsigned int out_channels = CUBEB_CHANNEL_LAYOUT_MAPS[out_layout].channels; - - // Conversion from 3F2 to 2F2-LFE or 3F1-LFE is allowed, so we use '<=' instead of '<'. - assert(out_channels <= in_channels); - - auto & downmix_matrix = DOWNMIX_MATRIX_3F2_LFE[out_layout - CUBEB_LAYOUT_MONO]; // The matrix is started from mono. - unsigned long out_index = 0; - for (unsigned long i = 0 ; i < inframes * in_channels; i += in_channels) { - for (unsigned int j = 0; j < out_channels; ++j) { - T sample = 0; - for (unsigned int k = 0 ; k < INPUT_CHANNEL_NUM ; ++k) { - // 3F2-LFE has 6 channels: L, R, C, LFE, LS, RS, while 3F2 has only 5 - // channels: L, R, C, LS, RS. Thus, we need to append 0 to LFE(index 3) - // to simulate a 3F2-LFE data when input layout is 3F2. - assert((in_layout == CUBEB_LAYOUT_3F2_LFE || k < 3) ? (i + k < in_len) : (k == 3) ? true : (i + k - 1 < in_len)); - T data = (in_layout == CUBEB_LAYOUT_3F2_LFE) ? in[i + k] : (k == 3) ? 0 : in[i + ((k < 3) ? k : k - 1)]; - sample += downmix_matrix[j][k] * data; - } - assert(out_index + j < out_len); - out[out_index + j] = sample; + if (!sane_layout(out_ch_layout)) { + LOG("Output Layout %x is not supported", _out_ch_layout); + return -1; + } + + for (uint32_t i = 0; i < FF_ARRAY_ELEMS(matrix); i++) { + if (in_ch_layout & out_ch_layout & (1U << i)) { + matrix[i][i] = 1.0; } -#if defined(USE_AUDIOUNIT) - out_index += in_channels; -#else - out_index += out_channels; -#endif } - return true; -} + cubeb_channel_layout unaccounted = in_ch_layout & ~out_ch_layout; -/* Map the audio data by channel name. */ -template<class T> -bool -mix_remap(long inframes, - T const * const in, unsigned long in_len, - T * out, unsigned long out_len, - cubeb_channel_layout in_layout, cubeb_channel_layout out_layout) -{ - assert(in_layout != out_layout && inframes >= 0); + // Rematrixing is done via a matrix of coefficient that should be applied to + // all channels. Channels are treated as pair and must be symmetrical (if a + // left channel exists, the corresponding right should exist too) unless the + // output layout has similar layout. Channels are then mixed toward the front + // center or back center if they exist with a slight bias toward the front. - // We might overwrite the data before we copied them to the mapped index - // (e.g. upmixing from stereo to 2F1 or mapping [L, R] to [R, L]) - if (in == out) { - return false; + if (unaccounted & CHANNEL_FRONT_CENTER) { + if ((out_ch_layout & CUBEB_LAYOUT_STEREO) == CUBEB_LAYOUT_STEREO) { + if (in_ch_layout & CUBEB_LAYOUT_STEREO) { + matrix[FRONT_LEFT][FRONT_CENTER] += _center_mix_level; + matrix[FRONT_RIGHT][FRONT_CENTER] += _center_mix_level; + } else { + matrix[FRONT_LEFT][FRONT_CENTER] += M_SQRT1_2; + matrix[FRONT_RIGHT][FRONT_CENTER] += M_SQRT1_2; + } + } } - - unsigned int in_channels = CUBEB_CHANNEL_LAYOUT_MAPS[in_layout].channels; - unsigned int out_channels = CUBEB_CHANNEL_LAYOUT_MAPS[out_layout].channels; - - uint32_t in_layout_mask = 0; - for (unsigned int i = 0 ; i < in_channels ; ++i) { - in_layout_mask |= 1 << CHANNEL_INDEX_TO_ORDER[in_layout][i]; + if (unaccounted & CUBEB_LAYOUT_STEREO) { + if (out_ch_layout & CHANNEL_FRONT_CENTER) { + matrix[FRONT_CENTER][FRONT_LEFT] += M_SQRT1_2; + matrix[FRONT_CENTER][FRONT_RIGHT] += M_SQRT1_2; + if (in_ch_layout & CHANNEL_FRONT_CENTER) + matrix[FRONT_CENTER][FRONT_CENTER] = _center_mix_level * M_SQRT2; + } } - uint32_t out_layout_mask = 0; - for (unsigned int i = 0 ; i < out_channels ; ++i) { - out_layout_mask |= 1 << CHANNEL_INDEX_TO_ORDER[out_layout][i]; + if (unaccounted & CHANNEL_BACK_CENTER) { + if (out_ch_layout & CHANNEL_BACK_LEFT) { + matrix[BACK_LEFT][BACK_CENTER] += M_SQRT1_2; + matrix[BACK_RIGHT][BACK_CENTER] += M_SQRT1_2; + } else if (out_ch_layout & CHANNEL_SIDE_LEFT) { + matrix[SIDE_LEFT][BACK_CENTER] += M_SQRT1_2; + matrix[SIDE_RIGHT][BACK_CENTER] += M_SQRT1_2; + } else if (out_ch_layout & CHANNEL_FRONT_LEFT) { + if (unaccounted & (CHANNEL_BACK_LEFT | CHANNEL_SIDE_LEFT)) { + matrix[FRONT_LEFT][BACK_CENTER] -= _surround_mix_level * M_SQRT1_2; + matrix[FRONT_RIGHT][BACK_CENTER] += _surround_mix_level * M_SQRT1_2; + } else { + matrix[FRONT_LEFT][BACK_CENTER] -= _surround_mix_level; + matrix[FRONT_RIGHT][BACK_CENTER] += _surround_mix_level; + } + } else if (out_ch_layout & CHANNEL_FRONT_CENTER) { + matrix[FRONT_CENTER][BACK_CENTER] += + _surround_mix_level * M_SQRT1_2; + } } - - // If there is no matched channel, then do nothing. - if (!(out_layout_mask & in_layout_mask)) { - return false; + if (unaccounted & CHANNEL_BACK_LEFT) { + if (out_ch_layout & CHANNEL_BACK_CENTER) { + matrix[BACK_CENTER][BACK_LEFT] += M_SQRT1_2; + matrix[BACK_CENTER][BACK_RIGHT] += M_SQRT1_2; + } else if (out_ch_layout & CHANNEL_SIDE_LEFT) { + if (in_ch_layout & CHANNEL_SIDE_LEFT) { + matrix[SIDE_LEFT][BACK_LEFT] += M_SQRT1_2; + matrix[SIDE_RIGHT][BACK_RIGHT] += M_SQRT1_2; + } else { + matrix[SIDE_LEFT][BACK_LEFT] += 1.0; + matrix[SIDE_RIGHT][BACK_RIGHT] += 1.0; + } + } else if (out_ch_layout & CHANNEL_FRONT_LEFT) { + matrix[FRONT_LEFT][BACK_LEFT] -= _surround_mix_level * M_SQRT1_2; + matrix[FRONT_LEFT][BACK_RIGHT] -= _surround_mix_level * M_SQRT1_2; + matrix[FRONT_RIGHT][BACK_LEFT] += _surround_mix_level * M_SQRT1_2; + matrix[FRONT_RIGHT][BACK_RIGHT] += _surround_mix_level * M_SQRT1_2; + } else if (out_ch_layout & CHANNEL_FRONT_CENTER) { + matrix[FRONT_CENTER][BACK_LEFT] += _surround_mix_level * M_SQRT1_2; + matrix[FRONT_CENTER][BACK_RIGHT] += _surround_mix_level * M_SQRT1_2; + } } - for (unsigned long i = 0, out_index = 0; i < (unsigned long)inframes * in_channels; i += in_channels, out_index += out_channels) { - for (unsigned int j = 0; j < out_channels; ++j) { - cubeb_channel channel = CHANNEL_INDEX_TO_ORDER[out_layout][j]; - uint32_t channel_mask = 1 << channel; - int channel_index = CHANNEL_ORDER_TO_INDEX[in_layout][channel]; - assert(channel_index >= -1); - assert(out_index + j < out_len); - if (in_layout_mask & channel_mask) { - assert(channel_index != -1); - assert(i + channel_index < in_len); - out[out_index + j] = in[i + channel_index]; + if (unaccounted & CHANNEL_SIDE_LEFT) { + if (out_ch_layout & CHANNEL_BACK_LEFT) { + /* if back channels do not exist in the input, just copy side + channels to back channels, otherwise mix side into back */ + if (in_ch_layout & CHANNEL_BACK_LEFT) { + matrix[BACK_LEFT][SIDE_LEFT] += M_SQRT1_2; + matrix[BACK_RIGHT][SIDE_RIGHT] += M_SQRT1_2; } else { - assert(channel_index == -1); - out[out_index + j] = 0; + matrix[BACK_LEFT][SIDE_LEFT] += 1.0; + matrix[BACK_RIGHT][SIDE_RIGHT] += 1.0; } + } else if (out_ch_layout & CHANNEL_BACK_CENTER) { + matrix[BACK_CENTER][SIDE_LEFT] += M_SQRT1_2; + matrix[BACK_CENTER][SIDE_RIGHT] += M_SQRT1_2; + } else if (out_ch_layout & CHANNEL_FRONT_LEFT) { + matrix[FRONT_LEFT][SIDE_LEFT] -= _surround_mix_level * M_SQRT1_2; + matrix[FRONT_LEFT][SIDE_RIGHT] -= _surround_mix_level * M_SQRT1_2; + matrix[FRONT_RIGHT][SIDE_LEFT] += _surround_mix_level * M_SQRT1_2; + matrix[FRONT_RIGHT][SIDE_RIGHT] += _surround_mix_level * M_SQRT1_2; + } else if (out_ch_layout & CHANNEL_FRONT_CENTER) { + matrix[FRONT_CENTER][SIDE_LEFT] += _surround_mix_level * M_SQRT1_2; + matrix[FRONT_CENTER][SIDE_RIGHT] += _surround_mix_level * M_SQRT1_2; } } - return true; -} - -/* Drop the extra channels beyond the provided output channels. */ -template<typename T> -void -downmix_fallback(long inframes, - T const * const in, unsigned long in_len, - T * out, unsigned long out_len, - unsigned int in_channels, unsigned int out_channels) -{ - assert(in_channels >= out_channels && inframes >= 0); - - if (in_channels == out_channels && in == out) { - return; + if (unaccounted & CHANNEL_FRONT_LEFT_OF_CENTER) { + if (out_ch_layout & CHANNEL_FRONT_LEFT) { + matrix[FRONT_LEFT][FRONT_LEFT_OF_CENTER] += 1.0; + matrix[FRONT_RIGHT][FRONT_RIGHT_OF_CENTER] += 1.0; + } else if (out_ch_layout & CHANNEL_FRONT_CENTER) { + matrix[FRONT_CENTER][FRONT_LEFT_OF_CENTER] += M_SQRT1_2; + matrix[FRONT_CENTER][FRONT_RIGHT_OF_CENTER] += M_SQRT1_2; + } } - - for (unsigned long i = 0, out_index = 0; i < (unsigned long)inframes * in_channels; i += in_channels, out_index += out_channels) { - for (unsigned int j = 0; j < out_channels; ++j) { - assert(i + j < in_len && out_index + j < out_len); - out[out_index + j] = in[i + j]; + /* mix LFE into front left/right or center */ + if (unaccounted & CHANNEL_LOW_FREQUENCY) { + if (out_ch_layout & CHANNEL_FRONT_CENTER) { + matrix[FRONT_CENTER][LOW_FREQUENCY] += _lfe_mix_level; + } else if (out_ch_layout & CHANNEL_FRONT_LEFT) { + matrix[FRONT_LEFT][LOW_FREQUENCY] += _lfe_mix_level * M_SQRT1_2; + matrix[FRONT_RIGHT][LOW_FREQUENCY] += _lfe_mix_level * M_SQRT1_2; } } -} - -template<typename T> -void -cubeb_downmix(long inframes, - T const * const in, unsigned long in_len, - T * out, unsigned long out_len, - cubeb_stream_params const * stream_params, - cubeb_stream_params const * mixer_params) -{ - assert(in && out); - assert(inframes); - assert(stream_params->channels >= mixer_params->channels && - mixer_params->channels > 0); - assert(stream_params->layout != CUBEB_LAYOUT_UNDEFINED); - - unsigned int in_channels = stream_params->channels; - cubeb_channel_layout in_layout = stream_params->layout; - - unsigned int out_channels = mixer_params->channels; - cubeb_channel_layout out_layout = mixer_params->layout; - - // If the channel number is different from the layout's setting, - // then we use fallback downmix mechanism. - if (out_channels == CUBEB_CHANNEL_LAYOUT_MAPS[out_layout].channels && - in_channels == CUBEB_CHANNEL_LAYOUT_MAPS[in_layout].channels) { - if (downmix_3f2(inframes, in, in_len, out, out_len, in_layout, out_layout)) { - return; + // Normalize the conversion matrix. + for (uint32_t out_i = 0, i = 0; i < CHANNELS_MAX; i++) { + double sum = 0; + int in_i = 0; + if ((out_ch_layout & (1U << i)) == 0) { + continue; } + for (uint32_t j = 0; j < CHANNELS_MAX; j++) { + if ((in_ch_layout & (1U << j)) == 0) { + continue; + } + if (i < FF_ARRAY_ELEMS(matrix) && j < FF_ARRAY_ELEMS(matrix[0])) { + _matrix[out_i][in_i] = matrix[i][j]; + } else { + _matrix[out_i][in_i] = + i == j && (in_ch_layout & out_ch_layout & (1U << i)); + } + sum += fabs(_matrix[out_i][in_i]); + in_i++; + } + maxcoef = std::max(maxcoef, sum); + out_i++; + } -#if defined(USE_AUDIOUNIT) - // We only support downmix for audio 5.1 on OS X currently. - return; -#endif + if (_format == CUBEB_SAMPLE_S16NE) { + maxval = 1.0; + } else { + maxval = INT_MAX; + } - if (mix_remap(inframes, in, in_len, out, out_len, in_layout, out_layout)) { - return; + // Normalize matrix if needed. + if (maxcoef > maxval) { + maxcoef /= maxval; + for (uint32_t i = 0; i < CHANNELS_MAX; i++) + for (uint32_t j = 0; j < CHANNELS_MAX; j++) { + _matrix[i][j] /= maxcoef; + } + } + + if (_format == CUBEB_SAMPLE_FLOAT32NE) { + for (uint32_t i = 0; i < FF_ARRAY_ELEMS(_matrix); i++) { + for (uint32_t j = 0; j < FF_ARRAY_ELEMS(_matrix[0]); j++) { + _matrix_flt[i][j] = _matrix[i][j]; + } } } - downmix_fallback(inframes, in, in_len, out, out_len, in_channels, out_channels); + return 0; } -/* Upmix function, copies a mono channel into L and R. */ -template<typename T> -void -mono_to_stereo(long insamples, T const * in, unsigned long in_len, - T * out, unsigned long out_len, unsigned int out_channels) +int MixerContext::init() { - for (long i = 0, j = 0; i < insamples; ++i, j += out_channels) { - assert((unsigned long)i < in_len && (unsigned long)j + 1 < out_len); - out[j] = out[j + 1] = in[i]; + int r = auto_matrix(); + if (r) { + return r; } -} -template<typename T> -void -cubeb_upmix(long inframes, - T const * const in, unsigned long in_len, - T * out, unsigned long out_len, - cubeb_stream_params const * stream_params, - cubeb_stream_params const * mixer_params) -{ - assert(in && out); - assert(inframes); - assert(mixer_params->channels >= stream_params->channels && - stream_params->channels > 0); - - unsigned int in_channels = stream_params->channels; - unsigned int out_channels = mixer_params->channels; - - /* Either way, if we have 2 or more channels, the first two are L and R. */ - /* If we are playing a mono stream over stereo speakers, copy the data over. */ - if (in_channels == 1 && out_channels >= 2) { - mono_to_stereo(inframes, in, in_len, out, out_len, out_channels); - } else { - /* Copy through. */ - for (unsigned int i = 0, o = 0; i < inframes * in_channels; - i += in_channels, o += out_channels) { - for (unsigned int j = 0; j < in_channels; ++j) { - assert(i + j < in_len && o + j < out_len); - out[o + j] = in[i + j]; + // Determine if matrix operation would overflow + if (_format == CUBEB_SAMPLE_S16NE) { + int maxsum = 0; + for (uint32_t i = 0; i < _out_ch_count; i++) { + double rem = 0; + int sum = 0; + + for (uint32_t j = 0; j < _in_ch_count; j++) { + double target = _matrix[i][j] * 32768 + rem; + int value = lrintf(target); + rem += target - value; + sum += std::abs(value); } + maxsum = std::max(maxsum, sum); + } + if (maxsum > 32768) { + _clipping = true; } } - /* Check if more channels. */ - if (out_channels <= 2) { - return; - } - - /* Put silence in remaining channels. */ - for (long i = 0, o = 0; i < inframes; ++i, o += out_channels) { - for (unsigned int j = in_channels; j < out_channels; ++j) { - assert((unsigned long)o + j < out_len); - out[o + j] = 0.0; + // FIXME quantize for integers + for (uint32_t i = 0; i < CHANNELS_MAX; i++) { + int ch_in = 0; + for (uint32_t j = 0; j < CHANNELS_MAX; j++) { + _matrix32[i][j] = lrintf(_matrix[i][j] * 32768); + if (_matrix[i][j]) { + _matrix_ch[i][++ch_in] = j; + } } + _matrix_ch[i][0] = ch_in; } + + return 0; } -bool -cubeb_should_upmix(cubeb_stream_params const * stream, cubeb_stream_params const * mixer) +template<typename TYPE_SAMPLE, typename TYPE_COEFF, typename F> +void +sum2(TYPE_SAMPLE * out, + uint32_t stride_out, + const TYPE_SAMPLE * in1, + const TYPE_SAMPLE * in2, + uint32_t stride_in, + TYPE_COEFF coeff1, + TYPE_COEFF coeff2, + F&& operand, + uint32_t frames) { - return mixer->channels > stream->channels; + static_assert( + std::is_same<TYPE_COEFF, + typename std::result_of<F(TYPE_COEFF)>::type>::value, + "function must return the same type as used by matrix_coeff"); + for (uint32_t i = 0; i < frames; i++) { + *out = operand(coeff1 * *in1 + coeff2 * *in2); + out += stride_out; + in1 += stride_in; + in2 += stride_in; + } } -bool -cubeb_should_downmix(cubeb_stream_params const * stream, cubeb_stream_params const * mixer) +template<typename TYPE_SAMPLE, typename TYPE_COEFF, typename F> +void +copy(TYPE_SAMPLE * out, + uint32_t stride_out, + const TYPE_SAMPLE * in, + uint32_t stride_in, + TYPE_COEFF coeff, + F&& operand, + uint32_t frames) { - if (mixer->channels > stream->channels || mixer->layout == stream->layout) { - return false; + static_assert( + std::is_same<TYPE_COEFF, + typename std::result_of<F(TYPE_COEFF)>::type>::value, + "function must return the same type as used by matrix_coeff"); + for (uint32_t i = 0; i < frames; i++) { + *out = operand(coeff * *in); + out += stride_out; + in += stride_in; } - - return mixer->channels < stream->channels || - // When mixer.channels == stream.channels - mixer->layout == CUBEB_LAYOUT_UNDEFINED || // fallback downmix - (stream->layout == CUBEB_LAYOUT_3F2 && // 3f2 downmix - (mixer->layout == CUBEB_LAYOUT_2F2_LFE || - mixer->layout == CUBEB_LAYOUT_3F1_LFE)); } -bool -cubeb_should_mix(cubeb_stream_params const * stream, cubeb_stream_params const * mixer) +template <typename TYPE, typename TYPE_COEFF, size_t COLS, typename F> +static int rematrix(const MixerContext * s, TYPE * aOut, const TYPE * aIn, + const TYPE_COEFF (&matrix_coeff)[COLS][COLS], + F&& aF, uint32_t frames) { - return stream->layout != CUBEB_LAYOUT_UNDEFINED && - (cubeb_should_upmix(stream, mixer) || cubeb_should_downmix(stream, mixer)); + static_assert( + std::is_same<TYPE_COEFF, + typename std::result_of<F(TYPE_COEFF)>::type>::value, + "function must return the same type as used by matrix_coeff"); + + for (uint32_t out_i = 0; out_i < s->_out_ch_count; out_i++) { + TYPE* out = aOut + out_i; + switch (s->_matrix_ch[out_i][0]) { + case 0: + for (uint32_t i = 0; i < frames; i++) { + out[i * s->_out_ch_count] = 0; + } + break; + case 1: { + int in_i = s->_matrix_ch[out_i][1]; + copy(out, + s->_out_ch_count, + aIn + in_i, + s->_in_ch_count, + matrix_coeff[out_i][in_i], + aF, + frames); + } break; + case 2: + sum2(out, + s->_out_ch_count, + aIn + s->_matrix_ch[out_i][1], + aIn + s->_matrix_ch[out_i][2], + s->_in_ch_count, + matrix_coeff[out_i][s->_matrix_ch[out_i][1]], + matrix_coeff[out_i][s->_matrix_ch[out_i][2]], + aF, + frames); + break; + default: + for (uint32_t i = 0; i < frames; i++) { + TYPE_COEFF v = 0; + for (uint32_t j = 0; j < s->_matrix_ch[out_i][0]; j++) { + uint32_t in_i = s->_matrix_ch[out_i][1 + j]; + v += + *(aIn + in_i + i * s->_in_ch_count) * matrix_coeff[out_i][in_i]; + } + out[i * s->_out_ch_count] = aF(v); + } + break; + } + } + return 0; } -struct cubeb_mixer { - virtual void mix(long frames, - void * input_buffer, unsigned long input_buffer_length, - void * output_buffer, unsigned long output_buffer_length, - cubeb_stream_params const * stream_params, - cubeb_stream_params const * mixer_params) = 0; - virtual ~cubeb_mixer() {}; -}; +struct cubeb_mixer +{ + cubeb_mixer(cubeb_sample_format format, + uint32_t in_channels, + cubeb_channel_layout in_layout, + uint32_t out_channels, + cubeb_channel_layout out_layout) + : _context(format, in_channels, in_layout, out_channels, out_layout) + { + } -template<typename T> -struct cubeb_mixer_impl : public cubeb_mixer { - explicit cubeb_mixer_impl(unsigned int d) - : direction(d) + template<typename T> + void copy_and_trunc(size_t frames, + const T * input_buffer, + T * output_buffer) const { + if (_context._in_ch_count <= _context._out_ch_count) { + // Not enough channels to copy, fill the gaps with silence. + for (uint32_t i = 0; i < frames; i++) { + PodCopy(output_buffer, input_buffer, _context._in_ch_count); + output_buffer += _context._in_ch_count; + input_buffer += _context._in_ch_count; + PodZero(output_buffer, _context._out_ch_count - _context._in_ch_count); + output_buffer += _context._out_ch_count - _context._in_ch_count; + } + } else { + for (uint32_t i = 0; i < frames; i++) { + PodCopy(output_buffer, input_buffer, _context._out_ch_count); + output_buffer += _context._out_ch_count; + input_buffer += _context._in_ch_count; + } + } } - void mix(long frames, - void * input_buffer, unsigned long input_buffer_length, - void * output_buffer, unsigned long output_buffer_length, - cubeb_stream_params const * stream_params, - cubeb_stream_params const * mixer_params) + int mix(size_t frames, + void * input_buffer, + size_t input_buffer_size, + void * output_buffer, + size_t output_buffer_size) const { - if (frames <= 0) { - return; + if (frames <= 0 || _context._out_ch_count == 0) { + return 0; + } + + // Check if output buffer is of sufficient size. + size_t size_read_needed = + frames * _context._in_ch_count * cubeb_sample_size(_context._format); + if (input_buffer_size < size_read_needed) { + // We don't have enough data to read! + return -1; + } + if (output_buffer_size * _context._in_ch_count < + size_read_needed * _context._out_ch_count) { + return -1; } - T * in = static_cast<T*>(input_buffer); - T * out = static_cast<T*>(output_buffer); + if (!valid()) { + // The channel layouts were invalid or unsupported, instead we will simply + // either drop the extra channels, or fill with silence the missing ones + if (_context._format == CUBEB_SAMPLE_FLOAT32NE) { + copy_and_trunc(frames, + static_cast<const float*>(input_buffer), + static_cast<float*>(output_buffer)); + } else { + assert(_context._format == CUBEB_SAMPLE_S16NE); + copy_and_trunc(frames, + static_cast<int16_t*>(input_buffer), + reinterpret_cast<int16_t*>(output_buffer)); + } + return 0; + } - if ((direction & CUBEB_MIXER_DIRECTION_DOWNMIX) && - cubeb_should_downmix(stream_params, mixer_params)) { - cubeb_downmix(frames, in, input_buffer_length, out, output_buffer_length, stream_params, mixer_params); - } else if ((direction & CUBEB_MIXER_DIRECTION_UPMIX) && - cubeb_should_upmix(stream_params, mixer_params)) { - cubeb_upmix(frames, in, input_buffer_length, out, output_buffer_length, stream_params, mixer_params); + switch (_context._format) + { + case CUBEB_SAMPLE_FLOAT32NE: { + auto f = [](float x) { return x; }; + return rematrix(&_context, + static_cast<float*>(output_buffer), + static_cast<const float*>(input_buffer), + _context._matrix_flt, + f, + frames); + } + case CUBEB_SAMPLE_S16NE: + if (_context._clipping) { + auto f = [](int x) { + int y = (x + 16384) >> 15; + // clip the signed integer value into the -32768,32767 range. + if ((y + 0x8000U) & ~0xFFFF) { + return (y >> 31) ^ 0x7FFF; + } + return y; + }; + return rematrix(&_context, + static_cast<int16_t*>(output_buffer), + static_cast<const int16_t*>(input_buffer), + _context._matrix32, + f, + frames); + } else { + auto f = [](int x) { return (x + 16384) >> 15; }; + return rematrix(&_context, + static_cast<int16_t*>(output_buffer), + static_cast<const int16_t*>(input_buffer), + _context._matrix32, + f, + frames); + } + break; + default: + assert(false); + break; } + + return -1; } - ~cubeb_mixer_impl() {}; + // Return false if any of the input or ouput layout were invalid. + bool valid() const { return _context._valid; } - unsigned char const direction; + virtual ~cubeb_mixer(){}; + + MixerContext _context; }; -cubeb_mixer * cubeb_mixer_create(cubeb_sample_format format, - unsigned char direction) +cubeb_mixer* cubeb_mixer_create(cubeb_sample_format format, + uint32_t in_channels, + cubeb_channel_layout in_layout, + uint32_t out_channels, + cubeb_channel_layout out_layout) { - assert(direction & CUBEB_MIXER_DIRECTION_DOWNMIX || - direction & CUBEB_MIXER_DIRECTION_UPMIX); - switch(format) { - case CUBEB_SAMPLE_S16NE: - return new cubeb_mixer_impl<short>(direction); - case CUBEB_SAMPLE_FLOAT32NE: - return new cubeb_mixer_impl<float>(direction); - default: - assert(false); - return nullptr; - } + return new cubeb_mixer( + format, in_channels, in_layout, out_channels, out_layout); } void cubeb_mixer_destroy(cubeb_mixer * mixer) @@ -559,13 +649,13 @@ void cubeb_mixer_destroy(cubeb_mixer * mixer) delete mixer; } -void cubeb_mixer_mix(cubeb_mixer * mixer, long frames, - void * input_buffer, unsigned long input_buffer_length, - void * output_buffer, unsigned long output_buffer_length, - cubeb_stream_params const * stream_params, - cubeb_stream_params const * mixer_params) +int cubeb_mixer_mix(cubeb_mixer * mixer, + size_t frames, + void* input_buffer, + size_t input_buffer_size, + void* output_buffer, + size_t output_buffer_size) { - assert(mixer); - mixer->mix(frames, input_buffer, input_buffer_length, output_buffer, output_buffer_length, - stream_params, mixer_params); + return mixer->mix( + frames, input_buffer, input_buffer_size, output_buffer, output_buffer_size); } diff --git a/third_party/rust/cubeb-sys/libcubeb/src/cubeb_mixer.h b/third_party/rust/cubeb-sys/libcubeb/src/cubeb_mixer.h index 51fb9088a83261d470485b5d488846afa40609e8..dd84b87b5c63c42de2d65dc5d873aafa0d589dc8 100644 --- a/third_party/rust/cubeb-sys/libcubeb/src/cubeb_mixer.h +++ b/third_party/rust/cubeb-sys/libcubeb/src/cubeb_mixer.h @@ -8,80 +8,27 @@ #ifndef CUBEB_MIXER #define CUBEB_MIXER -#include "cubeb/cubeb.h" // for cubeb_channel_layout ,CUBEB_CHANNEL_LAYOUT_MAPS and cubeb_stream_params. -#include <stdbool.h> +#include "cubeb/cubeb.h" // for cubeb_channel_layout and cubeb_stream_params. #if defined(__cplusplus) extern "C" { #endif -typedef enum { - CHANNEL_INVALID = -1, - CHANNEL_MONO = 0, - CHANNEL_LEFT, - CHANNEL_RIGHT, - CHANNEL_CENTER, - CHANNEL_LS, - CHANNEL_RS, - CHANNEL_RLS, - CHANNEL_RCENTER, - CHANNEL_RRS, - CHANNEL_LFE, - CHANNEL_UNMAPPED, - CHANNEL_MAX = 256 // Max number of supported channels. -} cubeb_channel; - -static cubeb_channel const CHANNEL_INDEX_TO_ORDER[CUBEB_LAYOUT_MAX][CHANNEL_MAX] = { - { CHANNEL_INVALID }, // UNDEFINED - { CHANNEL_LEFT, CHANNEL_RIGHT }, // DUAL_MONO - { CHANNEL_LEFT, CHANNEL_RIGHT, CHANNEL_LFE }, // DUAL_MONO_LFE - { CHANNEL_MONO }, // MONO - { CHANNEL_MONO, CHANNEL_LFE }, // MONO_LFE - { CHANNEL_LEFT, CHANNEL_RIGHT }, // STEREO - { CHANNEL_LEFT, CHANNEL_RIGHT, CHANNEL_LFE }, // STEREO_LFE - { CHANNEL_LEFT, CHANNEL_RIGHT, CHANNEL_CENTER }, // 3F - { CHANNEL_LEFT, CHANNEL_RIGHT, CHANNEL_CENTER, CHANNEL_LFE }, // 3F_LFE - { CHANNEL_LEFT, CHANNEL_RIGHT, CHANNEL_RCENTER }, // 2F1 - { CHANNEL_LEFT, CHANNEL_RIGHT, CHANNEL_LFE, CHANNEL_RCENTER }, // 2F1_LFE - { CHANNEL_LEFT, CHANNEL_RIGHT, CHANNEL_CENTER, CHANNEL_RCENTER }, // 3F1 - { CHANNEL_LEFT, CHANNEL_RIGHT, CHANNEL_CENTER, CHANNEL_LFE, CHANNEL_RCENTER }, // 3F1_LFE - { CHANNEL_LEFT, CHANNEL_RIGHT, CHANNEL_LS, CHANNEL_RS }, // 2F2 - { CHANNEL_LEFT, CHANNEL_RIGHT, CHANNEL_LFE, CHANNEL_LS, CHANNEL_RS }, // 2F2_LFE - { CHANNEL_LEFT, CHANNEL_RIGHT, CHANNEL_CENTER, CHANNEL_LS, CHANNEL_RS }, // 3F2 - { CHANNEL_LEFT, CHANNEL_RIGHT, CHANNEL_CENTER, CHANNEL_LFE, CHANNEL_LS, CHANNEL_RS }, // 3F2_LFE - { CHANNEL_LEFT, CHANNEL_RIGHT, CHANNEL_CENTER, CHANNEL_LFE, CHANNEL_RCENTER, CHANNEL_LS, CHANNEL_RS }, // 3F3R_LFE - { CHANNEL_LEFT, CHANNEL_RIGHT, CHANNEL_CENTER, CHANNEL_LFE, CHANNEL_RLS, CHANNEL_RRS, CHANNEL_LS, CHANNEL_RS } // 3F4_LFE - // When more channels are present, the stream is considered unmapped to a - // particular speaker set. -}; - -typedef struct { - unsigned int channels; - cubeb_channel map[CHANNEL_MAX]; -} cubeb_channel_map; - -cubeb_channel_layout cubeb_channel_map_to_layout(cubeb_channel_map const * channel_map); - -bool cubeb_should_upmix(cubeb_stream_params const * stream, cubeb_stream_params const * mixer); - -bool cubeb_should_downmix(cubeb_stream_params const * stream, cubeb_stream_params const * mixer); - -bool cubeb_should_mix(cubeb_stream_params const * stream, cubeb_stream_params const * mixer); - -typedef enum { - CUBEB_MIXER_DIRECTION_DOWNMIX = 0x01, - CUBEB_MIXER_DIRECTION_UPMIX = 0x02, -} cubeb_mixer_direction; - typedef struct cubeb_mixer cubeb_mixer; cubeb_mixer * cubeb_mixer_create(cubeb_sample_format format, - unsigned char direction); + uint32_t in_channels, + cubeb_channel_layout in_layout, + uint32_t out_channels, + cubeb_channel_layout out_layout); void cubeb_mixer_destroy(cubeb_mixer * mixer); -void cubeb_mixer_mix(cubeb_mixer * mixer, long frames, - void * input_buffer, unsigned long input_buffer_length, - void * output_buffer, unsigned long output_buffer_length, - cubeb_stream_params const * stream_params, - cubeb_stream_params const * mixer_params); +int cubeb_mixer_mix(cubeb_mixer * mixer, + size_t frames, + void * input_buffer, + size_t input_buffer_size, + void * output_buffer, + size_t output_buffer_size); + +unsigned int cubeb_channel_layout_nb_channels(cubeb_channel_layout channel_layout); #if defined(__cplusplus) } diff --git a/third_party/rust/cubeb-sys/libcubeb/src/cubeb_opensl.c b/third_party/rust/cubeb-sys/libcubeb/src/cubeb_opensl.c index 8e9d4c73f2d68a5dac0ef74b6ede9958cc94c5cd..01784304567224e97e4268e2f9aee32769f40d0e 100644 --- a/third_party/rust/cubeb-sys/libcubeb/src/cubeb_opensl.c +++ b/third_party/rust/cubeb-sys/libcubeb/src/cubeb_opensl.c @@ -26,6 +26,7 @@ #include "cubeb_resampler.h" #include "cubeb-sles.h" #include "cubeb_array_queue.h" +#include "android/cubeb-output-latency.h" #if defined(__ANDROID__) #ifdef LOG @@ -61,14 +62,13 @@ #endif #define DEFAULT_SAMPLE_RATE 48000 +#define DEFAULT_NUM_OF_FRAMES 480 static struct cubeb_ops const opensl_ops; struct cubeb { struct cubeb_ops const * ops; void * lib; - void * libmedia; - int32_t (* get_output_latency)(uint32_t * latency, int stream_type); SLInterfaceID SL_IID_BUFFERQUEUE; SLInterfaceID SL_IID_PLAY; #if defined(__ANDROID__) @@ -80,11 +80,11 @@ struct cubeb { SLObjectItf engObj; SLEngineItf eng; SLObjectItf outmixObj; + output_latency_function * p_output_latency_function; }; #define NELEMS(A) (sizeof(A) / sizeof A[0]) #define NBUFS 4 -#define AUDIO_STREAM_TYPE_MUSIC 3 struct cubeb_stream { /* Note: Must match cubeb_stream layout in cubeb.c. */ @@ -153,7 +153,7 @@ struct cubeb_stream { cubeb_state_callback state_callback; cubeb_resampler * resampler; - unsigned int inputrate; + unsigned int user_output_rate; unsigned int output_configured_rate; unsigned int latency_frames; int64_t lastPosition; @@ -236,7 +236,6 @@ static void play_callback(SLPlayItf caller, void * user_ptr, SLuint32 event) { cubeb_stream * stm = user_ptr; - int draining; assert(stm); switch (event) { case SL_PLAYEVENT_HEADATMARKER: @@ -668,30 +667,11 @@ opensl_init(cubeb ** context, char const * context_name) ctx->ops = &opensl_ops; ctx->lib = dlopen("libOpenSLES.so", RTLD_LAZY); - ctx->libmedia = dlopen("libmedia.so", RTLD_LAZY); - if (!ctx->lib || !ctx->libmedia) { + if (!ctx->lib) { free(ctx); return CUBEB_ERROR; } - /* Get the latency, in ms, from AudioFlinger */ - /* status_t AudioSystem::getOutputLatency(uint32_t* latency, - * audio_stream_type_t streamType) */ - /* First, try the most recent signature. */ - ctx->get_output_latency = - dlsym(ctx->libmedia, "_ZN7android11AudioSystem16getOutputLatencyEPj19audio_stream_type_t"); - if (!ctx->get_output_latency) { - /* in case of failure, try the legacy version. */ - /* status_t AudioSystem::getOutputLatency(uint32_t* latency, - * int streamType) */ - ctx->get_output_latency = - dlsym(ctx->libmedia, "_ZN7android11AudioSystem16getOutputLatencyEPji"); - if (!ctx->get_output_latency) { - opensl_destroy(ctx); - return CUBEB_ERROR; - } - } - typedef SLresult (*slCreateEngine_t)(SLObjectItf *, SLuint32, const SLEngineOption *, @@ -761,6 +741,11 @@ opensl_init(cubeb ** context, char const * context_name) return CUBEB_ERROR; } + ctx->p_output_latency_function = cubeb_output_latency_load_method(android_version); + if (!ctx->p_output_latency_function) { + LOG("Warning: output latency is not available, cubeb_stream_get_position() is not supported"); + } + *context = ctx; LOG("Cubeb init (%p) success", ctx); @@ -784,124 +769,6 @@ opensl_get_max_channel_count(cubeb * ctx, uint32_t * max_channels) return CUBEB_OK; } -static int -opensl_get_preferred_sample_rate(cubeb * ctx, uint32_t * rate) -{ - /* https://android.googlesource.com/platform/ndk.git/+/master/docs/opensles/index.html - * We don't want to deal with JNI here (and we don't have Java on b2g anyways), - * so we just dlopen the library and get the two symbols we need. */ - int r; - void * libmedia; - uint32_t (*get_primary_output_samplingrate)(); - uint32_t (*get_output_samplingrate)(int * samplingRate, int streamType); - - libmedia = dlopen("libmedia.so", RTLD_LAZY); - if (!libmedia) { - return CUBEB_ERROR; - } - - /* uint32_t AudioSystem::getPrimaryOutputSamplingRate(void) */ - get_primary_output_samplingrate = - dlsym(libmedia, "_ZN7android11AudioSystem28getPrimaryOutputSamplingRateEv"); - if (!get_primary_output_samplingrate) { - /* fallback to - * status_t AudioSystem::getOutputSamplingRate(int* samplingRate, int streamType) - * if we cannot find getPrimaryOutputSamplingRate. */ - get_output_samplingrate = - dlsym(libmedia, "_ZN7android11AudioSystem21getOutputSamplingRateEPj19audio_stream_type_t"); - if (!get_output_samplingrate) { - /* Another signature exists, with a int instead of an audio_stream_type_t */ - get_output_samplingrate = - dlsym(libmedia, "_ZN7android11AudioSystem21getOutputSamplingRateEPii"); - if (!get_output_samplingrate) { - dlclose(libmedia); - return CUBEB_ERROR; - } - } - } - - if (get_primary_output_samplingrate) { - *rate = get_primary_output_samplingrate(); - } else { - /* We don't really know about the type, here, so we just pass music. */ - r = get_output_samplingrate((int *) rate, AUDIO_STREAM_TYPE_MUSIC); - if (r) { - dlclose(libmedia); - return CUBEB_ERROR; - } - } - - dlclose(libmedia); - - /* Depending on which method we called above, we can get a zero back, yet have - * a non-error return value, especially if the audio system is not - * ready/shutting down (i.e. when we can't get our hand on the AudioFlinger - * thread). */ - if (*rate == 0) { - return CUBEB_ERROR; - } - - return CUBEB_OK; -} - -static int -opensl_get_min_latency(cubeb * ctx, cubeb_stream_params params, uint32_t * latency_frames) -{ - /* https://android.googlesource.com/platform/ndk.git/+/master/docs/opensles/index.html - * We don't want to deal with JNI here (and we don't have Java on b2g anyways), - * so we just dlopen the library and get the two symbols we need. */ - - int r; - void * libmedia; - size_t (*get_primary_output_frame_count)(void); - int (*get_output_frame_count)(size_t * frameCount, int streamType); - uint32_t primary_sampling_rate; - size_t primary_buffer_size; - - r = opensl_get_preferred_sample_rate(ctx, &primary_sampling_rate); - - if (r) { - return CUBEB_ERROR; - } - - libmedia = dlopen("libmedia.so", RTLD_LAZY); - if (!libmedia) { - return CUBEB_ERROR; - } - - /* JB variant */ - /* size_t AudioSystem::getPrimaryOutputFrameCount(void) */ - get_primary_output_frame_count = - dlsym(libmedia, "_ZN7android11AudioSystem26getPrimaryOutputFrameCountEv"); - if (!get_primary_output_frame_count) { - /* ICS variant */ - /* status_t AudioSystem::getOutputFrameCount(int* frameCount, int streamType) */ - get_output_frame_count = - dlsym(libmedia, "_ZN7android11AudioSystem19getOutputFrameCountEPii"); - if (!get_output_frame_count) { - dlclose(libmedia); - return CUBEB_ERROR; - } - } - - if (get_primary_output_frame_count) { - primary_buffer_size = get_primary_output_frame_count(); - } else { - if (get_output_frame_count(&primary_buffer_size, AUDIO_STREAM_TYPE_MUSIC) != 0) { - return CUBEB_ERROR; - } - } - - /* To get a fast track in Android's mixer, we need to be at the native - * samplerate, which is device dependant. Some devices might be able to - * resample when playing a fast track, but it's pretty rare. */ - *latency_frames = primary_buffer_size; - - dlclose(libmedia); - - return CUBEB_OK; -} - static void opensl_destroy(cubeb * ctx) { @@ -910,7 +777,8 @@ opensl_destroy(cubeb * ctx) if (ctx->engObj) cubeb_destroy_sles_engine(&ctx->engObj); dlclose(ctx->lib); - dlclose(ctx->libmedia); + if (ctx->p_output_latency_function) + cubeb_output_latency_unload_method(ctx->p_output_latency_function); free(ctx); } @@ -997,13 +865,9 @@ opensl_configure_capture(cubeb_stream * stm, cubeb_stream_params * params) // api for input device this is a safe choice. stm->input_device_rate = stm->output_configured_rate; } else { - // The output preferred rate is used for input only scenario. This is - // the correct rate to use to get a fast track for input only. - r = opensl_get_preferred_sample_rate(stm->context, &stm->input_device_rate); - if (r != CUBEB_OK) { - // If everything else fail use a safe choice for Android. - stm->input_device_rate = DEFAULT_SAMPLE_RATE; - } + // The output preferred rate is used for an input only scenario. + // The default rate expected to be supported from all android devices. + stm->input_device_rate = DEFAULT_SAMPLE_RATE; } lDataFormat.samplesPerSec = stm->input_device_rate * 1000; res = (*stm->context->eng)->CreateAudioRecorder(stm->context->eng, @@ -1114,7 +978,7 @@ opensl_configure_playback(cubeb_stream * stm, cubeb_stream_params * params) { assert(stm); assert(params); - stm->inputrate = params->rate; + stm->user_output_rate = params->rate; stm->framesize = params->channels * sizeof(int16_t); stm->lastPosition = -1; stm->lastPositionTimeStamp = 0; @@ -1151,20 +1015,7 @@ opensl_configure_playback(cubeb_stream * stm, cubeb_stream_params * params) { #endif assert(NELEMS(ids) == NELEMS(req)); - unsigned int latency_frames = stm->latency_frames; - uint32_t preferred_sampling_rate = stm->inputrate; -#if defined(__ANDROID__) - if (get_android_version() >= ANDROID_VERSION_MARSHMALLOW) { - // Reset preferred samping rate to trigger fallback to native sampling rate. - preferred_sampling_rate = 0; - if (opensl_get_min_latency(stm->context, *params, &latency_frames) != CUBEB_OK) { - // Default to AudioFlinger's advertised fast track latency of 10ms. - latency_frames = 440; - } - stm->latency_frames = latency_frames; - } -#endif - + uint32_t preferred_sampling_rate = stm->user_output_rate; SLresult res = SL_RESULT_CONTENT_UNSUPPORTED; if (preferred_sampling_rate) { res = (*stm->context->eng)->CreateAudioPlayer(stm->context->eng, @@ -1177,12 +1028,9 @@ opensl_configure_playback(cubeb_stream * stm, cubeb_stream_params * params) { } // Sample rate not supported? Try again with primary sample rate! - if (res == SL_RESULT_CONTENT_UNSUPPORTED) { - if (opensl_get_preferred_sample_rate(stm->context, &preferred_sampling_rate)) { - // If fail default is used - preferred_sampling_rate = DEFAULT_SAMPLE_RATE; - } - + if (res == SL_RESULT_CONTENT_UNSUPPORTED && + preferred_sampling_rate != DEFAULT_SAMPLE_RATE) { + preferred_sampling_rate = DEFAULT_SAMPLE_RATE; format.samplesPerSec = preferred_sampling_rate * 1000; res = (*stm->context->eng)->CreateAudioPlayer(stm->context->eng, &stm->playerObj, @@ -1200,7 +1048,7 @@ opensl_configure_playback(cubeb_stream * stm, cubeb_stream_params * params) { stm->output_configured_rate = preferred_sampling_rate; stm->bytespersec = stm->output_configured_rate * stm->framesize; - stm->queuebuf_len = stm->framesize * latency_frames; + stm->queuebuf_len = stm->framesize * stm->latency_frames; // Calculate the capacity of input array stm->queuebuf_capacity = NBUFS; @@ -1337,7 +1185,7 @@ opensl_stream_init(cubeb * ctx, cubeb_stream ** stream, char const * stream_name stm->data_callback = data_callback; stm->state_callback = state_callback; stm->user_ptr = user_ptr; - stm->latency_frames = latency_frames; + stm->latency_frames = latency_frames ? latency_frames : DEFAULT_NUM_OF_FRAMES; stm->input_enabled = (input_stream_params) ? 1 : 0; stm->output_enabled = (output_stream_params) ? 1 : 0; stm->shutdown = 1; @@ -1601,11 +1449,12 @@ static int opensl_stream_get_position(cubeb_stream * stm, uint64_t * position) { SLmillisecond msec; - uint64_t samplerate; - SLresult res; - int r; - uint32_t mixer_latency; uint32_t compensation_msec = 0; + SLresult res; + + if (!cubeb_output_latency_method_is_loaded(stm->context->p_output_latency_function)) { + return CUBEB_ERROR_NOT_SUPPORTED; + } res = (*stm->play)->GetPosition(stm->play, &msec); if (res != SL_RESULT_SUCCESS) @@ -1621,15 +1470,11 @@ opensl_stream_get_position(cubeb_stream * stm, uint64_t * position) stm->lastPosition = msec; } - samplerate = stm->inputrate; - - r = stm->context->get_output_latency(&mixer_latency, AUDIO_STREAM_TYPE_MUSIC); - if (r) { - return CUBEB_ERROR; - } + uint64_t samplerate = stm->user_output_rate; + uint32_t mixer_latency = cubeb_get_output_latency(stm->context->p_output_latency_function); pthread_mutex_lock(&stm->mutex); - int64_t maximum_position = stm->written * (int64_t)stm->inputrate / stm->output_configured_rate; + int64_t maximum_position = stm->written * (int64_t)stm->user_output_rate / stm->output_configured_rate; pthread_mutex_unlock(&stm->mutex); assert(maximum_position >= 0); @@ -1652,24 +1497,6 @@ opensl_stream_get_position(cubeb_stream * stm, uint64_t * position) return CUBEB_OK; } -int -opensl_stream_get_latency(cubeb_stream * stm, uint32_t * latency) -{ - int r; - uint32_t mixer_latency; // The latency returned by AudioFlinger is in ms. - - /* audio_stream_type_t is an int, so this is okay. */ - r = stm->context->get_output_latency(&mixer_latency, AUDIO_STREAM_TYPE_MUSIC); - if (r) { - return CUBEB_ERROR; - } - - *latency = stm->latency_frames + // OpenSL latency - mixer_latency * stm->inputrate / 1000; // AudioFlinger latency - - return CUBEB_OK; -} - int opensl_stream_set_volume(cubeb_stream * stm, float volume) { @@ -1705,9 +1532,8 @@ static struct cubeb_ops const opensl_ops = { .init = opensl_init, .get_backend_id = opensl_get_backend_id, .get_max_channel_count = opensl_get_max_channel_count, - .get_min_latency = opensl_get_min_latency, - .get_preferred_sample_rate = opensl_get_preferred_sample_rate, - .get_preferred_channel_layout = NULL, + .get_min_latency = NULL, + .get_preferred_sample_rate = NULL, .enumerate_devices = NULL, .device_collection_destroy = NULL, .destroy = opensl_destroy, @@ -1717,7 +1543,7 @@ static struct cubeb_ops const opensl_ops = { .stream_stop = opensl_stream_stop, .stream_reset_default_device = NULL, .stream_get_position = opensl_stream_get_position, - .stream_get_latency = opensl_stream_get_latency, + .stream_get_latency = NULL, .stream_set_volume = opensl_stream_set_volume, .stream_set_panning = NULL, .stream_get_current_device = NULL, diff --git a/third_party/rust/cubeb-sys/libcubeb/src/cubeb_pulse.c b/third_party/rust/cubeb-sys/libcubeb/src/cubeb_pulse.c index 1cac5eadd45b9ff6183bee866bc9c3d44f75da00..079fd69c4a7d5271b2e37f90d58d85dc53bf549b 100644 --- a/third_party/rust/cubeb-sys/libcubeb/src/cubeb_pulse.c +++ b/third_party/rust/cubeb-sys/libcubeb/src/cubeb_pulse.c @@ -7,14 +7,14 @@ #undef NDEBUG #include <assert.h> #include <dlfcn.h> -#include <stdlib.h> #include <pulse/pulseaudio.h> +#include <stdio.h> +#include <stdlib.h> #include <string.h> -#include "cubeb/cubeb.h" #include "cubeb-internal.h" +#include "cubeb/cubeb.h" #include "cubeb_mixer.h" #include "cubeb_strings.h" -#include <stdio.h> #ifdef DISABLE_LIBPULSE_DLOPEN #define WRAP(x) x @@ -511,44 +511,45 @@ stream_update_timing_info(cubeb_stream * stm) static pa_channel_position_t cubeb_channel_to_pa_channel(cubeb_channel channel) { - assert(channel != CHANNEL_INVALID); - - // This variable may be used for multiple times, so we should avoid to - // allocate it in stack, or it will be created and removed repeatedly. - // Use static to allocate this local variable in data space instead of stack. - static pa_channel_position_t map[CHANNEL_MAX] = { - // PA_CHANNEL_POSITION_INVALID, // CHANNEL_INVALID - PA_CHANNEL_POSITION_MONO, // CHANNEL_MONO - PA_CHANNEL_POSITION_FRONT_LEFT, // CHANNEL_LEFT - PA_CHANNEL_POSITION_FRONT_RIGHT, // CHANNEL_RIGHT - PA_CHANNEL_POSITION_FRONT_CENTER, // CHANNEL_CENTER - PA_CHANNEL_POSITION_SIDE_LEFT, // CHANNEL_LS - PA_CHANNEL_POSITION_SIDE_RIGHT, // CHANNEL_RS - PA_CHANNEL_POSITION_REAR_LEFT, // CHANNEL_RLS - PA_CHANNEL_POSITION_REAR_CENTER, // CHANNEL_RCENTER - PA_CHANNEL_POSITION_REAR_RIGHT, // CHANNEL_RRS - PA_CHANNEL_POSITION_LFE // CHANNEL_LFE - }; - - return map[channel]; -} - -static cubeb_channel -pa_channel_to_cubeb_channel(pa_channel_position_t channel) -{ - assert(channel != PA_CHANNEL_POSITION_INVALID); - switch(channel) { - case PA_CHANNEL_POSITION_MONO: return CHANNEL_MONO; - case PA_CHANNEL_POSITION_FRONT_LEFT: return CHANNEL_LEFT; - case PA_CHANNEL_POSITION_FRONT_RIGHT: return CHANNEL_RIGHT; - case PA_CHANNEL_POSITION_FRONT_CENTER: return CHANNEL_CENTER; - case PA_CHANNEL_POSITION_SIDE_LEFT: return CHANNEL_LS; - case PA_CHANNEL_POSITION_SIDE_RIGHT: return CHANNEL_RS; - case PA_CHANNEL_POSITION_REAR_LEFT: return CHANNEL_RLS; - case PA_CHANNEL_POSITION_REAR_CENTER: return CHANNEL_RCENTER; - case PA_CHANNEL_POSITION_REAR_RIGHT: return CHANNEL_RRS; - case PA_CHANNEL_POSITION_LFE: return CHANNEL_LFE; - default: return CHANNEL_INVALID; + switch (channel) { + case CHANNEL_FRONT_LEFT: + return PA_CHANNEL_POSITION_FRONT_LEFT; + case CHANNEL_FRONT_RIGHT: + return PA_CHANNEL_POSITION_FRONT_RIGHT; + case CHANNEL_FRONT_CENTER: + return PA_CHANNEL_POSITION_FRONT_CENTER; + case CHANNEL_LOW_FREQUENCY: + return PA_CHANNEL_POSITION_LFE; + case CHANNEL_BACK_LEFT: + return PA_CHANNEL_POSITION_REAR_LEFT; + case CHANNEL_BACK_RIGHT: + return PA_CHANNEL_POSITION_REAR_RIGHT; + case CHANNEL_FRONT_LEFT_OF_CENTER: + return PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER; + case CHANNEL_FRONT_RIGHT_OF_CENTER: + return PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER; + case CHANNEL_BACK_CENTER: + return PA_CHANNEL_POSITION_REAR_CENTER; + case CHANNEL_SIDE_LEFT: + return PA_CHANNEL_POSITION_SIDE_LEFT; + case CHANNEL_SIDE_RIGHT: + return PA_CHANNEL_POSITION_SIDE_RIGHT; + case CHANNEL_TOP_CENTER: + return PA_CHANNEL_POSITION_TOP_CENTER; + case CHANNEL_TOP_FRONT_LEFT: + return PA_CHANNEL_POSITION_TOP_FRONT_LEFT; + case CHANNEL_TOP_FRONT_CENTER: + return PA_CHANNEL_POSITION_TOP_FRONT_CENTER; + case CHANNEL_TOP_FRONT_RIGHT: + return PA_CHANNEL_POSITION_TOP_FRONT_RIGHT; + case CHANNEL_TOP_BACK_LEFT: + return PA_CHANNEL_POSITION_TOP_REAR_LEFT; + case CHANNEL_TOP_BACK_CENTER: + return PA_CHANNEL_POSITION_TOP_REAR_CENTER; + case CHANNEL_TOP_BACK_RIGHT: + return PA_CHANNEL_POSITION_TOP_REAR_RIGHT; + default: + return PA_CHANNEL_POSITION_INVALID; } } @@ -558,21 +559,18 @@ layout_to_channel_map(cubeb_channel_layout layout, pa_channel_map * cm) assert(cm && layout != CUBEB_LAYOUT_UNDEFINED); WRAP(pa_channel_map_init)(cm); - cm->channels = CUBEB_CHANNEL_LAYOUT_MAPS[layout].channels; - for (uint8_t i = 0 ; i < cm->channels ; ++i) { - cm->map[i] = cubeb_channel_to_pa_channel(CHANNEL_INDEX_TO_ORDER[layout][i]); - } -} -static cubeb_channel_layout -channel_map_to_layout(pa_channel_map * cm) -{ - cubeb_channel_map cubeb_map; - cubeb_map.channels = cm->channels; - for (uint32_t i = 0 ; i < cm->channels ; ++i) { - cubeb_map.map[i] = pa_channel_to_cubeb_channel(cm->map[i]); + uint32_t channels = 0; + cubeb_channel_layout channelMap = layout; + for (uint32_t i = 0 ; channelMap != 0; ++i) { + uint32_t channel = (channelMap & 1) << i; + if (channel != 0) { + cm->map[channels] = cubeb_channel_to_pa_channel(channel); + channels++; + } + channelMap = channelMap >> 1; } - return cubeb_channel_map_to_layout(&cubeb_map); + cm->channels = cubeb_channel_layout_nb_channels(layout); } static void pulse_context_destroy(cubeb * ctx); @@ -714,20 +712,6 @@ pulse_get_preferred_sample_rate(cubeb * ctx, uint32_t * rate) return CUBEB_OK; } -static int -pulse_get_preferred_channel_layout(cubeb * ctx, cubeb_channel_layout * layout) -{ - assert(ctx && layout); - (void)ctx; - - if (!ctx->default_sink_info) - return CUBEB_ERROR; - - *layout = channel_map_to_layout(&ctx->default_sink_info->channel_map); - - return CUBEB_OK; -} - static int pulse_get_min_latency(cubeb * ctx, cubeb_stream_params params, uint32_t * latency_frames) { @@ -808,7 +792,7 @@ create_pa_stream(cubeb_stream * stm, assert(&stm->input_stream == pa_stm || (&stm->output_stream == pa_stm && (stream_params->layout == CUBEB_LAYOUT_UNDEFINED || (stream_params->layout != CUBEB_LAYOUT_UNDEFINED && - CUBEB_CHANNEL_LAYOUT_MAPS[stream_params->layout].channels == stream_params->channels)))); + cubeb_channel_layout_nb_channels(stream_params->layout) == stream_params->channels)))); if (stream_params->prefs & CUBEB_STREAM_PREF_LOOPBACK) { return CUBEB_ERROR_NOT_SUPPORTED; } @@ -1279,7 +1263,7 @@ pulse_sink_info_cb(pa_context * context, const pa_sink_info * info, device_id = info->name; if (intern_device_id(list_data->context, &device_id) != CUBEB_OK) { - assert(false); + assert(NULL); return; } @@ -1348,7 +1332,7 @@ pulse_source_info_cb(pa_context * context, const pa_source_info * info, device_id = info->name; if (intern_device_id(list_data->context, &device_id) != CUBEB_OK) { - assert(false); + assert(NULL); return; } @@ -1588,7 +1572,6 @@ static struct cubeb_ops const pulse_ops = { .get_max_channel_count = pulse_get_max_channel_count, .get_min_latency = pulse_get_min_latency, .get_preferred_sample_rate = pulse_get_preferred_sample_rate, - .get_preferred_channel_layout = pulse_get_preferred_channel_layout, .enumerate_devices = pulse_enumerate_devices, .device_collection_destroy = pulse_device_collection_destroy, .destroy = pulse_destroy, diff --git a/third_party/rust/cubeb-sys/libcubeb/src/cubeb_sndio.c b/third_party/rust/cubeb-sys/libcubeb/src/cubeb_sndio.c index e5b7ab5d471961e50d1935c2c5809ed08359885c..5a4334316f8325ad579e1ab2bc48ddf45cc1cd0a 100644 --- a/third_party/rust/cubeb-sys/libcubeb/src/cubeb_sndio.c +++ b/third_party/rust/cubeb-sys/libcubeb/src/cubeb_sndio.c @@ -536,7 +536,6 @@ static struct cubeb_ops const sndio_ops = { .get_max_channel_count = sndio_get_max_channel_count, .get_min_latency = sndio_get_min_latency, .get_preferred_sample_rate = sndio_get_preferred_sample_rate, - .get_preferred_channel_layout = NULL, .enumerate_devices = sndio_enumerate_devices, .device_collection_destroy = sndio_device_collection_destroy, .destroy = sndio_destroy, diff --git a/third_party/rust/cubeb-sys/libcubeb/src/cubeb_utils.cpp b/third_party/rust/cubeb-sys/libcubeb/src/cubeb_utils.cpp new file mode 100644 index 0000000000000000000000000000000000000000..85572a9feaff3399a3d297b9432f5c1161c0290c --- /dev/null +++ b/third_party/rust/cubeb-sys/libcubeb/src/cubeb_utils.cpp @@ -0,0 +1,23 @@ +/* + * Copyright © 2018 Mozilla Foundation + * + * This program is made available under an ISC-style license. See the + * accompanying file LICENSE for details. + */ + +#include "cubeb_utils.h" + +size_t cubeb_sample_size(cubeb_sample_format format) +{ + switch (format) { + case CUBEB_SAMPLE_S16LE: + case CUBEB_SAMPLE_S16BE: + return sizeof(int16_t); + case CUBEB_SAMPLE_FLOAT32LE: + case CUBEB_SAMPLE_FLOAT32BE: + return sizeof(float); + default: + // should never happen as all cases are handled above. + assert(false); + } +} diff --git a/third_party/rust/cubeb-sys/libcubeb/src/cubeb_utils.h b/third_party/rust/cubeb-sys/libcubeb/src/cubeb_utils.h index dc08fec9928d0d40d5536a36df8b56ec2f1fe010..df675115596f8573504c138a519e21e735f4ac08 100644 --- a/third_party/rust/cubeb-sys/libcubeb/src/cubeb_utils.h +++ b/third_party/rust/cubeb-sys/libcubeb/src/cubeb_utils.h @@ -333,6 +333,10 @@ private: auto_array<T> ar; }; +extern "C" { + size_t cubeb_sample_size(cubeb_sample_format format); +} + using auto_lock = std::lock_guard<owned_critical_section>; #endif // __cplusplus diff --git a/third_party/rust/cubeb-sys/libcubeb/src/cubeb_wasapi.cpp b/third_party/rust/cubeb-sys/libcubeb/src/cubeb_wasapi.cpp index a7d89234386655e7066e87ee707265ecf2639dc7..ac6c6b416c2ad13a091941f403d74b1b543ba170 100644 --- a/third_party/rust/cubeb-sys/libcubeb/src/cubeb_wasapi.cpp +++ b/third_party/rust/cubeb-sys/libcubeb/src/cubeb_wasapi.cpp @@ -135,32 +135,6 @@ private: T * ptr = nullptr; }; -struct auto_com { - auto_com() { - result = CoInitializeEx(NULL, COINIT_MULTITHREADED); - } - ~auto_com() { - if (result == RPC_E_CHANGED_MODE) { - // This is not an error, COM was not initialized by this function, so it is - // not necessary to uninit it. - LOG("COM was already initialized in STA."); - } else if (result == S_FALSE) { - // This is not an error. We are allowed to call CoInitializeEx more than - // once, as long as it is matches by an CoUninitialize call. - // We do that in the dtor which is guaranteed to be called. - LOG("COM was already initialized in MTA"); - } - if (SUCCEEDED(result)) { - CoUninitialize(); - } - } - bool ok() { - return result == RPC_E_CHANGED_MODE || SUCCEEDED(result); - } -private: - HRESULT result; -}; - extern cubeb_ops const wasapi_ops; int wasapi_stream_stop(cubeb_stream * stm); @@ -273,9 +247,10 @@ struct cubeb_stream { uint32_t output_buffer_frame_count = 0; /* Resampler instance. Resampling will only happen if necessary. */ std::unique_ptr<cubeb_resampler, decltype(&cubeb_resampler_destroy)> resampler = { nullptr, cubeb_resampler_destroy }; - /* Mixer interface */ - std::unique_ptr<cubeb_mixer, decltype(&cubeb_mixer_destroy)> mixer = { nullptr, cubeb_mixer_destroy }; - /* A buffer for up/down mixing multi-channel audio. */ + /* Mixer interfaces */ + std::unique_ptr<cubeb_mixer, decltype(&cubeb_mixer_destroy)> output_mixer = { nullptr, cubeb_mixer_destroy }; + std::unique_ptr<cubeb_mixer, decltype(&cubeb_mixer_destroy)> input_mixer = { nullptr, cubeb_mixer_destroy }; + /* A buffer for up/down mixing multi-channel audio output. */ std::vector<BYTE> mix_buffer; /* WASAPI input works in "packets". We re-linearize the audio packets * into this buffer before handing it to the resampler. */ @@ -425,61 +400,11 @@ double stream_to_mix_samplerate_ratio(cubeb_stream_params & stream, cubeb_stream /* Convert the channel layout into the corresponding KSAUDIO_CHANNEL_CONFIG. See more: https://msdn.microsoft.com/en-us/library/windows/hardware/ff537083(v=vs.85).aspx */ -#define MASK_DUAL_MONO (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT) -#define MASK_DUAL_MONO_LFE (MASK_DUAL_MONO | SPEAKER_LOW_FREQUENCY) -#define MASK_MONO (KSAUDIO_SPEAKER_MONO) -#define MASK_MONO_LFE (MASK_MONO | SPEAKER_LOW_FREQUENCY) -#define MASK_STEREO (KSAUDIO_SPEAKER_STEREO) -#define MASK_STEREO_LFE (MASK_STEREO | SPEAKER_LOW_FREQUENCY) -#define MASK_3F (MASK_STEREO | SPEAKER_FRONT_CENTER) -#define MASK_3F_LFE (MASK_3F | SPEAKER_LOW_FREQUENCY) -#define MASK_2F1 (MASK_STEREO | SPEAKER_BACK_CENTER) -#define MASK_2F1_LFE (MASK_2F1 | SPEAKER_LOW_FREQUENCY) -#define MASK_3F1 (KSAUDIO_SPEAKER_SURROUND) -#define MASK_3F1_LFE (MASK_3F1 | SPEAKER_LOW_FREQUENCY) -#define MASK_2F2 (MASK_STEREO | SPEAKER_SIDE_LEFT | SPEAKER_SIDE_RIGHT) -#define MASK_2F2_LFE (MASK_2F2 | SPEAKER_LOW_FREQUENCY) -#define MASK_3F2 (MASK_3F | SPEAKER_SIDE_LEFT | SPEAKER_SIDE_RIGHT) -#define MASK_3F2_LFE (KSAUDIO_SPEAKER_5POINT1_SURROUND) -#define MASK_3F3R_LFE (MASK_3F2_LFE | SPEAKER_BACK_CENTER) -#define MASK_3F4_LFE (KSAUDIO_SPEAKER_7POINT1_SURROUND) - -static DWORD -channel_layout_to_mask(cubeb_channel_layout layout) -{ - XASSERT(layout < CUBEB_LAYOUT_MAX && "invalid conversion."); - - // This variable may be used for multiple times, so we should avoid to - // allocate it in stack, or it will be created and removed repeatedly. - // Use static to allocate this local variable in data space instead of stack. - static DWORD map[CUBEB_LAYOUT_MAX] = { - KSAUDIO_SPEAKER_DIRECTOUT, // CUBEB_LAYOUT_UNDEFINED - MASK_DUAL_MONO, // CUBEB_LAYOUT_DUAL_MONO - MASK_DUAL_MONO_LFE, // CUBEB_LAYOUT_DUAL_MONO_LFE - MASK_MONO, // CUBEB_LAYOUT_MONO - MASK_MONO_LFE, // CUBEB_LAYOUT_MONO_LFE - MASK_STEREO, // CUBEB_LAYOUT_STEREO - MASK_STEREO_LFE, // CUBEB_LAYOUT_STEREO_LFE - MASK_3F, // CUBEB_LAYOUT_3F - MASK_3F_LFE, // CUBEB_LAYOUT_3F_LFE - MASK_2F1, // CUBEB_LAYOUT_2F1 - MASK_2F1_LFE, // CUBEB_LAYOUT_2F1_LFE - MASK_3F1, // CUBEB_LAYOUT_3F1 - MASK_3F1_LFE, // CUBEB_LAYOUT_3F1_LFE - MASK_2F2, // CUBEB_LAYOUT_2F2 - MASK_2F2_LFE, // CUBEB_LAYOUT_2F2_LFE - MASK_3F2, // CUBEB_LAYOUT_3F2 - MASK_3F2_LFE, // CUBEB_LAYOUT_3F2_LFE - MASK_3F3R_LFE, // CUBEB_LAYOUT_3F3R_LFE - MASK_3F4_LFE, // CUBEB_LAYOUT_3F4_LFE - }; - return map[layout]; -} cubeb_channel_layout mask_to_channel_layout(WAVEFORMATEX const * fmt) { - DWORD mask = 0; + cubeb_channel_layout mask = 0; if (fmt->wFormatTag == WAVE_FORMAT_EXTENSIBLE) { WAVEFORMATEXTENSIBLE const * ext = reinterpret_cast<WAVEFORMATEXTENSIBLE const *>(fmt); @@ -487,44 +412,12 @@ mask_to_channel_layout(WAVEFORMATEX const * fmt) } else if (fmt->wFormatTag == WAVE_FORMAT_PCM || fmt->wFormatTag == WAVE_FORMAT_IEEE_FLOAT) { if (fmt->nChannels == 1) { - mask = MASK_MONO; + mask = CHANNEL_FRONT_CENTER; } else if (fmt->nChannels == 2) { - mask = MASK_STEREO; + mask = CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT; } } - - switch (mask) { - // MASK_DUAL_MONO(_LFE) is same as STEREO(_LFE), so we skip it. - case MASK_MONO: return CUBEB_LAYOUT_MONO; - case MASK_MONO_LFE: return CUBEB_LAYOUT_MONO_LFE; - case MASK_STEREO: return CUBEB_LAYOUT_STEREO; - case MASK_STEREO_LFE: return CUBEB_LAYOUT_STEREO_LFE; - case MASK_3F: return CUBEB_LAYOUT_3F; - case MASK_3F_LFE: return CUBEB_LAYOUT_3F_LFE; - case MASK_2F1: return CUBEB_LAYOUT_2F1; - case MASK_2F1_LFE: return CUBEB_LAYOUT_2F1_LFE; - case MASK_3F1: return CUBEB_LAYOUT_3F1; - case MASK_3F1_LFE: return CUBEB_LAYOUT_3F1_LFE; - case MASK_2F2: return CUBEB_LAYOUT_2F2; - // Special case similar to MASK_2F2 but with rear left and right - // speakers instead of side left and right. This mapping is a band-aid as - // cubeb does not current have an enum to differentiate this and MASK_2F2, - // but is preferred to returning an undefined layout. - // See: https://github.com/kinetiknz/cubeb/issues/178 and https://bugzilla.mozilla.org/show_bug.cgi?id=1325023 - case KSAUDIO_SPEAKER_QUAD: return CUBEB_LAYOUT_2F2; - case MASK_2F2_LFE: return CUBEB_LAYOUT_2F2_LFE; - case MASK_3F2: return CUBEB_LAYOUT_3F2; - case MASK_3F2_LFE: return CUBEB_LAYOUT_3F2_LFE; - // Special case similar to MASK_3F2_LFE but with rear left and right - // speakers instead of side left and right. his mapping is a band-aid as - // cubeb does not current have an enum to differentiate this and MASK_3F2_LFE, - // but is preferred to returning an undefined layout. - // See: https://github.com/kinetiknz/cubeb/issues/178 and https://bugzilla.mozilla.org/show_bug.cgi?id=1325023 - case KSAUDIO_SPEAKER_5POINT1: return CUBEB_LAYOUT_3F2_LFE; - case MASK_3F3R_LFE: return CUBEB_LAYOUT_3F3R_LFE; - case MASK_3F4_LFE: return CUBEB_LAYOUT_3F4_LFE; - default: return CUBEB_LAYOUT_UNDEFINED; - } + return mask; } uint32_t @@ -574,7 +467,7 @@ refill(cubeb_stream * stm, void * input_buffer, long input_frames_count, avoid a copy. Avoid exposing output if it is a dummy stream. */ void * dest = nullptr; if (has_output(stm) && !stm->has_dummy_output) { - if (cubeb_should_mix(&stm->output_stream_params, &stm->output_mix_params)) { + if (stm->output_mixer) { dest = stm->mix_buffer.data(); } else { dest = output_buffer; @@ -594,8 +487,11 @@ refill(cubeb_stream * stm, void * input_buffer, long input_frames_count, stm->frames_written += out_frames; } - /* Go in draining mode if we got fewer frames than requested. */ - if (out_frames < output_frames_needed) { + /* Go in draining mode if we got fewer frames than requested. If the stream + has no output we still expect the callback to return number of frames read + from input, otherwise we stop. */ + if ((out_frames < output_frames_needed) || + (!has_output(stm) && out_frames < input_frames_count)) { LOG("start draining."); stm->draining = true; } @@ -605,14 +501,22 @@ refill(cubeb_stream * stm, void * input_buffer, long input_frames_count, XASSERT(out_frames == output_frames_needed || stm->draining || !has_output(stm) || stm->has_dummy_output); // We don't bother mixing dummy output as it will be silenced, otherwise mix output if needed - if (!stm->has_dummy_output && has_output(stm) && cubeb_should_mix(&stm->output_stream_params, &stm->output_mix_params)) { + if (!stm->has_dummy_output && has_output(stm) && stm->output_mixer) { XASSERT(dest == stm->mix_buffer.data()); - unsigned long dest_len = out_frames * stm->output_stream_params.channels; - XASSERT(dest_len <= stm->mix_buffer.size() / stm->bytes_per_sample); - unsigned long output_buffer_len = out_frames * stm->output_mix_params.channels; - cubeb_mixer_mix(stm->mixer.get(), out_frames, - dest, dest_len, output_buffer, output_buffer_len, - &stm->output_stream_params, &stm->output_mix_params); + size_t dest_size = + out_frames * stm->output_stream_params.channels * stm->bytes_per_sample; + XASSERT(dest_size <= stm->mix_buffer.size()); + size_t output_buffer_size = + out_frames * stm->output_mix_params.channels * stm->bytes_per_sample; + int ret = cubeb_mixer_mix(stm->output_mixer.get(), + out_frames, + dest, + dest_size, + output_buffer, + output_buffer_size); + if (ret < 0) { + LOG("Error remixing content (%d)", ret); + } } return out_frames; @@ -655,9 +559,9 @@ bool get_input_buffer(cubeb_stream * stm) return false; } - UINT32 packet_size; + UINT32 frames; hr = stm->capture_client->GetBuffer(&input_packet, - &packet_size, + &frames, &flags, &dev_pos, NULL); @@ -665,7 +569,9 @@ bool get_input_buffer(cubeb_stream * stm) LOG("GetBuffer failed for capture: %lx", hr); return false; } - XASSERT(packet_size == next); + XASSERT(frames == next); + + UINT32 input_stream_samples = frames * stm->input_stream_params.channels; // We do not explicitly handle the AUDCLNT_BUFFERFLAGS_DATA_DISCONTINUITY // flag. There a two primary (non exhaustive) scenarios we anticipate this // flag being set in: @@ -682,32 +588,38 @@ bool get_input_buffer(cubeb_stream * stm) // For more info: https://msdn.microsoft.com/en-us/library/windows/desktop/dd370859(v=vs.85).aspx, // https://msdn.microsoft.com/en-us/library/windows/desktop/dd371458(v=vs.85).aspx if (flags & AUDCLNT_BUFFERFLAGS_SILENT) { - LOG("insert silence: ps=%u", packet_size); - stm->linear_input_buffer->push_silence(packet_size * stm->input_stream_params.channels); + LOG("insert silence: ps=%u", frames); + stm->linear_input_buffer->push_silence(input_stream_samples); } else { - if (cubeb_should_mix(&stm->input_mix_params, &stm->input_stream_params)) { - bool ok = stm->linear_input_buffer->reserve(stm->linear_input_buffer->length() + - packet_size * stm->input_stream_params.channels); + if (stm->input_mixer) { + bool ok = stm->linear_input_buffer->reserve( + stm->linear_input_buffer->length() + input_stream_samples); XASSERT(ok); - unsigned long input_packet_length = packet_size * stm->input_mix_params.channels; - unsigned long linear_input_buffer_length = packet_size * stm->input_stream_params.channels; - cubeb_mixer_mix(stm->mixer.get(), packet_size, - input_packet, input_packet_length, - stm->linear_input_buffer->end(), linear_input_buffer_length, - &stm->input_mix_params, - &stm->input_stream_params); - stm->linear_input_buffer->set_length(stm->linear_input_buffer->length() + linear_input_buffer_length); + size_t input_packet_size = + frames * stm->input_mix_params.channels * + cubeb_sample_size(stm->input_mix_params.format); + size_t linear_input_buffer_size = + input_stream_samples * + cubeb_sample_size(stm->input_stream_params.format); + cubeb_mixer_mix(stm->input_mixer.get(), + frames, + input_packet, + input_packet_size, + stm->linear_input_buffer->end(), + linear_input_buffer_size); + stm->linear_input_buffer->set_length( + stm->linear_input_buffer->length() + input_stream_samples); } else { - stm->linear_input_buffer->push(input_packet, - packet_size * stm->input_stream_params.channels); + stm->linear_input_buffer->push( + input_packet, input_stream_samples); } } - hr = stm->capture_client->ReleaseBuffer(packet_size); + hr = stm->capture_client->ReleaseBuffer(frames); if (FAILED(hr)) { LOG("FAILED to release intput buffer"); return false; } - offset += packet_size; + offset += input_stream_samples; } XASSERT(stm->linear_input_buffer->length() >= offset); @@ -904,7 +816,7 @@ refill_callback_output(cubeb_stream * stm) output_frames, got); XASSERT(got >= 0); - XASSERT((unsigned long) got == output_frames || stm->draining); + XASSERT(size_t(got) == output_frames || stm->draining); hr = stm->render_client->ReleaseBuffer(got, 0); if (FAILED(hr)) { @@ -912,7 +824,7 @@ refill_callback_output(cubeb_stream * stm) return false; } - return (unsigned long) got == output_frames || stm->draining; + return size_t(got) == output_frames || stm->draining; } static unsigned int __stdcall @@ -931,12 +843,15 @@ wasapi_stream_render_loop(LPVOID stream) HANDLE mmcss_handle = NULL; HRESULT hr = 0; DWORD mmcss_task_index = 0; - auto_com com; - if (!com.ok()) { - LOG("COM initialization failed on render_loop thread."); - stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_ERROR); - return 0; - } + struct auto_com { + auto_com() { + HRESULT hr = CoInitializeEx(nullptr, COINIT_MULTITHREADED); + XASSERT(SUCCEEDED(hr)); + } + ~auto_com() { + CoUninitialize(); + } + } com; /* We could consider using "Pro Audio" here for WebAudio and maybe WebRTC. */ @@ -1079,6 +994,7 @@ HRESULT register_notification_client(cubeb_stream * stm) IID_PPV_ARGS(stm->device_enumerator.receive())); if (FAILED(hr)) { LOG("Could not get device enumerator: %lx", hr); + XASSERT(hr != CO_E_NOTINITIALIZED); return hr; } @@ -1125,6 +1041,7 @@ HRESULT get_endpoint(com_ptr<IMMDevice> & device, LPCWSTR devid) IID_PPV_ARGS(enumerator.receive())); if (FAILED(hr)) { LOG("Could not get device enumerator: %lx", hr); + XASSERT(hr != CO_E_NOTINITIALIZED); return hr; } @@ -1145,6 +1062,7 @@ HRESULT get_default_endpoint(com_ptr<IMMDevice> & device, EDataFlow direction) IID_PPV_ARGS(enumerator.receive())); if (FAILED(hr)) { LOG("Could not get device enumerator: %lx", hr); + XASSERT(hr != CO_E_NOTINITIALIZED); return hr; } hr = enumerator->GetDefaultAudioEndpoint(direction, eConsole, device.receive()); @@ -1229,17 +1147,11 @@ stream_set_volume(cubeb_stream * stm, float volume) extern "C" { int wasapi_init(cubeb ** context, char const * context_name) { - HRESULT hr; - auto_com com; - if (!com.ok()) { - return CUBEB_ERROR; - } - /* We don't use the device yet, but need to make sure we can initialize one so that this backend is not incorrectly enabled on platforms that don't support WASAPI. */ com_ptr<IMMDevice> device; - hr = get_default_endpoint(device, eRender); + HRESULT hr = get_default_endpoint(device, eRender); if (FAILED(hr)) { LOG("Could not get device: %lx", hr); return CUBEB_ERROR; @@ -1334,16 +1246,10 @@ char const * wasapi_get_backend_id(cubeb * context) int wasapi_get_max_channel_count(cubeb * ctx, uint32_t * max_channels) { - HRESULT hr; - auto_com com; - if (!com.ok()) { - return CUBEB_ERROR; - } - XASSERT(ctx && max_channels); com_ptr<IMMDevice> device; - hr = get_default_endpoint(device, eRender); + HRESULT hr = get_default_endpoint(device, eRender); if (FAILED(hr)) { return CUBEB_ERROR; } @@ -1371,19 +1277,12 @@ wasapi_get_max_channel_count(cubeb * ctx, uint32_t * max_channels) int wasapi_get_min_latency(cubeb * ctx, cubeb_stream_params params, uint32_t * latency_frames) { - HRESULT hr; - REFERENCE_TIME default_period; - auto_com com; - if (!com.ok()) { - return CUBEB_ERROR; - } - if (params.format != CUBEB_SAMPLE_FLOAT32NE && params.format != CUBEB_SAMPLE_S16NE) { return CUBEB_ERROR_INVALID_FORMAT; } com_ptr<IMMDevice> device; - hr = get_default_endpoint(device, eRender); + HRESULT hr = get_default_endpoint(device, eRender); if (FAILED(hr)) { LOG("Could not get default endpoint: %lx", hr); return CUBEB_ERROR; @@ -1399,6 +1298,7 @@ wasapi_get_min_latency(cubeb * ctx, cubeb_stream_params params, uint32_t * laten } /* The second parameter is for exclusive mode, that we don't use. */ + REFERENCE_TIME default_period; hr = client->GetDevicePeriod(&default_period, NULL); if (FAILED(hr)) { LOG("Could not get device period: %lx", hr); @@ -1421,14 +1321,8 @@ wasapi_get_min_latency(cubeb * ctx, cubeb_stream_params params, uint32_t * laten int wasapi_get_preferred_sample_rate(cubeb * ctx, uint32_t * rate) { - HRESULT hr; - auto_com com; - if (!com.ok()) { - return CUBEB_ERROR; - } - com_ptr<IMMDevice> device; - hr = get_default_endpoint(device, eRender); + HRESULT hr = get_default_endpoint(device, eRender); if (FAILED(hr)) { return CUBEB_ERROR; } @@ -1455,43 +1349,6 @@ wasapi_get_preferred_sample_rate(cubeb * ctx, uint32_t * rate) return CUBEB_OK; } -int -wasapi_get_preferred_channel_layout(cubeb * context, cubeb_channel_layout * layout) -{ - HRESULT hr; - auto_com com; - if (!com.ok()) { - return CUBEB_ERROR; - } - - com_ptr<IMMDevice> device; - hr = get_default_endpoint(device, eRender); - if (FAILED(hr)) { - return CUBEB_ERROR; - } - - com_ptr<IAudioClient> client; - hr = device->Activate(__uuidof(IAudioClient), - CLSCTX_INPROC_SERVER, - NULL, client.receive_vpp()); - if (FAILED(hr)) { - return CUBEB_ERROR; - } - - WAVEFORMATEX * tmp = nullptr; - hr = client->GetMixFormat(&tmp); - if (FAILED(hr)) { - return CUBEB_ERROR; - } - com_heap_ptr<WAVEFORMATEX> mix_format(tmp); - - *layout = mask_to_channel_layout(mix_format.get()); - - LOG("Preferred channel layout: %s", CUBEB_CHANNEL_LAYOUT_MAPS[*layout].name); - - return CUBEB_OK; -} - void wasapi_stream_destroy(cubeb_stream * stm); static void @@ -1528,7 +1385,7 @@ handle_channel_layout(cubeb_stream * stm, EDataFlow direction, com_heap_ptr<WAV /* Get the channel mask by the channel layout. If the layout is not supported, we will get a closest settings below. */ - format_pcm->dwChannelMask = channel_layout_to_mask(stream_params->layout); + format_pcm->dwChannelMask = stream_params->layout; mix_format->nChannels = stream_params->channels; waveformatex_update_derived_properties(mix_format.get()); @@ -1648,6 +1505,7 @@ int setup_wasapi_stream_one_side(cubeb_stream * stm, format_pcm->SubFormat = stm->waveformatextensible_sub_format; } waveformatex_update_derived_properties(mix_format.get()); + /* Set channel layout only when there're more than two channels. Otherwise, * use the default setting retrieved from the stream format of the audio * engine's internal processing by GetMixFormat. */ @@ -1659,20 +1517,12 @@ int setup_wasapi_stream_one_side(cubeb_stream * stm, mix_params->rate = mix_format->nSamplesPerSec; mix_params->channels = mix_format->nChannels; mix_params->layout = mask_to_channel_layout(mix_format.get()); - if (mix_params->layout == CUBEB_LAYOUT_UNDEFINED) { - LOG("Stream using undefined layout! Any mixing may be unpredictable!\n"); - } else if (mix_format->nChannels != CUBEB_CHANNEL_LAYOUT_MAPS[mix_params->layout].channels) { - // The CUBEB_CHANNEL_LAYOUT_MAPS[mix_params->layout].channels may be - // different from the mix_params->channels. 6 channel ouput with stereo - // layout is acceptable in Windows. If this happens, it should not downmix - // audio according to layout. - LOG("Channel count is different from the layout standard!\n"); - } - LOG("Setup requested=[f=%d r=%u c=%u l=%s] mix=[f=%d r=%u c=%u l=%s]", + + LOG("Setup requested=[f=%d r=%u c=%u l=%u] mix=[f=%d r=%u c=%u l=%u]", stream_params->format, stream_params->rate, stream_params->channels, - CUBEB_CHANNEL_LAYOUT_MAPS[stream_params->layout].name, + stream_params->layout, mix_params->format, mix_params->rate, mix_params->channels, - CUBEB_CHANNEL_LAYOUT_MAPS[mix_params->layout].name); + mix_params->layout); DWORD flags = AUDCLNT_STREAMFLAGS_NOPERSIST; @@ -1701,10 +1551,6 @@ int setup_wasapi_stream_one_side(cubeb_stream * stm, " for %s %lx.", DIRECTION_NAME, hr); return CUBEB_ERROR; } - // Input is up/down mixed when depacketized in get_input_buffer. - if (has_output(stm) && cubeb_should_mix(stream_params, mix_params)) { - stm->mix_buffer.resize(frames_to_bytes_before_mix(stm, *buffer_frame_count)); - } // Events are used if not looping back if (!is_loopback) { @@ -1729,17 +1575,10 @@ int setup_wasapi_stream_one_side(cubeb_stream * stm, int setup_wasapi_stream(cubeb_stream * stm) { - HRESULT hr; int rv; stm->stream_reset_lock.assert_current_thread_owns(); - auto_com com; - if (!com.ok()) { - LOG("Failure to initialize COM."); - return CUBEB_ERROR; - } - XASSERT((!stm->output_client || !stm->input_client) && "WASAPI stream already setup, close it first."); if (has_input(stm)) { @@ -1812,8 +1651,8 @@ int setup_wasapi_stream(cubeb_stream * stm) return rv; } - hr = stm->output_client->GetService(__uuidof(IAudioStreamVolume), - stm->audio_stream_volume.receive_vpp()); + HRESULT hr = stm->output_client->GetService(__uuidof(IAudioStreamVolume), + stm->audio_stream_volume.receive_vpp()); if (FAILED(hr)) { LOG("Could not get the IAudioStreamVolume: %lx", hr); return CUBEB_ERROR; @@ -1881,6 +1720,39 @@ int setup_wasapi_stream(cubeb_stream * stm) stm->refill_callback = refill_callback_output; } + // Create input mixer. + if (has_input(stm) && + ((stm->input_mix_params.layout != CUBEB_LAYOUT_UNDEFINED && + stm->input_mix_params.layout != stm->input_stream_params.layout) || + (stm->input_mix_params.channels != stm->input_stream_params.channels))) { + if (stm->input_mix_params.layout == CUBEB_LAYOUT_UNDEFINED) { + LOG("Input stream using undefined layout! Any mixing may be " + "unpredictable!\n"); + } + stm->input_mixer.reset(cubeb_mixer_create(stm->input_stream_params.format, + stm->input_mix_params.channels, + stm->input_mix_params.layout, + stm->input_stream_params.channels, + stm->input_stream_params.layout)); + assert(stm->input_mixer); + } + + // Create output mixer. + if (has_output(stm) && stm->output_mix_params.layout != stm->output_stream_params.layout) { + if (stm->output_mix_params.layout == CUBEB_LAYOUT_UNDEFINED) { + LOG("Output stream using undefined layout! Any mixing may be unpredictable!\n"); + } + stm->output_mixer.reset(cubeb_mixer_create(stm->output_stream_params.format, + stm->output_stream_params.channels, + stm->output_stream_params.layout, + stm->output_mix_params.channels, + stm->output_mix_params.layout)); + assert(stm->output_mixer); + // Input is up/down mixed when depacketized in get_input_buffer. + stm->mix_buffer.resize( + frames_to_bytes_before_mix(stm, stm->output_buffer_frame_count)); + } + return CUBEB_OK; } @@ -1894,12 +1766,7 @@ wasapi_stream_init(cubeb * context, cubeb_stream ** stream, unsigned int latency_frames, cubeb_data_callback data_callback, cubeb_state_callback state_callback, void * user_ptr) { - HRESULT hr; int rv; - auto_com com; - if (!com.ok()) { - return CUBEB_ERROR; - } XASSERT(context && stream && (input_stream_params || output_stream_params)); @@ -1917,16 +1784,10 @@ wasapi_stream_init(cubeb * context, cubeb_stream ** stream, if (input_stream_params) { stm->input_stream_params = *input_stream_params; stm->input_device = utf8_to_wstr(reinterpret_cast<char const *>(input_device)); - // Make sure the layout matches the channel count. - XASSERT(stm->input_stream_params.layout == CUBEB_LAYOUT_UNDEFINED || - stm->input_stream_params.channels == CUBEB_CHANNEL_LAYOUT_MAPS[stm->input_stream_params.layout].channels); } if (output_stream_params) { stm->output_stream_params = *output_stream_params; stm->output_device = utf8_to_wstr(reinterpret_cast<char const *>(output_device)); - // Make sure the layout matches the channel count. - XASSERT(stm->output_stream_params.layout == CUBEB_LAYOUT_UNDEFINED || - stm->output_stream_params.channels == CUBEB_CHANNEL_LAYOUT_MAPS[stm->output_stream_params.layout].channels); } switch (output_stream_params ? output_stream_params->format : input_stream_params->format) { @@ -1943,9 +1804,6 @@ wasapi_stream_init(cubeb * context, cubeb_stream ** stream, default: return CUBEB_ERROR_INVALID_FORMAT; } - stm->mixer.reset(cubeb_mixer_create(output_stream_params ? output_stream_params->format : - input_stream_params->format, - CUBEB_MIXER_DIRECTION_DOWNMIX | CUBEB_MIXER_DIRECTION_UPMIX)); stm->latency = latency_frames; @@ -1979,7 +1837,7 @@ wasapi_stream_init(cubeb * context, cubeb_stream ** stream, return rv; } - hr = register_notification_client(stm.get()); + HRESULT hr = register_notification_client(stm.get()); if (FAILED(hr)) { /* this is not fatal, we can still play audio, but we won't be able to keep using the default audio endpoint if it changes. */ @@ -2011,7 +1869,8 @@ void close_wasapi_stream(cubeb_stream * stm) stm->frames_written = 0; stm->resampler.reset(); - + stm->output_mixer.reset(); + stm->input_mixer.reset(); stm->mix_buffer.clear(); } @@ -2036,7 +1895,6 @@ void wasapi_stream_destroy(cubeb_stream * stm) // The variables intialized in wasapi_stream_init, // must be destroyed in wasapi_stream_destroy. - stm->mixer.reset(); stm->linear_input_buffer.reset(); { @@ -2442,20 +2300,17 @@ static int wasapi_enumerate_devices(cubeb * context, cubeb_device_type type, cubeb_device_collection * out) { - auto_com com; com_ptr<IMMDeviceEnumerator> enumerator; com_ptr<IMMDeviceCollection> collection; HRESULT hr; UINT cc, i; EDataFlow flow; - if (!com.ok()) - return CUBEB_ERROR; - hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, - CLSCTX_INPROC_SERVER, IID_PPV_ARGS(enumerator.receive())); + CLSCTX_INPROC_SERVER, IID_PPV_ARGS(enumerator.receive())); if (FAILED(hr)) { LOG("Could not get device enumerator: %lx", hr); + XASSERT(hr != CO_E_NOTINITIALIZED); return CUBEB_ERROR; } @@ -2519,7 +2374,6 @@ cubeb_ops const wasapi_ops = { /*.get_max_channel_count =*/ wasapi_get_max_channel_count, /*.get_min_latency =*/ wasapi_get_min_latency, /*.get_preferred_sample_rate =*/ wasapi_get_preferred_sample_rate, - /*.get_preferred_channel_layout =*/ wasapi_get_preferred_channel_layout, /*.enumerate_devices =*/ wasapi_enumerate_devices, /*.device_collection_destroy =*/ wasapi_device_collection_destroy, /*.destroy =*/ wasapi_destroy, diff --git a/third_party/rust/cubeb-sys/libcubeb/src/cubeb_winmm.c b/third_party/rust/cubeb-sys/libcubeb/src/cubeb_winmm.c index 20dff4c7a1c87d8e29a5c82e6e3b452691142055..40c80b3e8c315f88d7e4e10a210c2252b801fa42 100644 --- a/third_party/rust/cubeb-sys/libcubeb/src/cubeb_winmm.c +++ b/third_party/rust/cubeb-sys/libcubeb/src/cubeb_winmm.c @@ -1050,7 +1050,6 @@ static struct cubeb_ops const winmm_ops = { /*.get_max_channel_count=*/ winmm_get_max_channel_count, /*.get_min_latency=*/ winmm_get_min_latency, /*.get_preferred_sample_rate =*/ winmm_get_preferred_sample_rate, - /*.get_preferred_channel_layout =*/ NULL, /*.enumerate_devices =*/ winmm_enumerate_devices, /*.device_collection_destroy =*/ winmm_device_collection_destroy, /*.destroy =*/ winmm_destroy, diff --git a/third_party/rust/cubeb-sys/libcubeb/test/common.h b/third_party/rust/cubeb-sys/libcubeb/test/common.h index 1419528871c699f95e7d5273df49721c6932ae5a..43af6a95f1da2e0ce59ad28c3ba9c7fdb2003819 100644 --- a/third_party/rust/cubeb-sys/libcubeb/test/common.h +++ b/third_party/rust/cubeb-sys/libcubeb/test/common.h @@ -11,6 +11,7 @@ #ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN #endif +#include <objbase.h> #include <windows.h> #else #include <unistd.h> @@ -44,31 +45,9 @@ void delay(unsigned int ms) typedef struct { char const * name; unsigned int const channels; - cubeb_channel_layout const layout; + uint32_t const layout; } layout_info; -layout_info const layout_infos[CUBEB_LAYOUT_MAX] = { - { "undefined", 0, CUBEB_LAYOUT_UNDEFINED }, - { "dual mono", 2, CUBEB_LAYOUT_DUAL_MONO }, - { "dual mono lfe", 3, CUBEB_LAYOUT_DUAL_MONO_LFE }, - { "mono", 1, CUBEB_LAYOUT_MONO }, - { "mono lfe", 2, CUBEB_LAYOUT_MONO_LFE }, - { "stereo", 2, CUBEB_LAYOUT_STEREO }, - { "stereo lfe", 3, CUBEB_LAYOUT_STEREO_LFE }, - { "3f", 3, CUBEB_LAYOUT_3F }, - { "3f lfe", 4, CUBEB_LAYOUT_3F_LFE }, - { "2f1", 3, CUBEB_LAYOUT_2F1 }, - { "2f1 lfe", 4, CUBEB_LAYOUT_2F1_LFE }, - { "3f1", 4, CUBEB_LAYOUT_3F1 }, - { "3f1 lfe", 5, CUBEB_LAYOUT_3F1_LFE }, - { "2f2", 4, CUBEB_LAYOUT_2F2 }, - { "2f2 lfe", 5, CUBEB_LAYOUT_2F2_LFE }, - { "3f2", 5, CUBEB_LAYOUT_3F2 }, - { "3f2 lfe", 6, CUBEB_LAYOUT_3F2_LFE }, - { "3f3r lfe", 7, CUBEB_LAYOUT_3F3R_LFE }, - { "3f4 lfe", 8, CUBEB_LAYOUT_3F4_LFE } -}; - int has_available_input_device(cubeb * ctx) { cubeb_device_collection devices; @@ -131,4 +110,24 @@ int common_init(cubeb ** ctx, char const * ctx_name) return r; } +#if defined( _WIN32) +class TestEnvironment : public ::testing::Environment { +public: + void SetUp() override { + hr = CoInitializeEx(nullptr, COINIT_MULTITHREADED); + } + + void TearDown() override { + if (SUCCEEDED(hr)) { + CoUninitialize(); + } + } + +private: + HRESULT hr; +}; + +::testing::Environment* const foo_env = ::testing::AddGlobalTestEnvironment(new TestEnvironment); +#endif + #endif /* TEST_COMMON */ diff --git a/third_party/rust/cubeb-sys/libcubeb/test/test_audio.cpp b/third_party/rust/cubeb-sys/libcubeb/test/test_audio.cpp index df513669517dd315e3d87d44d53f52f0d9b33cc4..2e6c34aafd4ef2616a52e3627789b743fb497a14 100644 --- a/third_party/rust/cubeb-sys/libcubeb/test/test_audio.cpp +++ b/third_party/rust/cubeb-sys/libcubeb/test/test_audio.cpp @@ -94,7 +94,7 @@ int supports_channel_count(string backend_id, int nchannels) (backend_id != "opensl" && backend_id != "audiotrack"); } -int run_test(int num_channels, layout_info layout, int sampling_rate, int is_float) +int run_test(int num_channels, int sampling_rate, int is_float) { int r = CUBEB_OK; @@ -116,13 +116,13 @@ int run_test(int num_channels, layout_info layout, int sampling_rate, int is_flo return CUBEB_OK; } - fprintf(stderr, "Testing %d channel(s), layout: %s, %d Hz, %s (%s)\n", num_channels, layout.name, sampling_rate, is_float ? "float" : "short", cubeb_get_backend_id(ctx)); + fprintf(stderr, "Testing %d channel(s), %d Hz, %s (%s)\n", num_channels, sampling_rate, is_float ? "float" : "short", cubeb_get_backend_id(ctx)); cubeb_stream_params params; params.format = is_float ? CUBEB_SAMPLE_FLOAT32NE : CUBEB_SAMPLE_S16NE; params.rate = sampling_rate; params.channels = num_channels; - params.layout = layout.layout; + params.layout = CUBEB_LAYOUT_UNDEFINED; params.prefs = CUBEB_STREAM_PREF_NONE; synth_state synth(params.channels, params.rate); @@ -246,12 +246,8 @@ TEST(cubeb, run_channel_rate_test) for(auto freq : freq_values) { ASSERT_TRUE(channels < MAX_NUM_CHANNELS); fprintf(stderr, "--------------------------\n"); - for (auto layout : layout_infos) { - if (layout.channels == channels) { - ASSERT_EQ(run_test(channels, layout, freq, 0), CUBEB_OK); - ASSERT_EQ(run_test(channels, layout, freq, 1), CUBEB_OK); - } - } + ASSERT_EQ(run_test(channels, freq, 0), CUBEB_OK); + ASSERT_EQ(run_test(channels, freq, 1), CUBEB_OK); } } } diff --git a/third_party/rust/cubeb-sys/libcubeb/test/test_callback_ret.cpp b/third_party/rust/cubeb-sys/libcubeb/test/test_callback_ret.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bc0a89e7ebcf72460f0576ad178a0ba5d7cc702b --- /dev/null +++ b/third_party/rust/cubeb-sys/libcubeb/test/test_callback_ret.cpp @@ -0,0 +1,204 @@ +/* +* Copyright © 2017 Mozilla Foundation +* +* This program is made available under an ISC-style license. See the +* accompanying file LICENSE for details. +*/ + +/* libcubeb api/function test. Test that different return values from user + specified callbacks are handled correctly. */ +#include "gtest/gtest.h" +#if !defined(_XOPEN_SOURCE) +#define _XOPEN_SOURCE 600 +#endif +#include <memory> +#include <atomic> +#include <string> +#include "cubeb/cubeb.h" +#include "common.h" + +const uint32_t SAMPLE_FREQUENCY = 48000; +const cubeb_sample_format SAMPLE_FORMAT = CUBEB_SAMPLE_S16NE; + +enum test_direction { + INPUT_ONLY, + OUTPUT_ONLY, + DUPLEX +}; + +// Structure which is used by data callbacks to track the total callbacks +// executed vs the number of callbacks expected. +struct user_state_callback_ret { + std::atomic<int> cb_count{ 0 }; + std::atomic<int> expected_cb_count{ 0 }; +}; + +// Data callback that always returns 0 +long data_cb_ret_zero(cubeb_stream * stream, void * user, const void * inputbuffer, void * outputbuffer, long nframes) +{ + user_state_callback_ret * u = (user_state_callback_ret *) user; + // If this is the first time the callback has been called set our expected + // callback count + if (u->cb_count == 0) { + u->expected_cb_count = 1; + } + u->cb_count++; + if (nframes < 1) { + // This shouldn't happen + EXPECT_TRUE(false) << "nframes should not be 0 in data callback!"; + } + return 0; +} + +// Data callback that always returns nframes - 1 +long data_cb_ret_nframes_minus_one(cubeb_stream * stream, void * user, const void * inputbuffer, void * outputbuffer, long nframes) +{ + user_state_callback_ret * u = (user_state_callback_ret *)user; + // If this is the first time the callback has been called set our expected + // callback count + if (u->cb_count == 0) { + u->expected_cb_count = 1; + } + u->cb_count++; + if (nframes < 1) { + // This shouldn't happen + EXPECT_TRUE(false) << "nframes should not be 0 in data callback!"; + } + if (outputbuffer != NULL) { + // If we have an output buffer insert silence + short * ob = (short *) outputbuffer; + for (long i = 0; i < nframes - 1; i++) { + ob[i] = 0; + } + } + return nframes - 1; +} + +// Data callback that always returns nframes +long data_cb_ret_nframes(cubeb_stream * stream, void * user, const void * inputbuffer, void * outputbuffer, long nframes) +{ + user_state_callback_ret * u = (user_state_callback_ret *)user; + u->cb_count++; + // Every callback returns nframes, so every callback is expected + u->expected_cb_count++; + if (nframes < 1) { + // This shouldn't happen + EXPECT_TRUE(false) << "nframes should not be 0 in data callback!"; + } + if (outputbuffer != NULL) { + // If we have an output buffer insert silence + short * ob = (short *) outputbuffer; + for (long i = 0; i < nframes; i++) { + ob[i] = 0; + } + } + return nframes; +} + +void state_cb_ret(cubeb_stream * stream, void * /*user*/, cubeb_state state) +{ + if (stream == NULL) + return; + + switch (state) { + case CUBEB_STATE_STARTED: + fprintf(stderr, "stream started\n"); break; + case CUBEB_STATE_STOPPED: + fprintf(stderr, "stream stopped\n"); break; + case CUBEB_STATE_DRAINED: + fprintf(stderr, "stream drained\n"); break; + default: + fprintf(stderr, "unknown stream state %d\n", state); + } + + return; +} + +void run_test_callback(test_direction direction, + cubeb_data_callback data_cb, + const std::string & test_desc) { + cubeb * ctx; + cubeb_stream * stream; + cubeb_stream_params input_params; + cubeb_stream_params output_params; + int r; + user_state_callback_ret user_state; + uint32_t latency_frames = 0; + + r = common_init(&ctx, "Cubeb callback return value example"); + ASSERT_EQ(r, CUBEB_OK) << "Error initializing cubeb library"; + + std::unique_ptr<cubeb, decltype(&cubeb_destroy)> + cleanup_cubeb_at_exit(ctx, cubeb_destroy); + + if ((direction == INPUT_ONLY || direction == DUPLEX) && + !has_available_input_device(ctx)) { + /* This test needs an available input device, skip it if this host does not + * have one. */ + return; + } + + // Setup all params, but only pass them later as required by direction + input_params.format = SAMPLE_FORMAT; + input_params.rate = SAMPLE_FREQUENCY; + input_params.channels = 1; + input_params.layout = CUBEB_LAYOUT_MONO; + input_params.prefs = CUBEB_STREAM_PREF_NONE; + output_params = input_params; + + r = cubeb_get_min_latency(ctx, &input_params, &latency_frames); + ASSERT_EQ(r, CUBEB_OK) << "Could not get minimal latency"; + + switch (direction) + { + case INPUT_ONLY: + r = cubeb_stream_init(ctx, &stream, "Cubeb callback ret input", + NULL, &input_params, NULL, NULL, + latency_frames, data_cb, state_cb_ret, &user_state); + break; + case OUTPUT_ONLY: + r = cubeb_stream_init(ctx, &stream, "Cubeb callback ret output", + NULL, NULL, NULL, &output_params, + latency_frames, data_cb, state_cb_ret, &user_state); + break; + case DUPLEX: + r = cubeb_stream_init(ctx, &stream, "Cubeb callback ret duplex", + NULL, &input_params, NULL, &output_params, + latency_frames, data_cb, state_cb_ret, &user_state); + break; + default: + ASSERT_TRUE(false) << "Unrecognized test direction!"; + } + EXPECT_EQ(r, CUBEB_OK) << "Error initializing cubeb stream"; + + std::unique_ptr<cubeb_stream, decltype(&cubeb_stream_destroy)> + cleanup_stream_at_exit(stream, cubeb_stream_destroy); + + cubeb_stream_start(stream); + delay(100); + cubeb_stream_stop(stream); + + ASSERT_EQ(user_state.expected_cb_count, user_state.cb_count) << + "Callback called unexpected number of times for " << test_desc << "!"; +} + +TEST(cubeb, test_input_callback) +{ + run_test_callback(INPUT_ONLY, data_cb_ret_zero, "input only, return 0"); + run_test_callback(INPUT_ONLY, data_cb_ret_nframes_minus_one, "input only, return nframes - 1"); + run_test_callback(INPUT_ONLY, data_cb_ret_nframes, "input only, return nframes"); +} + +TEST(cubeb, test_output_callback) +{ + run_test_callback(OUTPUT_ONLY, data_cb_ret_zero, "output only, return 0"); + run_test_callback(OUTPUT_ONLY, data_cb_ret_nframes_minus_one, "output only, return nframes - 1"); + run_test_callback(OUTPUT_ONLY, data_cb_ret_nframes, "output only, return nframes"); +} + +TEST(cubeb, test_duplex_callback) +{ + run_test_callback(DUPLEX, data_cb_ret_zero, "duplex, return 0"); + run_test_callback(DUPLEX, data_cb_ret_nframes_minus_one, "duplex, return nframes - 1"); + run_test_callback(DUPLEX, data_cb_ret_nframes, "duplex, return nframes"); +} diff --git a/third_party/rust/cubeb-sys/libcubeb/test/test_loopback.cpp b/third_party/rust/cubeb-sys/libcubeb/test/test_loopback.cpp index 4fe513708fa65ea878650dce12ac25fb5bc224c4..41624b7df9afcd6dd24782e247fc09da89d057a5 100644 --- a/third_party/rust/cubeb-sys/libcubeb/test/test_loopback.cpp +++ b/third_party/rust/cubeb-sys/libcubeb/test/test_loopback.cpp @@ -294,7 +294,7 @@ void run_loopback_duplex_test(bool is_float) cleanup_stream_at_exit(stream, cubeb_stream_destroy); cubeb_stream_start(stream); - delay(150); + delay(300); cubeb_stream_stop(stream); /* access after stop should not happen, but lock just in case and to appease sanitization tools */ @@ -377,7 +377,7 @@ void run_loopback_separate_streams_test(bool is_float) cubeb_stream_start(input_stream); cubeb_stream_start(output_stream); - delay(150); + delay(300); cubeb_stream_stop(output_stream); cubeb_stream_stop(input_stream); @@ -444,7 +444,7 @@ void run_loopback_silence_test(bool is_float) cleanup_input_stream_at_exit(input_stream, cubeb_stream_destroy); cubeb_stream_start(input_stream); - delay(50); + delay(300); cubeb_stream_stop(input_stream); /* access after stop should not happen, but lock just in case and to appease sanitization tools */ @@ -453,7 +453,7 @@ void run_loopback_silence_test(bool is_float) /* expect to have at least ~50ms of frames */ ASSERT_GE(input_frames.size(), SAMPLE_FREQUENCY / 20); - double EPISILON = 0.000001; + double EPISILON = 0.0001; /* frames should be 0.0, but use epsilon to avoid possible issues with impls that may use ~0.0 silence values. */ for (double frame : input_frames) { @@ -544,7 +544,7 @@ void run_loopback_device_selection_test(bool is_float) cubeb_stream_start(input_stream); cubeb_stream_start(output_stream); - delay(150); + delay(300); cubeb_stream_stop(output_stream); cubeb_stream_stop(input_stream); diff --git a/third_party/rust/cubeb-sys/libcubeb/test/test_mixer.cpp b/third_party/rust/cubeb-sys/libcubeb/test/test_mixer.cpp deleted file mode 100644 index b7daea9a9a4ac413d14fe20d8a2cc00f828a3342..0000000000000000000000000000000000000000 --- a/third_party/rust/cubeb-sys/libcubeb/test/test_mixer.cpp +++ /dev/null @@ -1,222 +0,0 @@ -/* - * Copyright © 2016 Mozilla Foundation - * - * This program is made available under an ISC-style license. See the - * accompanying file LICENSE for details. - */ -#include "gtest/gtest.h" -#include "cubeb/cubeb.h" -#include "cubeb_mixer.h" -#include "common.h" -#include <memory> -#include <vector> - -using std::vector; - -#define STREAM_FREQUENCY 48000 -#define STREAM_FORMAT CUBEB_SAMPLE_FLOAT32LE - -float const M = 1.0f; // Mono -float const L = 2.0f; // Left -float const R = 3.0f; // Right -float const C = 4.0f; // Center -float const LS = 5.0f; // Left Surround -float const RS = 6.0f; // Right Surround -float const RLS = 7.0f; // Rear Left Surround -float const RC = 8.0f; // Rear Center -float const RRS = 9.0f; // Rear Right Surround -float const LFE = 10.0f; // Low Frequency Effects - -float const INV_SQRT_2 = 0.707106f; // 1/sqrt(2) -static float const DOWNMIX_3F2_RESULTS[2][12][5] = { - // 3F2 - { - { INV_SQRT_2*(L+R) + C + 0.5f*(LS+RS) }, // Mono - { INV_SQRT_2*(L+R) + C + 0.5f*(LS+RS), 0 }, // Mono-LFE - { L + INV_SQRT_2*(C+LS), R + INV_SQRT_2*(C+RS) }, // Stereo - { L + INV_SQRT_2*(C+LS), R + INV_SQRT_2*(C+RS), 0 }, // Stereo-LFE - { L + INV_SQRT_2*LS, R + INV_SQRT_2*RS, C }, // 3F - { L + INV_SQRT_2*LS, R + INV_SQRT_2*RS, C, 0 }, // 3F-LFE - { L + C*INV_SQRT_2, R + C*INV_SQRT_2, INV_SQRT_2*(LS+RS) }, // 2F1 - { L + C*INV_SQRT_2, R + C*INV_SQRT_2, 0, INV_SQRT_2*(LS+RS) }, // 2F1-LFE - { L, R, C, INV_SQRT_2*(LS+RS) }, // 3F1 - { L, R, C, 0, INV_SQRT_2*(LS+RS) }, // 3F1-LFE - { L + INV_SQRT_2*C, R + INV_SQRT_2*C, LS, RS }, // 2F2 - { L + INV_SQRT_2*C, R + INV_SQRT_2*C, 0, LS, RS } // 2F2-LFE - }, - // 3F2-LFE - { - { INV_SQRT_2*(L+R) + C + 0.5f*(LS+RS) }, // Mono - { INV_SQRT_2*(L+R) + C + 0.5f*(LS+RS), LFE }, // Mono-LFE - { L + INV_SQRT_2*(C+LS), R + INV_SQRT_2*(C+RS) }, // Stereo - { L + INV_SQRT_2*(C+LS), R + INV_SQRT_2*(C+RS), LFE }, // Stereo-LFE - { L + INV_SQRT_2*LS, R + INV_SQRT_2*RS, C }, // 3F - { L + INV_SQRT_2*LS, R + INV_SQRT_2*RS, C, LFE }, // 3F-LFE - { L + C*INV_SQRT_2, R + C*INV_SQRT_2, INV_SQRT_2*(LS+RS) }, // 2F1 - { L + C*INV_SQRT_2, R + C*INV_SQRT_2, LFE, INV_SQRT_2*(LS+RS) }, // 2F1-LFE - { L, R, C, INV_SQRT_2*(LS+RS) }, // 3F1 - { L, R, C, LFE, INV_SQRT_2*(LS+RS) }, // 3F1-LFE - { L + INV_SQRT_2*C, R + INV_SQRT_2*C, LS, RS }, // 2F2 - { L + INV_SQRT_2*C, R + INV_SQRT_2*C, LFE, LS, RS } // 2F2-LFE - } -}; - -typedef struct { - cubeb_channel_layout layout; - float data[10]; -} audio_input; - -audio_input audio_inputs[CUBEB_LAYOUT_MAX] = { - { CUBEB_LAYOUT_UNDEFINED, { } }, - { CUBEB_LAYOUT_DUAL_MONO, { L, R } }, - { CUBEB_LAYOUT_DUAL_MONO_LFE, { L, R, LFE } }, - { CUBEB_LAYOUT_MONO, { M } }, - { CUBEB_LAYOUT_MONO_LFE, { M, LFE } }, - { CUBEB_LAYOUT_STEREO, { L, R } }, - { CUBEB_LAYOUT_STEREO_LFE, { L, R, LFE } }, - { CUBEB_LAYOUT_3F, { L, R, C } }, - { CUBEB_LAYOUT_3F_LFE, { L, R, C, LFE } }, - { CUBEB_LAYOUT_2F1, { L, R, RC } }, - { CUBEB_LAYOUT_2F1_LFE, { L, R, LFE, RC } }, - { CUBEB_LAYOUT_3F1, { L, R, C, RC } }, - { CUBEB_LAYOUT_3F1_LFE, { L, R, C, LFE, RC } }, - { CUBEB_LAYOUT_2F2, { L, R, LS, RS } }, - { CUBEB_LAYOUT_2F2_LFE, { L, R, LFE, LS, RS } }, - { CUBEB_LAYOUT_3F2, { L, R, C, LS, RS } }, - { CUBEB_LAYOUT_3F2_LFE, { L, R, C, LFE, LS, RS } }, - { CUBEB_LAYOUT_3F3R_LFE, { L, R, C, LFE, RC, LS, RS } }, - { CUBEB_LAYOUT_3F4_LFE, { L, R, C, LFE, RLS, RRS, LS, RS } } -}; - -char const * channel_names[CHANNEL_UNMAPPED + 1] = { - "mono", // CHANNEL_MONO - "left", // CHANNEL_LEFT - "right", // CHANNEL_RIGHT - "center", // CHANNEL_CENTER - "left surround", // CHANNEL_LS - "right surround", // CHANNEL_RS - "rear left surround", // CHANNEL_RLS - "rear center", // CHANNEL_RCENTER - "rear right surround", // CHANNEL_RRS - "low frequency effects", // CHANNEL_LFE - "unmapped" // CHANNEL_UNMAPPED -}; - -// The test cases must be aligned with cubeb_downmix. -void -downmix_test(float const * data, cubeb_channel_layout in_layout, cubeb_channel_layout out_layout) -{ - if (in_layout == CUBEB_LAYOUT_UNDEFINED) { - return; // Only possible output layout would be UNDEFINED. - } - - cubeb_stream_params in_params = { - STREAM_FORMAT, - STREAM_FREQUENCY, - layout_infos[in_layout].channels, - in_layout, - CUBEB_STREAM_PREF_NONE - }; - - cubeb_stream_params out_params = { - STREAM_FORMAT, - STREAM_FREQUENCY, - // To downmix audio data with undefined layout, its channel number must be - // smaller than or equal to the input channels. - (out_layout == CUBEB_LAYOUT_UNDEFINED) ? - layout_infos[in_layout].channels : layout_infos[out_layout].channels, - out_layout, - CUBEB_STREAM_PREF_NONE - }; - - if (!cubeb_should_downmix(&in_params, &out_params)) { - return; - } - - fprintf(stderr, "Downmix from %s to %s\n", layout_infos[in_layout].name, layout_infos[out_layout].name); - - unsigned int const inframes = 10; - vector<float> in(in_params.channels * inframes); -#if defined(__APPLE__) - // The mixed buffer size doesn't be changed based on the channel layout set on OSX. - // Please see the comment above downmix_3f2 in cubeb_mixer.cpp. - vector<float> out(in_params.channels * inframes); -#else - // In normal case, the mixed buffer size is based on the mixing channel layout. - vector<float> out(out_params.channels * inframes); -#endif - - for (unsigned int offset = 0 ; offset < inframes * in_params.channels ; offset += in_params.channels) { - for (unsigned int i = 0 ; i < in_params.channels ; ++i) { - in[offset + i] = data[i]; - } - } - - // Create a mixer for downmix only. - std::unique_ptr<cubeb_mixer, decltype(&cubeb_mixer_destroy)> - mixer(cubeb_mixer_create(in_params.format, CUBEB_MIXER_DIRECTION_DOWNMIX), cubeb_mixer_destroy); - - assert(!in.empty() && !out.empty() && out.size() <= in.size()); - cubeb_mixer_mix(mixer.get(), inframes, in.data(), in.size(), out.data(), out.size(), &in_params, &out_params); - - uint32_t in_layout_mask = 0; - for (unsigned int i = 0 ; i < in_params.channels; ++i) { - in_layout_mask |= 1 << CHANNEL_INDEX_TO_ORDER[in_layout][i]; - } - - uint32_t out_layout_mask = 0; - for (unsigned int i = 0 ; out_layout != CUBEB_LAYOUT_UNDEFINED && i < out_params.channels; ++i) { - out_layout_mask |= 1 << CHANNEL_INDEX_TO_ORDER[out_layout][i]; - } - - for (unsigned int i = 0 ; i < out.size() ; ++i) { - assert(in_params.channels && out_params.channels); // to pass the scan-build warning: Division by zero. -#if defined(__APPLE__) - // The size of audio mix buffer(vector out above) on OS X is same as input, - // so we need to check whether the out[i] will be dropped or not. - unsigned int index = i % in_params.channels; - if (index >= out_params.channels) { - // The out[i] will be dropped, so we don't care the data inside. - fprintf(stderr, "\tOS X: %d will be dropped. Ignore it.\n", i); - continue; - } -#else - unsigned int index = i % out_params.channels; -#endif - - // downmix_3f2 - if ((in_layout == CUBEB_LAYOUT_3F2 || in_layout == CUBEB_LAYOUT_3F2_LFE) && - out_layout >= CUBEB_LAYOUT_MONO && out_layout <= CUBEB_LAYOUT_2F2_LFE) { - auto & downmix_results = DOWNMIX_3F2_RESULTS[in_layout - CUBEB_LAYOUT_3F2][out_layout - CUBEB_LAYOUT_MONO]; - fprintf(stderr, "\t[3f2] %d(%s) - Expect: %lf, Get: %lf\n", i, channel_names[ CHANNEL_INDEX_TO_ORDER[out_layout][index] ], downmix_results[index], out[i]); - ASSERT_EQ(downmix_results[index], out[i]); - continue; - } - -#if defined(__APPLE__) - fprintf(stderr, "\tOS X: We only support downmix for audio 5.1 currently.\n"); - return; -#endif - - // mix_remap - if (out_layout_mask & in_layout_mask) { - uint32_t mask = 1 << CHANNEL_INDEX_TO_ORDER[out_layout][index]; - fprintf(stderr, "\t[remap] %d(%s) - Expect: %lf, Get: %lf\n", i, channel_names[ CHANNEL_INDEX_TO_ORDER[out_layout][index] ], (mask & in_layout_mask) ? audio_inputs[out_layout].data[index] : 0, out[i]); - ASSERT_EQ((mask & in_layout_mask) ? audio_inputs[out_layout].data[index] : 0, out[i]); - continue; - } - - // downmix_fallback - fprintf(stderr, "\t[fallback] %d - Expect: %lf, Get: %lf\n", i, audio_inputs[in_layout].data[index], out[i]); - ASSERT_EQ(audio_inputs[in_layout].data[index], out[i]); - } -} - -TEST(cubeb, mixer) -{ - for (auto audio_input : audio_inputs) { - for (auto audio_output : layout_infos) { - downmix_test(audio_input.data, audio_input.layout, audio_output.layout); - } - } -} diff --git a/third_party/rust/cubeb-sys/libcubeb/test/test_sanity.cpp b/third_party/rust/cubeb-sys/libcubeb/test/test_sanity.cpp index d3546d6f0cbbb6c73f99cf7584b65bbae4ce22cb..d33666f22f52a5e842554b5eb13a8c8d60655a34 100644 --- a/third_party/rust/cubeb-sys/libcubeb/test/test_sanity.cpp +++ b/third_party/rust/cubeb-sys/libcubeb/test/test_sanity.cpp @@ -114,7 +114,6 @@ TEST(cubeb, context_variables) int r; cubeb * ctx; uint32_t value; - cubeb_channel_layout layout; cubeb_stream_params params; r = common_init(&ctx, "test_context_variables"); @@ -139,11 +138,6 @@ TEST(cubeb, context_variables) ASSERT_TRUE(value > 0); } - r = cubeb_get_preferred_channel_layout(ctx, &layout); - ASSERT_TRUE(r == CUBEB_ERROR_NOT_SUPPORTED || - (r == CUBEB_OK && layout != CUBEB_LAYOUT_UNDEFINED) || - (r == CUBEB_ERROR && layout == CUBEB_LAYOUT_UNDEFINED)); - cubeb_destroy(ctx); } diff --git a/third_party/rust/cubeb-sys/src/channel.rs b/third_party/rust/cubeb-sys/src/channel.rs index ba7cda852fbeaae095ada617ad2d80d15385f661..d802c1f1e328477b97c640e2c462f35e72813761 100644 --- a/third_party/rust/cubeb-sys/src/channel.rs +++ b/third_party/rust/cubeb-sys/src/channel.rs @@ -3,78 +3,67 @@ // This program is made available under an ISC-style license. See the // accompanying file LICENSE for details. -use std::{fmt, mem}; -use std::os::raw::{c_int, c_uint}; +use std::os::raw::c_uint; cubeb_enum! { - pub enum cubeb_channel : c_int { - CHANNEL_INVALID = -1, - CHANNEL_MONO = 0, - CHANNEL_LEFT, - CHANNEL_RIGHT, - CHANNEL_CENTER, - CHANNEL_LS, - CHANNEL_RS, - CHANNEL_RLS, - CHANNEL_RCENTER, - CHANNEL_RRS, - CHANNEL_LFE, - CHANNEL_UNMAPPED, - CHANNEL_MAX = 256, + pub enum cubeb_channel : c_uint { + CHANNEL_UNKNOWN = 0, + CHANNEL_FRONT_LEFT = 1 << 0, + CHANNEL_FRONT_RIGHT = 1 << 1, + CHANNEL_FRONT_CENTER = 1 << 2, + CHANNEL_LOW_FREQUENCY = 1 << 3, + CHANNEL_BACK_LEFT = 1 << 4, + CHANNEL_BACK_RIGHT = 1 << 5, + CHANNEL_FRONT_LEFT_OF_CENTER = 1 << 6, + CHANNEL_FRONT_RIGHT_OF_CENTER = 1 << 7, + CHANNEL_BACK_CENTER = 1 << 8, + CHANNEL_SIDE_LEFT = 1 << 9, + CHANNEL_SIDE_RIGHT = 1 << 10, + CHANNEL_TOP_CENTER = 1 << 11, + CHANNEL_TOP_FRONT_LEFT = 1 << 12, + CHANNEL_TOP_FRONT_CENTER = 1 << 13, + CHANNEL_TOP_FRONT_RIGHT = 1 << 14, + CHANNEL_TOP_BACK_LEFT = 1 << 15, + CHANNEL_TOP_BACK_CENTER = 1 << 16, + CHANNEL_TOP_BACK_RIGHT = 1 << 17, } } cubeb_enum! { pub enum cubeb_channel_layout { - CUBEB_LAYOUT_UNDEFINED, - - CUBEB_LAYOUT_DUAL_MONO, - CUBEB_LAYOUT_DUAL_MONO_LFE, - CUBEB_LAYOUT_MONO, - CUBEB_LAYOUT_MONO_LFE, - CUBEB_LAYOUT_STEREO, - CUBEB_LAYOUT_STEREO_LFE, - CUBEB_LAYOUT_3F, - CUBEB_LAYOUT_3F_LFE, - CUBEB_LAYOUT_2F1, - CUBEB_LAYOUT_2F1_LFE, - CUBEB_LAYOUT_3F1, - CUBEB_LAYOUT_3F1_LFE, - CUBEB_LAYOUT_2F2, - CUBEB_LAYOUT_2F2_LFE, - CUBEB_LAYOUT_3F2, - CUBEB_LAYOUT_3F2_LFE, - CUBEB_LAYOUT_3F3R_LFE, - CUBEB_LAYOUT_3F4_LFE, - CUBEB_LAYOUT_MAX, - } -} - -#[repr(C)] -#[derive(Clone, Copy)] -pub struct cubeb_channel_map { - pub channels: c_uint, - pub map: [cubeb_channel; CHANNEL_MAX as usize], -} - -impl Default for cubeb_channel_map { - fn default() -> Self { - unsafe { mem::zeroed() } + CUBEB_LAYOUT_UNDEFINED = 0, + CUBEB_LAYOUT_MONO = CHANNEL_FRONT_CENTER, + CUBEB_LAYOUT_MONO_LFE = CUBEB_LAYOUT_MONO | CHANNEL_LOW_FREQUENCY, + CUBEB_LAYOUT_STEREO = CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT, + CUBEB_LAYOUT_STEREO_LFE = CUBEB_LAYOUT_STEREO | CHANNEL_LOW_FREQUENCY, + CUBEB_LAYOUT_3F = CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT | + CHANNEL_FRONT_CENTER, + CUBEB_LAYOUT_3F_LFE = CUBEB_LAYOUT_3F | CHANNEL_LOW_FREQUENCY, + CUBEB_LAYOUT_2F1 = CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT | + CHANNEL_BACK_CENTER, + CUBEB_LAYOUT_2F1_LFE = CUBEB_LAYOUT_2F1 | CHANNEL_LOW_FREQUENCY, + CUBEB_LAYOUT_3F1 = CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT | + CHANNEL_FRONT_CENTER | CHANNEL_BACK_CENTER, + CUBEB_LAYOUT_3F1_LFE = CUBEB_LAYOUT_3F1 | CHANNEL_LOW_FREQUENCY, + CUBEB_LAYOUT_2F2 = CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT | + CHANNEL_SIDE_LEFT | CHANNEL_SIDE_RIGHT, + CUBEB_LAYOUT_2F2_LFE = CUBEB_LAYOUT_2F2 | CHANNEL_LOW_FREQUENCY, + CUBEB_LAYOUT_QUAD = CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT | + CHANNEL_BACK_LEFT | CHANNEL_BACK_RIGHT, + CUBEB_LAYOUT_QUAD_LFE = CUBEB_LAYOUT_QUAD | CHANNEL_LOW_FREQUENCY, + CUBEB_LAYOUT_3F2 = CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT | + CHANNEL_FRONT_CENTER | CHANNEL_SIDE_LEFT | + CHANNEL_SIDE_RIGHT, + CUBEB_LAYOUT_3F2_LFE = CUBEB_LAYOUT_3F2 | CHANNEL_LOW_FREQUENCY, + CUBEB_LAYOUT_3F2_BACK = CUBEB_LAYOUT_QUAD | CHANNEL_FRONT_CENTER, + CUBEB_LAYOUT_3F2_LFE_BACK = CUBEB_LAYOUT_3F2_BACK | CHANNEL_LOW_FREQUENCY, + CUBEB_LAYOUT_3F3R_LFE = CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT | + CHANNEL_FRONT_CENTER | CHANNEL_LOW_FREQUENCY | + CHANNEL_BACK_CENTER | CHANNEL_SIDE_LEFT | + CHANNEL_SIDE_RIGHT, + CUBEB_LAYOUT_3F4_LFE = CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT | + CHANNEL_FRONT_CENTER | CHANNEL_LOW_FREQUENCY | + CHANNEL_BACK_LEFT | CHANNEL_BACK_RIGHT | + CHANNEL_SIDE_LEFT | CHANNEL_SIDE_RIGHT, } } - -// Explicit Debug impl to work around bug in ctest -impl fmt::Debug for cubeb_channel_map { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_struct("cubeb_channel_map") - .field("channels", &self.channels) - .field("map", &self.map.iter().take(self.channels as usize)) - .finish() - } -} - -extern "C" { - pub fn cubeb_channel_map_to_layout( - channel_map: *const cubeb_channel_map, - ) -> cubeb_channel_layout; -} diff --git a/third_party/rust/cubeb-sys/src/context.rs b/third_party/rust/cubeb-sys/src/context.rs index 4afe2a7a799d37f0fccf61884eca02dccb7bcf11..b7f6e1193e7f963aa85355e93a587958fdedf4db 100644 --- a/third_party/rust/cubeb-sys/src/context.rs +++ b/third_party/rust/cubeb-sys/src/context.rs @@ -4,7 +4,6 @@ // accompanying file LICENSE for details. use callbacks::{cubeb_data_callback, cubeb_state_callback}; -use channel::cubeb_channel_layout; use device::cubeb_devid; use std::os::raw::{c_char, c_int, c_uint, c_void}; use stream::{cubeb_stream, cubeb_stream_params}; @@ -25,10 +24,6 @@ extern "C" { latency_frames: *mut c_uint, ) -> c_int; pub fn cubeb_get_preferred_sample_rate(context: *mut cubeb, rate: *mut c_uint) -> c_int; - pub fn cubeb_get_preferred_channel_layout( - context: *mut cubeb, - layout: *mut cubeb_channel_layout, - ) -> c_int; pub fn cubeb_destroy(context: *mut cubeb); pub fn cubeb_stream_init( context: *mut cubeb, diff --git a/third_party/rust/cubeb-sys/src/mixer.rs b/third_party/rust/cubeb-sys/src/mixer.rs index 99a39804f62932ddeb8abd98172e578f2b50b23a..25597cdbd4103a6cd93976604bec4b5266ed40cb 100644 --- a/third_party/rust/cubeb-sys/src/mixer.rs +++ b/third_party/rust/cubeb-sys/src/mixer.rs @@ -3,47 +3,29 @@ // This program is made available under an ISC-style license. See the // accompanying file LICENSE for details. -use channel::{cubeb_channel, CHANNEL_MAX, CUBEB_LAYOUT_MAX}; +use channel::cubeb_channel_layout; use format::cubeb_sample_format; -use std::os::raw::{c_long, c_uchar, c_ulong, c_void}; -use stream::cubeb_stream_params; - -cubeb_enum! { - pub enum cubeb_mixer_direction { - CUBEB_MIXER_DIRECTION_DOWNMIX = 0x01, - CUBEB_MIXER_DIRECTION_UPMIX = 0x02, - } -} +use std::os::raw::{c_int, c_uint, c_void}; pub enum cubeb_mixer {} extern "C" { - pub fn cubeb_should_upmix( - stream: *const cubeb_stream_params, - mixer: *const cubeb_stream_params, - ) -> bool; - pub fn cubeb_should_downmix( - stream: *const cubeb_stream_params, - mixer: *const cubeb_stream_params, - ) -> bool; - pub fn cubeb_should_mix( - stream: *const cubeb_stream_params, - mixer: *const cubeb_stream_params, - ) -> bool; - - pub fn cubeb_mixer_create(format: cubeb_sample_format, direction: c_uchar) -> *mut cubeb_mixer; + pub fn cubeb_mixer_create( + format: cubeb_sample_format, + in_channels: u32, + in_layout: cubeb_channel_layout, + out_channels: u32, + out_layout: cubeb_channel_layout, + ) -> *mut cubeb_mixer; pub fn cubeb_mixer_destroy(mixer: *mut cubeb_mixer); pub fn cubeb_mixer_mix( mixer: *mut cubeb_mixer, - frames: c_long, + frames: usize, input_buffer: *mut c_void, - input_buffer_length: c_ulong, + input_buffer_length: usize, output_buffer: *mut c_void, - output_buffer_length: c_ulong, - stream_params: *const cubeb_stream_params, - mixer_params: *const cubeb_stream_params, - ); + output_buffer_length: usize, + ) -> c_int; - pub static CHANNEL_INDEX_TO_ORDER: - [[cubeb_channel; CHANNEL_MAX as usize]; CUBEB_LAYOUT_MAX as usize]; + pub fn cubeb_channel_layout_nb_channels(channel_layout: cubeb_channel_layout) -> c_uint; } diff --git a/third_party/rust/cubeb/.cargo-checksum.json b/third_party/rust/cubeb/.cargo-checksum.json index ef537054d2e35fda8496a8990cf6937d359e3eac..e770624abdf4350bf7f8ed6048d7397b8b1d7606 100644 --- a/third_party/rust/cubeb/.cargo-checksum.json +++ b/third_party/rust/cubeb/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"bbdd7a6000f97f9dda6fd9234dd39eead1ab035994fc0423529bba952a927e89","LICENSE":"8c044baa5d883274736eeece0b955249076c2697b826e576fce59496235b2cf5","README.md":"408c573ec240927cf5b9c036098e94e374ec41f71991415422586f450586b214","examples/common/mod.rs":"a5e1b79fc2b4addff1e442879ba3dbcb1cf5973e76b9a62d97dd0042597480db","examples/devices.rs":"89e13542853995d1ae4a49d6829156efb29dd25c6caffdf22496c28c8263ffeb","examples/tone.rs":"ca5f609374c891c2134e7b208a3b2c31e433e6fc9121c7f9b755c1a38121bd67","src/context.rs":"03511fa960a411728163e700edc2fd6cfbfcf09766ffe62ee82a2cbd08fdf243","src/frame.rs":"ed1e8f4576022d0c23106bb115125e5a2967b0375a10d0c54bbe99f04a70cc3f","src/lib.rs":"98e9280890551ac9305f2f808e315b6aa6bcd5781b8e96a078787ded0ef91e2a","src/log.rs":"af1d787754706e34d6b8f4ac88aa89078ae9a16970b168ad8dc17cc4180688c2","src/sample.rs":"e23be3b691052001916f920ce9c1a0051bd097e39c9d34cbcb80ab8120265f45","src/stream.rs":"b01bcdce3b89b5f93d485c52350129a8ca7a98d2255246eab9d0b0184dca7986","src/try_call.rs":"37701edc461178fc2025c282ca0e5691bcb4dabeec916204a6eb9f0f439c0af4","src/util.rs":"9b09a4247c2eace2da1e7a946d2319cc95563040a05862acb73d2688bed268a8"},"package":"ed237804b9799d1c29089e6cab3f4b7160186179981a61865feff13d55a902f8"} \ No newline at end of file +{"files":{"Cargo.toml":"a2c6655c60b3df90ea552b24c6316cbfdf7b2b915e960ce7c03abdcdb73c92ff","LICENSE":"8c044baa5d883274736eeece0b955249076c2697b826e576fce59496235b2cf5","README.md":"408c573ec240927cf5b9c036098e94e374ec41f71991415422586f450586b214","examples/common/mod.rs":"a5e1b79fc2b4addff1e442879ba3dbcb1cf5973e76b9a62d97dd0042597480db","examples/devices.rs":"89e13542853995d1ae4a49d6829156efb29dd25c6caffdf22496c28c8263ffeb","examples/tone.rs":"8f5f9851b6d99f6f16c597fcb9312e3ef81769cbfb89341d2ea2522ca2e2214e","src/context.rs":"03511fa960a411728163e700edc2fd6cfbfcf09766ffe62ee82a2cbd08fdf243","src/frame.rs":"ed1e8f4576022d0c23106bb115125e5a2967b0375a10d0c54bbe99f04a70cc3f","src/lib.rs":"98e9280890551ac9305f2f808e315b6aa6bcd5781b8e96a078787ded0ef91e2a","src/log.rs":"af1d787754706e34d6b8f4ac88aa89078ae9a16970b168ad8dc17cc4180688c2","src/sample.rs":"e23be3b691052001916f920ce9c1a0051bd097e39c9d34cbcb80ab8120265f45","src/stream.rs":"3e2c7ec590bed0eb740057a89a4dc254fe962f402e6ed316308152d96bd1288a"},"package":"7923bed2d5a1a64ba0c3e8b6badc360508ba488d1f2f59f16a688802e755bb85"} \ No newline at end of file diff --git a/third_party/rust/cubeb/Cargo.toml b/third_party/rust/cubeb/Cargo.toml index 2b574c7c75c8abf660f264e17d5ba74bfe96548b..9f5e1dcd775d8920054326e1af840b9cc873ff15 100644 --- a/third_party/rust/cubeb/Cargo.toml +++ b/third_party/rust/cubeb/Cargo.toml @@ -12,7 +12,7 @@ [package] name = "cubeb" -version = "0.4.1" +version = "0.5.0" authors = ["Dan Glastonbury <dglastonbury@mozilla.com>"] description = "Bindings to libcubeb for interacting with system audio from rust.\n" homepage = "https://github.com/djg/cubeb-rs" @@ -22,7 +22,7 @@ categories = ["api-bindings"] license = "ISC" repository = "https://github.com/djg/cubeb-rs" [dependencies.cubeb-core] -version = "0.4.1" +version = "0.5.0" [features] gecko-in-tree = ["cubeb-core/gecko-in-tree"] diff --git a/third_party/rust/cubeb/examples/tone.rs b/third_party/rust/cubeb/examples/tone.rs index 0fb6e3f402779df5aed5ea6902ae897103b070e7..97e940bc9490f37aa4175546cc104d4bc6abdfef 100644 --- a/third_party/rust/cubeb/examples/tone.rs +++ b/third_party/rust/cubeb/examples/tone.rs @@ -25,7 +25,7 @@ fn main() { .format(STREAM_FORMAT) .rate(SAMPLE_FREQUENCY) .channels(1) - .layout(cubeb::ChannelLayout::Mono) + .layout(cubeb::ChannelLayout::MONO) .take(); let mut position = 0u32; diff --git a/third_party/rust/cubeb/src/stream.rs b/third_party/rust/cubeb/src/stream.rs index e02a063abeeaebe6864f4d6aee6bb0e777160baa..a5329a5ba6317b510beb9ef269557ebb2baef990 100644 --- a/third_party/rust/cubeb/src/stream.rs +++ b/third_party/rust/cubeb/src/stream.rs @@ -20,7 +20,7 @@ //! .format(cubeb::SampleFormat::Float32LE) //! .rate(44_100) //! .channels(1) -//! .layout(cubeb::ChannelLayout::Mono) +//! .layout(cubeb::ChannelLayout::MONO) //! .prefs(cubeb::StreamPrefs::NONE) //! .take(); //! diff --git a/third_party/rust/cubeb/src/try_call.rs b/third_party/rust/cubeb/src/try_call.rs deleted file mode 100644 index 9d49c5b12dfde256dc4168b5712030905ad18973..0000000000000000000000000000000000000000 --- a/third_party/rust/cubeb/src/try_call.rs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright © 2017-2018 Mozilla Foundation -// -// This program is made available under an ISC-style license. See the -// accompanying file LICENSE for details. - -use Error; -use std::os::raw::c_int; - -pub fn cvt_r(ret: c_int) -> Result<(), Error> { - match ret { - n if n < 0 => Err(unsafe { Error::from_raw(n) }), - _ => Ok(()), - } -} - -macro_rules! try_call { - (raw::$p:ident ($($e:expr),*)) => ({ - match ::try_call::cvt_r(ffi::$p($($e),*)) { - Ok(o) => o, - Err(e) => { return Err(e) } - } - }) -} diff --git a/third_party/rust/cubeb/src/util.rs b/third_party/rust/cubeb/src/util.rs deleted file mode 100644 index 5aedf9aa330e8b7eb055fbba3a7f9ee1a4ddcca6..0000000000000000000000000000000000000000 --- a/third_party/rust/cubeb/src/util.rs +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright © 2017 Mozilla Foundation -// -// This program is made available under an ISC-style license. See the -// accompanying file LICENSE for details. - -use cubeb_core::Error; -use ffi; -use std::ffi::CString; - -/// A class of types that can be converted to C strings. -/// -/// These types are represented internally as byte slices and it is quite rare -/// for them to contain an interior 0 byte. -pub trait IntoCString { - /// Consume this container, converting it into a CString - fn into_c_string(self) -> Result<CString, Error>; -} - -impl<'a, T: IntoCString + Clone> IntoCString for &'a T { - fn into_c_string(self) -> Result<CString, Error> { self.clone().into_c_string() } -} - -impl<'a> IntoCString for &'a str { - fn into_c_string(self) -> Result<CString, Error> { - match CString::new(self) { - Ok(s) => Ok(s), - Err(_) => Err(unsafe { Error::from_raw(ffi::CUBEB_ERROR) }), - } - } -} - -impl IntoCString for String { - fn into_c_string(self) -> Result<CString, Error> { - match CString::new(self.into_bytes()) { - Ok(s) => Ok(s), - Err(_) => Err(unsafe { Error::from_raw(ffi::CUBEB_ERROR) }), - } - } -} - -impl IntoCString for CString { - fn into_c_string(self) -> Result<CString, Error> { Ok(self) } -} - -impl IntoCString for Vec<u8> { - fn into_c_string(self) -> Result<CString, Error> { Ok(try!(CString::new(self))) } -} diff --git a/toolkit/library/rust/shared/Cargo.toml b/toolkit/library/rust/shared/Cargo.toml index e02d948a0afe771b6776758e4cded9a45401fa29..55b150887507323efc7a7b2cc7bc909baa330dac 100644 --- a/toolkit/library/rust/shared/Cargo.toml +++ b/toolkit/library/rust/shared/Cargo.toml @@ -16,7 +16,7 @@ prefs_parser = { path = "../../../../modules/libpref/parser" } rust_url_capi = { path = "../../../../netwerk/base/rust-url-capi" } webrender_bindings = { path = "../../../../gfx/webrender_bindings", optional = true } cubeb-pulse = { path = "../../../../media/libcubeb/cubeb-pulse-rs", optional = true, features=["pulse-dlopen"] } -cubeb-sys = { version = "0.4.1", optional = true, features=["gecko-in-tree"] } +cubeb-sys = { version = "0.5.0", optional = true, features=["gecko-in-tree"] } encoding_c = "0.8.0" encoding_glue = { path = "../../../../intl/encoding_glue" } audioipc-client = { path = "../../../../media/audioipc/client", optional = true }