aboutsummaryrefslogtreecommitdiff
path: root/v_windows/v/examples/sokol/sounds/melody.v
diff options
context:
space:
mode:
Diffstat (limited to 'v_windows/v/examples/sokol/sounds/melody.v')
-rw-r--r--v_windows/v/examples/sokol/sounds/melody.v75
1 files changed, 75 insertions, 0 deletions
diff --git a/v_windows/v/examples/sokol/sounds/melody.v b/v_windows/v/examples/sokol/sounds/melody.v
new file mode 100644
index 0000000..aa5ebc4
--- /dev/null
+++ b/v_windows/v/examples/sokol/sounds/melody.v
@@ -0,0 +1,75 @@
+import gg
+import gx
+import sokol.audio
+
+const credits = 'Based on the ByteBeat formula from: https://www.youtube.com/watch?v=V4GfkFbDojc \n "Techno" by Gabriel Miceli'
+
+struct AppState {
+mut:
+ gframe int // the current graphical frame
+ frame_0 int // offset of the current audio frames, relative to the start of the music
+ frames [2048]f32 // a copy of the last rendered audio frames
+ gg &gg.Context // used for drawing
+}
+
+fn my_audio_stream_callback(buffer &f32, num_frames int, num_channels int, mut acontext AppState) {
+ mut soundbuffer := unsafe { buffer }
+ for frame := 0; frame < num_frames; frame++ {
+ t := int(f32(acontext.frame_0 + frame) * 0.245)
+ // "Techno" by Gabriel Miceli
+ y := (t * (((t / 10 | 0) ^ ((t / 10 | 0) - 1280)) % 11) / 2 & 127) +
+ (t * (((t / 640 | 0) ^ ((t / 640 | 0) - 2)) % 13) / 2 & 127)
+ for ch := 0; ch < num_channels; ch++ {
+ idx := frame * num_channels + ch
+ unsafe {
+ a := f32(byte(y) - 127) / 255.0
+ soundbuffer[idx] = a
+ acontext.frames[idx & 2047] = a
+ }
+ }
+ }
+ acontext.frame_0 += num_frames
+}
+
+fn main() {
+ println(credits)
+ mut state := &AppState{
+ gg: 0
+ }
+ audio.setup(
+ stream_userdata_cb: my_audio_stream_callback
+ user_data: state
+ )
+ state.gg = gg.new_context(
+ bg_color: gx.rgb(50, 50, 50)
+ width: 1024
+ height: 400
+ create_window: true
+ window_title: 'ByteBeat Music'
+ frame_fn: graphics_frame
+ user_data: state
+ )
+ state.gg.run()
+ audio.shutdown()
+}
+
+fn graphics_frame(mut state AppState) {
+ state.gframe++
+ state.gg.begin()
+ state.draw()
+ state.gg.end()
+}
+
+[inline]
+fn (mut state AppState) bsample(idx int) byte {
+ return byte(127 + state.frames[(state.gframe + idx) & 2047] * 128)
+}
+
+fn (mut state AppState) draw() {
+ // first, reset and setup ortho projection
+ for x in 0 .. 1024 {
+ mut y := 100 * (state.frames[2 * x] + state.frames[2 * x + 1])
+ state.gg.draw_line(x, 200, x, 200 + y, gx.rgba(state.bsample(x), state.bsample(x + 300),
+ state.bsample(x + 700), 255))
+ }
+}