Skip to content

Commit

Permalink
Unify AudioSink and AudioHandle (#21)
Browse files Browse the repository at this point in the history
  • Loading branch information
harudagondi authored Aug 29, 2022
1 parent 0a573b9 commit 5091a5f
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 55 deletions.
67 changes: 67 additions & 0 deletions examples/gain.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
use bevy::{
prelude::{App, Assets, Commands, Deref, Handle, Res, ResMut, StartupStage},
reflect::TypeUuid,
time::Time,
DefaultPlugins,
};
use bevy_oddio::{builtins::sine, output::AudioSink, Audio, AudioApp, AudioPlugin, ToSignal};
use oddio::Sample;

#[derive(TypeUuid)]
#[uuid = "54498976-f7db-4ee7-a2e6-5fee0fcadbfb"]
struct SineWithGain;

impl ToSignal for SineWithGain {
type Settings = sine::Settings;
type Signal = oddio::Gain<oddio::Sine>;

fn to_signal(&self, settings: Self::Settings) -> Self::Signal {
oddio::Gain::new(oddio::Sine::new(settings.phase, settings.frequency_hz))
}
}

fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_plugin(AudioPlugin)
.add_audio_source::<1, _, SineWithGain>()
.add_startup_system(init_assets)
.add_startup_system_to_stage(StartupStage::PostStartup, play_sine_with_gain)
.add_system(change_volume)
.run();
}

#[derive(Deref)]
struct SineWithGainHandle(Handle<SineWithGain>);

struct SineWithGainSink(Handle<AudioSink<SineWithGain>>);

fn init_assets(mut commands: Commands, mut assets: ResMut<Assets<SineWithGain>>) {
let handle = assets.add(SineWithGain);
commands.insert_resource(SineWithGainHandle(handle));
}

fn play_sine_with_gain(
mut commands: Commands,
mut audio: ResMut<Audio<Sample, SineWithGain>>,
sine_with_gain: Res<SineWithGainHandle>,
) {
let handle = audio.play(sine_with_gain.clone(), sine::Settings::new(0.0, 440.0));
commands.insert_resource(SineWithGainSink(handle));
}

fn change_volume(
sink_handle: Res<SineWithGainSink>,
mut sinks: ResMut<Assets<AudioSink<SineWithGain>>>,
time: Res<Time>,
) {
let sink = match sinks.get_mut(&sink_handle.0) {
Some(sink) => sink,
None => return,
};

let factor = (time.seconds_since_startup().sin() + 1.0) / 2.0;

sink.control::<oddio::Gain<_>, _>()
.set_amplitude_ratio(factor as f32);
}
12 changes: 4 additions & 8 deletions examples/noise.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,7 @@ use bevy::{
reflect::TypeUuid,
DefaultPlugins,
};
use bevy_oddio::{
frames::Stereo,
output::{AudioHandle, AudioSink},
Audio, AudioApp, AudioPlugin, ToSignal,
};
use bevy_oddio::{frames::Stereo, output::AudioSink, Audio, AudioApp, AudioPlugin, ToSignal};
use oddio::Signal;

#[derive(TypeUuid)]
Expand Down Expand Up @@ -49,7 +45,7 @@ fn main() {
#[derive(Deref)]
struct NoiseHandle(Handle<Noise>);

struct NoiseSink(Handle<AudioHandle<Noise>>, Handle<AudioSink<Noise>>);
struct NoiseSink(Handle<AudioSink<Noise>>);

fn init_assets(mut commands: Commands, mut assets: ResMut<Assets<Noise>>) {
let handle = assets.add(Noise);
Expand All @@ -61,6 +57,6 @@ fn play_noise(
mut audio: ResMut<Audio<Stereo, Noise>>,
noise: Res<NoiseHandle>,
) {
let handles = audio.play(noise.clone(), ());
commands.insert_resource(NoiseSink(handles.0, handles.1));
let handle = audio.play(noise.clone(), ());
commands.insert_resource(NoiseSink(handle));
}
8 changes: 4 additions & 4 deletions examples/sine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use bevy::{
};
use bevy_oddio::{
builtins::sine::{self, Sine},
output::{AudioHandle, AudioSink},
output::AudioSink,
Audio, AudioPlugin,
};
use oddio::Sample;
Expand All @@ -21,7 +21,7 @@ fn main() {
#[derive(Deref)]
struct SineHandle(Handle<Sine>);

struct SineSink(Handle<AudioHandle<Sine>>, Handle<AudioSink<Sine>>);
struct SineSink(Handle<AudioSink<Sine>>);

fn init_assets(mut commands: Commands, mut assets: ResMut<Assets<Sine>>) {
let handle = assets.add(Sine);
Expand All @@ -34,6 +34,6 @@ fn play_sine(
noise: Res<SineHandle>,
) {
// Note is in A4.
let handles = audio.play(noise.clone(), sine::Settings::new(0.0, 440.0));
commands.insert_resource(SineSink(handles.0, handles.1));
let handle = audio.play(noise.clone(), sine::Settings::new(0.0, 440.0));
commands.insert_resource(SineSink(handle));
}
17 changes: 3 additions & 14 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use frames::{FromFrame, Mono, Stereo};
use oddio::{Frame, Frames, FramesSignal, Sample, Signal};

pub use oddio;
use output::{play_queued_audio, AudioHandle, AudioHandles, AudioOutput, AudioSink, AudioSinks};
use output::{play_queued_audio, AudioOutput, AudioSink, AudioSinks};
use parking_lot::RwLock;

/// [`oddio`] builtin types that can be directly used in [`Audio::play`].
Expand All @@ -41,7 +41,6 @@ where
{
source_handle: BevyHandle<Source>,
stop_handle: HandleId,
audio_handle: HandleId,
settings: Source::Settings,
}

Expand All @@ -67,23 +66,15 @@ where
&mut self,
source_handle: BevyHandle<Source>,
settings: Source::Settings,
) -> (
BevyHandle<AudioHandle<Source>>,
BevyHandle<AudioSink<Source>>,
) {
) -> BevyHandle<AudioSink<Source>> {
let stop_handle = HandleId::random::<AudioSink<Source>>();
let audio_handle = HandleId::random::<AudioHandle<Source>>();
let audio_to_play = AudioToPlay {
source_handle,
stop_handle,
audio_handle,
settings,
};
self.queue.write().push_back(audio_to_play);
(
BevyHandle::<AudioHandle<Source>>::weak(audio_handle),
BevyHandle::<AudioSink<Source>>::weak(stop_handle),
)
BevyHandle::<AudioSink<Source>>::weak(stop_handle)
}
}

Expand Down Expand Up @@ -178,10 +169,8 @@ impl AudioApp for App {
{
self.add_asset::<Source>()
.add_asset::<AudioSink<Source>>()
.add_asset::<AudioHandle<Source>>()
.init_resource::<Audio<F, Source>>()
.init_resource::<AudioSinks<Source>>()
.init_resource::<AudioHandles<Source>>()
.add_system_to_stage(CoreStage::PostUpdate, play_queued_audio::<N, F, Source>)
}
}
Expand Down
32 changes: 3 additions & 29 deletions src/output.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ pub struct AudioOutput<const N: usize, F: Frame + FromFrame<[Sample; N]>> {
}

impl<const N: usize, F: Frame + FromFrame<[Sample; N]> + 'static> AudioOutput<N, F> {
fn play<S>(&mut self, signal: SplitSignal<S::Signal>) -> AudioSink<S>
fn play<S>(&mut self, signal: S::Signal) -> AudioSink<S>
where
S: ToSignal + Asset,
S::Signal: Signal<Frame = F> + Send,
Expand Down Expand Up @@ -103,8 +103,6 @@ pub fn play_queued_audio<const N: usize, F, Source>(
sources: Res<Assets<Source>>,
mut sink_assets: ResMut<Assets<AudioSink<Source>>>,
mut sinks: ResMut<AudioSinks<Source>>,
mut handle_assets: ResMut<Assets<AudioHandle<Source>>>,
mut handles: ResMut<AudioHandles<Source>>,
) where
Source: ToSignal + Asset + Send,
Source::Signal: Signal<Frame = F> + Send,
Expand All @@ -116,15 +114,10 @@ pub fn play_queued_audio<const N: usize, F, Source>(
while i < len {
let config = queue.pop_front().unwrap(); // This should not panic
if let Some(audio_source) = sources.get(&config.source_handle) {
let (handle, split) = oddio::split(audio_source.to_signal(config.settings));
let sink = audio_output.play::<Source>(split);
let sink = audio_output.play::<Source>(audio_source.to_signal(config.settings));
// Unlike bevy_audio, we should not drop this
let sink_handle = sink_assets.set(config.stop_handle, sink);
sinks.insert(sink_handle.id, sink_handle.clone());

let audio_handle = AudioHandle(ManuallyDrop::new(handle));
let signal_handle = handle_assets.set(config.audio_handle, audio_handle);
handles.insert(signal_handle.id, signal_handle.clone());
} else {
queue.push_back(config);
}
Expand All @@ -136,34 +129,15 @@ pub fn play_queued_audio<const N: usize, F, Source>(
#[derive(TypeUuid, Deref, DerefMut)]
#[uuid = "82317ee9-8f2d-4973-bb7f-8f4a5b74cc55"]
pub struct AudioSink<Source: ToSignal + Asset>(
ManuallyDrop<OddioHandle<Stop<SplitSignal<<Source as ToSignal>::Signal>>>>,
ManuallyDrop<OddioHandle<Stop<<Source as ToSignal>::Signal>>>,
);

/// Storage of all audio sinks.
#[derive(Deref, DerefMut)]
pub struct AudioSinks<Source: ToSignal + Asset>(HashMap<HandleId, BevyHandle<AudioSink<Source>>>);

/// [`oddio::Handle`] asset for a given signal.
#[derive(TypeUuid, Deref, DerefMut)]
#[uuid = "18b98538-c486-4355-8712-cbfc558a4994"]
pub struct AudioHandle<Source: ToSignal + Asset>(
ManuallyDrop<OddioHandle<<Source as ToSignal>::Signal>>,
);

/// Storage of all audio handles.
#[derive(Deref, DerefMut)]
pub struct AudioHandles<Source: ToSignal + Asset>(
HashMap<HandleId, BevyHandle<AudioHandle<Source>>>,
);

impl<Source: ToSignal + Asset> Default for AudioSinks<Source> {
fn default() -> Self {
Self(HashMap::default())
}
}

impl<Source: ToSignal + Asset> Default for AudioHandles<Source> {
fn default() -> Self {
Self(HashMap::default())
}
}

0 comments on commit 5091a5f

Please sign in to comment.