Compare commits

..

No commits in common. "b381e1501fba06f0871f84c6498b6ca1466a9af0" and "f498565215b71f96128d9a2c2cb7aee800a84b64" have entirely different histories.

4 changed files with 80 additions and 171 deletions

View File

@ -11,11 +11,11 @@ repository = "https://labs.lightsout.games/projects/bevy_synthizer"
[dependencies] [dependencies]
anyhow = "1" anyhow = "1"
bevy = { version = "0.10", default-features = false, features = ["bevy_asset"] } bevy = { version = "0.9", default-features = false, features = ["bevy_asset"] }
synthizer = "0.5.6" synthizer = "0.5"
[dev-dependencies] [dev-dependencies]
bevy = { version = "0.10", default-features = true } bevy = { version = "0.9", default-features = true }
[package.metadata.release] [package.metadata.release]
publish = false publish = false

View File

@ -31,7 +31,7 @@ fn load_and_create(
return; return;
} }
handles.loaded = asset_server handles.loaded = asset_server
.get_group_load_state(handles.sounds.iter().map(|handle| handle.id())) .get_group_load_state(handles.sounds.iter().map(|handle| handle.id))
== LoadState::Loaded; == LoadState::Loaded;
if handles.loaded { if handles.loaded {
commands.spawn(( commands.spawn((
@ -45,7 +45,7 @@ fn load_and_create(
TransformBundle::from(Transform::from_translation(Vec3::new(10., 0., 0.))), TransformBundle::from(Transform::from_translation(Vec3::new(10., 0., 0.))),
Source::default(), Source::default(),
Sound { Sound {
audio: buffer.into(), buffer,
looping: true, looping: true,
..default() ..default()
}, },

View File

@ -1,55 +0,0 @@
use std::f32;
use bevy::prelude::*;
use bevy_synthizer::*;
#[derive(Component, Deref, DerefMut)]
struct RotationTimer(Timer);
impl Default for RotationTimer {
fn default() -> Self {
Self(Timer::from_seconds(30., TimerMode::Repeating))
}
}
fn setup(mut commands: Commands, context: Res<Context>) {
commands.spawn((
TransformBundle::default(),
Listener,
RotationTimer::default(),
));
let generator: syz::Generator = syz::FastSineBankGenerator::new_sine(&context, 440.)
.expect("Failed to create generator")
.into();
commands.spawn((
TransformBundle::from(Transform::from_translation(Vec3::new(10., 0., 0.))),
Source::default(),
Sound {
audio: generator.into(),
looping: true,
..default()
},
));
}
fn rotate_listener(time: Res<Time>, mut query: Query<(&mut RotationTimer, &mut Transform)>) {
for (mut timer, mut transform) in query.iter_mut() {
timer.tick(time.delta());
let angle = f32::consts::PI * 2. * timer.percent();
transform.rotation = Quat::from_rotation_z(angle);
}
}
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_plugin(SynthizerPlugin {
default_panner_strategy: Some(bevy_synthizer::syz::PannerStrategy::Hrtf),
default_distance_model: Some(bevy_synthizer::syz::DistanceModel::Inverse),
..default()
})
.add_system(bevy::window::close_on_esc)
.add_startup_system(setup)
.add_system(rotate_listener)
.run();
}

View File

@ -122,45 +122,23 @@ impl ScalarPan {
} }
} }
#[derive(Component, Clone, Debug, PartialEq, Eq)] #[derive(Component, Clone, Debug, Reflect)]
pub enum Audio { #[reflect(Component)]
Buffer(Handle<Buffer>),
Generator(syz::Generator),
}
impl Default for Audio {
fn default() -> Self {
Self::Buffer(default())
}
}
impl From<Handle<Buffer>> for Audio {
fn from(value: Handle<Buffer>) -> Self {
Audio::Buffer(value)
}
}
impl From<syz::Generator> for Audio {
fn from(value: syz::Generator) -> Self {
Self::Generator(value)
}
}
#[derive(Component, Clone, Debug)]
pub struct Sound { pub struct Sound {
pub audio: Audio, pub buffer: Handle<Buffer>,
pub gain: f64, pub gain: f64,
pub pitch: f64, pub pitch: f64,
pub looping: bool, pub looping: bool,
pub paused: bool, pub paused: bool,
pub restart: bool, pub restart: bool,
#[reflect(ignore)]
pub generator: Option<syz::Generator>, pub generator: Option<syz::Generator>,
} }
impl Default for Sound { impl Default for Sound {
fn default() -> Self { fn default() -> Self {
Self { Self {
audio: default(), buffer: default(),
gain: 1., gain: 1.,
pitch: 1., pitch: 1.,
looping: false, looping: false,
@ -273,52 +251,42 @@ fn add_generator(
) { ) {
for (entity, parent, mut sound) in &mut query { for (entity, parent, mut sound) in &mut query {
if sound.generator.is_none() { if sound.generator.is_none() {
let mut source = if let Ok(s) = sources.get_mut(entity) { if let Some(b) = buffers.get(&sound.buffer) {
Some(s) let mut source = if let Ok(s) = sources.get_mut(entity) {
} else if let Some(parent) = parent { Some(s)
let mut parent: Option<&Parent> = Some(parent); } else if let Some(parent) = parent {
let mut target = None; let mut parent: Option<&Parent> = Some(parent);
while let Some(p) = parent { let mut target = None;
if sources.get(**p).is_ok() { while let Some(p) = parent {
target = Some(**p); if sources.get(**p).is_ok() {
break; target = Some(**p);
} break;
parent = parents.get(**p).ok();
}
target.map(|v| sources.get_mut(v).unwrap())
} else {
None
};
if let Some(source) = source.as_mut() {
if let Some(handle) = source.handle.as_mut() {
let generator: Option<syz::Generator> = match &sound.audio {
Audio::Buffer(buffer) => {
if let Some(b) = buffers.get(buffer) {
let generator = syz::BufferGenerator::new(&context)
.expect("Failed to create generator");
generator.buffer().set(&**b).expect("Unable to set buffer");
Some(generator.into())
} else {
None
}
} }
Audio::Generator(generator) => Some(generator.clone()), parent = parents.get(**p).ok();
}; }
if let Some(generator) = generator { target.map(|v| sources.get_mut(v).unwrap())
} else {
None
};
if let Some(source) = source.as_mut() {
if let Some(handle) = source.handle.as_mut() {
let generator = syz::BufferGenerator::new(&context)
.expect("Failed to create generator");
generator.buffer().set(&**b).expect("Unable to set buffer");
assert!(sound.gain >= 0.); assert!(sound.gain >= 0.);
assert!(sound.pitch > 0. && sound.pitch <= 2.);
generator generator
.gain() .gain()
.set(sound.gain) .set(sound.gain)
.expect("Failed to set gain"); .expect("Failed to set gain");
assert!(sound.pitch > 0. && sound.pitch <= 2.);
generator generator
.pitch_bend() .pitch_bend()
.set(sound.pitch) .set(sound.pitch)
.expect("Failed to set pitch"); .expect("Failed to set pitch");
handle handle
.add_generator(generator.handle()) .add_generator(&generator)
.expect("Unable to add generator"); .expect("Unable to add generator");
sound.generator = Some(generator); sound.generator = Some(generator.into());
} }
} }
} }
@ -348,25 +316,25 @@ fn add_sound_without_source(
} }
#[derive(Resource, Default, Deref, DerefMut)] #[derive(Resource, Default, Deref, DerefMut)]
struct LastAudio(HashMap<Entity, Audio>); struct LastBuffer(HashMap<Entity, Handle<Buffer>>);
fn swap_buffers( fn swap_buffers(
mut last_audio: ResMut<LastAudio>, mut last_buffer: ResMut<LastBuffer>,
mut query: Query<(Entity, &mut Sound), Changed<Sound>>, mut query: Query<(Entity, &mut Sound), Changed<Sound>>,
) { ) {
for (entity, mut sound) in &mut query { for (entity, mut sound) in &mut query {
if let Some(l) = last_audio.get(&entity) { if let Some(l) = last_buffer.get(&entity) {
if sound.audio != *l { if sound.buffer != *l {
sound.generator = None; sound.generator = None;
} }
} }
last_audio.insert(entity, sound.audio.clone()); last_buffer.insert(entity, sound.buffer.clone());
} }
} }
fn change_panner_strategy( fn change_panner_strategy(
changed: Query<(Entity, Ref<PannerStrategy>)>, changed: Query<(Entity, ChangeTrackers<PannerStrategy>)>,
mut removed: RemovedComponents<PannerStrategy>, removed: RemovedComponents<PannerStrategy>,
mut sources: Query<&mut Source>, mut sources: Query<&mut Source>,
) { ) {
let mut check = vec![]; let mut check = vec![];
@ -589,7 +557,7 @@ fn update_sound_playback_state(query: Query<&Sound>) {
} }
} }
fn remove_sound(mut last_buffer: ResMut<LastAudio>, mut removed: RemovedComponents<Source>) { fn remove_sound(mut last_buffer: ResMut<LastBuffer>, removed: RemovedComponents<Source>) {
for entity in removed.iter() { for entity in removed.iter() {
last_buffer.remove(&entity); last_buffer.remove(&entity);
} }
@ -691,7 +659,7 @@ fn events(
}); });
} }
#[derive(SystemSet, Clone, Hash, Debug, PartialEq, Eq)] #[derive(SystemLabel, Clone, Hash, Debug, PartialEq, Eq)]
pub enum SynthizerSystems { pub enum SynthizerSystems {
UpdateHandles, UpdateHandles,
UpdateProperties, UpdateProperties,
@ -750,76 +718,72 @@ impl Plugin for SynthizerPlugin {
.register_type::<AngularPan>() .register_type::<AngularPan>()
.register_type::<ScalarPan>() .register_type::<ScalarPan>()
.register_type::<Source>() .register_type::<Source>()
.register_type::<Sound>()
.register_type::<Listener>() .register_type::<Listener>()
.insert_resource(guard) .insert_resource(guard)
.insert_resource(context) .insert_resource(context)
.init_resource::<LastAudio>() .init_resource::<LastBuffer>()
.insert_resource(defaults) .insert_resource(defaults)
.add_event::<SynthizerEvent>() .add_event::<SynthizerEvent>()
.add_system(sync_config.in_base_set(CoreSet::PreUpdate)) .add_system_to_stage(CoreStage::PreUpdate, sync_config)
.add_system( .add_system_to_stage(
swap_buffers CoreStage::PostUpdate,
.in_base_set(CoreSet::PostUpdate) swap_buffers.before(SynthizerSystems::UpdateHandles),
.before(SynthizerSystems::UpdateHandles),
) )
.add_system( .add_system_to_stage(
change_panner_strategy CoreStage::PostUpdate,
.in_base_set(CoreSet::PostUpdate) change_panner_strategy.before(SynthizerSystems::UpdateHandles),
.before(SynthizerSystems::UpdateHandles),
) )
.add_system( .add_system_to_stage(
CoreStage::PostUpdate,
add_source_handle add_source_handle
.in_base_set(CoreSet::PostUpdate) .label(SynthizerSystems::UpdateHandles)
.in_set(SynthizerSystems::UpdateHandles)
.before(SynthizerSystems::UpdateProperties), .before(SynthizerSystems::UpdateProperties),
) )
.add_system( .add_system_to_stage(
CoreStage::PostUpdate,
add_generator add_generator
.in_base_set(CoreSet::PostUpdate) .label(SynthizerSystems::UpdateHandles)
.in_set(SynthizerSystems::UpdateHandles)
.before(SynthizerSystems::UpdateProperties), .before(SynthizerSystems::UpdateProperties),
) )
.add_system( .add_system_to_stage(
CoreStage::PostUpdate,
add_sound_without_source add_sound_without_source
.in_base_set(CoreSet::PostUpdate) .label(SynthizerSystems::UpdateHandles)
.in_set(SynthizerSystems::UpdateHandles)
.before(SynthizerSystems::UpdateProperties), .before(SynthizerSystems::UpdateProperties),
) )
.add_system( .add_system_to_stage(
CoreStage::PostUpdate,
update_listener update_listener
.in_base_set(CoreSet::PostUpdate) .label(SynthizerSystems::UpdateProperties)
.in_set(SynthizerSystems::UpdateProperties)
.after(TransformSystem::TransformPropagate) .after(TransformSystem::TransformPropagate)
.before(SynthizerSystems::UpdateState), .before(SynthizerSystems::UpdateState),
) )
.add_system( .add_system_to_stage(
CoreStage::PostUpdate,
update_source_properties update_source_properties
.in_base_set(CoreSet::PostUpdate) .label(SynthizerSystems::UpdateProperties)
.in_set(SynthizerSystems::UpdateProperties)
.after(TransformSystem::TransformPropagate) .after(TransformSystem::TransformPropagate)
.before(SynthizerSystems::UpdateState), .before(SynthizerSystems::UpdateState),
) )
.add_system( .add_system_to_stage(
CoreStage::PostUpdate,
update_sound_properties update_sound_properties
.in_base_set(CoreSet::PostUpdate) .label(SynthizerSystems::UpdateProperties)
.in_set(SynthizerSystems::UpdateProperties)
.before(SynthizerSystems::UpdateState), .before(SynthizerSystems::UpdateState),
) )
.add_system( .add_system_to_stage(
update_source_playback_state CoreStage::PostUpdate,
.in_base_set(CoreSet::PostUpdate) update_source_playback_state.label(SynthizerSystems::UpdateState),
.in_set(SynthizerSystems::UpdateState),
) )
.add_system( .add_system_to_stage(
update_sound_playback_state CoreStage::PostUpdate,
.in_base_set(CoreSet::PostUpdate) update_sound_playback_state.label(SynthizerSystems::UpdateState),
.in_set(SynthizerSystems::UpdateState),
) )
.add_system(remove_sound.in_base_set(CoreSet::PostUpdate)) .add_system_to_stage(CoreStage::PostUpdate, remove_sound)
.add_system( .add_system_to_stage(
events CoreStage::PostUpdate,
.in_base_set(CoreSet::PostUpdate) events.after(SynthizerSystems::UpdateState),
.after(SynthizerSystems::UpdateState),
); );
} }
} }