Skip to content

Commit 952f63e

Browse files
committed
examples: add examples/sokol/sounds/simple_keyboard_synth.v
1 parent f177237 commit 952f63e

1 file changed

Lines changed: 114 additions & 0 deletions

File tree

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
import time
2+
import math
3+
import term
4+
import sokol.audio
5+
6+
struct Note {
7+
mut:
8+
phase f32
9+
freq f32
10+
amplitude f32
11+
}
12+
13+
struct App {
14+
mut:
15+
notes shared []Note
16+
}
17+
18+
fn main() {
19+
println('Press the keys (a, s, d, f, g, h, j, k) to play notes. Press ESC to quit.')
20+
mut app := &App{
21+
notes: []Note{len: 32}
22+
}
23+
audio.setup(
24+
stream_userdata_cb: audio_callback
25+
user_data: app
26+
)
27+
defer { audio.shutdown() }
28+
term.enable_echo(false)
29+
defer { term.enable_echo(true) }
30+
for {
31+
key := term.key_pressed(blocking: false)
32+
app.handle_key(key) or { break }
33+
time.sleep(5 * time.millisecond)
34+
}
35+
}
36+
37+
const c_2_pi = 2 * math.pi
38+
const c_phase_step_per_freq = c_2_pi / 44100.0
39+
const c_note_start_amplitude = 0.33
40+
const c_note_decay = 0.3 / 44100.0
41+
42+
fn (mut app App) handle_key(key i64) ? {
43+
if key == -1 {
44+
return
45+
}
46+
mut freq := f32(0.0)
47+
match key {
48+
27 { return none }
49+
` ` { app.silence() }
50+
`a` { freq = 261.63 }
51+
`s` { freq = 293.66 }
52+
`d` { freq = 329.63 }
53+
`f` { freq = 349.23 }
54+
`g` { freq = 392.00 }
55+
`h` { freq = 440.00 }
56+
`j` { freq = 493.88 }
57+
`k` { freq = 523.25 }
58+
else {}
59+
}
60+
if freq > 0 {
61+
app.play(freq, c_note_start_amplitude)
62+
}
63+
}
64+
65+
fn (mut app App) play(freq f32, volume f32) {
66+
lock app.notes {
67+
for mut note in app.notes {
68+
note.amplitude -= 0.2
69+
}
70+
for mut note in app.notes {
71+
if note.amplitude <= 0 {
72+
note = Note{
73+
phase: 0.0
74+
freq: freq
75+
amplitude: volume
76+
}
77+
break
78+
}
79+
}
80+
}
81+
}
82+
83+
fn (mut app App) silence() {
84+
lock app.notes {
85+
for mut note in app.notes {
86+
note.amplitude = 0
87+
}
88+
}
89+
}
90+
91+
fn audio_callback(mut soundbuffer &f32, num_frames int, num_channels int, mut app App) {
92+
lock app.notes {
93+
for frame in 0 .. num_frames {
94+
mut sample := f32(0.0)
95+
for mut note in app.notes {
96+
if note.amplitude <= 0 {
97+
continue
98+
}
99+
sample += note.amplitude * math.sinf(note.phase)
100+
sample += note.amplitude * math.sinf(note.phase * 2.718)
101+
sample += note.amplitude * math.sinf(note.phase * 3.141)
102+
103+
note.phase += note.freq * c_phase_step_per_freq
104+
for note.phase >= c_2_pi {
105+
note.phase -= c_2_pi
106+
}
107+
note.amplitude -= c_note_decay
108+
}
109+
for ch in 0 .. num_channels {
110+
soundbuffer[frame * num_channels + ch] = sample
111+
}
112+
}
113+
}
114+
}

0 commit comments

Comments
 (0)