forked from bevyengine/bevy
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
) # Objective - Fixes bevyengine#6361 - Fixes bevyengine#6362 - Fixes bevyengine#6364 ## Solution - Added an example for creating a custom `Decodable` type - Clarified the documentation on `Decodable` - Added an `AddAudioSource` trait and implemented it for `App` Co-authored-by: dis-da-moe <84386186+dis-da-moe@users.noreply.github.com>
- Loading branch information
Showing
5 changed files
with
155 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
//! Shows how to create a custom `Decodable` type by implementing a Sine wave. | ||
//! ***WARNING THIS EXAMPLE IS VERY LOUD.*** Turn your volume down. | ||
use bevy::audio::AddAudioSource; | ||
use bevy::audio::Source; | ||
use bevy::prelude::*; | ||
use bevy::reflect::TypeUuid; | ||
use bevy::utils::Duration; | ||
|
||
// This struct usually contains the data for the audio being played. | ||
// This is where data read from an audio file would be stored, for example. | ||
// Implementing `TypeUuid` will automatically implement `Asset`. | ||
// This allows the type to be registered as an asset. | ||
#[derive(TypeUuid)] | ||
#[uuid = "c2090c23-78fd-44f1-8508-c89b1f3cec29"] | ||
struct SineAudio { | ||
frequency: f32, | ||
} | ||
// This decoder is responsible for playing the audio, | ||
// and so stores data about the audio being played. | ||
struct SineDecoder { | ||
// how far along one period the wave is (between 0 and 1) | ||
current_progress: f32, | ||
// how much we move along the period every frame | ||
progress_per_frame: f32, | ||
// how long a period is | ||
period: f32, | ||
sample_rate: u32, | ||
} | ||
|
||
impl SineDecoder { | ||
fn new(frequency: f32) -> Self { | ||
// standard sample rate for most recordings | ||
let sample_rate = 44_100; | ||
SineDecoder { | ||
current_progress: 0., | ||
progress_per_frame: frequency / sample_rate as f32, | ||
period: std::f32::consts::PI * 2., | ||
sample_rate, | ||
} | ||
} | ||
} | ||
|
||
// The decoder must implement iterator so that it can implement `Decodable`. | ||
impl Iterator for SineDecoder { | ||
type Item = f32; | ||
|
||
fn next(&mut self) -> Option<Self::Item> { | ||
self.current_progress += self.progress_per_frame; | ||
// we loop back round to 0 to avoid floating point inaccuracies | ||
self.current_progress %= 1.; | ||
Some(f32::sin(self.period * self.current_progress)) | ||
} | ||
} | ||
// `Source` is what allows the audio source to be played by bevy. | ||
// This trait provides information on the audio. | ||
impl Source for SineDecoder { | ||
fn current_frame_len(&self) -> Option<usize> { | ||
None | ||
} | ||
|
||
fn channels(&self) -> u16 { | ||
1 | ||
} | ||
|
||
fn sample_rate(&self) -> u32 { | ||
self.sample_rate | ||
} | ||
|
||
fn total_duration(&self) -> Option<Duration> { | ||
None | ||
} | ||
} | ||
|
||
// Finally `Decodable` can be implemented for our `SineAudio`. | ||
impl Decodable for SineAudio { | ||
type Decoder = SineDecoder; | ||
|
||
type DecoderItem = <SineDecoder as Iterator>::Item; | ||
|
||
fn decoder(&self) -> Self::Decoder { | ||
SineDecoder::new(self.frequency) | ||
} | ||
} | ||
|
||
fn main() { | ||
let mut app = App::new(); | ||
// register the audio source so that it can be used | ||
app.add_plugins(DefaultPlugins) | ||
.add_audio_source::<SineAudio>() | ||
.add_startup_system(setup) | ||
.run(); | ||
} | ||
|
||
fn setup(mut assets: ResMut<Assets<SineAudio>>, audio: Res<Audio<SineAudio>>) { | ||
// add a `SineAudio` to the asset server so that it can be played | ||
let audio_handle = assets.add(SineAudio { | ||
frequency: 440., //this is the frequency of A4 | ||
}); | ||
audio.play(audio_handle); | ||
} |