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

More ergonomic spatial audio #9800

Merged
merged 17 commits into from Oct 9, 2023
Merged

Conversation

rparrett
Copy link
Contributor

@rparrett rparrett commented Sep 13, 2023

Objective

Spatial audio was heroically thrown together at the last minute for Bevy 0.10, but right now it's a bit of a pain to use -- users need to manually update audio sinks with the position of the listener / emitter.

Hopefully the migration guide entry speaks for itself.

Solution

Add a new SpatialListener component and automatically update sinks with the position of the listener and and emitter.

Changelog

SpatialAudioSinks are now automatically updated with positions of emitters and listeners.

Migration Guide

Spatial audio now automatically uses the transform of the AudioBundle and of an entity with a SpatialListener component.

If you were manually scaling emitter/listener positions, you can use the spatial_scale field of AudioPlugin instead.

// Old

commands.spawn(
    SpatialAudioBundle {
        source: asset_server.load("sounds/Windless Slopes.ogg"),
        settings: PlaybackSettings::LOOP,
        spatial: SpatialSettings::new(listener_position, gap, emitter_position),
    },
);

fn update(
    emitter_query: Query<(&Transform, &SpatialAudioSink)>,
    listener_query: Query<&Transform, With<Listener>>,
) {
    let listener = listener_query.single();

    for (transform, sink) in &emitter_query {
        sink.set_emitter_position(transform.translation);
        sink.set_listener_position(*listener, gap);
    }
}

// New

commands.spawn((
    SpatialBundle::from_transform(Transform::from_translation(emitter_position)),
    AudioBundle {
        source: asset_server.load("sounds/Windless Slopes.ogg"),
        settings: PlaybackSettings::LOOP.with_spatial(true),
    },
));

commands.spawn((
    SpatialBundle::from_transform(Transform::from_translation(listener_position)),
    SpatialListener::new(gap),
));

Discussion

I removed SpatialAudioBundle because the SpatialSettings component was made mostly redundant, and without that it was identical to AudioBundle.

SpatialListener is a bare component and not a bundle which is feeling like a maybe a strange choice. That happened from a natural aversion both to nested bundles and to duplicating Transform etc in bundles and from figuring that it is likely to just be tacked on to some other bundle (player, head, camera) most of the time.

Let me know what you think about these things / everything else.

@rparrett rparrett added C-Enhancement A new feature A-Audio Sounds playback and modification C-Breaking-Change A breaking change to Bevy's public API that needs to be noted in a migration guide labels Sep 13, 2023
@nerdachse
Copy link

Glancing over the changes I must applaud you. Looks way nicer to use. As soonish I want to incorporate spatial audio in my game, this would be a welcome addition!

@hymm hymm added this to the 0.12 milestone Sep 18, 2023
Copy link
Contributor

@hymm hymm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Made some comments, but nothing blocking. This API definitely makes more sense to me than the status quo.

crates/bevy_audio/src/audio.rs Show resolved Hide resolved
crates/bevy_audio/src/audio_output.rs Show resolved Hide resolved
@rparrett
Copy link
Contributor Author

rparrett commented Oct 1, 2023

I fixed a few major issues that weren't showing up in the examples and expanded the examples a bit so that you can move the listener around.

This has changed enough that previous approvals should probably be invalidated.

@mockersf mockersf requested a review from hymm October 1, 2023 20:53
@rparrett
Copy link
Contributor Author

rparrett commented Oct 2, 2023

Sorry for the noise. I'm done fiddling with this now.

Copy link
Contributor

@hymm hymm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving, but my nits should probably be fixed before merging.

crates/bevy_audio/src/audio.rs Outdated Show resolved Hide resolved
crates/bevy_audio/src/audio_output.rs Outdated Show resolved Hide resolved
crates/bevy_audio/src/audio_output.rs Outdated Show resolved Hide resolved
Co-authored-by: Mike <mike.hsu@gmail.com>
rparrett and others added 2 commits October 3, 2023 20:55
Co-authored-by: Mike <mike.hsu@gmail.com>
@mockersf mockersf added the S-Ready-For-Final-Review This PR has been approved by the community. It's ready for a maintainer to consider merging it label Oct 7, 2023
@alice-i-cecile alice-i-cecile added this pull request to the merge queue Oct 9, 2023
Merged via the queue into bevyengine:main with commit 39c68e3 Oct 9, 2023
22 checks passed
@cart cart mentioned this pull request Oct 13, 2023
43 tasks
regnarock pushed a commit to regnarock/bevy that referenced this pull request Oct 13, 2023
# Objective

Spatial audio was heroically thrown together at the last minute for Bevy
0.10, but right now it's a bit of a pain to use -- users need to
manually update audio sinks with the position of the listener / emitter.

Hopefully the migration guide entry speaks for itself.

## Solution

Add a new `SpatialListener` component and automatically update sinks
with the position of the listener and and emitter.

## Changelog

`SpatialAudioSink`s are now automatically updated with positions of
emitters and listeners.

## Migration Guide

Spatial audio now automatically uses the transform of the `AudioBundle`
and of an entity with a `SpatialListener` component.

If you were manually scaling emitter/listener positions, you can use the
`spatial_scale` field of `AudioPlugin` instead.

```rust

// Old

commands.spawn(
    SpatialAudioBundle {
        source: asset_server.load("sounds/Windless Slopes.ogg"),
        settings: PlaybackSettings::LOOP,
        spatial: SpatialSettings::new(listener_position, gap, emitter_position),
    },
);

fn update(
    emitter_query: Query<(&Transform, &SpatialAudioSink)>,
    listener_query: Query<&Transform, With<Listener>>,
) {
    let listener = listener_query.single();

    for (transform, sink) in &emitter_query {
        sink.set_emitter_position(transform.translation);
        sink.set_listener_position(*listener, gap);
    }
}

// New

commands.spawn((
    SpatialBundle::from_transform(Transform::from_translation(emitter_position)),
    AudioBundle {
        source: asset_server.load("sounds/Windless Slopes.ogg"),
        settings: PlaybackSettings::LOOP.with_spatial(true),
    },
));

commands.spawn((
    SpatialBundle::from_transform(Transform::from_translation(listener_position)),
    SpatialListener::new(gap),
));
```

## Discussion

I removed `SpatialAudioBundle` because the `SpatialSettings` component
was made mostly redundant, and without that it was identical to
`AudioBundle`.

`SpatialListener` is a bare component and not a bundle which is feeling
like a maybe a strange choice. That happened from a natural aversion
both to nested bundles and to duplicating `Transform` etc in bundles and
from figuring that it is likely to just be tacked on to some other
bundle (player, head, camera) most of the time.

Let me know what you think about these things / everything else.

---------

Co-authored-by: Mike <mike.hsu@gmail.com>
ameknite pushed a commit to ameknite/bevy that referenced this pull request Nov 6, 2023
# Objective

Spatial audio was heroically thrown together at the last minute for Bevy
0.10, but right now it's a bit of a pain to use -- users need to
manually update audio sinks with the position of the listener / emitter.

Hopefully the migration guide entry speaks for itself.

## Solution

Add a new `SpatialListener` component and automatically update sinks
with the position of the listener and and emitter.

## Changelog

`SpatialAudioSink`s are now automatically updated with positions of
emitters and listeners.

## Migration Guide

Spatial audio now automatically uses the transform of the `AudioBundle`
and of an entity with a `SpatialListener` component.

If you were manually scaling emitter/listener positions, you can use the
`spatial_scale` field of `AudioPlugin` instead.

```rust

// Old

commands.spawn(
    SpatialAudioBundle {
        source: asset_server.load("sounds/Windless Slopes.ogg"),
        settings: PlaybackSettings::LOOP,
        spatial: SpatialSettings::new(listener_position, gap, emitter_position),
    },
);

fn update(
    emitter_query: Query<(&Transform, &SpatialAudioSink)>,
    listener_query: Query<&Transform, With<Listener>>,
) {
    let listener = listener_query.single();

    for (transform, sink) in &emitter_query {
        sink.set_emitter_position(transform.translation);
        sink.set_listener_position(*listener, gap);
    }
}

// New

commands.spawn((
    SpatialBundle::from_transform(Transform::from_translation(emitter_position)),
    AudioBundle {
        source: asset_server.load("sounds/Windless Slopes.ogg"),
        settings: PlaybackSettings::LOOP.with_spatial(true),
    },
));

commands.spawn((
    SpatialBundle::from_transform(Transform::from_translation(listener_position)),
    SpatialListener::new(gap),
));
```

## Discussion

I removed `SpatialAudioBundle` because the `SpatialSettings` component
was made mostly redundant, and without that it was identical to
`AudioBundle`.

`SpatialListener` is a bare component and not a bundle which is feeling
like a maybe a strange choice. That happened from a natural aversion
both to nested bundles and to duplicating `Transform` etc in bundles and
from figuring that it is likely to just be tacked on to some other
bundle (player, head, camera) most of the time.

Let me know what you think about these things / everything else.

---------

Co-authored-by: Mike <mike.hsu@gmail.com>
rdrpenguin04 pushed a commit to rdrpenguin04/bevy that referenced this pull request Jan 9, 2024
# Objective

Spatial audio was heroically thrown together at the last minute for Bevy
0.10, but right now it's a bit of a pain to use -- users need to
manually update audio sinks with the position of the listener / emitter.

Hopefully the migration guide entry speaks for itself.

## Solution

Add a new `SpatialListener` component and automatically update sinks
with the position of the listener and and emitter.

## Changelog

`SpatialAudioSink`s are now automatically updated with positions of
emitters and listeners.

## Migration Guide

Spatial audio now automatically uses the transform of the `AudioBundle`
and of an entity with a `SpatialListener` component.

If you were manually scaling emitter/listener positions, you can use the
`spatial_scale` field of `AudioPlugin` instead.

```rust

// Old

commands.spawn(
    SpatialAudioBundle {
        source: asset_server.load("sounds/Windless Slopes.ogg"),
        settings: PlaybackSettings::LOOP,
        spatial: SpatialSettings::new(listener_position, gap, emitter_position),
    },
);

fn update(
    emitter_query: Query<(&Transform, &SpatialAudioSink)>,
    listener_query: Query<&Transform, With<Listener>>,
) {
    let listener = listener_query.single();

    for (transform, sink) in &emitter_query {
        sink.set_emitter_position(transform.translation);
        sink.set_listener_position(*listener, gap);
    }
}

// New

commands.spawn((
    SpatialBundle::from_transform(Transform::from_translation(emitter_position)),
    AudioBundle {
        source: asset_server.load("sounds/Windless Slopes.ogg"),
        settings: PlaybackSettings::LOOP.with_spatial(true),
    },
));

commands.spawn((
    SpatialBundle::from_transform(Transform::from_translation(listener_position)),
    SpatialListener::new(gap),
));
```

## Discussion

I removed `SpatialAudioBundle` because the `SpatialSettings` component
was made mostly redundant, and without that it was identical to
`AudioBundle`.

`SpatialListener` is a bare component and not a bundle which is feeling
like a maybe a strange choice. That happened from a natural aversion
both to nested bundles and to duplicating `Transform` etc in bundles and
from figuring that it is likely to just be tacked on to some other
bundle (player, head, camera) most of the time.

Let me know what you think about these things / everything else.

---------

Co-authored-by: Mike <mike.hsu@gmail.com>
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-Breaking-Change A breaking change to Bevy's public API that needs to be noted in a migration guide C-Enhancement A new feature S-Ready-For-Final-Review This PR has been approved by the community. It's ready for a maintainer to consider merging it
Projects
Status: No status
Development

Successfully merging this pull request may close these issues.

None yet

5 participants