vizcore 0.1.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (126) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +544 -9
  3. data/docs/.nojekyll +0 -0
  4. data/docs/assets/site.css +744 -0
  5. data/docs/assets/vizcore-demo.gif +0 -0
  6. data/docs/assets/vizcore-poster.png +0 -0
  7. data/docs/assets/vj-tunnel.js +159 -0
  8. data/docs/index.html +224 -0
  9. data/examples/README.md +59 -0
  10. data/examples/assets/README.md +19 -0
  11. data/examples/audio_inspector.rb +34 -0
  12. data/examples/club_intro_drop.rb +78 -0
  13. data/examples/kansai_rubykaigi_visual.rb +70 -0
  14. data/examples/live_coding_minimal.rb +22 -0
  15. data/examples/midi_controller_show.rb +78 -0
  16. data/examples/midi_scene_switch.rb +3 -1
  17. data/examples/parser_visualizer.rb +48 -0
  18. data/examples/readme_demo.rb +17 -0
  19. data/examples/rhythm_geometry.rb +34 -0
  20. data/examples/ruby_crystal_show.rb +35 -0
  21. data/examples/shader_playground.rb +18 -0
  22. data/examples/unyo_liquid.rb +59 -0
  23. data/examples/vj_ambient_chill_room.rb +124 -0
  24. data/examples/vj_dnb_jungle.rb +170 -0
  25. data/examples/vj_festival_mainstage.rb +245 -0
  26. data/examples/vj_festival_mainstage.yml +17 -0
  27. data/examples/vj_glitch_industrial.rb +164 -0
  28. data/examples/vj_hiphop_cipher.rb +167 -0
  29. data/examples/vj_jpop_idol_live.rb +210 -0
  30. data/examples/vj_synthwave_retro.rb +173 -0
  31. data/examples/vj_techno_warehouse.rb +195 -0
  32. data/frontend/index.html +468 -2
  33. data/frontend/src/audio-inspector.js +40 -0
  34. data/frontend/src/live-controls.js +131 -0
  35. data/frontend/src/main.js +792 -16
  36. data/frontend/src/midi-learn.js +194 -0
  37. data/frontend/src/performance-monitor.js +183 -0
  38. data/frontend/src/plugin-runtime.js +130 -0
  39. data/frontend/src/projector-mode.js +56 -0
  40. data/frontend/src/renderer/engine.js +148 -3
  41. data/frontend/src/renderer/layer-manager.js +428 -30
  42. data/frontend/src/renderer/shader-manager.js +26 -0
  43. data/frontend/src/runtime-control-preset.js +11 -0
  44. data/frontend/src/shader-error-overlay.js +29 -0
  45. data/frontend/src/shader-param-controls.js +93 -0
  46. data/frontend/src/shaders/builtins.js +380 -2
  47. data/frontend/src/shaders/post-effects.js +52 -0
  48. data/frontend/src/visual-regression.js +67 -0
  49. data/frontend/src/visual-settings-preset.js +103 -0
  50. data/frontend/src/visuals/geometry.js +268 -0
  51. data/frontend/src/visuals/image-renderer.js +291 -0
  52. data/frontend/src/visuals/particle-system.js +56 -10
  53. data/frontend/src/visuals/spectrogram-renderer.js +226 -0
  54. data/frontend/src/visuals/text-renderer.js +112 -11
  55. data/frontend/src/websocket-client.js +12 -1
  56. data/lib/vizcore/analysis/adaptive_normalizer.rb +70 -0
  57. data/lib/vizcore/analysis/beat_detector.rb +4 -2
  58. data/lib/vizcore/analysis/bpm_estimator.rb +8 -0
  59. data/lib/vizcore/analysis/feature_recorder.rb +159 -0
  60. data/lib/vizcore/analysis/feature_replay.rb +84 -0
  61. data/lib/vizcore/analysis/pipeline.rb +235 -11
  62. data/lib/vizcore/analysis/tap_tempo.rb +74 -0
  63. data/lib/vizcore/analysis.rb +4 -0
  64. data/lib/vizcore/audio/dummy_sine_input.rb +1 -1
  65. data/lib/vizcore/audio/fixture_input.rb +65 -0
  66. data/lib/vizcore/audio/input_manager.rb +4 -2
  67. data/lib/vizcore/audio/mic_input.rb +24 -8
  68. data/lib/vizcore/audio/portaudio_ffi.rb +106 -1
  69. data/lib/vizcore/audio.rb +1 -0
  70. data/lib/vizcore/cli/doctor.rb +159 -0
  71. data/lib/vizcore/cli/dsl_reference.rb +99 -0
  72. data/lib/vizcore/cli/layer_docs.rb +46 -0
  73. data/lib/vizcore/cli/scene_diagnostics.rb +23 -0
  74. data/lib/vizcore/cli/scene_inspector.rb +136 -0
  75. data/lib/vizcore/cli/scene_validator.rb +245 -0
  76. data/lib/vizcore/cli/shader_template.rb +68 -0
  77. data/lib/vizcore/cli/shader_uniform_docs.rb +54 -0
  78. data/lib/vizcore/cli.rb +689 -18
  79. data/lib/vizcore/config.rb +103 -2
  80. data/lib/vizcore/control_preset.rb +68 -0
  81. data/lib/vizcore/dsl/engine.rb +277 -5
  82. data/lib/vizcore/dsl/layer_builder.rb +491 -22
  83. data/lib/vizcore/dsl/layer_group_builder.rb +112 -0
  84. data/lib/vizcore/dsl/mapping_resolver.rb +132 -3
  85. data/lib/vizcore/dsl/mapping_transform_builder.rb +71 -0
  86. data/lib/vizcore/dsl/reaction_builder.rb +44 -0
  87. data/lib/vizcore/dsl/scene_builder.rb +61 -5
  88. data/lib/vizcore/dsl/shader_source_resolver.rb +67 -6
  89. data/lib/vizcore/dsl/style_builder.rb +68 -0
  90. data/lib/vizcore/dsl/timeline_builder.rb +138 -0
  91. data/lib/vizcore/dsl/transition_controller.rb +77 -0
  92. data/lib/vizcore/dsl.rb +5 -1
  93. data/lib/vizcore/layer_catalog.rb +273 -0
  94. data/lib/vizcore/project_manifest.rb +152 -0
  95. data/lib/vizcore/renderer/png_writer.rb +57 -0
  96. data/lib/vizcore/renderer/render_sequence.rb +153 -0
  97. data/lib/vizcore/renderer/scene_frame_source.rb +119 -0
  98. data/lib/vizcore/renderer/scene_serializer.rb +36 -3
  99. data/lib/vizcore/renderer/snapshot.rb +38 -0
  100. data/lib/vizcore/renderer/snapshot_renderer.rb +446 -0
  101. data/lib/vizcore/renderer.rb +5 -0
  102. data/lib/vizcore/server/frame_broadcaster.rb +91 -5
  103. data/lib/vizcore/server/gallery_app.rb +155 -0
  104. data/lib/vizcore/server/gallery_page.rb +100 -0
  105. data/lib/vizcore/server/gallery_runner.rb +48 -0
  106. data/lib/vizcore/server/rack_app.rb +203 -4
  107. data/lib/vizcore/server/runner.rb +370 -22
  108. data/lib/vizcore/server/scene_dependency_watcher.rb +79 -0
  109. data/lib/vizcore/server/websocket_handler.rb +60 -10
  110. data/lib/vizcore/server.rb +4 -0
  111. data/lib/vizcore/sync/osc_message.rb +103 -0
  112. data/lib/vizcore/sync/osc_receiver.rb +68 -0
  113. data/lib/vizcore/sync.rb +4 -0
  114. data/lib/vizcore/templates/midi_control_scene.rb +3 -1
  115. data/lib/vizcore/templates/plugin_layer.rb +20 -0
  116. data/lib/vizcore/templates/plugin_readme.md +23 -0
  117. data/lib/vizcore/templates/plugin_renderer.js +43 -0
  118. data/lib/vizcore/templates/plugin_scene.rb +14 -0
  119. data/lib/vizcore/templates/project_readme.md +7 -23
  120. data/lib/vizcore/templates/rubykaigi_scene.rb +30 -0
  121. data/lib/vizcore/version.rb +1 -1
  122. data/lib/vizcore.rb +27 -0
  123. data/scripts/browser_capture.mjs +75 -0
  124. data/sig/vizcore.rbs +362 -0
  125. metadata +83 -3
  126. data/docs/GETTING_STARTED.md +0 -105
@@ -0,0 +1,78 @@
1
+ # frozen_string_literal: true
2
+
3
+ # MIDI controller showcase: pads switch scenes, knobs control global shader uniforms.
4
+ Vizcore.define do
5
+ set :global_intensity, 0.65
6
+ set :global_color, 0.15
7
+
8
+ midi :controller, device: :default
9
+
10
+ scene :midi_warmup do
11
+ layer :ribbon do
12
+ shader :waveform_ribbon
13
+ blend :screen
14
+ effect :bloom
15
+ map mid, to: :effect_intensity, range: 0.08..0.24
16
+ end
17
+
18
+ layer :title do
19
+ type :text
20
+ content "MIDI CONTROL"
21
+ font_size 72
22
+ color "#e8fbff"
23
+ glow_strength 0.16
24
+ blend :screen
25
+ map beat_pulse, to: :glow_strength, range: 0.12..0.65
26
+ end
27
+ end
28
+
29
+ scene :midi_drop do
30
+ layer :stars do
31
+ shader :starfield
32
+ blend :screen
33
+ effect :glitch
34
+ map high, to: :effect_intensity, range: 0.1..0.65
35
+ end
36
+
37
+ layer :drop_text do
38
+ type :text
39
+ content "DROP"
40
+ font_size 118
41
+ color "#fff1d6"
42
+ glow_strength 0.25
43
+ blend :add
44
+ map beat_pulse, to: :glow_strength, range: 0.25..1.0
45
+ end
46
+ end
47
+
48
+ scene :midi_crystal do
49
+ layer :crystal do
50
+ shader :ruby_crystal
51
+ facets 7.0
52
+ refraction 0.44
53
+ blend :screen
54
+ map bass, to: :refraction, gain: 0.9, range: 0.32..0.82
55
+ map mid, to: :facets, gain: 1.8, range: 5.0..10.0
56
+ end
57
+ end
58
+
59
+ midi_map note: 36 do
60
+ switch_scene :midi_warmup
61
+ end
62
+
63
+ midi_map note: 37 do
64
+ switch_scene :midi_drop
65
+ end
66
+
67
+ midi_map note: 38 do
68
+ switch_scene :midi_crystal
69
+ end
70
+
71
+ midi_map cc: 1 do |value|
72
+ set :global_intensity, value / 127.0
73
+ end
74
+
75
+ midi_map cc: 2 do |value|
76
+ set :global_color, value / 127.0
77
+ end
78
+ end
@@ -1,11 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  Vizcore.define do
4
+ set :global_intensity, 0.65
5
+
4
6
  midi :controller, device: :default
5
7
 
6
8
  scene :warmup do
7
9
  layer :grid do
8
- shader :neon_grid
10
+ shader :waveform_ribbon
9
11
  map frequency_band(:mid) => :intensity
10
12
  end
11
13
  end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Parser-themed visual sketch: token flow, AST energy, and reduce flashes.
4
+ Vizcore.define do
5
+ scene :parser_visualizer do
6
+ layer :token_stream do
7
+ shader :waveform_ribbon
8
+ blend :screen
9
+ effect :crt
10
+ effect_intensity 0.18
11
+ map amplitude, to: :effect_intensity, range: 0.08..0.32
12
+ end
13
+
14
+ layer :ast_nodes do
15
+ type :particle_field
16
+ count 2200
17
+ force_field :vortex
18
+ turbulence 0.28
19
+ blend :add
20
+ map bass, to: :size, gain: 3.0, range: 1.8..6.5, curve: :sqrt
21
+ map mid, to: :speed, gain: 2.0, range: 0.4..4.2
22
+ map hihat, to: :sparkle, gain: 2.2, range: 0.0..1.0
23
+ end
24
+
25
+ layer :reduce_flash do
26
+ shader :ruby_crystal
27
+ facets 7.0
28
+ refraction 0.42
29
+ blend :add
30
+ effect :bloom
31
+ map kick, to: :effect_intensity, gain: 2.0, range: 0.05..0.55
32
+ map beat_pulse, to: :refraction, range: 0.32..0.86
33
+ end
34
+
35
+ layer :parser_label do
36
+ type :text
37
+ content "SHIFT -> REDUCE -> ACCEPT"
38
+ font "IBM Plex Mono"
39
+ font_size 58
40
+ align :center
41
+ fill "#d9ffe8"
42
+ stroke width: 2, color: "#06111f"
43
+ glow_strength 0.26
44
+ blend :screen
45
+ map beat_pulse, to: :glow_strength, range: 0.18..0.9
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Minimal scene used to generate docs/assets/vizcore-demo.gif.
4
+ # It intentionally shows one idea: detected beats expand the rings.
5
+ Vizcore.define do
6
+ scene :readme_demo do
7
+ layer :beat_rings do
8
+ palette "#24f6ff", "#ff2bbd", "#caff2e"
9
+
10
+ circle count: 4 do
11
+ radius 92
12
+ stroke 3
13
+ map beat_pulse, to: :radius, gain: 160.0, min: 56, max: 164, attack: 1.0, release: 0.2
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Recommended audio file for this scene:
4
+ # examples/assets/complex_demo_loop.wav
5
+ # Drum-only sync check:
6
+ # spec/fixtures/audio/kick_120bpm.wav
7
+ # Motion is gated by audio level, so silence holds the shape still.
8
+ Vizcore.define do
9
+ scene :rhythm_geometry do
10
+ layer :morphing_geometry do
11
+ shader :unyo_geometry
12
+ sides 7.0
13
+ scale 1.02
14
+ wobble 0.72
15
+ twist 0.84
16
+ pulse 0.0
17
+ kick 0.0
18
+ snare 0.0
19
+ line_glow 0.38
20
+ effect :bloom
21
+ effect_intensity 0.42
22
+
23
+ map beat_count => :seed
24
+ map beat_pulse, to: :pulse, range: 0.0..1.65, attack: 1.0, release: 0.14
25
+ map amplitude, to: :scale, gain: 0.7, range: 0.82..1.25, curve: :sqrt, attack: 0.95, release: 0.18
26
+ map frequency_band(:low), to: :kick, gain: 3.8, range: 0.0..1.45, curve: :sqrt, attack: 1.0, release: 0.08
27
+ map frequency_band(:low), to: :wobble, gain: 3.0, range: 0.45..1.7, curve: :sqrt, attack: 0.95, release: 0.16
28
+ map frequency_band(:mid), to: :twist, gain: 2.4, range: 0.55..2.4, curve: :sqrt
29
+ map frequency_band(:high), to: :snare, gain: 2.2, range: 0.0..1.1, curve: :sqrt, attack: 1.0, release: 0.12
30
+ map frequency_band(:high), to: :line_glow, gain: 2.0, range: 0.28..1.3
31
+ map frequency_band(:high), to: :effect_intensity, gain: 1.4, range: 0.24..0.78
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Ruby-themed showcase using crystal, text, and particle layers.
4
+ Vizcore.define do
5
+ scene :ruby_crystal do
6
+ layer :crystal_core do
7
+ shader :ruby_crystal
8
+ facets 6.0
9
+ refraction 0.48
10
+ blend :screen
11
+
12
+ map bass, to: :refraction, gain: 0.8, range: 0.28..0.78, curve: :sqrt
13
+ map mid, to: :facets, gain: 2.0, range: 5.0..10.0
14
+ end
15
+
16
+ layer :gem_sparks do
17
+ type :particle_field
18
+ count 2600
19
+ blend :add
20
+ map amplitude, to: :speed, gain: 2.6, range: 0.2..4.8, curve: :sqrt
21
+ map bass, to: :size, gain: 3.2, range: 1.8..7.0
22
+ map treble, to: :sparkle, gain: 2.6, range: 0.0..1.0
23
+ end
24
+
25
+ layer :ruby_title do
26
+ type :text
27
+ content "RUBY"
28
+ font_size 118
29
+ color "#ff335f"
30
+ glow_strength 0.35
31
+ blend :screen
32
+ map beat_pulse, to: :glow_strength, range: 0.24..0.9
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Minimal shader-focused scene for trying mapped parameters.
4
+ Vizcore.define do
5
+ scene :shader_playground do
6
+ layer :liquid do
7
+ shader :liquid_wobble
8
+ param :wobble, default: 0.35, range: 0.0..2.0, step: 0.05
9
+ param :warp, default: 0.45, range: 0.0..3.0, step: 0.05
10
+ param :distortion, default: 0.25, range: 0.0..2.0, step: 0.05
11
+ blend :screen
12
+
13
+ map amplitude, to: :wobble, gain: 2.2, range: 0.18..1.2, curve: :sqrt
14
+ map bass, to: :warp, gain: 2.4, range: 0.25..2.2
15
+ map treble, to: :distortion, gain: 2.0, range: 0.2..1.6
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ Vizcore.define do
4
+ scene :unyo do
5
+ layer :liquid do
6
+ shader :liquid_wobble
7
+ opacity 1.0
8
+ blend :alpha
9
+ effect :feedback
10
+ effect_intensity 0.14
11
+ wobble 0.25
12
+ warp 0.45
13
+ distortion 0.25
14
+
15
+ map amplitude, to: :wobble, gain: 3.5, range: 0.12..1.4, curve: :sqrt, attack: 0.9, release: 0.18
16
+ map frequency_band(:low), to: :warp, gain: 2.2, range: 0.25..2.4, attack: 0.8, release: 0.2
17
+ map frequency_band(:high), to: :distortion, gain: 1.8, range: 0.1..1.6
18
+ map beat_pulse, to: :effect_intensity, range: 0.08..0.35, attack: 1.0, release: 0.2
19
+ end
20
+
21
+ layer :particles do
22
+ type :particle_field
23
+ count 7000
24
+ blend :add
25
+ opacity 0.55
26
+ size 2.8
27
+ force_field :vortex
28
+ turbulence 0.55
29
+ bass_explosion 0.9
30
+ sparkle 0.35
31
+
32
+ map amplitude, to: :speed, gain: 4.0, range: 0.4..4.0, curve: :sqrt
33
+ map frequency_band(:low), to: :size, gain: 6.0, range: 2.0..8.0, curve: :sqrt
34
+ map beat_pulse, to: :bass_explosion, gain: 1.2, range: 0.3..1.8
35
+ end
36
+
37
+ layer :blob_outline do
38
+ type :radial_blob
39
+ blend :add
40
+ opacity 0.65
41
+ segments 192
42
+ radius 0.42
43
+ wobble 0.2
44
+
45
+ map fft_spectrum => :spectrum
46
+ map amplitude, to: :wobble, gain: 2.8, range: 0.08..0.75, curve: :sqrt
47
+ map frequency_band(:low), to: :radius, gain: 0.8, range: 0.36..0.72
48
+ end
49
+
50
+ layer :title do
51
+ type :text
52
+ content "UNYO"
53
+ font_size 72
54
+ color "#f8fbff"
55
+ glow_strength 0.08
56
+ map beat_pulse, to: :glow_strength, range: 0.08..0.42, attack: 1.0, release: 0.2
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,124 @@
1
+ # frozen_string_literal: true
2
+
3
+ # vj_ambient_chill_room.rb
4
+ #
5
+ # Genre : Ambient / Chill Room
6
+ # BPM : none, or 60-90 when a pulse appears
7
+ # Duration: slow rotation between two long scenes
8
+ # Audio : --audio-source mic
9
+ # --audio-source file --audio-file examples/assets/complex_demo_loop.wav
10
+ # Keys : 1 bloom, 2 nebula, B blackout, F freeze
11
+ # MIDI : note 36..37 = scenes, CC 1 = global intensity
12
+ Vizcore.define do
13
+ set :global_intensity, 0.7
14
+ audio_normalize mode: :adaptive, window: 8.0, target: 0.72, floor: 0.03
15
+
16
+ theme :chill_room do
17
+ palette "#1e293b", "#64748b", "#a5b4fc", "#f8fafc"
18
+ background "#020617"
19
+ end
20
+
21
+ style :soft_screen do
22
+ blend :screen
23
+ opacity 0.52
24
+ end
25
+
26
+ scene :bloom do
27
+ use_theme :chill_room
28
+
29
+ layer :slow_ribbon do
30
+ shader :waveform_ribbon
31
+ use_style :soft_screen
32
+ effect :bloom
33
+ effect_intensity 0.18
34
+ map amplitude, to: :opacity, gain: 0.85, range: 0.28..0.86, curve: :sqrt, attack: 0.18, release: 0.72
35
+ map beat_pulse, to: :effect_intensity, range: 0.12..0.34, attack: 0.24, release: 0.82
36
+ map fft_spectrum => :deform
37
+ end
38
+
39
+ layer :breathing_halo do
40
+ type :radial_blob
41
+ opacity 0.46
42
+ blend :add
43
+ segments 192
44
+ radius 0.42
45
+ wobble 0.18
46
+ map amplitude, to: :wobble, gain: 1.3, range: 0.08..0.48, curve: :sqrt, attack: 0.2, release: 0.82
47
+ map beat_confidence, to: :radius, gain: 0.14, range: 0.38..0.54
48
+ map fft_spectrum => :deform
49
+ end
50
+ end
51
+
52
+ scene :nebula do
53
+ use_theme :chill_room
54
+
55
+ layer :deep_spectrum do
56
+ type :spectrogram
57
+ scroll :horizontal
58
+ bins 80
59
+ history 220
60
+ gain 0.62
61
+ opacity 0.5
62
+ blend :screen
63
+ effect :motion_blur
64
+ effect_intensity 0.12
65
+ map amplitude, to: :opacity, gain: 0.7, range: 0.22..0.68, attack: 0.18, release: 0.76
66
+ map beat_pulse, to: :effect_intensity, range: 0.08..0.26, release: 0.82
67
+ map fft_spectrum => :deform
68
+ end
69
+
70
+ layer :nebula_points do
71
+ type :particle_field
72
+ count 1200
73
+ speed 0.18
74
+ size 2.6
75
+ force_field :drift
76
+ turbulence 0.12
77
+ opacity 0.42
78
+ blend :add
79
+ map amplitude, to: :speed, gain: 0.9, range: 0.08..0.72, curve: :sqrt, attack: 0.22, release: 0.84
80
+ map low, to: :size, gain: 2.2, range: 1.8..5.2
81
+ map fft_spectrum => :deform
82
+ end
83
+ end
84
+
85
+ transition from: :bloom, to: :nebula do
86
+ trigger { seconds >= 90 || beat_count >= 96 }
87
+ effect :crossfade, duration: 3.0
88
+ end
89
+
90
+ transition from: :nebula, to: :bloom do
91
+ trigger { seconds >= 90 || beat_count >= 96 }
92
+ effect :crossfade, duration: 3.0
93
+ end
94
+
95
+ midi :controller, device: :default
96
+
97
+ midi_map note: 36 do
98
+ switch_scene :bloom
99
+ end
100
+
101
+ midi_map note: 37 do
102
+ switch_scene :nebula
103
+ end
104
+
105
+ midi_map cc: 1 do |value|
106
+ set :global_intensity, value / 127.0
107
+ end
108
+
109
+ key "1" do
110
+ switch_scene :bloom
111
+ end
112
+
113
+ key "2" do
114
+ switch_scene :nebula
115
+ end
116
+
117
+ key "b" do
118
+ blackout
119
+ end
120
+
121
+ key "f" do
122
+ freeze
123
+ end
124
+ end
@@ -0,0 +1,170 @@
1
+ # frozen_string_literal: true
2
+
3
+ # vj_dnb_jungle.rb
4
+ #
5
+ # Genre : Drum & Bass / Jungle
6
+ # BPM : 170-180
7
+ # Duration: 3-scene break workout
8
+ # Audio : --audio-source mic
9
+ # --audio-source file --audio-file examples/assets/complex_demo_loop.wav
10
+ # Keys : 1 rollers, 2 amen, 3 reese, B blackout, F freeze, Space tap-tempo
11
+ # MIDI : note 36..38 = scenes, note 40 = reese, CC 1 = global intensity
12
+ Vizcore.define do
13
+ set :global_intensity, 0.88
14
+ audio_normalize mode: :adaptive, window: 2.5, target: 0.86, floor: 0.04
15
+ bpm 176
16
+ bpm_lock true
17
+ tap_tempo key: :space
18
+
19
+ theme :jungle_neon do
20
+ palette "#00f5d4", "#00bbf9", "#f15bb5", "#fee440"
21
+ background "#030712"
22
+ end
23
+
24
+ style :fast_add do
25
+ blend :add
26
+ opacity 0.76
27
+ end
28
+
29
+ scene :rollers do
30
+ use_theme :jungle_neon
31
+
32
+ layer :star_tunnel do
33
+ shader :starfield
34
+ blend :screen
35
+ effect :motion_blur
36
+ effect_intensity 0.16
37
+ map amplitude, to: :warp, gain: 1.8, range: 0.18..1.3, curve: :sqrt
38
+ map beat_pulse, to: :effect_intensity, range: 0.12..0.42, attack: 1.0, release: 0.08
39
+ map fft_spectrum => :deform
40
+ end
41
+
42
+ layer :rolling_particles do
43
+ type :particle_field
44
+ count 4200 # tune: 2600 for laptops, 6000 for stage machines
45
+ force_field :flow
46
+ speed 2.6
47
+ size 1.6
48
+ use_style :fast_add
49
+ react_to amplitude do
50
+ change :speed, gain: 3.6, range: 1.2..7.2, curve: :sqrt
51
+ change :size, gain: 2.4, range: 1.2..4.6
52
+ end
53
+ map hihat, to: :sparkle, gain: 2.8, range: 0.1..1.0, attack: 1.0, release: 0.05
54
+ map fft_spectrum => :deform
55
+ end
56
+ end
57
+
58
+ scene :amen do
59
+ use_theme :jungle_neon
60
+
61
+ layer :kick_cube do
62
+ type :wireframe_cube
63
+ opacity 0.6
64
+ blend :add
65
+ map kick, to: :scale, gain: 0.9, range: 0.74..1.46, curve: :sqrt, attack: 1.0, release: 0.08
66
+ map low, to: :rotation_speed, gain: 1.4, range: 0.12..2.4
67
+ map fft_spectrum => :deform
68
+ end
69
+
70
+ layer :snare_cube do
71
+ type :wireframe_cube
72
+ opacity 0.48
73
+ blend :difference
74
+ map snare, to: :color_shift, gain: 2.2, range: 0.1..1.0, attack: 1.0, release: 0.06
75
+ map mid, to: :rotation_speed, gain: 1.6, range: 0.2..2.8
76
+ map fft_spectrum => :deform
77
+ end
78
+
79
+ layer :hat_text do
80
+ type :text
81
+ content "176 BPM"
82
+ font "Inter"
83
+ font_size 52
84
+ align :center
85
+ color "#eaffff"
86
+ glow_strength 0.18
87
+ blend :screen
88
+ map hihat, to: :glow_strength, gain: 2.8, range: 0.16..0.95, attack: 1.0, release: 0.05
89
+ map beat_pulse, to: :letter_spacing, gain: 18.0, min: 0.0, max: 24.0
90
+ map fft_spectrum => :deform
91
+ end
92
+ end
93
+
94
+ scene :reese do
95
+ use_theme :jungle_neon
96
+
97
+ layer :reese_warp do
98
+ shader :bass_tunnel
99
+ blend :screen
100
+ effect :feedback
101
+ effect_intensity 0.18
102
+ map bass, to: :warp, gain: 3.0, range: 0.2..2.2, curve: :sqrt
103
+ map kick, to: :effect_intensity, gain: 1.1, range: 0.12..0.62, attack: 1.0, release: 0.1
104
+ map fft_spectrum => :deform
105
+ end
106
+
107
+ layer :chromatic_noise do
108
+ shader :glitch_flash
109
+ blend :add
110
+ effect :chromatic
111
+ effect_intensity 0.22
112
+ opacity 0.58
113
+ map amplitude, to: :opacity, gain: 0.8, range: 0.34..0.84
114
+ map onset(:high), to: :effect_intensity, gain: 2.4, range: 0.12..0.9, attack: 1.0, release: 0.05
115
+ map fft_spectrum => :deform
116
+ end
117
+ end
118
+
119
+ transition from: :rollers, to: :amen do
120
+ trigger { beat_count >= 32 || frame_count >= 360 }
121
+ effect :crossfade, duration: 0.45
122
+ end
123
+
124
+ transition from: :amen, to: :rollers do
125
+ trigger { beat_count >= 64 || frame_count >= 720 }
126
+ effect :flash, duration: 0.18
127
+ end
128
+
129
+ midi :controller, device: :default
130
+
131
+ midi_map note: 36 do
132
+ switch_scene :rollers
133
+ end
134
+
135
+ midi_map note: 37 do
136
+ switch_scene :amen
137
+ end
138
+
139
+ midi_map note: 38 do
140
+ switch_scene :reese
141
+ end
142
+
143
+ midi_map note: 40 do
144
+ switch_scene :reese
145
+ end
146
+
147
+ midi_map cc: 1 do |value|
148
+ set :global_intensity, value / 127.0
149
+ end
150
+
151
+ key "1" do
152
+ switch_scene :rollers
153
+ end
154
+
155
+ key "2" do
156
+ switch_scene :amen
157
+ end
158
+
159
+ key "3" do
160
+ switch_scene :reese
161
+ end
162
+
163
+ key "b" do
164
+ blackout
165
+ end
166
+
167
+ key "f" do
168
+ freeze
169
+ end
170
+ end