Skip to content

Commit

Permalink
Voice Rework -- Events, Track Queues (#806)
Browse files Browse the repository at this point in the history
This implements a proof-of-concept for an improved audio frontend. The largest change is the introduction of events and event handling: both by time elapsed and by track events, such as ending or looping. Following on from this, the library now includes a basic, event-driven track queue system (which people seem to ask for unusually often). A new sample, `examples/13_voice_events`, demonstrates both the `TrackQueue` system and some basic events via the `~queue` and `~play_fade` commands.

Locks are removed from around the control of `Audio` objects, which should allow the backend to be moved to a more granular futures-based backend solution in a cleaner way.
  • Loading branch information
FelixMcFelix authored and arqunis committed Oct 31, 2020
0 parents commit 7e4392a
Show file tree
Hide file tree
Showing 76 changed files with 8,756 additions and 0 deletions.
155 changes: 155 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
[package]
authors = ["Kyle Simpson <[email protected]>"]
description = "An async Rust library for the Discord voice API."
documentation = "https://docs.rs/songbird"
edition = "2018"
homepage = "https://github.com/serenity-rs/serenity"
include = ["src/**/*.rs", "Cargo.toml"]
keywords = ["discord", "api", "rtp", "audio"]
license = "ISC"
name = "songbird"
readme = "README.md"
repository = "https://github.com/serenity-rs/serenity.git"
version = "0.1.0"

[dependencies]
serde = { version = "1", features = ["derive"] }
serde_json = "1"
tracing = "0.1"
tracing-futures = "0.2"

[dependencies.async-trait]
optional = true
version = "0.1"

[dependencies.async-tungstenite]
default-features = false
features = ["tokio-runtime"]
optional = true
version = "0.9"

[dependencies.audiopus]
optional = true
version = "0.2"

[dependencies.byteorder]
optional = true
version = "1"

[dependencies.discortp]
features = ["discord-full"]
optional = true
version = "0.2"

[dependencies.flume]
optional = true
version = "0.9"

[dependencies.futures]
version = "0.3"

[dependencies.parking_lot]
optional = true
version = "0.11"

[dependencies.rand]
optional = true
version = "0.7"

[dependencies.serenity]
optional = true
features = ["voice", "gateway"]
path = "../"
version = "0.9.0-rc.2"

[dependencies.serenity-voice-model]
optional = true
path = "../voice-model"
version = "0.9.0-rc.2"

[dependencies.spin_sleep]
optional = true
version = "1"

[dependencies.streamcatcher]
optional = true
version = "0.1"

[dependencies.tokio]
optional = true
version = "0.2"
default-features = false

[dependencies.twilight-gateway]
optional = true
version = "0.1"
default-features = false

[dependencies.twilight-model]
optional = true
version = "0.1"
default-features = false

[dependencies.url]
optional = true
version = "2"

[dependencies.xsalsa20poly1305]
optional = true
version = "0.5"

[dev-dependencies]
criterion = "0.3"
utils = { path = "utils" }

[features]
default = [
"serenity-rustls",
"driver",
"gateway",
]
gateway = [
"flume",
"parking_lot",
"tokio/sync",
]
driver = [
"async-trait",
"async-tungstenite",
"audiopus",
"byteorder",
"discortp",
"flume",
"parking_lot",
"rand",
"serenity-voice-model",
"spin_sleep",
"streamcatcher",
"tokio/fs",
"tokio/io-util",
"tokio/net",
"tokio/rt-core",
"tokio/time",
"tokio/process",
"tokio/sync",
"url",
"xsalsa20poly1305",
]
rustls = ["async-tungstenite/tokio-rustls"]
native = ["async-tungstenite/tokio-native-tls"]
serenity-rustls = ["serenity/rustls_backend", "rustls", "gateway", "serenity-deps"]
serenity-native = ["serenity/native_tls_backend", "native", "gateway", "serenity-deps"]
twilight-rustls = ["twilight", "twilight-gateway/rustls", "rustls", "gateway"]
twilight-native = ["twilight", "twilight-gateway/native", "native", "gateway"]
twilight = ["twilight-model"]
simd-zlib = ["twilight-gateway/simd-zlib"]
stock-zlib = ["twilight-gateway/stock-zlib"]
serenity-deps = ["async-trait"]

[[bench]]
name = "mixing"
path = "benches/mixing.rs"
harness = false

[package.metadata.docs.rs]
all-features = true
29 changes: 29 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Songbird

![](songbird.png)

Songbird is an async, cross-library compatible voice system for Discord, written in Rust.
The library offers:
* A standalone gateway frontend compatible with [serenity] and [twilight] using the
`"gateway"` and `"[serenity/twilight]-[rustls/native]"` features. You can even run
driverless, to help manage your [lavalink] sessions.
* A standalone driver for voice calls, via the `"driver"` feature. If you can create
a `ConnectionInfo` using any other gateway, or language for your bot, then you
can run the songbird voice driver.
* And, by default, a fully featured voice system featuring events, queues, RT(C)P packet
handling, seeking on compatible streams, shared multithreaded audio stream caches,
and direct Opus data passthrough from DCA files.

## Examples
Full examples showing various types of functionality and integrations can be found as part of [serenity's examples], and in [this crate's examples directory].

## Attribution

Songbird's logo is based upon the copyright-free image ["Black-Capped Chickadee"] by George Gorgas White.

[serenity]: https://github.com/serenity-rs/serenity
[twilight]: https://github.com/twilight-rs/twilight
["Black-Capped Chickadee"]: https://www.oldbookillustrations.com/illustrations/black-capped-chickadee/
[lavalink]: https://github.com/Frederikam/Lavalink
[serenity's examples]: https://github.com/serenity-rs/serenity/tree/current/examples
[this crate's examples directory]: https://github.com/serenity-rs/serenity/tree/current/songbird/examples
30 changes: 30 additions & 0 deletions benches/mixing.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
use criterion::{black_box, criterion_group, criterion_main, BatchSize, Criterion};
use songbird::{constants::*, input::Input};

pub fn mix_one_frame(c: &mut Criterion) {
let floats = utils::make_sine(STEREO_FRAME_SIZE, true);
let mut raw_buf = [0f32; STEREO_FRAME_SIZE];

c.bench_function("Mix stereo source", |b| {
b.iter_batched_ref(
|| black_box(Input::float_pcm(true, floats.clone().into())),
|input| {
input.mix(black_box(&mut raw_buf), black_box(1.0));
},
BatchSize::SmallInput,
)
});

c.bench_function("Mix mono source", |b| {
b.iter_batched_ref(
|| black_box(Input::float_pcm(false, floats.clone().into())),
|input| {
input.mix(black_box(&mut raw_buf), black_box(1.0));
},
BatchSize::SmallInput,
)
});
}

criterion_group!(benches, mix_one_frame);
criterion_main!(benches);
23 changes: 23 additions & 0 deletions build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#[cfg(all(feature = "driver", not(any(feature = "rustls", feature = "native"))))]
compile_error!(
"You have the `driver` feature enabled: \
either the `rustls` or `native` feature must be
selected to let Songbird's driver use websockets.\n\
- `rustls` uses Rustls, a pure Rust TLS-implemenation.\n\
- `native` uses SChannel on Windows, Secure Transport on macOS, \
and OpenSSL on other platforms.\n\
If you are unsure, go with `rustls`."
);

#[cfg(all(
feature = "twilight",
not(any(feature = "simd-zlib", feature = "stock-zlib"))
))]
compile_error!(
"Twilight requires you to specify a zlib backend: \
either the `simd-zlib` or `stock-zlib` feature must be
selected.\n\
If you are unsure, go with `stock-zlib`."
);

fn main() {}
3 changes: 3 additions & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Songbird examples

These examples show more advanced use of Songbird, or how to include Songbird in bots built on other libraries, such as twilight.
21 changes: 21 additions & 0 deletions examples/twilight/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
[package]
name = "basic-twilight-bot"
version = "0.1.0"
authors = ["Twilight and Serenity Contributors"]
edition = "2018"

[dependencies]
futures = "0.3"
tracing = "0.1"
tracing-subscriber = "0.2"
serde_json = { version = "1" }
tokio = { features = ["macros", "rt-threaded", "sync"], version = "0.2" }
twilight-gateway = "0.1"
twilight-http = "0.1"
twilight-model = "0.1"
twilight-standby = "0.1"

[dependencies.songbird]
path = "../.."
default-features = false
features = ["twilight-rustls", "gateway", "driver", "stock-zlib"]
Loading

0 comments on commit 7e4392a

Please sign in to comment.