Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Spatial Audio Functional Regression - different spatial scaling factor for each object #10414

Closed
johnny-smitherson opened this issue Nov 6, 2023 · 4 comments · Fixed by #10419
Labels
A-Audio Sounds playback and modification C-Feature A new feature, making something new possible D-Trivial Nice and easy! A great choice to get started with Bevy P-Regression Functionality that used to work but no longer does. Add a test for this!

Comments

@johnny-smitherson
Copy link

johnny-smitherson commented Nov 6, 2023

What problem does this solve or what need does it fill?

I want to scale spatial audio differently for each effect. This is so I can have some "far away" effects (low volume, low distance scaling) mixed together with some "close up" effects (high volume, high distance scaling).

For example, explosions - when they happen far away, https://freesound.org/people/rhapsodize/sounds/255111/

When they happen close up, https://freesound.org/people/juskiddink/sounds/108641/

Both effects need to live at the same time with different spatial scales, because the camera can quickly move closer/further away from the audio source.

I would also want this to work on multiple listeners at the same time: one main camera for 80% volume, and a few extra cameras for 20% volume each.

This was trivial under Bevy 0.11 (in the old update positions system), but now is impossible with bevy_audio 0.12:

https://bevyengine.org/learn/migration-guides/0.11-0.12/#more-ergonomic-spatial-audio
If you were manually scaling emitter/listener positions, you can use the spatial_scale field of AudioPlugin instead.

But the AudioPlugin is a global, so all objects must share the same spatial scale.

What solution would you like?

Extra field spatial scale for each Spatial Audio Source

What alternative(s) have you considered?

  • in a system, manually change the RelativeVolume component based on distance and some formula
    • problem: doesn't work with multiple listeners, because the volume is set per-effect not per-listener
  • swap out bevy_audio for one of the external plugins
@johnny-smitherson johnny-smitherson added C-Feature A new feature, making something new possible S-Needs-Triage This issue needs to be labelled labels Nov 6, 2023
@johnny-smitherson johnny-smitherson changed the title Spatial Audio Functional Regression - different scaling factor for each object Spatial Audio Functional Regression - different spatial scaling factor for each object Nov 6, 2023
@rparrett
Copy link
Contributor

rparrett commented Nov 6, 2023

"Spatial Scale" in Bevy 0.11 was also "global" -- it affects the position of the ears as well. At least how it was implemented in the examples.

I think another potential workaround would be adding a system that multiplies your emitter GlobalTransform translations after TransformSystem::TransformPropagate but before AudioPlaySet. If that works for you, I'm not sure if this needs to be treated as a regression.

Affecting a particular audio source's distance attenuation seems useful. I'd like to see examples of how other game engine audio APIs work for this use-case. Would a minimum and maximum attenuation distance be more useful? I'm not sure how much fancier we could get without ditching rodio. Your suggestion sounds reasonable enough to me though.

@rparrett rparrett added A-Audio Sounds playback and modification and removed S-Needs-Triage This issue needs to be labelled labels Nov 6, 2023
@alice-i-cecile alice-i-cecile added D-Trivial Nice and easy! A great choice to get started with Bevy P-Regression Functionality that used to work but no longer does. Add a test for this! labels Nov 6, 2023
@rparrett
Copy link
Contributor

rparrett commented Nov 6, 2023

Godot has the following on its emitters:

  • Attentuation model
  • Max distance
  • "Unit Size" (scale)

And no configuration for the listener, only position. There can only be one active listener.

@johnny-smitherson
Copy link
Author

johnny-smitherson commented Nov 6, 2023

"Spatial Scale" in Bevy 0.11 was also "global" -- it affects the position of the ears as well. At least how it was implemented in the examples.

Yes, what I did was scale the sink around the listener:

fn update_spatial_audio_locations(
    emitter_query: Query<(&GlobalTransform, &SpatialAudioSink, &SpatialAudioEffect)>,
    listener_query: Query<&GlobalTransform, With<SpatialAudioListener>>,
) {
    let Ok(listener) = listener_query.get_single() else {
        return;
    };
    let listener = listener.compute_transform();

    for (emitter, sink, effect_info) in &emitter_query {
        let emitter = emitter.compute_transform().translation;
        let emitter =
            listener.translation + (emitter - listener.translation) * effect_info.scale_range;
        sink.set_emitter_position(emitter);
        // don't touch the listener: sink.set_listener_position(listener, SPATIAL_AUDIO_EAR_GAP);
    }
}

I think another potential workaround would be adding a system that multiplies your emitter GlobalTransform translations after TransformSystem::TransformPropagate but before AudioPlaySet

I'll take a look, thanks!


I'd like to see examples of how other game engine audio APIs work for this use-case.

Godot

Unity

Unreal


I guess there are 2 separate discussions:

  • different spatial audio settings for each emitter object
  • meaningful support for multiple simultaneous listeners with different spatial settings and positions (like Godot Audio Busses) - should open a different feature request for this one

@rparrett
Copy link
Contributor

rparrett commented Nov 6, 2023

  • different spatial audio settings for each emitter object
    meaningful support for multiple simultaneous listeners with different spatial settings and positions (like Godot Audio Busses)
  • should open a different feature request for this one

Agreed, thanks for doing that roundup. (and for the excellent issue writeup). On the first bullet point, I know that scale is obviously feasible but I'm guessing that other attenuation options might not be doable with rodio.

Just need to determine whether or not there's an acceptable workaround now.

github-merge-queue bot pushed a commit that referenced this issue Jan 25, 2024
# Objective

Fixes #10414.

That issue and its comments do a great job of laying out the case for
this.

## Solution

Added an optional `spatial_scale` field to `PlaybackSettings`, which
overrides the default value set on `AudioPlugin`.

## Changelog

- `AudioPlugin::spatial_scale` has been renamed to
`default_spatial_scale`.
- `SpatialScale` is no longer a resource and is wrapped by
`DefaultSpatialScale`.
- Added an optional `spatial_scale` to `PlaybackSettings`.

## Migration Guide

`AudioPlugin::spatial_scale` has been renamed to `default_spatial_scale`
and the default spatial scale can now be overridden on individual audio
sources with `PlaybackSettings::spatial_scale`.

If you were modifying or reading `SpatialScale` at run time, use
`DefaultSpatialScale` instead.

```rust
// before
app.add_plugins(DefaultPlugins.set(AudioPlugin {
    spatial_scale: SpatialScale::new(AUDIO_SCALE),
    ..default()
}));

// after
app.add_plugins(DefaultPlugins.set(AudioPlugin {
    default_spatial_scale: SpatialScale::new(AUDIO_SCALE),
    ..default()
}));
```
tjamaan pushed a commit to tjamaan/bevy that referenced this issue Feb 6, 2024
# Objective

Fixes bevyengine#10414.

That issue and its comments do a great job of laying out the case for
this.

## Solution

Added an optional `spatial_scale` field to `PlaybackSettings`, which
overrides the default value set on `AudioPlugin`.

## Changelog

- `AudioPlugin::spatial_scale` has been renamed to
`default_spatial_scale`.
- `SpatialScale` is no longer a resource and is wrapped by
`DefaultSpatialScale`.
- Added an optional `spatial_scale` to `PlaybackSettings`.

## Migration Guide

`AudioPlugin::spatial_scale` has been renamed to `default_spatial_scale`
and the default spatial scale can now be overridden on individual audio
sources with `PlaybackSettings::spatial_scale`.

If you were modifying or reading `SpatialScale` at run time, use
`DefaultSpatialScale` instead.

```rust
// before
app.add_plugins(DefaultPlugins.set(AudioPlugin {
    spatial_scale: SpatialScale::new(AUDIO_SCALE),
    ..default()
}));

// after
app.add_plugins(DefaultPlugins.set(AudioPlugin {
    default_spatial_scale: SpatialScale::new(AUDIO_SCALE),
    ..default()
}));
```
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-Audio Sounds playback and modification C-Feature A new feature, making something new possible D-Trivial Nice and easy! A great choice to get started with Bevy P-Regression Functionality that used to work but no longer does. Add a test for this!
Projects
Status: No status
Development

Successfully merging a pull request may close this issue.

3 participants