1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
use super::*;
pub(crate) struct AudioContext {
#[cfg(not(target_arch = "wasm32"))]
pub(crate) output_stream_handle: Arc<rodio::OutputStreamHandle>,
}
impl AudioContext {
#[cfg(target_arch = "wasm32")]
pub(crate) fn new() -> Self {
Self {}
}
#[cfg(not(target_arch = "wasm32"))]
pub(crate) fn new() -> Self {
{
let stream_handle = std::thread::spawn(|| {
let (stream, handle) = rodio::OutputStream::try_default().unwrap();
mem::forget(stream);
handle
})
.join()
.unwrap();
Self {
output_stream_handle: Arc::new(stream_handle),
}
}
}
}
pub struct Sound {
#[cfg(not(target_arch = "wasm32"))]
pub(crate) output_stream_handle: Arc<rodio::OutputStreamHandle>,
#[cfg(target_arch = "wasm32")]
pub(crate) inner: web_sys::HtmlAudioElement,
#[cfg(not(target_arch = "wasm32"))]
pub(crate) data: Arc<[u8]>,
pub looped: bool,
}
impl Sound {
pub fn effect(&self) -> SoundEffect {
SoundEffect {
#[cfg(target_arch = "wasm32")]
inner: {
let effect = self
.inner
.clone_node()
.unwrap()
.dyn_into::<web_sys::HtmlAudioElement>()
.unwrap();
effect.set_loop(self.looped);
effect
},
#[cfg(not(target_arch = "wasm32"))]
sink: Some({
let sink = rodio::Sink::try_new(&self.output_stream_handle).unwrap();
sink.pause();
if self.looped {
sink.append(rodio::Source::repeat_infinite(
rodio::Decoder::new(std::io::Cursor::new(self.data.clone())).unwrap(),
));
} else {
sink.append(
rodio::Decoder::new(std::io::Cursor::new(self.data.clone())).unwrap(),
);
}
sink
}),
}
}
pub fn play(&self) -> SoundEffect {
let mut effect = self.effect();
effect.play();
effect
}
}
pub struct SoundEffect {
#[cfg(target_arch = "wasm32")]
inner: web_sys::HtmlAudioElement,
#[cfg(not(target_arch = "wasm32"))]
sink: Option<rodio::Sink>,
}
impl SoundEffect {
pub fn set_volume(&mut self, volume: f64) {
#[cfg(target_arch = "wasm32")]
self.inner.set_volume(volume);
#[cfg(not(target_arch = "wasm32"))]
self.sink().set_volume(volume as f32);
}
pub fn play(&mut self) {
#[cfg(target_arch = "wasm32")]
self.inner.play();
#[cfg(not(target_arch = "wasm32"))]
self.sink().play();
}
pub fn pause(&mut self) {
#[cfg(target_arch = "wasm32")]
self.inner.pause();
#[cfg(not(target_arch = "wasm32"))]
self.sink().pause();
}
#[cfg(not(target_arch = "wasm32"))]
fn sink(&mut self) -> &mut rodio::Sink {
self.sink.as_mut().unwrap()
}
}
impl Drop for SoundEffect {
fn drop(&mut self) {
#[cfg(not(target_arch = "wasm32"))]
self.sink.take().unwrap().detach();
}
}