use {
bevy::{
prelude::{
App, Assets, Commands, Deref, Handle, PostStartup, Res, ResMut, Resource, Startup,
Update,
},
reflect::{TypePath, TypeUuid},
time::Time,
DefaultPlugins,
},
bevy_oddio::{builtins::sine, output::AudioSink, Audio, AudioApp, AudioPlugin, ToSignal},
oddio::Sample,
};
#[derive(TypeUuid, TypePath)]
#[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_plugins(AudioPlugin::new())
.add_audio_source::<_, SineWithGain>()
.add_systems(Startup, init_assets)
.add_systems(PostStartup, play_sine_with_gain)
.add_systems(Update, change_volume)
.run();
}
#[derive(Resource, Deref)]
struct SineWithGainHandle(Handle<SineWithGain>);
#[derive(Resource)]
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 Some(sink) = sinks.get_mut(&sink_handle.0) else {
return;
};
let factor = (time.elapsed_seconds_wrapped().sin() + 1.0) / 2.0;
sink.control::<oddio::Gain<_>, _>()
.set_amplitude_ratio(factor);
}