rodio/lib.rs
1//! Audio playback library.
2//!
3//! The main concept of this library is the [`Source`] trait, which
4//! represents a sound (streaming or not). In order to play a sound, there are three steps:
5//!
6//! - Create an object that represents the streaming sound. It can be a sine wave, a buffer, a
7//! [`decoder`], etc. or even your own type that implements the [`Source`] trait.
8//! - Get an output stream handle to a physical device. For example, get a stream to the system's
9//! default sound device with [`OutputStream::try_default()`]
10//! - Call [`.play_raw(source)`](OutputStreamHandle::play_raw) on the output stream handle.
11//!
12//! The [`play_raw`](OutputStreamHandle::play_raw) function expects the source to produce [`f32`]s,
13//! which may not be the case. If you get a compilation error, try calling
14//! [`.convert_samples()`](Source::convert_samples) on the source to fix it.
15//!
16//! For example, here is how you would play an audio file:
17//!
18//! ```no_run
19//! use std::fs::File;
20//! use std::io::BufReader;
21//! use rodio::{Decoder, OutputStream, source::Source};
22//!
23//! // Get an output stream handle to the default physical sound device.
24//! // Note that no sound will be played if _stream is dropped
25//! let (_stream, stream_handle) = OutputStream::try_default().unwrap();
26//! // Load a sound from a file, using a path relative to Cargo.toml
27//! let file = BufReader::new(File::open("examples/music.ogg").unwrap());
28//! // Decode that sound file into a source
29//! let source = Decoder::new(file).unwrap();
30//! // Play the sound directly on the device
31//! stream_handle.play_raw(source.convert_samples());
32//!
33//! // The sound plays in a separate audio thread,
34//! // so we need to keep the main thread alive while it's playing.
35//! std::thread::sleep(std::time::Duration::from_secs(5));
36//! ```
37//!
38//! ## Sink
39//!
40//! In order to make it easier to control the playback, the rodio library also provides a type
41//! named [`Sink`] which represents an audio track.
42//!
43//! Instead of playing the sound with [`play_raw`](OutputStreamHandle::play_raw), you can add it to
44//! a [`Sink`] instead.
45//!
46//! - Get a [`Sink`] to the output stream, and [`.append()`](Sink::append) your sound to it.
47//!
48//! ```no_run
49//! use std::fs::File;
50//! use std::io::BufReader;
51//! use std::time::Duration;
52//! use rodio::{Decoder, OutputStream, Sink};
53//! use rodio::source::{SineWave, Source};
54//!
55//! // _stream must live as long as the sink
56//! let (_stream, stream_handle) = OutputStream::try_default().unwrap();
57//! let sink = Sink::try_new(&stream_handle).unwrap();
58//!
59//! // Add a dummy source of the sake of the example.
60//! let source = SineWave::new(440.0).take_duration(Duration::from_secs_f32(0.25)).amplify(0.20);
61//! sink.append(source);
62//!
63//! // The sound plays in a separate thread. This call will block the current thread until the sink
64//! // has finished playing all its queued sounds.
65//! sink.sleep_until_end();
66//! ```
67//!
68//! The [`append`](Sink::append) method will add the sound at the end of the
69//! sink. It will be played when all the previous sounds have been played. If you want multiple
70//! sounds to play simultaneously, you should create multiple [`Sink`]s.
71//!
72//! The [`Sink`] type also provides utilities such as playing/pausing or controlling the volume.
73//!
74//! **Please note that the [`Sink`] requires the [`OutputStream`], make sure that the OutputStream is not dropped before the sink.**
75//!
76//! ## Filters
77//!
78//! The [`Source`] trait provides various filters, similar to the standard [`Iterator`] trait.
79//!
80//! Example:
81//!
82//! ```
83//! use rodio::Source;
84//! use std::time::Duration;
85//!
86//! // Repeats the first five seconds of the sound forever.
87//! # let source = rodio::source::SineWave::new(440.0);
88//! let source = source.take_duration(Duration::from_secs(5)).repeat_infinite();
89//! ```
90//!
91//! ## Alternative Decoder Backends
92//!
93//! [Symphonia](https://github.com/pdeljanov/Symphonia) is an alternative decoder library that can be used in place
94//! of many of the default backends.
95//! Currently, the main benefit is that Symphonia is the only backend that supports M4A and AAC,
96//! but it may be used to implement additional optional functionality in the future.
97//!
98//! To use, enable either the `symphonia-all` feature to enable all Symphonia codecs
99//! or enable specific codecs using one of the `symphonia-{codec name}` features.
100//! If you enable one or more of the Symphonia codecs, you may want to set `default-features = false` in order
101//! to avoid adding extra crates to your binary.
102//! See the [available feature flags](https://docs.rs/crate/rodio/latest/features) for all options.
103//!
104//! ## Optional Features
105//!
106//! Rodio provides several optional features that are guarded with feature gates.
107//!
108//! ### Feature "tracing"
109//!
110//! The "tracing" feature replaces the print to stderr when a stream error happens with a
111//! recording an error event with tracing.
112//!
113//! ### Feature "Noise"
114//!
115//! The "noise" feature adds support for white and pink noise sources. This feature requires the
116//! "rand" crate.
117//!
118//! ## How it works under the hood
119//!
120//! Rodio spawns a background thread that is dedicated to reading from the sources and sending
121//! the output to the device. Whenever you give up ownership of a [`Source`] in order to play it,
122//! it is sent to this background thread where it will be read by rodio.
123//!
124//! All the sounds are mixed together by rodio before being sent to the operating system or the
125//! hardware. Therefore there is no restriction on the number of sounds that play simultaneously or
126//! the number of sinks that can be created (except for the fact that creating too many will slow
127//! down your program).
128
129#![cfg_attr(test, deny(missing_docs))]
130pub use cpal::{
131 self, traits::DeviceTrait, Device, Devices, DevicesError, InputDevices, OutputDevices,
132 SupportedStreamConfig,
133};
134
135mod conversions;
136mod sink;
137mod spatial_sink;
138mod stream;
139
140pub mod buffer;
141pub mod decoder;
142pub mod dynamic_mixer;
143pub mod queue;
144pub mod source;
145pub mod static_buffer;
146
147pub use crate::conversions::Sample;
148pub use crate::decoder::Decoder;
149pub use crate::sink::Sink;
150pub use crate::source::Source;
151pub use crate::spatial_sink::SpatialSink;
152pub use crate::stream::{OutputStream, OutputStreamHandle, PlayError, StreamError};