Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use builder to init output stream #641

Merged
merged 36 commits into from
Nov 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
184b383
Support buffer size selection
PetrGlad Nov 6, 2022
dd48390
Make configurable buffer API public
PetrGlad Nov 14, 2022
5d42375
Correct API signatures
PetrGlad Nov 14, 2022
4c62dd3
Bump version
PetrGlad Oct 1, 2023
1a8d63a
Reduce API changes
PetrGlad Oct 1, 2023
c17712f
Reformat code
PetrGlad Oct 1, 2023
08207b1
Merge branch 'master' into configurable-buffer-size
PetrGlad Oct 20, 2023
dd1edbb
WIP, simplify output stream initialization
PetrGlad Sep 23, 2024
e82b208
WIP. Implementing OpenStreamBuilder
PetrGlad Nov 6, 2024
fcfbabc
Revert to using mixer as default output
PetrGlad Nov 8, 2024
7154439
Remove source plug prototype
PetrGlad Nov 8, 2024
e2c74a5
Streamline default stream logic
PetrGlad Nov 8, 2024
dbd1d1f
Remove Criterion dependency
PetrGlad Nov 8, 2024
5cfe61f
Update a basic example
PetrGlad Nov 9, 2024
cabdda7
Update tests and examples
PetrGlad Nov 9, 2024
352c399
Add example comments
PetrGlad Nov 10, 2024
2ee0a3c
Merge remote-tracking branch 'rust-audio/master' into init-revamp
PetrGlad Nov 10, 2024
c5850ab
Sync Cargo.toml with master branch
PetrGlad Nov 10, 2024
83c0025
Update doc examples
PetrGlad Nov 10, 2024
179d41a
Reformat code
PetrGlad Nov 13, 2024
af92566
Cleanup
PetrGlad Nov 14, 2024
ebc673e
Cleanup, remove unnecessay imports
PetrGlad Nov 14, 2024
b720273
Revert extra changes for merge request
PetrGlad Nov 14, 2024
689670d
UPdate documentation
PetrGlad Nov 15, 2024
6a6e94c
Rename dynamic_mixer.rs
PetrGlad Nov 15, 2024
1af733e
Cleanup: fix lint warnings
PetrGlad Nov 15, 2024
6f6385b
Add documentation for output stream public exports
PetrGlad Nov 16, 2024
77c50cd
Clarify API documentation
PetrGlad Nov 17, 2024
4101ae9
Remove unwrap and expect from example code
PetrGlad Nov 19, 2024
0ba6021
Hide OutputStreamConfig struct
PetrGlad Nov 21, 2024
95060b1
Stream initialization fix
PetrGlad Nov 21, 2024
678df03
Custom output stream config example
PetrGlad Nov 21, 2024
d1d5726
Rename try_open_stream and try_default_stream
PetrGlad Nov 21, 2024
c23ec2c
Update documentation
PetrGlad Nov 21, 2024
5972eeb
Update CHANGELOG.md
PetrGlad Nov 21, 2024
435222a
Merge remote-tracking branch 'rust-audio/master' into init-revamp
PetrGlad Nov 22, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Added
- Output audio stream buffer size can now be adjusted.

### Changed
- Breaking: `OutputStreamBuilder` should now be used to initialize audio output stream.
- Breaking: `OutputStreamHandle` removed, use `OutputStream` and `OutputStream::mixer()` instead.
- Breaking: `DynamicMixerController` renamed to `Mixer`, `DynamicMixer` renamed to `MixerSource`.
- Breaking: `Sink::try_new` renamed to `connect_new` and does not return error anymore.
`Sink::new_idle` was renamed to `new`.

# Version 0.20.1 (2024-11-08)

### Fixed
Expand Down
19 changes: 11 additions & 8 deletions examples/automatic_gain_control.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
use rodio::source::Source;
use rodio::Decoder;
use std::error::Error;
use std::fs::File;
use std::io::BufReader;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
use std::thread;
use std::time::Duration;

fn main() {
let (_stream, handle) = rodio::OutputStream::try_default().unwrap();
let sink = rodio::Sink::try_new(&handle).unwrap();
fn main() -> Result<(), Box<dyn Error>> {
let stream_handle = rodio::OutputStreamBuilder::open_default_stream()?;
let sink = rodio::Sink::connect_new(&stream_handle.mixer());

// Decode the sound file into a source
let file = BufReader::new(File::open("assets/music.flac").unwrap());
let source = Decoder::new(file).unwrap();
let file = BufReader::new(File::open("assets/music.flac")?);
let source = Decoder::new(file)?;

// Apply automatic gain control to the source
let agc_source = source.automatic_gain_control(1.0, 4.0, 0.005, 5.0);
Expand All @@ -24,14 +25,15 @@ fn main() {
let agc_enabled = Arc::new(AtomicBool::new(true));
let agc_enabled_clone = agc_enabled.clone();
let controlled = agc_source.periodic_access(Duration::from_millis(5), move |agc_source| {
#[cfg(not(feature = "experimental"))]
agc_source.set_enabled(agc_enabled_clone.load(Ordering::Relaxed));
});

// Add the source now equipped with automatic gain control and controlled via
// periodic_access to the sink for playback
// periodic_access to the sink for the playback.
sink.append(controlled);

// after 5 seconds of playback disable automatic gain control using the
// After 5 seconds of playback disable automatic gain control using the
// shared AtomicBool `agc_enabled`. You could do this from another part
// of the program since `agc_enabled` is of type Arc<AtomicBool> which
// is freely clone-able and move-able.
Expand All @@ -41,6 +43,7 @@ fn main() {
thread::sleep(Duration::from_secs(5));
agc_enabled.store(false, Ordering::Relaxed);

// Keep the program running until playback is complete
// Keep the program running until the playback is complete.
sink.sleep_until_end();
Ok(())
}
52 changes: 35 additions & 17 deletions examples/basic.rs
Original file line number Diff line number Diff line change
@@ -1,30 +1,46 @@
use rodio::source::SineWave;
use rodio::Source;
use std::error::Error;
use std::io::BufReader;
use std::thread;
use std::time::Duration;

fn main() {
let (_stream, stream_handle) = rodio::OutputStream::try_default().unwrap();

let file = std::fs::File::open("assets/beep.wav").unwrap();
let beep1 = stream_handle.play_once(BufReader::new(file)).unwrap();
beep1.set_volume(0.2);
#[cfg(feature = "tracing")]
use tracing;

fn main() -> Result<(), Box<dyn Error>> {
let stream_handle = rodio::OutputStreamBuilder::open_default_stream()?;
let mixer = stream_handle.mixer();

let beep1 = {
// Play a WAV file.
let file = std::fs::File::open("assets/beep.wav")?;
let sink = rodio::play(&mixer, BufReader::new(file))?;
sink.set_volume(0.2);
sink
};
println!("Started beep1");

thread::sleep(Duration::from_millis(1500));

let file = std::fs::File::open("assets/beep2.wav").unwrap();
let beep2 = stream_handle.play_once(BufReader::new(file)).unwrap();
beep2.set_volume(0.3);
beep2.detach();
{
// Generate sine wave.
let wave = SineWave::new(740.0)
.amplify(0.2)
.take_duration(Duration::from_secs(3));
mixer.add(wave);
}
println!("Started beep2");

thread::sleep(Duration::from_millis(1500));
let file = std::fs::File::open("assets/beep3.ogg").unwrap();
let beep3 = stream_handle.play_once(file).unwrap();
beep3.set_volume(0.2);
println!("Started beep3");

let beep3 = {
// Play an OGG file.
let file = std::fs::File::open("assets/beep3.ogg")?;
let sink = rodio::play(&mixer, BufReader::new(file))?;
sink.set_volume(0.2);
sink
};
println!("Started beep3");
thread::sleep(Duration::from_millis(1500));

drop(beep1);
println!("Stopped beep1");

Expand All @@ -33,4 +49,6 @@ fn main() {
println!("Stopped beep3");

thread::sleep(Duration::from_millis(1500));

Ok(())
}
35 changes: 35 additions & 0 deletions examples/custom_config.rs
dvdsk marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
use cpal::traits::HostTrait;
use cpal::{BufferSize, SampleFormat, SampleRate};
use rodio::source::SineWave;
use rodio::Source;
use std::error::Error;
use std::thread;
use std::time::Duration;

fn main() -> Result<(), Box<dyn Error>> {
// You can use any other output device that can be queried from CPAL.
let default_device = cpal::default_host()
.default_output_device()
.ok_or("No default audio output device is found.")?;
let stream_handle = rodio::OutputStreamBuilder::from_device(default_device)?
// No need to set all parameters explicitly here,
// the defaults were set from the device's description.
.with_buffer_size(BufferSize::Fixed(256))
.with_sample_rate(SampleRate(48_000))
.with_sample_format(SampleFormat::F32)
// Note that the function below still tries alternative configs if the specified one fails.
// If you need to only use the exact specified configuration,
// then use OutputStreamBuilder::open_stream() instead.
.open_stream_or_fallback()?;
let mixer = stream_handle.mixer();

let wave = SineWave::new(740.0)
.amplify(0.1)
.take_duration(Duration::from_secs(1));
mixer.add(wave);

println!("Beep...");
thread::sleep(Duration::from_millis(1500));

Ok(())
}
13 changes: 8 additions & 5 deletions examples/mix_multiple_sources.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
use rodio::mixer;
use rodio::source::{SineWave, Source};
use rodio::{dynamic_mixer, OutputStream, Sink};
use std::error::Error;
use std::time::Duration;

fn main() {
fn main() -> Result<(), Box<dyn Error>> {
// Construct a dynamic controller and mixer, stream_handle, and sink.
let (controller, mixer) = dynamic_mixer::mixer::<f32>(2, 44_100);
let (_stream, stream_handle) = OutputStream::try_default().unwrap();
let sink = Sink::try_new(&stream_handle).unwrap();
let (controller, mixer) = mixer::mixer::<f32>(2, 44_100);
let stream_handle = rodio::OutputStreamBuilder::open_default_stream()?;
let sink = rodio::Sink::connect_new(&stream_handle.mixer());

// Create four unique sources. The frequencies used here correspond
// notes in the key of C and in octave 4: C4, or middle C on a piano,
Expand Down Expand Up @@ -35,4 +36,6 @@ fn main() {

// Sleep the thread until sink is empty.
sink.sleep_until_end();

Ok(())
}
13 changes: 8 additions & 5 deletions examples/music_flac.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
use std::error::Error;
use std::io::BufReader;

fn main() {
let (_stream, handle) = rodio::OutputStream::try_default().unwrap();
let sink = rodio::Sink::try_new(&handle).unwrap();
fn main() -> Result<(), Box<dyn Error>> {
let stream_handle = rodio::OutputStreamBuilder::open_default_stream()?;
let sink = rodio::Sink::connect_new(&stream_handle.mixer());

let file = std::fs::File::open("assets/music.flac").unwrap();
sink.append(rodio::Decoder::new(BufReader::new(file)).unwrap());
let file = std::fs::File::open("assets/music.flac")?;
sink.append(rodio::Decoder::new(BufReader::new(file))?);

sink.sleep_until_end();

Ok(())
}
13 changes: 8 additions & 5 deletions examples/music_m4a.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
use std::error::Error;
use std::io::BufReader;

fn main() {
let (_stream, handle) = rodio::OutputStream::try_default().unwrap();
let sink = rodio::Sink::try_new(&handle).unwrap();
fn main() -> Result<(), Box<dyn Error>> {
let stream_handle = rodio::OutputStreamBuilder::open_default_stream()?;
let sink = rodio::Sink::connect_new(&stream_handle.mixer());

let file = std::fs::File::open("assets/music.m4a").unwrap();
sink.append(rodio::Decoder::new(BufReader::new(file)).unwrap());
let file = std::fs::File::open("assets/music.m4a")?;
sink.append(rodio::Decoder::new(BufReader::new(file))?);

sink.sleep_until_end();

Ok(())
}
13 changes: 8 additions & 5 deletions examples/music_mp3.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
use std::error::Error;
use std::io::BufReader;

fn main() {
let (_stream, handle) = rodio::OutputStream::try_default().unwrap();
let sink = rodio::Sink::try_new(&handle).unwrap();
fn main() -> Result<(), Box<dyn Error>> {
let stream_handle = rodio::OutputStreamBuilder::open_default_stream()?;
let sink = rodio::Sink::connect_new(&stream_handle.mixer());

let file = std::fs::File::open("assets/music.mp3").unwrap();
sink.append(rodio::Decoder::new(BufReader::new(file)).unwrap());
let file = std::fs::File::open("assets/music.mp3")?;
sink.append(rodio::Decoder::new(BufReader::new(file))?);

sink.sleep_until_end();

Ok(())
}
13 changes: 8 additions & 5 deletions examples/music_ogg.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
use std::error::Error;
use std::io::BufReader;

fn main() {
let (_stream, handle) = rodio::OutputStream::try_default().unwrap();
let sink = rodio::Sink::try_new(&handle).unwrap();
fn main() -> Result<(), Box<dyn Error>> {
let stream_handle = rodio::OutputStreamBuilder::open_default_stream()?;
let sink = rodio::Sink::connect_new(&stream_handle.mixer());

let file = std::fs::File::open("assets/music.ogg").unwrap();
sink.append(rodio::Decoder::new(BufReader::new(file)).unwrap());
let file = std::fs::File::open("assets/music.ogg")?;
sink.append(rodio::Decoder::new(BufReader::new(file))?);

sink.sleep_until_end();

Ok(())
}
13 changes: 8 additions & 5 deletions examples/music_wav.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
use std::error::Error;
use std::io::BufReader;

fn main() {
let (_stream, handle) = rodio::OutputStream::try_default().unwrap();
let sink = rodio::Sink::try_new(&handle).unwrap();
fn main() -> Result<(), Box<dyn Error>> {
let stream_handle = rodio::OutputStreamBuilder::open_default_stream()?;
let sink = rodio::Sink::connect_new(&stream_handle.mixer());

let file = std::fs::File::open("assets/music.wav").unwrap();
sink.append(rodio::Decoder::new(BufReader::new(file)).unwrap());
let file = std::fs::File::open("assets/music.wav")?;
sink.append(rodio::Decoder::new(BufReader::new(file))?);

sink.sleep_until_end();

Ok(())
}
32 changes: 16 additions & 16 deletions examples/noise_generator.rs
Original file line number Diff line number Diff line change
@@ -1,37 +1,37 @@
//! Noise generator example. Use the "noise" feature to enable the noise generator sources.

use std::error::Error;

#[cfg(feature = "noise")]
fn main() {
fn main() -> Result<(), Box<dyn Error>> {
use rodio::source::{pink, white, Source};
use std::thread;
use std::time::Duration;

let (_stream, stream_handle) = rodio::OutputStream::try_default().unwrap();
let stream_handle = rodio::OutputStreamBuilder::open_default_stream()?;

let noise_duration = Duration::from_millis(1000);
let interval_duration = Duration::from_millis(1500);

stream_handle
.play_raw(
white(cpal::SampleRate(48000))
.amplify(0.1)
.take_duration(noise_duration),
)
.unwrap();
stream_handle.mixer().add(
white(cpal::SampleRate(48000))
.amplify(0.1)
.take_duration(noise_duration),
);
println!("Playing white noise");

thread::sleep(interval_duration);

stream_handle
.play_raw(
pink(cpal::SampleRate(48000))
.amplify(0.1)
.take_duration(noise_duration),
)
.unwrap();
stream_handle.mixer().add(
pink(cpal::SampleRate(48000))
.amplify(0.1)
.take_duration(noise_duration),
);
println!("Playing pink noise");

thread::sleep(interval_duration);

Ok(())
}

#[cfg(not(feature = "noise"))]
Expand Down
13 changes: 8 additions & 5 deletions examples/reverb.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
use rodio::Source;
use std::error::Error;
use std::io::BufReader;
use std::time::Duration;

fn main() {
let (_stream, handle) = rodio::OutputStream::try_default().unwrap();
let sink = rodio::Sink::try_new(&handle).unwrap();
fn main() -> Result<(), Box<dyn Error>> {
let stream_handle = rodio::OutputStreamBuilder::open_default_stream()?;
let sink = rodio::Sink::connect_new(&stream_handle.mixer());

let file = std::fs::File::open("assets/music.ogg").unwrap();
let source = rodio::Decoder::new(BufReader::new(file)).unwrap();
let file = std::fs::File::open("assets/music.ogg")?;
let source = rodio::Decoder::new(BufReader::new(file))?;
let with_reverb = source.buffered().reverb(Duration::from_millis(40), 0.7);
sink.append(with_reverb);

sink.sleep_until_end();

Ok(())
}
Loading