Skip to content

Commit 9a2608e

Browse files
committed
Add guitar tuner example
1 parent a246805 commit 9a2608e

File tree

5 files changed

+70
-2
lines changed

5 files changed

+70
-2
lines changed

caw/Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,3 +63,7 @@ required-features = [ "interactive" ]
6363
[[example]]
6464
name = "audio_file_playback"
6565
required-features = [ "interactive", "audio_file" ]
66+
67+
[[example]]
68+
name = "guitar_strings"
69+
required-features = [ "interactive" ]

caw/examples/guitar_strings.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
use caw::prelude::*;
2+
3+
fn note_from_key(
4+
note_by_key: Vec<(KeyFrameSig, Note)>,
5+
) -> FrameSig<impl FrameSigT<Item = Option<Note>>> {
6+
FrameSig::option_first_some(
7+
note_by_key
8+
.into_iter()
9+
.map(|(key, note)| key.on(move || note)),
10+
)
11+
}
12+
13+
fn main() {
14+
let window = Window::builder().build();
15+
let input = window.input();
16+
let sig = {
17+
let keyboard = input.keyboard.clone();
18+
let (gate, note) = note_from_key(vec![
19+
(keyboard.q, Note::E2),
20+
(keyboard.w, Note::A2),
21+
(keyboard.e, Note::D3),
22+
(keyboard.r, Note::G3),
23+
(keyboard.t, Note::B3),
24+
(keyboard.y, Note::E4),
25+
])
26+
.map(|note_opt| (note_opt.is_some(), note_opt))
27+
.unzip();
28+
let note = note.option_or_last(note::C4);
29+
let env = adsr_linear_01(gate).release_s(1.0).build().exp_01(1.0);
30+
oscillator(Saw, note.freq_hz())
31+
.build()
32+
.filter(low_pass::default(env * 10000.0))
33+
.filter(reverb::default())
34+
};
35+
window.play_mono(sig, Default::default()).unwrap();
36+
}

core/src/frame_sig.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,23 @@ where
9393
}
9494
}
9595

96+
impl<S, T, U> FrameSig<S>
97+
where
98+
T: Clone,
99+
U: Clone,
100+
S: FrameSigT<Item = (T, U)>,
101+
{
102+
pub fn unzip(
103+
self,
104+
) -> (
105+
FrameSig<impl FrameSigT<Item = T>>,
106+
FrameSig<impl FrameSigT<Item = U>>,
107+
) {
108+
let shared = frame_sig_shared(self);
109+
(shared.clone().map(|x| x.0), shared.map(|x| x.1))
110+
}
111+
}
112+
96113
impl<S> FrameSig<S>
97114
where
98115
S: FrameSigT + 'static,
@@ -327,6 +344,16 @@ where
327344
) -> FrameSig<impl FrameSigT<Item = Option<T>>> {
328345
FrameSig(OptionFirstSome(s.into_iter().collect()))
329346
}
347+
348+
pub fn option_or_last(self, init: T) -> FrameSig<impl FrameSigT<Item = T>> {
349+
let mut last = init;
350+
self.map(move |x| {
351+
if let Some(x) = x {
352+
last = x;
353+
}
354+
last.clone()
355+
})
356+
}
330357
}
331358

332359
impl<F, T> FrameSig<FrameSigFn<F, T>>

interactive/src/input.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@ impl<P: Clone, B: Clone> MouseGeneric<P, B> {
3737
}
3838
}
3939

40-
pub type Keyboard = KeyboardGeneric<FrameSig<FrameSigVar<bool>>>;
40+
pub type KeyFrameSig = FrameSig<FrameSigVar<bool>>;
41+
pub type Keyboard = KeyboardGeneric<KeyFrameSig>;
4142
pub type Mouse =
4243
MouseGeneric<FrameSig<FrameSigVar<f32>>, FrameSig<FrameSigVar<bool>>>;
4344

interactive/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
pub mod input;
22
pub mod window;
33
pub use caw_player::ConfigSync;
4-
pub use input::{Input, Key, MouseButton};
4+
pub use input::{Input, Key, KeyFrameSig, MouseButton};
55
pub use window::{Visualization, Window};

0 commit comments

Comments
 (0)