use bevy::{
audio::{AddAudioSource, AudioPlugin, Source},
math::ops,
prelude::*,
reflect::TypePath,
utils::Duration,
};
#[derive(Asset, TypePath)]
struct SineAudio {
frequency: f32,
}
struct SineDecoder {
current_progress: f32,
progress_per_frame: f32,
period: f32,
sample_rate: u32,
}
impl SineDecoder {
fn new(frequency: f32) -> Self {
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,
}
}
}
impl Iterator for SineDecoder {
type Item = f32;
fn next(&mut self) -> Option<Self::Item> {
self.current_progress += self.progress_per_frame;
self.current_progress %= 1.;
Some(ops::sin(self.period * self.current_progress))
}
}
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
}
}
impl Decodable for SineAudio {
type DecoderItem = <SineDecoder as Iterator>::Item;
type Decoder = SineDecoder;
fn decoder(&self) -> Self::Decoder {
SineDecoder::new(self.frequency)
}
}
fn main() {
let mut app = App::new();
app.add_plugins(DefaultPlugins.set(AudioPlugin {
global_volume: GlobalVolume::new(0.2),
..default()
}))
.add_audio_source::<SineAudio>()
.add_systems(Startup, setup)
.run();
}
fn setup(mut assets: ResMut<Assets<SineAudio>>, mut commands: Commands) {
let audio_handle = assets.add(SineAudio {
frequency: 440., });
commands.spawn(AudioPlayer(audio_handle));
}