1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
//! Audio playback library.
//!
//! The main concept of this library is the [`Source`] trait, which
//! represents a sound (streaming or not). In order to play a sound, there are three steps:
//!
//! - Get an OS-Sink handle to a physical device. For example, get a sink to the system's
//! default sound device with [`DeviceSinkBuilder::open_default_sink()`].
//! - Create an object that represents the streaming sound. It can be a sine wave, a buffer, a
//! [`decoder`], etc. or even your own type that implements the [`Source`] trait.
//! - Add the source to the OS-Sink using [`MixerDeviceSink::mixer()`]
//! on the OS-Sink handle.
//!
//! Here is a complete example of how you would play an audio file:
//!
//! use std::fs::File;
//! use rodio::{Decoder, MixerDeviceSink, source::Source};
//!
//! // Get an OS-Sink handle to the default physical sound device.
//! // Note that the playback stops when the handle is dropped.//!
//! let handle = rodio::DeviceSinkBuilder::open_default_sink()
//! .expect("open default audio stream");
//! let player = rodio::Player::connect_new(&handle.mixer());
//! // Load a sound from a file, using a path relative to Cargo.toml
//! let file = File::open("examples/music.ogg").unwrap();
//! // Decode that sound file into a source
//! let source = Decoder::try_from(file).unwrap();
//! // Play the sound directly on the device
//! handle.mixer().add(source);
//!
//! // The sound plays in a separate audio thread,
//! // so we need to keep the main thread alive while it's playing.
//! std::thread::sleep(std::time::Duration::from_secs(5));
//! ```
//!
//! [`rodio::play()`](crate::play) helps to simplify the above
//! use std::fs::File;
//! use std::io::BufReader;
//! use rodio::{Decoder, MixerDeviceSink, source::Source};
//!
//! // Get an OS-Sink handle to the default physical sound device.
//! // Note that the playback stops when the sink_handle is dropped.
//! let sink_handle = rodio::DeviceSinkBuilder::open_default_sink()
//! .expect("open default audio stream");
//!
//! // Load a sound from a file, using a path relative to Cargo.toml
//! let file = BufReader::new(File::open("examples/music.ogg").unwrap());
//! // Note that the playback stops when the player is dropped
//! let player = rodio::play(&sink_handle.mixer(), file).unwrap();
//!
//! // The sound plays in a separate audio thread,
//! // so we need to keep the main thread alive while it's playing.
//! std::thread::sleep(std::time::Duration::from_secs(5));
//! ```
//!
//!
//! ## Player
//!
//! In order to make it easier to control the playback, the rodio library also provides a type
//! named [`Player`] which represents an audio track. [`Player`] plays its input sources sequentially,
//! one after another. To play sounds in simultaneously in parallel, use [`mixer::Mixer`] instead.
//!
//! To play a song Create a [`Player`], connect it to the OS-Sink,
//! and [`.append()`](Player::append) your sound to it.
//!
//! use std::time::Duration;
//! use rodio::{MixerDeviceSink, Player};
//! use rodio::source::{SineWave, Source};
//!
//! // _stream must live as long as the sink
//! let handle = rodio::DeviceSinkBuilder::open_default_sink()
//! .expect("open default audio stream");
//! let player = rodio::Player::connect_new(&handle.mixer());
//!
//! // Add a dummy source of the sake of the example.
//! let source = SineWave::new(440.0).take_duration(Duration::from_secs_f32(0.25)).amplify(0.20);
//! player.append(source);
//!
//! // The sound plays in a separate thread. This call will block the current thread until the
//! // player has finished playing all its queued sounds.
//! player.sleep_until_end();
//! ```
//!
//! The [`append`](Player::append) method will add the sound at the end of the
//! player. It will be played when all the previous sounds have been played. If you want multiple
//! sounds to play simultaneously consider building your own [`Player`] from rodio parts.
//!
//! The [`Player`] type also provides utilities such as playing/pausing or controlling the volume.
//!
//! <div class="warning">Note that playback through Player will end if the associated
//! DeviceSink is dropped.</div>
//!
//! ## Filters
//!
//! The [`Source`] trait provides various filters, similar to the standard [`Iterator`] trait.
//!
//! Example:
//!
//! use rodio::Source;
//! use std::time::Duration;
//!
//! // Repeats the first five seconds of the sound forever.
//! # let source = rodio::source::SineWave::new(440.0);
//! let source = source.take_duration(Duration::from_secs(5)).repeat_infinite();
//! ```
//!
//! ## Decoder Backends
//!
//! [Symphonia](https://github.com/pdeljanov/Symphonia) is the default decoder library.
//! Rodio supports enabling all of Symphonia's codecs using the `symphonia-all` feature
//! or enabling specific codecs using one of the `symphonia-{codec name}` features.
//! By default, decoders for the most common file types (flac, mp3, mp4, vorbis, wav) are enabled.
//!
//! ### Alternative Decoders
//!
//! Alternative decoder libraries are available for some filetypes:
//!
//! - claxon (flac)
//! - hound (wav)
//! - lewton (vorbis)
//! - minimp3 (mp3)
//!
//! Symphonia is recommended for most usage. However, the alternative decoders are all licensed
//! under either MIT or Apache 2.0 while Symphonia is licensed under MPL-2.0, so
//! this may be a factor if you have strict licensing requirements.
//!
//! If you enable one of these, you may want to set `default-features = false`
//! to avoid adding extra crates to your binary.
//! See the [available feature flags](https://docs.rs/crate/rodio/latest/features) for all options.
//!
//! ## Optional Features
//!
//! Rodio provides several optional features that are guarded with feature gates.
//!
//! ### Feature "tracing"
//!
//! The "tracing" feature replaces the print to stderr when a stream error happens with a
//! recording an error event with tracing.
//!
//! ### Feature "noise"
//!
//! The "noise" feature adds support for white and pink noise sources. This feature requires the
//! "rand" crate.
//!
//! ### Feature "playback"
//!
//! The "playback" feature adds support for playing audio. This feature requires the "cpal" crate.
//!
//! ### Feature "64bit"
//!
//! The "64bit" feature enables 64-bit sample precision using `f64` for audio samples and most
//! internal calculations. By default, rodio uses 32-bit floats (`f32`), which offers better
//! performance and is sufficient for most use cases. The 64-bit mode addresses precision drift
//! when chaining many audio operations together and in long-running signal generators where
//! phase errors compound over time.
//!
//! ## How it works under the hood
//!
//! Rodio spawns a background thread that is dedicated to reading from the sources and sending
//! the output to the device. Whenever you give up ownership of a [`Source`] in order to play it,
//! it is sent to this background thread where it will be read by rodio.
//!
//! All the sounds are mixed together by rodio before being sent to the operating system or the
//! hardware. Therefore, there is no restriction on the number of sounds that play simultaneously or
//! on the number of sinks that can be created (except for the fact that creating too many will slow
//! down your program).
pub use ;
/// Microphone input support for audio recording.
pub use crate;
pub use crateDecoder;
pub use crateFixedSource;
pub use cratePlayer;
pub use crateSource;
pub use crateSpatialPlayer;
pub use crate;
pub use cratewav_to_file;
pub use cratewav_to_writer;