| 1 |
|
| 2 |
|
| 3 |
use bevy::{ |
| 4 |
audio::{AddAudioSource, AudioPlugin, ChannelCount, SampleRate, Source, Volume}, |
| 5 |
math::ops, |
| 6 |
prelude::*, |
| 7 |
reflect::TypePath, |
| 8 |
}; |
| 9 |
use core::time::Duration; |
| 10 |
|
| 11 |
|
| 12 |
|
| 13 |
|
| 14 |
#[derive(Asset, TypePath)] |
| 15 |
struct SineAudio { |
| 16 |
frequency: f32, |
| 17 |
} |
| 18 |
|
| 19 |
|
| 20 |
struct SineDecoder { |
| 21 |
|
| 22 |
current_progress: f32, |
| 23 |
|
| 24 |
progress_per_frame: f32, |
| 25 |
|
| 26 |
period: f32, |
| 27 |
sample_rate: SampleRate, |
| 28 |
} |
| 29 |
|
| 30 |
impl SineDecoder { |
| 31 |
fn new(frequency: f32) -> Self { |
| 32 |
|
| 33 |
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 |
|
| 43 |
|
| 44 |
impl 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 |
|
| 50 |
self.current_progress %= 1.; |
| 51 |
Some(ops::sin(self.period * self.current_progress)) |
| 52 |
} |
| 53 |
} |
| 54 |
|
| 55 |
|
| 56 |
impl 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 |
|
| 74 |
|
| 75 |
impl Decodable for SineAudio { |
| 76 |
type Decoder = SineDecoder; |
| 77 |
|
| 78 |
fn decoder(&self) -> Self::Decoder { |
| 79 |
SineDecoder::new(self.frequency) |
| 80 |
} |
| 81 |
} |
| 82 |
|
| 83 |
fn main() { |
| 84 |
let mut app = App::new(); |
| 85 |
|
| 86 |
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 |
|
| 95 |
fn setup(mut assets: ResMut<Assets<SineAudio>>, mut commands: Commands) { |
| 96 |
|
| 97 |
let audio_handle = assets.add(SineAudio { |
| 98 |
frequency: 440., |
| 99 |
}); |
| 100 |
commands.spawn(AudioPlayer(audio_handle)); |
| 101 |
} |