1use bevy::{
4 audio::{AddAudioSource, AudioPlugin, ChannelCount, SampleRate, 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: SampleRate,
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: SampleRate::new(sample_rate).unwrap(),
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_span_len(&self) -> Option<usize> {
58 None
59 }
60
61 fn channels(&self) -> ChannelCount {
62 ChannelCount::new(1).unwrap()
63 }
64
65 fn sample_rate(&self) -> SampleRate {
66 self.sample_rate
67 }
68
69 fn total_duration(&self) -> Option<Duration> {
70 None
71 }
72}
73
74impl Decodable for SineAudio {
76 type Decoder = SineDecoder;
77
78 fn decoder(&self) -> Self::Decoder {
79 SineDecoder::new(self.frequency)
80 }
81}
82
83fn main() {
84 let mut app = App::new();
85 app.add_plugins(DefaultPlugins.set(AudioPlugin {
87 global_volume: Volume::Linear(0.2).into(),
88 ..default()
89 }))
90 .add_audio_source::<SineAudio>()
91 .add_systems(Startup, setup)
92 .run();
93}
94
95fn setup(mut assets: ResMut<Assets<SineAudio>>, mut commands: Commands) {
96 let audio_handle = assets.add(SineAudio {
98 frequency: 440., });
100 commands.spawn(AudioPlayer(audio_handle));
101}