Compare commits
No commits in common. "b381e1501fba06f0871f84c6498b6ca1466a9af0" and "f498565215b71f96128d9a2c2cb7aee800a84b64" have entirely different histories.
b381e1501f
...
f498565215
|
@ -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
|
||||||
|
|
|
@ -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()
|
||||||
},
|
},
|
|
@ -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();
|
|
||||||
}
|
|
186
src/lib.rs
186
src/lib.rs
|
@ -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),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user