mirror of
https://github.com/bevyengine/bevy
synced 2024-11-10 07:04:33 +00:00
Added Pitch as an alternative sound source (#9225)
# Objective My attempt at implementing #7515 ## Solution Added struct `Pitch` and implemented on it `Source` trait. ## Changelog ### Added - File pitch.rs to bevy_audio crate - Struct `Pitch` and type aliases for `AudioSourceBundle<Pitch>` and `SpatialAudioSourceBundle<Pitch>` - New example showing how to use `PitchBundle` ### Changed - `AudioPlugin` now adds system for `Pitch` audio --------- Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
This commit is contained in:
parent
a88b9fc6a9
commit
fb9c5a6cbb
5 changed files with 110 additions and 2 deletions
10
Cargo.toml
10
Cargo.toml
|
@ -1043,6 +1043,16 @@ description = "Shows how to play spatial audio, and moving the emitter in 3D"
|
||||||
category = "Audio"
|
category = "Audio"
|
||||||
wasm = true
|
wasm = true
|
||||||
|
|
||||||
|
[[example]]
|
||||||
|
name = "pitch"
|
||||||
|
path = "examples/audio/pitch.rs"
|
||||||
|
|
||||||
|
[package.metadata.example.pitch]
|
||||||
|
name = "Pitch"
|
||||||
|
description = "Shows how to directly play a simple pitch"
|
||||||
|
category = "Audio"
|
||||||
|
wasm = true
|
||||||
|
|
||||||
# Diagnostics
|
# Diagnostics
|
||||||
[[example]]
|
[[example]]
|
||||||
name = "log_diagnostics"
|
name = "log_diagnostics"
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
mod audio;
|
mod audio;
|
||||||
mod audio_output;
|
mod audio_output;
|
||||||
mod audio_source;
|
mod audio_source;
|
||||||
|
mod pitch;
|
||||||
mod sinks;
|
mod sinks;
|
||||||
|
|
||||||
#[allow(missing_docs)]
|
#[allow(missing_docs)]
|
||||||
|
@ -34,13 +35,14 @@ pub mod prelude {
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub use crate::{
|
pub use crate::{
|
||||||
AudioBundle, AudioSink, AudioSinkPlayback, AudioSource, AudioSourceBundle, Decodable,
|
AudioBundle, AudioSink, AudioSinkPlayback, AudioSource, AudioSourceBundle, Decodable,
|
||||||
GlobalVolume, PlaybackSettings, SpatialAudioBundle, SpatialAudioSink,
|
GlobalVolume, Pitch, PitchBundle, PlaybackSettings, SpatialAudioBundle, SpatialAudioSink,
|
||||||
SpatialAudioSourceBundle, SpatialSettings,
|
SpatialAudioSourceBundle, SpatialPitchBundle, SpatialSettings,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub use audio::*;
|
pub use audio::*;
|
||||||
pub use audio_source::*;
|
pub use audio_source::*;
|
||||||
|
pub use pitch::*;
|
||||||
|
|
||||||
pub use rodio::cpal::Sample as CpalSample;
|
pub use rodio::cpal::Sample as CpalSample;
|
||||||
pub use rodio::source::Source;
|
pub use rodio::source::Source;
|
||||||
|
@ -77,6 +79,8 @@ impl Plugin for AudioPlugin {
|
||||||
app.add_audio_source::<AudioSource>();
|
app.add_audio_source::<AudioSource>();
|
||||||
app.init_asset_loader::<AudioLoader>();
|
app.init_asset_loader::<AudioLoader>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
app.add_audio_source::<Pitch>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
38
crates/bevy_audio/src/pitch.rs
Normal file
38
crates/bevy_audio/src/pitch.rs
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
use crate::{AudioSourceBundle, Decodable, SpatialAudioSourceBundle};
|
||||||
|
use bevy_reflect::{TypePath, TypeUuid};
|
||||||
|
use rodio::{source::SineWave, source::TakeDuration, Source};
|
||||||
|
|
||||||
|
/// A source of sine wave sound
|
||||||
|
#[derive(Debug, Clone, TypeUuid, TypePath)]
|
||||||
|
#[uuid = "cbc63be3-b0b9-4d2c-a03c-88b58f1a19ef"]
|
||||||
|
pub struct Pitch {
|
||||||
|
/// Frequency at which sound will be played
|
||||||
|
pub frequency: f32,
|
||||||
|
/// Duration for which sound will be played
|
||||||
|
pub duration: std::time::Duration,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Pitch {
|
||||||
|
/// Creates a new note
|
||||||
|
pub fn new(frequency: f32, duration: std::time::Duration) -> Self {
|
||||||
|
Pitch {
|
||||||
|
frequency,
|
||||||
|
duration,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Decodable for Pitch {
|
||||||
|
type DecoderItem = <SineWave as Iterator>::Item;
|
||||||
|
type Decoder = TakeDuration<SineWave>;
|
||||||
|
|
||||||
|
fn decoder(&self) -> Self::Decoder {
|
||||||
|
SineWave::new(self.frequency).take_duration(self.duration)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Bundle for playing a bevy note sound
|
||||||
|
pub type PitchBundle = AudioSourceBundle<Pitch>;
|
||||||
|
|
||||||
|
/// Bundle for playing a bevy note sound with a 3D position
|
||||||
|
pub type SpatialPitchBundle = SpatialAudioSourceBundle<Pitch>;
|
|
@ -195,6 +195,7 @@ Example | Description
|
||||||
[Audio](../examples/audio/audio.rs) | Shows how to load and play an audio file
|
[Audio](../examples/audio/audio.rs) | Shows how to load and play an audio file
|
||||||
[Audio Control](../examples/audio/audio_control.rs) | Shows how to load and play an audio file, and control how it's played
|
[Audio Control](../examples/audio/audio_control.rs) | Shows how to load and play an audio file, and control how it's played
|
||||||
[Decodable](../examples/audio/decodable.rs) | Shows how to create and register a custom audio source by implementing the `Decodable` type.
|
[Decodable](../examples/audio/decodable.rs) | Shows how to create and register a custom audio source by implementing the `Decodable` type.
|
||||||
|
[Pitch](../examples/audio/pitch.rs) | Shows how to directly play a simple pitch
|
||||||
[Spatial Audio 2D](../examples/audio/spatial_audio_2d.rs) | Shows how to play spatial audio, and moving the emitter in 2D
|
[Spatial Audio 2D](../examples/audio/spatial_audio_2d.rs) | Shows how to play spatial audio, and moving the emitter in 2D
|
||||||
[Spatial Audio 3D](../examples/audio/spatial_audio_3d.rs) | Shows how to play spatial audio, and moving the emitter in 3D
|
[Spatial Audio 3D](../examples/audio/spatial_audio_3d.rs) | Shows how to play spatial audio, and moving the emitter in 3D
|
||||||
|
|
||||||
|
|
55
examples/audio/pitch.rs
Normal file
55
examples/audio/pitch.rs
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
//! This example illustrates how to play a single-frequency sound (aka a pitch)
|
||||||
|
|
||||||
|
use bevy::prelude::*;
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
App::new()
|
||||||
|
.add_plugins(DefaultPlugins)
|
||||||
|
.add_event::<PlayPitch>()
|
||||||
|
.add_systems(Startup, setup)
|
||||||
|
.add_systems(Update, (play_pitch, keyboard_input_system))
|
||||||
|
.run();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Event, Default)]
|
||||||
|
struct PlayPitch;
|
||||||
|
|
||||||
|
#[derive(Resource)]
|
||||||
|
struct PitchFrequency(f32);
|
||||||
|
|
||||||
|
fn setup(mut commands: Commands) {
|
||||||
|
commands.insert_resource(PitchFrequency(220.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn play_pitch(
|
||||||
|
mut pitch_assets: ResMut<Assets<Pitch>>,
|
||||||
|
frequency: Res<PitchFrequency>,
|
||||||
|
mut events: EventReader<PlayPitch>,
|
||||||
|
mut commands: Commands,
|
||||||
|
) {
|
||||||
|
for _ in events.iter() {
|
||||||
|
info!("playing pitch with frequency: {}", frequency.0);
|
||||||
|
commands.spawn(PitchBundle {
|
||||||
|
source: pitch_assets.add(Pitch::new(frequency.0, Duration::new(1, 0))),
|
||||||
|
settings: PlaybackSettings::DESPAWN,
|
||||||
|
});
|
||||||
|
info!("number of pitch assets: {}", pitch_assets.len());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn keyboard_input_system(
|
||||||
|
keyboard_input: Res<Input<KeyCode>>,
|
||||||
|
mut frequency: ResMut<PitchFrequency>,
|
||||||
|
mut events: EventWriter<PlayPitch>,
|
||||||
|
) {
|
||||||
|
if keyboard_input.just_pressed(KeyCode::Up) {
|
||||||
|
frequency.0 *= 2.0f32.powf(1.0 / 12.0);
|
||||||
|
}
|
||||||
|
if keyboard_input.just_pressed(KeyCode::Down) {
|
||||||
|
frequency.0 /= 2.0f32.powf(1.0 / 12.0);
|
||||||
|
}
|
||||||
|
if keyboard_input.just_pressed(KeyCode::Space) {
|
||||||
|
events.send(PlayPitch);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue