1use bevy::{
4 audio::{AddAudioSource, AudioPlugin, Source, Volume},
5 math::ops,
6 prelude::*,
7 reflect::TypePath,
8};
9use core::time::Duration;
10
11#[derive(Asset, TypePath)]
15struct SineAudio {
16 frequency: f32,
17}
18struct SineDecoder {
21 current_progress: f32,
23 progress_per_frame: f32,
25 period: f32,
27 sample_rate: u32,
28}
29
30impl SineDecoder {
31 fn new(frequency: f32) -> Self {
32 let sample_rate = 44_100;
34 SineDecoder {
35 current_progress: 0.,
36 progress_per_frame: frequency / sample_rate as f32,
37 period: std::f32::consts::PI * 2.,
38 sample_rate,
39 }
40 }
41}
42
43impl Iterator for SineDecoder {
45 type Item = f32;
46
47 fn next(&mut self) -> Option<Self::Item> {
48 self.current_progress += self.progress_per_frame;
49 self.current_progress %= 1.;
51 Some(ops::sin(self.period * self.current_progress))
52 }
53}
54impl Source for SineDecoder {
57 fn current_frame_len(&self) -> Option<usize> {
58 None
59 }
60
61 fn channels(&self) -> u16 {
62 1
63 }
64
65 fn sample_rate(&self) -> u32 {
66 self.sample_rate
67 }
68
69 fn total_duration(&self) -> Option<Duration> {
70 None
71 }
72}
73
74impl Decodable for SineAudio {
76 type DecoderItem = <SineDecoder as Iterator>::Item;
77
78 type Decoder = SineDecoder;
79
80 fn decoder(&self) -> Self::Decoder {
81 SineDecoder::new(self.frequency)
82 }
83}
84
85fn main() {
86 let mut app = App::new();
87 app.add_plugins(DefaultPlugins.set(AudioPlugin {
89 global_volume: Volume::Linear(0.2).into(),
90 ..default()
91 }))
92 .add_audio_source::<SineAudio>()
93 .add_systems(Startup, setup)
94 .run();
95}
96
97fn setup(mut assets: ResMut<Assets<SineAudio>>, mut commands: Commands) {
98 let audio_handle = assets.add(SineAudio {
100 frequency: 440., });
102 commands.spawn(AudioPlayer(audio_handle));
103}