Add RecordedAudioTrack
This commit is contained in:
parent
e12c2e8877
commit
749caa14a5
|
|
@ -39,6 +39,12 @@ version = "1.0.95"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04"
|
checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "arrayvec"
|
||||||
|
version = "0.7.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "autocfg"
|
name = "autocfg"
|
||||||
version = "1.4.0"
|
version = "1.4.0"
|
||||||
|
|
@ -81,6 +87,12 @@ version = "3.16.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
|
checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bytemuck"
|
||||||
|
version = "1.21.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ef657dfab802224e671f5818e9a4935f9b1957ed18e58292690cc39e7a4092a3"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bytes"
|
name = "bytes"
|
||||||
version = "1.9.0"
|
version = "1.9.0"
|
||||||
|
|
@ -211,12 +223,27 @@ version = "1.13.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
|
checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "encoding_rs"
|
||||||
|
version = "0.8.35"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "equivalent"
|
name = "equivalent"
|
||||||
version = "1.0.1"
|
version = "1.0.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
|
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "extended"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "af9673d8203fcb076b19dfd17e38b3d4ae9f44959416ea532ce72415a6020365"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "glob"
|
name = "glob"
|
||||||
version = "0.3.2"
|
version = "0.3.2"
|
||||||
|
|
@ -229,6 +256,12 @@ version = "0.15.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289"
|
checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hound"
|
||||||
|
version = "3.5.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "62adaabb884c94955b19907d60019f4e145d091c75345379e70d1ee696f7854f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "indexmap"
|
name = "indexmap"
|
||||||
version = "2.7.1"
|
version = "2.7.1"
|
||||||
|
|
@ -289,6 +322,12 @@ dependencies = [
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lazy_static"
|
||||||
|
version = "1.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.169"
|
version = "0.2.169"
|
||||||
|
|
@ -312,9 +351,15 @@ dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"console_error_panic_hook",
|
"console_error_panic_hook",
|
||||||
"cpal",
|
"cpal",
|
||||||
|
"hound",
|
||||||
|
"js-sys",
|
||||||
"log",
|
"log",
|
||||||
|
"minimp3",
|
||||||
|
"rubato",
|
||||||
"serde",
|
"serde",
|
||||||
|
"symphonia",
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
|
"wasm-bindgen-futures",
|
||||||
"wasm-logger",
|
"wasm-logger",
|
||||||
"web-sys",
|
"web-sys",
|
||||||
]
|
]
|
||||||
|
|
@ -325,6 +370,15 @@ version = "0.4.25"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "04cbf5b083de1c7e0222a7a51dbfdba1cbe1c6ab0b15e29fff3f6c077fd9cd9f"
|
checksum = "04cbf5b083de1c7e0222a7a51dbfdba1cbe1c6ab0b15e29fff3f6c077fd9cd9f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mach"
|
||||||
|
version = "0.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b823e83b2affd8f40a9ee8c29dbc56404c1e34cd2710921f2801e2cf29527afa"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mach2"
|
name = "mach2"
|
||||||
version = "0.4.2"
|
version = "0.4.2"
|
||||||
|
|
@ -346,6 +400,26 @@ version = "0.2.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
|
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "minimp3"
|
||||||
|
version = "0.5.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "985438f75febf74c392071a975a29641b420dd84431135a6e6db721de4b74372"
|
||||||
|
dependencies = [
|
||||||
|
"minimp3-sys",
|
||||||
|
"slice-deque",
|
||||||
|
"thiserror",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "minimp3-sys"
|
||||||
|
version = "0.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e21c73734c69dc95696c9ed8926a2b393171d98b3f5f5935686a26a487ab9b90"
|
||||||
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ndk"
|
name = "ndk"
|
||||||
version = "0.8.0"
|
version = "0.8.0"
|
||||||
|
|
@ -385,6 +459,15 @@ dependencies = [
|
||||||
"minimal-lexical",
|
"minimal-lexical",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-complex"
|
||||||
|
version = "0.4.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495"
|
||||||
|
dependencies = [
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-derive"
|
name = "num-derive"
|
||||||
version = "0.4.2"
|
version = "0.4.2"
|
||||||
|
|
@ -396,6 +479,15 @@ dependencies = [
|
||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-integer"
|
||||||
|
version = "0.1.46"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f"
|
||||||
|
dependencies = [
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-traits"
|
name = "num-traits"
|
||||||
version = "0.2.19"
|
version = "0.2.19"
|
||||||
|
|
@ -461,6 +553,15 @@ version = "0.3.31"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2"
|
checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "primal-check"
|
||||||
|
version = "0.3.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dc0d895b311e3af9902528fbb8f928688abbd95872819320517cc24ca6b2bd08"
|
||||||
|
dependencies = [
|
||||||
|
"num-integer",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro-crate"
|
name = "proc-macro-crate"
|
||||||
version = "1.3.1"
|
version = "1.3.1"
|
||||||
|
|
@ -489,6 +590,15 @@ dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "realfft"
|
||||||
|
version = "3.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "390252372b7f2aac8360fc5e72eba10136b166d6faeed97e6d0c8324eb99b2b1"
|
||||||
|
dependencies = [
|
||||||
|
"rustfft",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "regex"
|
name = "regex"
|
||||||
version = "1.11.1"
|
version = "1.11.1"
|
||||||
|
|
@ -518,12 +628,39 @@ version = "0.8.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
|
checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rubato"
|
||||||
|
version = "0.14.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e6dd52e80cfc21894deadf554a5673002938ae4625f7a283e536f9cf7c17b0d5"
|
||||||
|
dependencies = [
|
||||||
|
"num-complex",
|
||||||
|
"num-integer",
|
||||||
|
"num-traits",
|
||||||
|
"realfft",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustc-hash"
|
name = "rustc-hash"
|
||||||
version = "1.1.0"
|
version = "1.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
|
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustfft"
|
||||||
|
version = "6.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "43806561bc506d0c5d160643ad742e3161049ac01027b5e6d7524091fd401d86"
|
||||||
|
dependencies = [
|
||||||
|
"num-complex",
|
||||||
|
"num-integer",
|
||||||
|
"num-traits",
|
||||||
|
"primal-check",
|
||||||
|
"strength_reduce",
|
||||||
|
"transpose",
|
||||||
|
"version_check",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustversion"
|
name = "rustversion"
|
||||||
version = "1.0.19"
|
version = "1.0.19"
|
||||||
|
|
@ -565,6 +702,218 @@ version = "1.3.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "slice-deque"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "31ef6ee280cdefba6d2d0b4b78a84a1c1a3f3a4cec98c2d4231c8bc225de0f25"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"mach",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "strength_reduce"
|
||||||
|
version = "0.2.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fe895eb47f22e2ddd4dabc02bce419d2e643c8e3b585c78158b349195bc24d82"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "symphonia"
|
||||||
|
version = "0.5.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "815c942ae7ee74737bb00f965fa5b5a2ac2ce7b6c01c0cc169bbeaf7abd5f5a9"
|
||||||
|
dependencies = [
|
||||||
|
"lazy_static",
|
||||||
|
"symphonia-bundle-flac",
|
||||||
|
"symphonia-bundle-mp3",
|
||||||
|
"symphonia-codec-aac",
|
||||||
|
"symphonia-codec-adpcm",
|
||||||
|
"symphonia-codec-alac",
|
||||||
|
"symphonia-codec-pcm",
|
||||||
|
"symphonia-codec-vorbis",
|
||||||
|
"symphonia-core",
|
||||||
|
"symphonia-format-caf",
|
||||||
|
"symphonia-format-isomp4",
|
||||||
|
"symphonia-format-mkv",
|
||||||
|
"symphonia-format-ogg",
|
||||||
|
"symphonia-format-riff",
|
||||||
|
"symphonia-metadata",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "symphonia-bundle-flac"
|
||||||
|
version = "0.5.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "72e34f34298a7308d4397a6c7fbf5b84c5d491231ce3dd379707ba673ab3bd97"
|
||||||
|
dependencies = [
|
||||||
|
"log",
|
||||||
|
"symphonia-core",
|
||||||
|
"symphonia-metadata",
|
||||||
|
"symphonia-utils-xiph",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "symphonia-bundle-mp3"
|
||||||
|
version = "0.5.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c01c2aae70f0f1fb096b6f0ff112a930b1fb3626178fba3ae68b09dce71706d4"
|
||||||
|
dependencies = [
|
||||||
|
"lazy_static",
|
||||||
|
"log",
|
||||||
|
"symphonia-core",
|
||||||
|
"symphonia-metadata",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "symphonia-codec-aac"
|
||||||
|
version = "0.5.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cdbf25b545ad0d3ee3e891ea643ad115aff4ca92f6aec472086b957a58522f70"
|
||||||
|
dependencies = [
|
||||||
|
"lazy_static",
|
||||||
|
"log",
|
||||||
|
"symphonia-core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "symphonia-codec-adpcm"
|
||||||
|
version = "0.5.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c94e1feac3327cd616e973d5be69ad36b3945f16b06f19c6773fc3ac0b426a0f"
|
||||||
|
dependencies = [
|
||||||
|
"log",
|
||||||
|
"symphonia-core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "symphonia-codec-alac"
|
||||||
|
version = "0.5.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2d8a6666649a08412906476a8b0efd9b9733e241180189e9f92b09c08d0e38f3"
|
||||||
|
dependencies = [
|
||||||
|
"log",
|
||||||
|
"symphonia-core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "symphonia-codec-pcm"
|
||||||
|
version = "0.5.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f395a67057c2ebc5e84d7bb1be71cce1a7ba99f64e0f0f0e303a03f79116f89b"
|
||||||
|
dependencies = [
|
||||||
|
"log",
|
||||||
|
"symphonia-core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "symphonia-codec-vorbis"
|
||||||
|
version = "0.5.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5a98765fb46a0a6732b007f7e2870c2129b6f78d87db7987e6533c8f164a9f30"
|
||||||
|
dependencies = [
|
||||||
|
"log",
|
||||||
|
"symphonia-core",
|
||||||
|
"symphonia-utils-xiph",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "symphonia-core"
|
||||||
|
version = "0.5.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "798306779e3dc7d5231bd5691f5a813496dc79d3f56bf82e25789f2094e022c3"
|
||||||
|
dependencies = [
|
||||||
|
"arrayvec",
|
||||||
|
"bitflags 1.3.2",
|
||||||
|
"bytemuck",
|
||||||
|
"lazy_static",
|
||||||
|
"log",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "symphonia-format-caf"
|
||||||
|
version = "0.5.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e43c99c696a388295a29fe71b133079f5d8b18041cf734c5459c35ad9097af50"
|
||||||
|
dependencies = [
|
||||||
|
"log",
|
||||||
|
"symphonia-core",
|
||||||
|
"symphonia-metadata",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "symphonia-format-isomp4"
|
||||||
|
version = "0.5.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "abfdf178d697e50ce1e5d9b982ba1b94c47218e03ec35022d9f0e071a16dc844"
|
||||||
|
dependencies = [
|
||||||
|
"encoding_rs",
|
||||||
|
"log",
|
||||||
|
"symphonia-core",
|
||||||
|
"symphonia-metadata",
|
||||||
|
"symphonia-utils-xiph",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "symphonia-format-mkv"
|
||||||
|
version = "0.5.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1bb43471a100f7882dc9937395bd5ebee8329298e766250b15b3875652fe3d6f"
|
||||||
|
dependencies = [
|
||||||
|
"lazy_static",
|
||||||
|
"log",
|
||||||
|
"symphonia-core",
|
||||||
|
"symphonia-metadata",
|
||||||
|
"symphonia-utils-xiph",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "symphonia-format-ogg"
|
||||||
|
version = "0.5.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ada3505789516bcf00fc1157c67729eded428b455c27ca370e41f4d785bfa931"
|
||||||
|
dependencies = [
|
||||||
|
"log",
|
||||||
|
"symphonia-core",
|
||||||
|
"symphonia-metadata",
|
||||||
|
"symphonia-utils-xiph",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "symphonia-format-riff"
|
||||||
|
version = "0.5.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "05f7be232f962f937f4b7115cbe62c330929345434c834359425e043bfd15f50"
|
||||||
|
dependencies = [
|
||||||
|
"extended",
|
||||||
|
"log",
|
||||||
|
"symphonia-core",
|
||||||
|
"symphonia-metadata",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "symphonia-metadata"
|
||||||
|
version = "0.5.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bc622b9841a10089c5b18e99eb904f4341615d5aa55bbf4eedde1be721a4023c"
|
||||||
|
dependencies = [
|
||||||
|
"encoding_rs",
|
||||||
|
"lazy_static",
|
||||||
|
"log",
|
||||||
|
"symphonia-core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "symphonia-utils-xiph"
|
||||||
|
version = "0.5.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "484472580fa49991afda5f6550ece662237b00c6f562c7d9638d1b086ed010fe"
|
||||||
|
dependencies = [
|
||||||
|
"symphonia-core",
|
||||||
|
"symphonia-metadata",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "2.0.96"
|
version = "2.0.96"
|
||||||
|
|
@ -613,12 +962,28 @@ dependencies = [
|
||||||
"winnow",
|
"winnow",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "transpose"
|
||||||
|
version = "0.2.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1ad61aed86bc3faea4300c7aee358b4c6d0c8d6ccc36524c96e4c92ccf26e77e"
|
||||||
|
dependencies = [
|
||||||
|
"num-integer",
|
||||||
|
"strength_reduce",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-ident"
|
name = "unicode-ident"
|
||||||
version = "1.0.15"
|
version = "1.0.15"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "11cd88e12b17c6494200a9c1b683a04fcac9573ed74cd1b62aeb2727c5592243"
|
checksum = "11cd88e12b17c6494200a9c1b683a04fcac9573ed74cd1b62aeb2727c5592243"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "version_check"
|
||||||
|
version = "0.9.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "walkdir"
|
name = "walkdir"
|
||||||
version = "2.5.0"
|
version = "2.5.0"
|
||||||
|
|
@ -721,6 +1086,22 @@ dependencies = [
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi"
|
||||||
|
version = "0.3.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||||
|
dependencies = [
|
||||||
|
"winapi-i686-pc-windows-gnu",
|
||||||
|
"winapi-x86_64-pc-windows-gnu",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-i686-pc-windows-gnu"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winapi-util"
|
name = "winapi-util"
|
||||||
version = "0.1.9"
|
version = "0.1.9"
|
||||||
|
|
@ -730,6 +1111,12 @@ dependencies = [
|
||||||
"windows-sys 0.59.0",
|
"windows-sys 0.59.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-x86_64-pc-windows-gnu"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows"
|
name = "windows"
|
||||||
version = "0.54.0"
|
version = "0.54.0"
|
||||||
|
|
|
||||||
|
|
@ -13,10 +13,20 @@ cpal = { version = "0.15", features = ["wasm-bindgen"] }
|
||||||
anyhow = "1.0"
|
anyhow = "1.0"
|
||||||
wasm-logger = "0.2"
|
wasm-logger = "0.2"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
|
rubato = "0.14.0"
|
||||||
|
symphonia = { version = "0.5", features = ["all"] }
|
||||||
|
|
||||||
[dependencies.web-sys]
|
[dependencies.web-sys]
|
||||||
version = "0.3.22"
|
version = "0.3.22"
|
||||||
features = ["console"]
|
features = ["console", "AudioContext"]
|
||||||
|
|
||||||
|
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
|
||||||
|
minimp3 = "0.5.1" # Only include minimp3 for native platforms
|
||||||
|
hound = "3.5.1" # Only include hound for native platforms
|
||||||
|
|
||||||
|
[target.'cfg(target_arch = "wasm32")'.dependencies]
|
||||||
|
wasm-bindgen-futures = "0.4"
|
||||||
|
js-sys = "0.3"
|
||||||
|
|
||||||
# The `console_error_panic_hook` crate provides better debugging of panics by
|
# The `console_error_panic_hook` crate provides better debugging of panics by
|
||||||
# logging them with `console.error`. This is great for development, but requires
|
# logging them with `console.error`. This is great for development, but requires
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,6 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
cd core
|
echo "Building native..."
|
||||||
|
cargo build
|
||||||
|
echo
|
||||||
|
echo "Building wasm..."
|
||||||
wasm-pack build --target web --out-dir ../src/pkg --features wasm
|
wasm-pack build --target web --out-dir ../src/pkg --features wasm
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,29 @@ use time::{Timestamp, Duration, Frame, SampleCount};
|
||||||
mod audio;
|
mod audio;
|
||||||
use audio::{CpalAudioOutput};
|
use audio::{CpalAudioOutput};
|
||||||
use log::{Level, LevelFilter, Log, Metadata, Record, SetLoggerError};
|
use log::{Level, LevelFilter, Log, Metadata, Record, SetLoggerError};
|
||||||
|
use rubato::{FftFixedIn, Resampler};
|
||||||
|
use std::io::Cursor;
|
||||||
|
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
|
use std::error::Error;
|
||||||
|
|
||||||
|
use symphonia::core::{
|
||||||
|
audio::AudioBufferRef,
|
||||||
|
audio::Signal,
|
||||||
|
codecs::{DecoderOptions},
|
||||||
|
formats::{FormatOptions},
|
||||||
|
io::MediaSourceStream,
|
||||||
|
meta::MetadataOptions,
|
||||||
|
probe::Hint,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
|
use std::io;
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
|
use std::io::Write;
|
||||||
|
|
||||||
|
|
||||||
|
#[cfg(target_arch = "wasm32")]
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
#[cfg(feature = "wasm")]
|
#[cfg(feature = "wasm")]
|
||||||
|
|
@ -34,6 +55,10 @@ pub trait Track: Send {
|
||||||
fn render_video(&self, _timestamp: Timestamp, _playing: bool) -> Option<Frame> {
|
fn render_video(&self, _timestamp: Timestamp, _playing: bool) -> Option<Frame> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set the sample rate of any audio this track might contain
|
||||||
|
fn set_sample_rate(&mut self, _sample_rate: u32) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct TrackManager {
|
pub struct TrackManager {
|
||||||
|
|
@ -154,6 +179,260 @@ impl Track for SineWaveTrack {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
struct AudioBuffer {
|
||||||
|
original_data: Vec<f32>,
|
||||||
|
original_sample_rate: u32,
|
||||||
|
resampled_data: Vec<f32>,
|
||||||
|
start_time: Timestamp,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AudioBuffer {
|
||||||
|
fn duration(&self) -> Duration {
|
||||||
|
if self.resampled_data.is_empty() {
|
||||||
|
Duration::from_seconds(0.0)
|
||||||
|
} else {
|
||||||
|
Duration::from_seconds(
|
||||||
|
self.resampled_data.len() as f64 /
|
||||||
|
self.original_sample_rate as f64
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pub struct RecordedAudioTrack {
|
||||||
|
name: String,
|
||||||
|
buffers: Vec<AudioBuffer>,
|
||||||
|
target_sample_rate: Option<u32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
impl RecordedAudioTrack {
|
||||||
|
pub fn new(name: &str) -> Self {
|
||||||
|
Self {
|
||||||
|
name: name.to_string(),
|
||||||
|
buffers: Vec::new(),
|
||||||
|
target_sample_rate: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add_buffer(&mut self, start_time: Timestamp, sample_rate: u32, data: Vec<f32>) {
|
||||||
|
let resampled_data = match self.target_sample_rate {
|
||||||
|
Some(target_rate) if sample_rate != target_rate =>
|
||||||
|
self::resample(&data, sample_rate, target_rate),
|
||||||
|
Some(_target_rate) =>
|
||||||
|
data.clone(), // Already at target rate
|
||||||
|
None =>
|
||||||
|
Vec::new(), // Will be resampled later
|
||||||
|
};
|
||||||
|
|
||||||
|
self.buffers.push(AudioBuffer {
|
||||||
|
original_data: data,
|
||||||
|
original_sample_rate: sample_rate,
|
||||||
|
resampled_data,
|
||||||
|
start_time,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Keep buffers sorted by start time
|
||||||
|
self.buffers.sort_by(|a, b| a.start_time.partial_cmp(&b.start_time).unwrap());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Track for RecordedAudioTrack {
|
||||||
|
fn get_name(&self) -> &str {
|
||||||
|
&self.name
|
||||||
|
}
|
||||||
|
fn set_sample_rate(&mut self, target_rate: u32) {
|
||||||
|
self.target_sample_rate = Some(target_rate);
|
||||||
|
|
||||||
|
for buffer in &mut self.buffers {
|
||||||
|
if buffer.original_sample_rate == target_rate {
|
||||||
|
buffer.resampled_data = buffer.original_data.clone();
|
||||||
|
} else {
|
||||||
|
buffer.resampled_data = self::resample(
|
||||||
|
&buffer.original_data,
|
||||||
|
buffer.original_sample_rate,
|
||||||
|
target_rate
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render_audio(
|
||||||
|
&mut self,
|
||||||
|
timestamp: Timestamp,
|
||||||
|
duration: SampleCount,
|
||||||
|
sample_rate: u32,
|
||||||
|
playing: bool,
|
||||||
|
) -> Option<Vec<f32>> {
|
||||||
|
if !playing || self.target_sample_rate != Some(sample_rate) {
|
||||||
|
return Some(vec![0.0; duration.as_usize()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// let chunk_samples = duration.as_usize();
|
||||||
|
let mut output = vec![0.0; duration.as_usize()];
|
||||||
|
let mut remaining_samples = duration;
|
||||||
|
let mut current_time = timestamp;
|
||||||
|
|
||||||
|
// Find the first buffer that overlaps with the requested time
|
||||||
|
let mut buffer_index = match self.buffers.binary_search_by(|b| {
|
||||||
|
b.start_time.partial_cmp(¤t_time).unwrap()
|
||||||
|
}) {
|
||||||
|
Ok(i) => i,
|
||||||
|
Err(i) if i > 0 => i - 1, // Check previous buffer if timestamp is between buffers
|
||||||
|
_ => 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
while remaining_samples.as_usize() > 0 && buffer_index < self.buffers.len() {
|
||||||
|
let buffer = &self.buffers[buffer_index];
|
||||||
|
|
||||||
|
// Calculate overlap with current buffer
|
||||||
|
let buffer_start = buffer.start_time;
|
||||||
|
let buffer_end = buffer_start + buffer.duration();
|
||||||
|
|
||||||
|
if current_time >= buffer_end {
|
||||||
|
// Move to next buffer
|
||||||
|
buffer_index += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate how many samples we can take from this buffer
|
||||||
|
let buffer_offset = ((current_time - buffer_start).as_seconds() * sample_rate as f64) as usize;
|
||||||
|
let available_samples = SampleCount::new(buffer.resampled_data.len().saturating_sub(buffer_offset));
|
||||||
|
let samples_to_take = remaining_samples.min(available_samples);
|
||||||
|
|
||||||
|
if samples_to_take == 0 {
|
||||||
|
// No more samples in this buffer
|
||||||
|
buffer_index += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy samples from buffer to output
|
||||||
|
let output_offset = duration - remaining_samples;
|
||||||
|
output[output_offset.as_usize()..(output_offset + samples_to_take).as_usize()]
|
||||||
|
.copy_from_slice(&buffer.resampled_data[buffer_offset..buffer_offset + samples_to_take.as_usize()]);
|
||||||
|
|
||||||
|
// Update state
|
||||||
|
remaining_samples -= samples_to_take;
|
||||||
|
current_time += samples_to_take.to_duration(sample_rate);
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(output)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn resample(input: &[f32], input_rate: u32, output_rate: u32) -> Vec<f32> {
|
||||||
|
if input_rate == output_rate {
|
||||||
|
return input.to_vec();
|
||||||
|
}
|
||||||
|
|
||||||
|
let input_rate = input_rate.try_into().unwrap();
|
||||||
|
let output_rate = output_rate.try_into().unwrap();
|
||||||
|
let chunk_size = input.len();
|
||||||
|
|
||||||
|
let mut resampler = FftFixedIn::new(
|
||||||
|
output_rate,
|
||||||
|
input_rate,
|
||||||
|
chunk_size,
|
||||||
|
1, // channel count
|
||||||
|
2, // fft size
|
||||||
|
).unwrap();
|
||||||
|
|
||||||
|
let output = resampler.process(&[input], None).unwrap();
|
||||||
|
output[0].clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait AudioLoader {
|
||||||
|
fn load_audio(
|
||||||
|
&self,
|
||||||
|
track: &mut RecordedAudioTrack,
|
||||||
|
start_time: Timestamp,
|
||||||
|
audio_data: &[u8],
|
||||||
|
) -> Result<(), Box<dyn Error>>;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct GenericAudioLoader;
|
||||||
|
|
||||||
|
impl AudioLoader for GenericAudioLoader {
|
||||||
|
fn load_audio(
|
||||||
|
&self,
|
||||||
|
track: &mut RecordedAudioTrack,
|
||||||
|
start_time: Timestamp,
|
||||||
|
audio_data: &[u8],
|
||||||
|
) -> Result<(), Box<dyn Error>> {
|
||||||
|
decode_audio(track, start_time, audio_data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn decode_audio(
|
||||||
|
track: &mut RecordedAudioTrack,
|
||||||
|
start_time: Timestamp,
|
||||||
|
audio_data: &[u8],
|
||||||
|
) -> Result<(), Box<dyn Error>> {
|
||||||
|
// Create a media source from the byte slice
|
||||||
|
let mss = MediaSourceStream::new(
|
||||||
|
Box::new(Cursor::new(audio_data.to_vec())),
|
||||||
|
Default::default(),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Use a fresh hint (no extension specified) for format detection
|
||||||
|
let hint = Hint::new();
|
||||||
|
|
||||||
|
// Probe the media source for a supported format
|
||||||
|
let probed = symphonia::default::get_probe()
|
||||||
|
.format(&hint, mss, &FormatOptions::default(), &MetadataOptions::default())?;
|
||||||
|
|
||||||
|
// Get the format reader
|
||||||
|
let mut format = probed.format;
|
||||||
|
|
||||||
|
// Find the first supported audio track
|
||||||
|
let default_track = format
|
||||||
|
.tracks()
|
||||||
|
.iter()
|
||||||
|
.find(|t| t.codec_params.codec != symphonia::core::codecs::CODEC_TYPE_NULL)
|
||||||
|
.ok_or("No supported audio track found")?;
|
||||||
|
|
||||||
|
// Create a decoder for the track
|
||||||
|
let mut decoder = symphonia::default::get_codecs()
|
||||||
|
.make(&default_track.codec_params, &DecoderOptions::default())?;
|
||||||
|
|
||||||
|
// Get the sample rate from the track
|
||||||
|
let sample_rate = default_track.codec_params.sample_rate.ok_or("Unknown sample rate")?;
|
||||||
|
let mut decoded_samples = Vec::new();
|
||||||
|
|
||||||
|
// Decode loop
|
||||||
|
loop {
|
||||||
|
let packet = match format.next_packet() {
|
||||||
|
Ok(packet) => packet,
|
||||||
|
Err(_) => break, // End of stream
|
||||||
|
};
|
||||||
|
|
||||||
|
match decoder.decode(&packet)? {
|
||||||
|
AudioBufferRef::F32(buf) => {
|
||||||
|
for i in 0..buf.frames() {
|
||||||
|
for c in 0..buf.spec().channels.count() {
|
||||||
|
decoded_samples.push(buf.chan(c)[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
AudioBufferRef::S16(buf) => {
|
||||||
|
for i in 0..buf.frames() {
|
||||||
|
for c in 0..buf.spec().channels.count() {
|
||||||
|
decoded_samples.push(buf.chan(c)[i] as f32 / 32768.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => return Err("Unsupported audio format".into()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the decoded audio to the track
|
||||||
|
track.add_buffer(start_time, sample_rate, decoded_samples);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(feature="wasm")]
|
#[cfg(feature="wasm")]
|
||||||
#[wasm_bindgen]
|
#[wasm_bindgen]
|
||||||
pub struct JsTrack {
|
pub struct JsTrack {
|
||||||
|
|
@ -261,17 +540,42 @@ impl Log for PlainTextLogger {
|
||||||
|
|
||||||
fn log(&self, record: &Record) {
|
fn log(&self, record: &Record) {
|
||||||
if self.enabled(record.metadata()) {
|
if self.enabled(record.metadata()) {
|
||||||
console::log_1(&format!(
|
#[cfg(target_arch = "wasm32")]
|
||||||
|
{
|
||||||
|
// WASM: Log to the JS console
|
||||||
|
console::log_1(
|
||||||
|
&format!(
|
||||||
"{} [{}:{}] {}",
|
"{} [{}:{}] {}",
|
||||||
record.level(),
|
record.level(),
|
||||||
record.file().unwrap_or("unknown"),
|
record.file().unwrap_or("unknown"),
|
||||||
record.line().unwrap_or(0),
|
record.line().unwrap_or(0),
|
||||||
record.args()
|
record.args()
|
||||||
).into());
|
)
|
||||||
|
.into(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
|
{
|
||||||
|
// Native: Log to stderr
|
||||||
|
let _ = writeln!(
|
||||||
|
io::stderr(),
|
||||||
|
"{} [{}:{}] {}",
|
||||||
|
record.level(),
|
||||||
|
record.file().unwrap_or("unknown"),
|
||||||
|
record.line().unwrap_or(0),
|
||||||
|
record.args()
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn flush(&self) {}
|
fn flush(&self) {
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
|
{
|
||||||
|
let _ = io::stderr().flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn init_plain_text_logger() -> Result<(), SetLoggerError> {
|
pub fn init_plain_text_logger() -> Result<(), SetLoggerError> {
|
||||||
|
|
|
||||||
|
|
@ -54,6 +54,14 @@ impl Timestamp {
|
||||||
pub fn set(&mut self, other: Timestamp) {
|
pub fn set(&mut self, other: Timestamp) {
|
||||||
self.0 = other.as_seconds();
|
self.0 = other.as_seconds();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn max(&self, other: Timestamp) -> Timestamp {
|
||||||
|
Timestamp(self.0.max(other.0))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn min(&self, other: Timestamp) -> Timestamp {
|
||||||
|
Timestamp(self.0.min(other.0))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Duration {
|
impl Duration {
|
||||||
|
|
@ -62,6 +70,11 @@ impl Duration {
|
||||||
Duration(seconds)
|
Duration(seconds)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Create a new duration from seconds. (dummy method)
|
||||||
|
pub fn from_seconds(seconds: f64) -> Self {
|
||||||
|
Duration(seconds)
|
||||||
|
}
|
||||||
|
|
||||||
/// Create a new duration from milliseconds.
|
/// Create a new duration from milliseconds.
|
||||||
pub fn from_millis(milliseconds: u64) -> Self {
|
pub fn from_millis(milliseconds: u64) -> Self {
|
||||||
Duration(milliseconds as f64 / 1000.0)
|
Duration(milliseconds as f64 / 1000.0)
|
||||||
|
|
@ -117,6 +130,24 @@ impl SampleCount {
|
||||||
pub fn as_usize(&self) -> usize {
|
pub fn as_usize(&self) -> usize {
|
||||||
self.0
|
self.0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn to_duration(&self, sample_rate: u32) -> Duration {
|
||||||
|
Duration((self.0 as f64) / (sample_rate as f64))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn max(&self, other: SampleCount) -> SampleCount {
|
||||||
|
SampleCount(self.0.max(other.0))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn min(&self, other: SampleCount) -> SampleCount {
|
||||||
|
SampleCount(self.0.min(other.0))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialEq<usize> for SampleCount{
|
||||||
|
fn eq(&self, other: &usize) -> bool {
|
||||||
|
self.0 == *other
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Overloading operators for more natural usage
|
// Overloading operators for more natural usage
|
||||||
|
|
@ -138,6 +169,14 @@ impl Sub<Duration> for Timestamp {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Sub<Timestamp> for Timestamp {
|
||||||
|
type Output = Duration;
|
||||||
|
|
||||||
|
fn sub(self, other: Timestamp) -> Duration {
|
||||||
|
self.subtract_timestamp(other)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl AddAssign<Duration> for Timestamp {
|
impl AddAssign<Duration> for Timestamp {
|
||||||
fn add_assign(&mut self, duration: Duration) {
|
fn add_assign(&mut self, duration: Duration) {
|
||||||
self.0 += duration.0;
|
self.0 += duration.0;
|
||||||
|
|
@ -150,6 +189,33 @@ impl SubAssign<Duration> for Timestamp {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
impl Add for SampleCount {
|
||||||
|
type Output = SampleCount;
|
||||||
|
fn add(self, other: SampleCount) -> SampleCount {
|
||||||
|
SampleCount(self.0 + other.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Sub for SampleCount {
|
||||||
|
type Output = SampleCount;
|
||||||
|
fn sub(self, other: SampleCount) -> SampleCount {
|
||||||
|
SampleCount(self.0 - other.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AddAssign<SampleCount> for SampleCount {
|
||||||
|
fn add_assign(&mut self, other: SampleCount) {
|
||||||
|
self.0 += other.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SubAssign<SampleCount> for SampleCount {
|
||||||
|
fn sub_assign(&mut self, other: SampleCount) {
|
||||||
|
self.0 -= other.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Represents a video frame.
|
/// Represents a video frame.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Frame {
|
pub struct Frame {
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@ export interface InitOutput {
|
||||||
readonly __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
|
readonly __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
|
||||||
readonly __wbindgen_add_to_stack_pointer: (a: number) => number;
|
readonly __wbindgen_add_to_stack_pointer: (a: number) => number;
|
||||||
readonly __wbindgen_free: (a: number, b: number, c: number) => void;
|
readonly __wbindgen_free: (a: number, b: number, c: number) => void;
|
||||||
readonly _dyn_core__ops__function__FnMut_____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h03a328ab39659ec3: (a: number, b: number) => void;
|
readonly _dyn_core__ops__function__FnMut_____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__hfe92e343adbc229b: (a: number, b: number) => void;
|
||||||
readonly __wbindgen_start: () => void;
|
readonly __wbindgen_start: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -250,7 +250,7 @@ export function main_js() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function __wbg_adapter_18(arg0, arg1) {
|
function __wbg_adapter_18(arg0, arg1) {
|
||||||
wasm._dyn_core__ops__function__FnMut_____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h03a328ab39659ec3(arg0, arg1);
|
wasm._dyn_core__ops__function__FnMut_____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__hfe92e343adbc229b(arg0, arg1);
|
||||||
}
|
}
|
||||||
|
|
||||||
const CoreInterfaceFinalization = (typeof FinalizationRegistry === 'undefined')
|
const CoreInterfaceFinalization = (typeof FinalizationRegistry === 'undefined')
|
||||||
|
|
@ -562,8 +562,8 @@ function __wbg_get_imports() {
|
||||||
const ret = false;
|
const ret = false;
|
||||||
return ret;
|
return ret;
|
||||||
};
|
};
|
||||||
imports.wbg.__wbindgen_closure_wrapper87 = function(arg0, arg1, arg2) {
|
imports.wbg.__wbindgen_closure_wrapper151 = function(arg0, arg1, arg2) {
|
||||||
const ret = makeMutClosure(arg0, arg1, 31, __wbg_adapter_18);
|
const ret = makeMutClosure(arg0, arg1, 73, __wbg_adapter_18);
|
||||||
return addHeapObject(ret);
|
return addHeapObject(ret);
|
||||||
};
|
};
|
||||||
imports.wbg.__wbindgen_debug_string = function(arg0, arg1) {
|
imports.wbg.__wbindgen_debug_string = function(arg0, arg1) {
|
||||||
|
|
|
||||||
Binary file not shown.
|
|
@ -20,5 +20,5 @@ export const __wbindgen_malloc: (a: number, b: number) => number;
|
||||||
export const __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
|
export const __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
|
||||||
export const __wbindgen_add_to_stack_pointer: (a: number) => number;
|
export const __wbindgen_add_to_stack_pointer: (a: number) => number;
|
||||||
export const __wbindgen_free: (a: number, b: number, c: number) => void;
|
export const __wbindgen_free: (a: number, b: number, c: number) => void;
|
||||||
export const _dyn_core__ops__function__FnMut_____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h03a328ab39659ec3: (a: number, b: number) => void;
|
export const _dyn_core__ops__function__FnMut_____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__hfe92e343adbc229b: (a: number, b: number) => void;
|
||||||
export const __wbindgen_start: () => void;
|
export const __wbindgen_start: () => void;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue