Skip to content

Commit

Permalink
Driver/Input: Migrate audio backend to Symphonia (#89)
Browse files Browse the repository at this point in the history
* Initial Symphonia libopus wrapper

* Messy DCA(1) framing for Symphonia, DCA export on `Compressed`

Export is mainly for testing, but I think it'd also be a nice backport.

* Primitive mixer code.

* Early measurements, thinking about right granularity for resampling wrt. different input packet sizes.

* Some structuring, committing for now.

* Prelim integration of mix code (not input readying yet...)

* Minor progress on dropping in new inputs...

* Deps: Depend on Serenity's `next` branch on Songbird's `next` branch (#6)

* Depend on Serenity's `next` branch on Songbird's `next` branch

* Update the examples to use the `next` branch

* Deps: Bump streamcatcher version -> 1.0 (#93)

* Examples: Fix serenity-next cache accesses (#99)

Serenity's cache design has changed, this (finally) prevents the examples from failing to compile on CI.

* Gateway: Add generics to `Call` methods. (#102)

Adds generics to any `Id` types on `Call`. Also includes the overlooked `Songbird::get_or_insert`.

Closes #94. Tested using `cargo make ready`.

* Gateway: Remove lifetime from Serenity setup trait (#103)

This matches a recent serenity change where `ClientBuilder` no longer has an explicit lifetime parameter.

This was tested using `cargo make ready`.

* Working MP3 playback.

MP3s now work great under the convert -> resample -> mix pipeline, even across unclean frame boundaries. Main issue seemed to be the number of internal subchunks in the resampler, which is still totally opaque... Oh well.

Actual instantiation of Lazy->Wrapped and Wrapped->Parsed elements in the driver is not yet covered.

Other formats are broken due to handling of the default track id, which is currently a) messy, and b) incorrect.

* Dumb hack for Ogg playback.

Oggs have some frames whose length is 0, yet must be decoded. I assume this covers the entire coder delay.

* Lazy input creation pipeline.

* Use new `last_decoded` Decoder semantics.

* Lazy inputs work as expected -- for Files at least.

* Http lazy inputs!

Tested with a URL extracted from bandcamp via youtube-dl, also includes the scaffolding necessary to have Reads/Seeks pass between sync/async boundaries.

This format is MP3, streamed in over an HTTP request via reqwest. Seeks not tested with e.g. Async Files -- they are programmed, though.

* Seek support.

Moves all sync creation/parsing/seeking etc. over to an elastically-sized thread pool. Since basically everything is now a restartable, this means that the `ForwardOnly` distinction can be handled really cleanly in general and we can try to recreate sources as needed.

* Basic youtube-dl input, remove old tokio support.

Asks for any streams without webm, since they're likely to be golden right now.

* Update to 2021 edition

* Re-enable SetTrack

* Redesign cached::Memory, port cached::Compressed

* Opus frame passthrough support restored

* Stereo/mono mix target support.

* DCA seek support, metadata fixes.

* WIP reorganisation, dead code removal.

* Deps: Depend on Serenity's `next` branch on Songbird's `next` branch (#6)

* Depend on Serenity's `next` branch on Songbird's `next` branch

* Update the examples to use the `next` branch

* Deps: Bump streamcatcher version -> 1.0 (#93)

* Examples: Fix serenity-next cache accesses (#99)

Serenity's cache design has changed, this (finally) prevents the examples from failing to compile on CI.

* Gateway: Add generics to `Call` methods. (#102)

Adds generics to any `Id` types on `Call`. Also includes the overlooked `Songbird::get_or_insert`.

Closes #94. Tested using `cargo make ready`.

* Gateway: Remove lifetime from Serenity setup trait (#103)

This matches a recent serenity change where `ClientBuilder` no longer has an explicit lifetime parameter.

This was tested using `cargo make ready`.

* The great clippification.

* Gateway: Generic Shard and Twilight v0.8 Support (#109)

This PR adds support for twilight v0.8, mainly adapting to significant API changes introduced by v0.7. As a result of these, twilight no longer accepts arbitrary JSON input, so it seemed sensible to adapt our `Shard` design to no longer require the same.

Adding to this, I've added in a trait to allow an arbitrary `Shard` to be installed, given only an implementation of a method to send a `VoiceStateUpdate`. Together, `Sharder::Generic` (songbird::shards::VoiceUpdate) and `Shard::Generic` (songbird::shards::GenericSharder) should allow any library to be hooked in to Songbird.

This PR was tested using `cargo make ready` and by manually testing `examples/twilight`.

* Gateway: Twilight v0.9 support (#110)

This handles twilight's migration to a unified `Id` type, which is the only design change needing any handling on our part. All our `From`/`Into`s are covered now, and deprecated type aliases are no longer used.

This was tested using `cargo make ready` and by manually running "examples/twilight".

* Update Audiopus -> 0.3.0-rc.0.

Simple enough, mainly forces us to do all the buffer size checks locally instead.

* WebM support merged upstream! Allow WebM from youtube-dl.

FFmpeg is finally gone.

* Fix Symphonia to v0.5

This version includes all the API changes we really need to function, and adds MKV support to a satisfactory level. This should free this PR up for an actual release down the line.

Additionally, this changes the symphonia dependency to remove default features so that choice over the codec suite (barring opus) is entirely user-driven.

* Catching up on documentation.

Also some assorted clippy niceties.

* Update ARCHITECTURE.md

* Add (untested) wrapper for raw PCM data.

* Add cached::decompressed, fix interleaved PCM adapter, nice docs for Input.

* Fix non-Send future in TrackQueue::add_raw

This arose from metadata collection occurring in this function.

* Resume HTTP sessions on failure.

Youtube-dl streams should now behave much, much nicer.

* Clean up imports in the HTTP/async adapter.

* Deps: Depend on Serenity's `next` branch on Songbird's `next` branch (#6)

* Depend on Serenity's `next` branch on Songbird's `next` branch

* Update the examples to use the `next` branch

* Deps: Bump streamcatcher version -> 1.0 (#93)

* Examples: Fix serenity-next cache accesses (#99)

Serenity's cache design has changed, this (finally) prevents the examples from failing to compile on CI.

* Gateway: Add generics to `Call` methods. (#102)

Adds generics to any `Id` types on `Call`. Also includes the overlooked `Songbird::get_or_insert`.

Closes #94. Tested using `cargo make ready`.

* Gateway: Remove lifetime from Serenity setup trait (#103)

This matches a recent serenity change where `ClientBuilder` no longer has an explicit lifetime parameter.

This was tested using `cargo make ready`.

* Gateway: Generic Shard and Twilight v0.8 Support (#109)

This PR adds support for twilight v0.8, mainly adapting to significant API changes introduced by v0.7. As a result of these, twilight no longer accepts arbitrary JSON input, so it seemed sensible to adapt our `Shard` design to no longer require the same.

Adding to this, I've added in a trait to allow an arbitrary `Shard` to be installed, given only an implementation of a method to send a `VoiceStateUpdate`. Together, `Sharder::Generic` (songbird::shards::VoiceUpdate) and `Shard::Generic` (songbird::shards::GenericSharder) should allow any library to be hooked in to Songbird.

This PR was tested using `cargo make ready` and by manually testing `examples/twilight`.

* Gateway: Twilight v0.9 support (#110)

This handles twilight's migration to a unified `Id` type, which is the only design change needing any handling on our part. All our `From`/`Into`s are covered now, and deprecated type aliases are no longer used.

This was tested using `cargo make ready` and by manually running "examples/twilight".

* Deps: Depend on Serenity's `next` branch on Songbird's `next` branch (#6)

* Depend on Serenity's `next` branch on Songbird's `next` branch

* Update the examples to use the `next` branch

* Deps: Bump streamcatcher version -> 1.0 (#93)

* Examples: Fix serenity-next cache accesses (#99)

Serenity's cache design has changed, this (finally) prevents the examples from failing to compile on CI.

* Gateway: Add generics to `Call` methods. (#102)

Adds generics to any `Id` types on `Call`. Also includes the overlooked `Songbird::get_or_insert`.

Closes #94. Tested using `cargo make ready`.

* Gateway: Remove lifetime from Serenity setup trait (#103)

This matches a recent serenity change where `ClientBuilder` no longer has an explicit lifetime parameter.

This was tested using `cargo make ready`.

* Gateway: Generic Shard and Twilight v0.8 Support (#109)

This PR adds support for twilight v0.8, mainly adapting to significant API changes introduced by v0.7. As a result of these, twilight no longer accepts arbitrary JSON input, so it seemed sensible to adapt our `Shard` design to no longer require the same.

Adding to this, I've added in a trait to allow an arbitrary `Shard` to be installed, given only an implementation of a method to send a `VoiceStateUpdate`. Together, `Sharder::Generic` (songbird::shards::VoiceUpdate) and `Shard::Generic` (songbird::shards::GenericSharder) should allow any library to be hooked in to Songbird.

This PR was tested using `cargo make ready` and by manually testing `examples/twilight`.

* Gateway: Twilight v0.9 support (#110)

This handles twilight's migration to a unified `Id` type, which is the only design change needing any handling on our part. All our `From`/`Into`s are covered now, and deprecated type aliases are no longer used.

This was tested using `cargo make ready` and by manually running "examples/twilight".

* Events: Remove deprecated events. (#115)

This removes the `ClientConnect`, `DriverConnectFailed`, `DriverReconnectFailed` and `SsrcKnown` events.

Tested using `cargo make ready`.

* Example cleanup.

* Update benchmarks to use symphonia, fix Compressed with 48kHz input

Hopefully, this should make it easier to see whether internal restructuring of Tracks has any odd effects. The benches are messy, but they function at least.

* Some restructuring work on Tracks

More to be done, just need to perf-test AoS vs SoA now.

* driver, queue: return track handle when adding an `Input` to the queue (#116)

* Gateway: Twilight v0.10 support (#117)

* Update to rubato v0.11.

* Driver, Gateway: Remove tokio 0.2 support (#118)

* Remove tokio 0.2 compat
* Remove tokio 0.2 test
* Remove tokio 0.2 CI

* Deps: Bump dependencies and document bumped MSRV (#119)

* Bump dependencies

* Document bumped MSRV

* Driver: Prevent panic when decrypting undersized RTP packets (#122)

Decrypt logic had two locations where the nonce would be separated from the payload without verifying the buffer size first, causing a panic for small packets.

Nonce and header removal now return an error if there are insufficient bytes.

Tested using `cargo make ready`, with some new tests to check that small packets simply return an `Err(...)`, and that encryption/decryption still function.

* Accidentally an await.

* Driver: Remove spin_sleep in `Mixer::march_deadline` (#124)

* Remove spin_sleep

* Remove comment

* Examples: support new Serenity Intents init

Fixes up the serenity examples to account for a bunch of API changes on `next`/v0.11.

Tested using `cargo make ready`.

* Deps: Update to Audiopus v0.3.0-rc.0 (#125)

Tested using `cargo make ready`.

Co-authored-by: André Vennberg <andre.vennberg@gmail.com>

* Update deps

* Fix otherwise broken state-change commands.

* Try fix clippy warnings

* fmt

* Bump MSRV to 1.61.0.

* Into<Input> for static/owned bytes

* Update twilight support to twilight 0.11 (#132)

* update twilight support to twilight 0.11

* rustfmt

* Fix broken 22.05kHz->48kHz resample

Doubles the resample chunk length to 10ms: I assume something odd is going on w/ integer math in rubato, but I'm not really willing to look into that

* Tracks + TrackHandles rework.

`create_player` and related functions are gone, Handles are now created *when* a Track is actually handed over.

`Track`s are now very small, since most state isn't actually needed/generated until you reach the driver. This means we can avoid having to make a bunch of `Track` state private to prevent users from, e.g., taking illegal actions via a `TrackHandle`. To avoid exposing internal details, `TrackHandle::action` now gets a `View` of track state generated as needed.

Still missing some docs and some cleanup. Still missing actual access to metadata, but it will happen through `View`.

* Add `aux_metadata()` to `Input`.

This should make it easier to access auxiliary metadata after, e.g., conversion to a `Track`.

* Expose probe and format metadata via `action`.

* Add + Expose ReadyState via View.

It's now possible to view whether a track is playable, lazy, or mid-preparation.

* Helper methods for input upgrading/creation/created access.

* Temporarily pin serenity version.

I don't have the time to rewrite examples to work around the Send nightmares introduced with the dashmap refs change atm: moreso if this is being released to target 0.11

* Create + Parse error signalling, listeners for TrackErrors

* Decode error handling + events.

* Some cleanup in the mixer logic.

* Refactor and reorganise mixing internals.

* Code restructure for `crate::input`.

Should be cleaner and easier to navigate now, external API is still the same (and pretty flat, hierarchically).

* Document `Symphonia` requirement in README and docs root

* Accidentally a space

* Update mixing benchmarks wrt. restructured code

* Document some errors, explain how to get (Aux)Metadata.

* Clarify failure reasons for Input::aux_metadata

* Document remaining types.

* A slightly exhausting example on the wonders of `Input`

* Removing some old error variants.

* Make Metadata link to action clearer.

* Make Passthrough a bit more lenient

A good few test inputs had final frames shorter than 20ms, meaning that they'd take an encoder delay's worth of silence before the last chunk of playback, which sounds awful.

This moves Passthrough enforcement to a 'three strikes' system to give a little more leeway on this front, preventing really awkward and expensive silent bursts at rhe end of Opus tracks.

* Appease Clippy

* Attempt to add yt-dlp to CI, make it the preferred fork in README.

* Clarify audiopus v0.3.0 build details.

* Make Driver.add_raw a public function

* Fix clippy::must_use_candidate

* Fix clippy::default_trait_access

* Fix clippy::match_same_arms

* Fix clippy::semicolon_if_nothing_returned

* Fix clippy::enum_glob_use

* Fix clippy::return_self_not_must_use

* Fix clippy::unused_self

* Fix clippy::trivially_copy_pass_by_ref

* Fix clippy::let_underscore_drop

* Fix clippy::map_unwrap_or

* Fix clippy::if_not_else

* Fix clippy::unnested_or_patterns

* Fix clippy::single_match_else

* Fmt and fix clippy::mut_mut

* Fix clippy::similar_names

* Fix clippy::needless_pass_by_value

* Fix clippy::match_wildcard_for_single_variants

* Fix clippy::redundant_closure_for_method_calls

* Fix clippy::doc_markdown

* Fix clippy::explicit_iter_loop

* Swap warn specific to warn all and allow, fix last couple warns

* Fix comment in lib.rs

Co-authored-by: Kyle Simpson <kyleandrew.simpson@gmail.com>

* Update DiscoRTP

* Initial work on headless test config for driver

* An actual driver test for the queue.

* Pin to another 0.11-ish version of next

* From<ChildContainer> for Input

* Recursive From/Into for all Input sources -> Track

* De-pub TrackHandle::new

This was definitely exposing too many implementation details.

* Typos in README/lib-docs

* Remove reused code from `Decompressed`'s byte transform

* Revisit LiveInput::promote

Slightly cleaner. Failure to find a track (or to create a decoder matching the format's default track) now result in an error rather than a panic.

* Placeholder YTDL test, convenience methods for output checking

* Add missing `Config` fields.

* Add Preparing and Playable events, expose ReadyState on TrackState.

This simplifies (and makes consistent) a *lot* of test methods.

* YoutubeDl seek tests.

* Fix: `Err(_)` events now also fire `End`

Fixes an issue where an errored track on the queue would just block (i.e., in event of a 404).

Later down the line, some errors may not fire ended (i.e., decode errors) which may be configured to play on.

* Move test/example resources to unified location.

* Hopefully fix windows CI. Unsure what's up with Http/Opus seeking.

* Add timeouts to all tests, unify code paths for format checking.

Seems to be the best way to rat out driver panics.

* Document/explain safety of OpusDecoder.

* Manually check for backseeking with one-way Inputs

It seems that some formats (MP4, Ogg) don't have logic to check that you're about to make a Very Bad Decision. We need to cache the inner bytestream's `is_seekable` and check this against a backwards seek ourselves, since pulling it out of a constructed source is nigh-on impossible.

MKV/WebM seek bug is still present: so far as I can tell it's because it uses a very different time base in the format than the decoder instances. I need to confirm whether other codecs do any local time_base corrections.

* Remove one incidental panic.

* Update tests to remove reliance on racy behaviour, record thoughts on MKV timing hell.

* Temporary pin to symphonia PR to keep the CI ticking.

* A nightly clippy nit.

* Temp Symphonia branch for my pile of fixes.

* Rework `add_raw` into `add_`/`enqueue_with_preload`.

This does a little bit of internal reworking to make this feasible, but this prevents us from having one function on `TrackHandles` while the rest are on `Track`s (so more user-friendly). Similarly, this prevents us from having to impose conditions on the target `TrackHandle` -- "you must pause your track first" is a bit of a footgun.

This also applies event listeners *before* tracks are handed over to the driver, which is more correct and means we don't need to wait a tick or similar.

* Next got forced, again.

* Rework ClientData to wrap in Option instead of initialised bool (#2)

* Repair some broken doc-links.

* Add cfg(test) around all testing paths (#5)

* Properly use cfg(test)

* Use Packet

* Reduce default thread pool allocation.

* Fix packet sending outside of cfg(test)

* Use YoutubeDl-suggested header values in HttpRequest

This should hopefully get past the ratelimiting.

* Support serenity@next instead of pinning version (#7)

* Support serenity@next instead of pinning version

* Fix tests and re-add From

* Update examples to work with serenity@next.

Also, twilight example was a bit broken.

* Bypass Youtube ratelimiting

Youtube expects a very particular set of HTTP headers, otherwise it will allocate you a very snug 70kB/s download rate. This didn't impact audio playout too badly, but it did prevent seeking as fast as required. Seeks now work just as well on Youtube as they do for all other HTTP sources.

* Seek/MakePlayable callbacks on TrackHandle.

* Unbreak tests.

* Callback tests, fix input ready notification on paused tracks.

* Document TrackCallback

* TrackHandle::seek_time -> seek

* Prevent track times from ticking while preparing.

Also, make an in-seek track return to `Preparing`.

* Accidental commit of some seek testing in example.

* Tests ensuring Loops work in perpetuity.

* Fix looping on streamed MKVs

Seeking back to t=0 requires a page realignment on Youtube's WebMs, which is impossible (backseek of around 7 bytes) and fails due to existing create-loop prevention checks.

Seeks to zero are now ignored after re-creating a source, as the track can be safely assumed to be at its beginning.

* Fix HTTP Range resume

Range requests were being horribly broken by a double range field that reqwest didn't filter out. Oops!

* Some leniency on tougher tests.

* Remove unnecessary poison messages (#6)

* Remove unnecessary poison messages

* Re-add Poison for CoreMessage

* Use OnceCell and DashMap (#8)

* Format, alphabetise feature deps.

* Fix ShardMessage for serenity::next

* Structify YoutubeDL Json reading

* Make `url` field mandatory in YtDL Output.

* FFprobe output as File::aux_metadata

* Quick once-over of the serenity examples.

* Review Pt. 1: Doc mix logic, extend passthrough to one *live* track

This is most relevant for queue users -- an extra track would cause opus passthrough to end, even though only one track was being actively used in mixing.

* Some unneeded refs caught by clippy

Corollary: this same new clippy lint adds a ton of false positives which *will* fail to compile.

* Minor cleanup: not a fan of From<&Type> vs. dedicated method.

* Track removals from event context, sans `Vec`

* Review Pt 2: Mixer task.

* Act on queued seeks given mid-track--prepare.

* Review pt 3: Starting on inputs

Will leave 're-computing filesize guesses' to a future issue.

* Remove unnecessary chrono dep (#9)

* Adapt examples to new serenity framework.

* impl Error for Cached adapters

* Review pt 4: adapters.

* Review pt 5: Inputs

* Finis

Co-authored-by: Alex M. M <acdenissk69@gmail.com>
Co-authored-by: tkt <37575408+tktcorporation@users.noreply.github.com>
Co-authored-by: Jan <66554238+vaporox@users.noreply.github.com>
Co-authored-by: Gnome! <45660393+GnomedDev@users.noreply.github.com>
Co-authored-by: André Vennberg <andre.vennberg@gmail.com>
Co-authored-by: Gnome <david2005thomas@gmail.com>
Co-authored-by: Erk <Erk-@users.noreply.github.com>
Co-authored-by: Alakh <36898190+alakhpc@users.noreply.github.com>
  • Loading branch information
9 people authored Jul 23, 2022
1 parent 0d66467 commit 5547de2
Show file tree
Hide file tree
Showing 136 changed files with 9,693 additions and 4,823 deletions.
15 changes: 12 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ jobs:
- Windows
- driver only
- gateway only
- legacy tokio

include:
- name: beta
Expand Down Expand Up @@ -75,6 +74,16 @@ jobs:
sudo apt-get update
sudo apt-get install -y libopus-dev
- name: Install yt-dlp (Unix)
if: runner.os != 'Windows'
run: |
sudo wget https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp -O /usr/local/bin/yt-dlp
sudo chmod a+rx /usr/local/bin/yt-dlp
- name: Install yt-dlp (Windows)
if: runner.os == 'Windows'
run: choco install yt-dlp

- name: Setup cache
if: runner.os != 'macOS'
uses: actions/cache@v2
Expand Down Expand Up @@ -175,9 +184,9 @@ jobs:
- name: 'Build serenity/voice_receive'
working-directory: examples
run: cargo build -p voice_receive
- name: 'Build serenity/voice_storage'
- name: 'Build serenity/voice_cached_audio'
working-directory: examples
run: cargo build -p voice_storage
run: cargo build -p voice_cached_audio
- name: 'Build twilight'
working-directory: examples
run: cargo build -p twilight
17 changes: 9 additions & 8 deletions ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,14 @@ Songbird's **driver** is a mixed sync/async system for running voice connections
Audio processing remains synchronous for the following reasons:
* Encryption, encoding, and mixing are compute bound tasks which cannot be subdivided cleanly by the Tokio executor. Having these block the scheduler's finite thread count has a significant impact on servicing other tasks.
* `Read` and `Seek` are considerably more user-friendly to use, implement, and integrate than `AsyncRead`, `AsyncBufRead`, and `AsyncSeek`.
* Symphonia implements all of its functionality based on synchronous I/O.

## Tasks
Songbird subdivides voice connection handling into several long- and short-lived tasks.

* **Core**: Handles and directs commands received from the driver. Responsible for connection/reconnection, and creates network tasks.
* **Mixer**: Combines audio sources together, Opus encodes the result, and encrypts the built packets every 20ms. Responsible for handling track commands/state. ***Synchronous***.
* **Thread Pool**: A dynamically sized thread-pool for I/O tasks. Creates lazy tracks using `Compose` if sync creation is needed, otherwise spawns a tokio task. Seek operations always go to the thread pool. ***Synchronous***.
* **Disposer**: Used by mixer thread to dispose of data with potentially long/blocking `Drop` implementations (i.e., audio sources). ***Synchronous***.
* **Events**: Stores and runs event handlers, tracks event timing, and handles
* **Websocket**: *Network task.* Sends speaking status updates and keepalives to Discord, and receives client (dis)connect events.
Expand All @@ -52,23 +54,22 @@ src/driver/*
## Audio handling

### Input
Inputs are raw audio sources: composed of a `Reader` (which can be `Read`-only or `Read + Seek`), a framing mechanism, and a codec.
Several wrappers exist to add `Seek` capabilities to one-way streams via storage or explicitly recreating the struct.
Inputs are audio sources supporting lazy initialisation, being either:
* **lazy inputs**—a trait object which allows an instructions to create an audio source to be cheaply stored. This will be initialised when needed either synchronously or asynchronously based on what which methods the trait object supports.
* **live inputs**—a usable audio object implementing `MediaSource: Read + Seek`. `Seek` support may be dummied in, as seek use and support is gated by `MediaSource`. These can be passed in at various stages of processing by symphonia.

Framing is not always needed (`Raw`), but makes it possible to consume the correct number of bytes needed to decode one audio packet (and/or simplify skipping through the stream).
Currently, Opus and raw (`i16`/`f32`) audio sources are supported, though only the DCA framing for Opus is implemented.
At present, the use of the FFmpeg executable allows us to receive raw input, but at heavy memory cost.
Further implementations are possible in the present framework (e.g., WebM/MKV and Ogg containers, MP3 and linked FFI FFmpeg as codecs).
Several wrappers exist to add `Seek` capabilities to one-way streams via storage or explicitly recreating the struct, `AsyncRead` adapters, and raw audio input adapters.

Internally, the mixer uses floating-point audio to prevent clipping and allow more granular volume control.
If a source is known to use the Opus codec (and is the only source), then it can bypass mixing altogether.
Symphonia is used to demux and decode input files in a variety of formats into this floating-point buffer: songbird supports all codecs and containers which are part of the symphonia project, while adding support for Opus decoding and DCA1 container files.
If a source uses the Opus codec (and is the only source), then it can bypass mixing and re-encoding altogether, saving CPU cycles per server.

```
src/input/*
```

### Tracks
Tracks hold additional state which is expected to change over the lifetime of a track: position, play state, and modifiers like volume.
Tracks hold additional state which is expected to change over the lifetime of a track: position, play state, and modifiers like volume.
Tracks (and their handles) also allow per-source events to be inserted.

Tracks are defined in user code, where they are fully modifiable, before being passed into the driver.
Expand Down
112 changes: 81 additions & 31 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,28 @@
authors = ["Kyle Simpson <kyleandrew.simpson@gmail.com>"]
description = "An async Rust library for the Discord voice API."
documentation = "https://docs.rs/songbird"
edition = "2018"
edition = "2021"
homepage = "https://github.com/serenity-rs/songbird"
include = ["src/**/*.rs", "Cargo.toml", "build.rs"]
keywords = ["discord", "api", "rtp", "audio"]
license = "ISC"
name = "songbird"
readme = "README.md"
repository = "https://github.com/serenity-rs/songbird.git"
version = "0.3.0"
version = "0.2.2"
rust-version = "1.61"

[dependencies]
derivative = "2"
pin-project = "1"
serde = { version = "1", features = ["derive"] }
serde_json = "1"
tracing = { version = "0.1", features = ["log"] }
tracing-futures = "0.2"
symphonia-core = "0.5"

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

[dependencies.async-trait]
optional = true
Expand All @@ -45,28 +50,50 @@ version = "5"
[dependencies.discortp]
features = ["discord-full"]
optional = true
version = "0.4"
version = "0.5"

# Temporary hack to pin MSRV.
[dependencies.flume]
optional = true
version = "0.10"

[dependencies.futures]
version = "0.3"

[dependencies.parking_lot]
[dependencies.lazy_static]
optional = true
version = "0.12"
version = "1"

[dependencies.pin-project]
[dependencies.parking_lot]
optional = true
version = "1"
version = "0.12"

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

[dependencies.reqwest]
optional = true
default-features = false
features = ["stream"]
version = "0.11"

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

[dependencies.rubato]
optional = true
version = "0.12"

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

[dependencies.serde-aux]
default-features = false
optional = true
version = "3"

[dependencies.serenity]
optional = true
default-features = false
Expand All @@ -83,11 +110,29 @@ branch = "next"
optional = true
version = "1"

[dependencies.symphonia]
optional = true
default-features = false
version = "0.5"
git = "https://github.com/FelixMcFelix/Symphonia"
branch = "songbird-fixes"

[dependencies.symphonia-core]
optional = true
version = "0.5"
git = "https://github.com/FelixMcFelix/Symphonia"
branch = "songbird-fixes"

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

[dependencies.tokio-util]
optional = true
version = "0.7"
features = ["io"]

[dependencies.twilight-gateway]
optional = true
version = "0.12.0"
Expand All @@ -108,7 +153,7 @@ version = "2"

[dependencies.uuid]
optional = true
version = "0.8"
version = "1"
features = ["v4"]

[dependencies.xsalsa20poly1305]
Expand All @@ -118,7 +163,10 @@ features = ["std"]

[dev-dependencies]
criterion = "0.3"
ntest = "0.8"
symphonia = { version = "0.5", features = ["mp3"], git = "https://github.com/FelixMcFelix/Symphonia", branch = "songbird-fixes" }
utils = { path = "utils" }
tokio = { version = "1", features = ["rt", "rt-multi-thread"] }

[features]
# Core features
Expand All @@ -128,45 +176,48 @@ default = [
"gateway",
]
gateway = [
"gateway-core",
"tokio/sync",
"tokio/time",
]
gateway-core = [
"dashmap",
"flume",
"once_cell",
"parking_lot",
"pin-project",
]
driver = [
"async-tungstenite",
"driver-core",
"tokio/fs",
"tokio/io-util",
"tokio/macros",
"tokio/net",
"tokio/process",
"tokio/rt",
"tokio/sync",
"tokio/time",
]
driver-core = [
driver = [
"async-trait",
"async-tungstenite",
"audiopus",
"byteorder",
"discortp",
"reqwest",
"flume",
"lazy_static",
"parking_lot",
"rand",
"ringbuf",
"rubato",
"serde-aux",
"serenity-voice-model",
"streamcatcher",
"symphonia",
"symphonia-core",
"rusty_pool",
"tokio-util",
"tokio/fs",
"tokio/io-util",
"tokio/macros",
"tokio/net",
"tokio/process",
"tokio/rt",
"tokio/sync",
"tokio/time",
"typemap_rev",
"url",
"uuid",
"xsalsa20poly1305",
]
rustls = ["async-tungstenite/tokio-rustls-webpki-roots", "rustls-marker"]
native = ["async-tungstenite/tokio-native-tls", "native-marker"]
rustls = ["async-tungstenite/tokio-rustls-webpki-roots", "reqwest/rustls-tls", "rustls-marker"]
native = ["async-tungstenite/tokio-native-tls", "native-marker", "reqwest/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-native-roots", "rustls", "gateway"]
Expand All @@ -180,8 +231,6 @@ rustls-marker = []
native-marker = []

# Behaviour altering features.
youtube-dlc = []
yt-dlp = []
builtin-queue = []

# Used for docgen/testing/benchmarking.
Expand All @@ -191,6 +240,7 @@ internals = []
[[bench]]
name = "base-mixing"
path = "benches/base-mixing.rs"
required-features = ["internals"]
harness = false

[[bench]]
Expand Down
4 changes: 4 additions & 0 deletions Makefile.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ dependencies = ["format"]
[tasks.build-variants]
dependencies = ["build", "build-gateway", "build-driver"]

[tasks.check]
args = ["check", "--features", "full-doc"]
dependencies = ["format"]

[tasks.clippy]
args = ["clippy", "--features", "full-doc", "--", "-D", "warnings"]
dependencies = ["format"]
Expand Down
Loading

0 comments on commit 5547de2

Please sign in to comment.