Minimize static set of audio entiites

main
Elijah Voigt 3 hours ago
parent 209e5f60c0
commit 61084e2251

@ -1,9 +1,11 @@
// TODO:
// * Lock down system scheduling/run_if conditions
// * Performance: have a limit on per-note+octave sounds
// * Use a finite set of N audio entities and scale volume instead of
// spawning a bunch of audio entities which is causing issues at >100
// cells
// * Volume slider
// * Invert mute/unmute icons
// * Only move camera when cells move out of view
// * Stop creating cells when I didn't mean to (clicking UI, click + dragging)
// * Keep some controls open when main ui panel is closed
// * Exclude power button from web build
@ -52,6 +54,7 @@ fn main() {
load_audio_tones,
load_materials,
load_meshes,
spawn_audio_players.after(load_audio_tones),
),
)
.configure_sets(
@ -106,14 +109,8 @@ fn main() {
.add_systems(
Update,
(
control_volume,
control_audio_players.in_set(GameSet::React),
update_pitch_map_resource_ui.run_if(resource_changed::<PitchMap>),
update_audio
.run_if(
any_component_added::<CellPitch>
.or_else(any_component_changed::<CellPitch>),
)
.in_set(GameSet::React),
),
)
// Debugging
@ -125,8 +122,7 @@ fn main() {
(
assert_cell_uniqueness
.run_if(any_with_component::<Cell>)
.after(update_material)
.after(update_audio),
.after(update_material),
update_debug_info_cell_count,
update_debug_info_active,
)
@ -928,7 +924,6 @@ fn new_cell(
template_value(playback_settings)
template_value(Transform::from_translation(c.as_translation() + Vec3::new(0.0, 0.0, 1.0)))
template_value(Mesh2dTemplate(cell_assets.mesh.clone().into()))
// AudioPlayer added by update_audio
// MeshMaterial2d added by update_material
template_value(MeshMaterial2dTemplate(cell_assets.materials.get(&cell_pitch).unwrap().clone().into()))
}
@ -1121,32 +1116,6 @@ fn load_audio_tones(mut pitches: ResMut<Assets<Pitch>>, mut cell_assets: ResMut<
debug_assert_eq!(cell_assets.pitches.iter().len(), 132);
}
fn control_volume(
audio_state: Res<State<AudioPlayback>>,
simulation_state: Res<State<SimulationPlayback>>,
mut sinks: Query<&mut AudioSink>,
) {
match audio_state.get() {
AudioPlayback::Play => match simulation_state.get() {
SimulationPlayback::Run => {
let ratio = 1.0 / sinks.count() as f32;
let volume = Volume::Linear(ratio);
sinks.par_iter_mut().for_each(|mut sink| {
sink.set_volume(volume);
})
}
SimulationPlayback::Pause | SimulationPlayback::Step => {
sinks.par_iter_mut().for_each(|mut sink| {
sink.mute();
})
}
},
AudioPlayback::Mute => sinks.par_iter_mut().for_each(|mut sink| {
sink.mute();
}),
}
}
fn load_materials(
server: ResMut<AssetServer>,
mut cell_assets: ResMut<CellAssets>,
@ -1332,18 +1301,6 @@ fn update_material(
})
}
// When CellPitch is added/updated on a cell, update the Pitch
fn update_audio(
mut query: Query<(&CellPitch, Entity), Or<(Added<CellPitch>, Changed<CellPitch>)>>,
cell_assets: ResMut<CellAssets>,
mut commands: Commands,
) {
query.iter_mut().for_each(|(cell_pitch, e)| {
let h = cell_assets.pitches.get(cell_pitch).unwrap().clone();
commands.entity(e).insert(AudioPlayer(h));
});
}
fn update_debug_info_cell_count(query: Query<&Cell>, mut text: Query<(&DebugInfo, &mut Text)>) {
text.iter_mut()
.filter(|(di, _)| **di == DebugInfo::CellCount)
@ -1452,3 +1409,70 @@ fn update_camera_position(mut query: Query<(&Coordinates, &mut Transform), With<
t.translation = c.as_translation();
});
}
// Ordering: first, once, after(load_audio_tones)
fn spawn_audio_players(mut commands: Commands, cell_assets: Res<CellAssets>) {
CellPitch::iter_all().for_each(|cp| {
let h = cell_assets.pitches.get(&cp).unwrap().clone();
commands.spawn((AudioPlayer(h), cp, PlaybackSettings::default().with_volume(Volume::Linear(0.0))));
});
}
// Ordering: React
fn control_audio_players(
audio_state: Res<State<AudioPlayback>>,
simulation_state: Res<State<SimulationPlayback>>,
mut players: Query<(&mut AudioSink, &CellPitch)>,
cells: Query<&CellPitch, With<Cell>>,
) {
match audio_state.get() {
AudioPlayback::Play => {
match simulation_state.get() {
SimulationPlayback::Run => {
let mut s: HashMap<CellPitch, usize> = HashMap::new();
cells.iter().for_each(|cp| {
let this = s.entry(cp.clone()).or_insert(0);
*this += 1;
});
let total: usize = s.values().sum();
players.iter_mut().for_each(|(mut sink, cp)| {
match s.get(cp) {
Some(v) => {
let new_volume: f32 = (*v as f64 / total as f64) as f32;
debug!("Setting volume for {:?} to {:?}", cp, new_volume);
if sink.is_paused() {
sink.play();
}
sink.set_volume(Volume::Linear(new_volume));
},
None => {
sink.pause();
sink.set_volume(Volume::Linear(0.0));
}
}
});
// create distribution of cell pitches
// then go back and adjust volume based on % with this CellPitch
// if volume is 0, pause
// if volume > 0, play
},
// If the sim is paused or stepping, mute an dpause audios
_ => {
players.iter_mut().for_each(|(mut sink, _)| {
sink.pause();
sink.set_volume(Volume::Linear(0.0));
});
}
}
}
AudioPlayback::Mute => {
players.iter_mut().for_each(|(mut sink, _)| {
sink.pause();
sink.set_volume(Volume::Linear(0.0));
});
},
}
}

Loading…
Cancel
Save