summaryrefslogtreecommitdiff
path: root/internal
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-04-27 09:30:32 +0300
committerPaul Buetow <paul@buetow.org>2026-04-27 09:30:32 +0300
commit06dd860ddc915031d2356faf23e73a16bb2b19cf (patch)
tree8239ca6d6810af2922b1bbc24048dc54eca9e159 /internal
parent91ac0b2136b5cdf19d30141b8575f21c06afbfd1 (diff)
refactor(generator): move theme sound data from Go code to embedded JSON files
- Generate sounds.json for each theme inside templates/themes/<name>/ - Load sound data at runtime from embedded FS via templates.ThemeSounds() - Replace ~1100 lines of hardcoded builder functions and presets with a 145-line loader (soundCache, initSoundCache, loadThemeSounds) - Update embed.go to include themes/*/sounds.json in the embedded FS - Update tests to use loadThemeSounds() instead of themeSoundPresets - Eliminates duplication between themeSoundPresets and JSON output Improves cohesion and DRY by keeping theme assets (CSS, JS, meta, sounds) in a single location per theme directory.
Diffstat (limited to 'internal')
-rw-r--r--internal/generator/generator_test.go19
-rw-r--r--internal/generator/templates/embed.go10
-rw-r--r--internal/generator/templates/themes/aurora/sounds.json447
-rw-r--r--internal/generator/templates/themes/biomech/sounds.json492
-rw-r--r--internal/generator/templates/themes/brutalist/sounds.json342
-rw-r--r--internal/generator/templates/themes/cathedral/sounds.json572
-rw-r--r--internal/generator/templates/themes/cosmos/sounds.json497
-rw-r--r--internal/generator/templates/themes/dos/sounds.json367
-rw-r--r--internal/generator/templates/themes/matrix/sounds.json283
-rw-r--r--internal/generator/templates/themes/neon/sounds.json337
-rw-r--r--internal/generator/templates/themes/noir/sounds.json472
-rw-r--r--internal/generator/templates/themes/nukem/sounds.json367
-rw-r--r--internal/generator/templates/themes/ocean/sounds.json427
-rw-r--r--internal/generator/templates/themes/plasma/sounds.json372
-rw-r--r--internal/generator/templates/themes/retro/sounds.json612
-rw-r--r--internal/generator/templates/themes/retrofuture/sounds.json322
-rw-r--r--internal/generator/templates/themes/spaceage/sounds.json472
-rw-r--r--internal/generator/templates/themes/surveillance/sounds.json451
-rw-r--r--internal/generator/templates/themes/synthwave/sounds.json472
-rw-r--r--internal/generator/templates/themes/terminal/sounds.json381
-rw-r--r--internal/generator/templates/themes/tropicale/sounds.json382
-rw-r--r--internal/generator/templates/themes/volcano/sounds.json322
-rw-r--r--internal/generator/theme_sounds.go1196
23 files changed, 8444 insertions, 1170 deletions
diff --git a/internal/generator/generator_test.go b/internal/generator/generator_test.go
index 50cd3d0..10116a2 100644
--- a/internal/generator/generator_test.go
+++ b/internal/generator/generator_test.go
@@ -94,15 +94,6 @@ func TestJSONStringOrNull(t *testing.T) {
}
}
-func TestThemeSoundPresetsMatchRegistry(t *testing.T) {
- t.Parallel()
- for name := range getThemeSet() {
- if _, ok := themeSoundPresets[name]; !ok {
- t.Errorf("theme %q has no sound preset in themeSoundPresets", name)
- }
- }
-}
-
func TestThemeSoundsJSONNonEmpty(t *testing.T) {
t.Parallel()
j := themeSoundsJSON("neon")
@@ -152,9 +143,9 @@ func TestThemeSoundPresetsAmbientPopulated(t *testing.T) {
t.Parallel()
for name := range getThemeSet() {
- preset, ok := themeSoundPresets[name]
- if !ok {
- t.Errorf("theme %q missing from themeSoundPresets", name)
+ preset, err := loadThemeSounds(name)
+ if err != nil {
+ t.Errorf("theme %q loadThemeSounds: %v", name, err)
continue
}
@@ -174,8 +165,8 @@ func TestThemeSoundPresetsAmbientValuesBounded(t *testing.T) {
t.Parallel()
for name := range getThemeSet() {
- preset, ok := themeSoundPresets[name]
- if !ok {
+ preset, err := loadThemeSounds(name)
+ if err != nil {
continue
}
diff --git a/internal/generator/templates/embed.go b/internal/generator/templates/embed.go
index ac3efbd..c5a4b22 100644
--- a/internal/generator/templates/embed.go
+++ b/internal/generator/templates/embed.go
@@ -1,6 +1,7 @@
// Package templates exposes the embedded HTML shell, shared CSS/JS bundles,
// and per-theme assets used by the generator. Themes live as directories
-// under templates/themes/<name>/ containing theme.css, theme.js, and meta.json.
+// under templates/themes/<name>/ containing theme.css, theme.js, meta.json,
+// and sounds.json.
// All assets are compiled into the binary via //go:embed so snonux still ships
// as a single self-contained executable.
package templates
@@ -13,7 +14,7 @@ import (
"sort"
)
-//go:embed shell.tmpl shared/*.tmpl shared/shared.css shared/shared.js themes/*/theme.css themes/*/theme.js themes/*/meta.json
+//go:embed shell.tmpl shared/*.tmpl shared/shared.css shared/shared.js themes/*/theme.css themes/*/theme.js themes/*/meta.json themes/*/sounds.json
var FS embed.FS
// Shell returns the body of shell.tmpl — the single page template used for
@@ -64,6 +65,11 @@ func ThemeMeta(name string) ([]byte, error) {
return FS.ReadFile(path.Join("themes", name, "meta.json"))
}
+// ThemeSounds returns the per-theme sounds.json bytes for the named theme.
+func ThemeSounds(name string) ([]byte, error) {
+ return FS.ReadFile(path.Join("themes", name, "sounds.json"))
+}
+
// ThemeNames returns a sorted list of available theme names derived from the
// directories present under templates/themes/.
func ThemeNames() ([]string, error) {
diff --git a/internal/generator/templates/themes/aurora/sounds.json b/internal/generator/templates/themes/aurora/sounds.json
new file mode 100644
index 0000000..1440fe9
--- /dev/null
+++ b/internal/generator/templates/themes/aurora/sounds.json
@@ -0,0 +1,447 @@
+{
+ "splash": {
+ "freqs": [
+ 392,
+ 493.88,
+ 587.33,
+ 783.99
+ ],
+ "spacing": 0.08,
+ "gain": 0.09,
+ "wave": "sine"
+ },
+ "nav": {
+ "freq": 261.63,
+ "wave": "triangle",
+ "dur": 0.085,
+ "gain": 0.1
+ },
+ "open": {
+ "wave": "sine",
+ "start": 390,
+ "end": 780,
+ "dur": 0.16,
+ "gain": 0.1
+ },
+ "close": {
+ "wave": "sine",
+ "start": 523,
+ "end": 196,
+ "dur": 0.18,
+ "gain": 0.09
+ },
+ "bounce": {
+ "wave": "triangle",
+ "start": 180,
+ "end": 90,
+ "dur": 0.12,
+ "gain": 0.09
+ },
+ "ambient": {
+ "normal": {
+ "bpm": 130,
+ "gain": 0.032,
+ "wave": "triangle",
+ "droneFreqs": [
+ 98,
+ 146.83,
+ 196
+ ],
+ "cutoffMin": 1200,
+ "cutoffMax": 5500,
+ "attack": 0.02,
+ "release": 0.1,
+ "melody": [
+ {
+ "freq": 98,
+ "dur": 0.3927,
+ "step": 0.462
+ },
+ {
+ "freq": 196,
+ "dur": 0.3927,
+ "step": 0.462
+ },
+ {
+ "freq": 98,
+ "dur": 0.3927,
+ "step": 0.462
+ },
+ {
+ "freq": 146.8340935339148,
+ "dur": 0.3927,
+ "step": 0.462
+ },
+ {
+ "freq": 196,
+ "dur": 1.77408,
+ "step": 0.6283200000000001
+ },
+ {
+ "freq": 246.9445257793951,
+ "dur": 1.1457600000000001,
+ "step": 0.60984
+ },
+ {
+ "freq": 293.6681870678296,
+ "dur": 0.5544,
+ "step": 0.60984
+ },
+ {
+ "freq": 783.99,
+ "dur": 0.21252000000000001,
+ "step": 0.231
+ },
+ {
+ "freq": 880,
+ "dur": 0.21252000000000001,
+ "step": 0.231
+ },
+ {
+ "freq": 987.77,
+ "dur": 0.21252000000000001,
+ "step": 0.231
+ },
+ {
+ "freq": 1174.66,
+ "dur": 0.21252000000000001,
+ "step": 0.231
+ },
+ {
+ "freq": 987.77,
+ "dur": 0.21252000000000001,
+ "step": 0.231
+ },
+ {
+ "freq": 880,
+ "dur": 0.42504000000000003,
+ "step": 0.462
+ },
+ {
+ "freq": 783.99,
+ "dur": 0.21252000000000001,
+ "step": 0.231
+ },
+ {
+ "freq": 82.41,
+ "dur": 0.3927,
+ "step": 0.462
+ },
+ {
+ "freq": 164.82,
+ "dur": 0.3927,
+ "step": 0.462
+ },
+ {
+ "freq": 82.41,
+ "dur": 0.3927,
+ "step": 0.462
+ },
+ {
+ "freq": 123.47548620540732,
+ "dur": 0.3927,
+ "step": 0.462
+ },
+ {
+ "freq": 164.81,
+ "dur": 1.77408,
+ "step": 0.6283200000000001
+ },
+ {
+ "freq": 195.99322462359845,
+ "dur": 1.1457600000000001,
+ "step": 0.60984
+ },
+ {
+ "freq": 246.9359893400459,
+ "dur": 0.5544,
+ "step": 0.60984
+ },
+ {
+ "freq": 659.25,
+ "dur": 0.21252000000000001,
+ "step": 0.231
+ },
+ {
+ "freq": 783.99,
+ "dur": 0.21252000000000001,
+ "step": 0.231
+ },
+ {
+ "freq": 880,
+ "dur": 0.21252000000000001,
+ "step": 0.231
+ },
+ {
+ "freq": 987.77,
+ "dur": 0.21252000000000001,
+ "step": 0.231
+ },
+ {
+ "freq": 880,
+ "dur": 0.21252000000000001,
+ "step": 0.231
+ },
+ {
+ "freq": 783.99,
+ "dur": 0.42504000000000003,
+ "step": 0.462
+ },
+ {
+ "freq": 659.25,
+ "dur": 0.21252000000000001,
+ "step": 0.231
+ },
+ {
+ "freq": 65.41,
+ "dur": 0.3927,
+ "step": 0.462
+ },
+ {
+ "freq": 130.82,
+ "dur": 0.3927,
+ "step": 0.462
+ },
+ {
+ "freq": 65.41,
+ "dur": 0.3927,
+ "step": 0.462
+ },
+ {
+ "freq": 98.00426589850373,
+ "dur": 0.3927,
+ "step": 0.462
+ },
+ {
+ "freq": 130.81,
+ "dur": 1.77408,
+ "step": 0.6283200000000001
+ },
+ {
+ "freq": 164.81027253674833,
+ "dur": 1.1457600000000001,
+ "step": 0.60984
+ },
+ {
+ "freq": 195.9935487262387,
+ "dur": 0.5544,
+ "step": 0.60984
+ },
+ {
+ "freq": 783.99,
+ "dur": 0.21252000000000001,
+ "step": 0.231
+ },
+ {
+ "freq": 880,
+ "dur": 0.21252000000000001,
+ "step": 0.231
+ },
+ {
+ "freq": 987.77,
+ "dur": 0.21252000000000001,
+ "step": 0.231
+ },
+ {
+ "freq": 1174.66,
+ "dur": 0.21252000000000001,
+ "step": 0.231
+ },
+ {
+ "freq": 1318.5,
+ "dur": 0.42504000000000003,
+ "step": 0.462
+ },
+ {
+ "freq": 1174.66,
+ "dur": 0.42504000000000003,
+ "step": 0.462
+ },
+ {
+ "freq": 73.42,
+ "dur": 0.3927,
+ "step": 0.462
+ },
+ {
+ "freq": 146.84,
+ "dur": 0.3927,
+ "step": 0.462
+ },
+ {
+ "freq": 73.42,
+ "dur": 0.3927,
+ "step": 0.462
+ },
+ {
+ "freq": 110.00570558428596,
+ "dur": 0.3927,
+ "step": 0.462
+ },
+ {
+ "freq": 146.83,
+ "dur": 1.77408,
+ "step": 0.6283200000000001
+ },
+ {
+ "freq": 184.9942077560642,
+ "dur": 1.1457600000000001,
+ "step": 0.60984
+ },
+ {
+ "freq": 219.99642809780318,
+ "dur": 0.5544,
+ "step": 0.60984
+ },
+ {
+ "freq": 880,
+ "dur": 0.21252000000000001,
+ "step": 0.231
+ },
+ {
+ "freq": 987.77,
+ "dur": 0.21252000000000001,
+ "step": 0.231
+ },
+ {
+ "freq": 1174.66,
+ "dur": 0.21252000000000001,
+ "step": 0.231
+ },
+ {
+ "freq": 1318.5,
+ "dur": 0.21252000000000001,
+ "step": 0.231
+ },
+ {
+ "freq": 1174.66,
+ "dur": 0.21252000000000001,
+ "step": 0.231
+ },
+ {
+ "freq": 987.77,
+ "dur": 0.42504000000000003,
+ "step": 0.462
+ },
+ {
+ "freq": 880,
+ "dur": 0.21252000000000001,
+ "step": 0.231
+ }
+ ],
+ "drums": [
+ "kick",
+ "_",
+ "hat",
+ "kick",
+ "snare",
+ "_",
+ "hat",
+ "_",
+ "kick",
+ "kick",
+ "hat",
+ "_",
+ "snare",
+ "_",
+ "hat",
+ "clap"
+ ]
+ },
+ "wild": {
+ "bpm": 170,
+ "gain": 0.065,
+ "wave": "sawtooth",
+ "droneFreqs": [
+ 98,
+ 196,
+ 293.66,
+ 392
+ ],
+ "cutoffMin": 2200,
+ "cutoffMax": 7500,
+ "attack": 0.02,
+ "release": 0.05,
+ "detuneCents": 12,
+ "melody": [
+ {
+ "freq": 196,
+ "dur": 0.30005,
+ "step": 0.353
+ },
+ {
+ "freq": 392,
+ "dur": 0.30005,
+ "step": 0.353
+ },
+ {
+ "freq": 196,
+ "dur": 0.30005,
+ "step": 0.353
+ },
+ {
+ "freq": 293.6681870678296,
+ "dur": 0.30005,
+ "step": 0.353
+ },
+ {
+ "freq": 1567.98,
+ "dur": 0.08119,
+ "step": 0.08825
+ },
+ {
+ "freq": 1760,
+ "dur": 0.08119,
+ "step": 0.08825
+ },
+ {
+ "freq": 1975.53,
+ "dur": 0.08119,
+ "step": 0.08825
+ },
+ {
+ "freq": 2349.32,
+ "dur": 0.08119,
+ "step": 0.08825
+ },
+ {
+ "freq": 1975.53,
+ "dur": 0.08119,
+ "step": 0.08825
+ },
+ {
+ "freq": 1760,
+ "dur": 0.08119,
+ "step": 0.08825
+ },
+ {
+ "freq": 1567.98,
+ "dur": 0.08119,
+ "step": 0.08825
+ },
+ {
+ "freq": 1318.5,
+ "dur": 0.08119,
+ "step": 0.08825
+ }
+ ],
+ "drums": [
+ "kick",
+ "_",
+ "hat",
+ "kick",
+ "snare",
+ "_",
+ "hat",
+ "_",
+ "kick",
+ "kick",
+ "hat",
+ "_",
+ "snare",
+ "_",
+ "hat",
+ "clap"
+ ]
+ }
+ }
+}
diff --git a/internal/generator/templates/themes/biomech/sounds.json b/internal/generator/templates/themes/biomech/sounds.json
new file mode 100644
index 0000000..ecb54ae
--- /dev/null
+++ b/internal/generator/templates/themes/biomech/sounds.json
@@ -0,0 +1,492 @@
+{
+ "splash": {
+ "freqs": [
+ 164.81,
+ 246.94,
+ 311.13,
+ 466.16
+ ],
+ "spacing": 0.09,
+ "gain": 0.095,
+ "wave": "triangle"
+ },
+ "nav": {
+ "freq": 233.08,
+ "wave": "sine",
+ "dur": 0.085,
+ "gain": 0.1
+ },
+ "open": {
+ "wave": "triangle",
+ "start": 220,
+ "end": 523.25,
+ "dur": 0.18,
+ "gain": 0.095
+ },
+ "close": {
+ "wave": "sine",
+ "start": 392,
+ "end": 130.81,
+ "dur": 0.2,
+ "gain": 0.09
+ },
+ "bounce": {
+ "wave": "triangle",
+ "start": 160,
+ "end": 80,
+ "dur": 0.14,
+ "gain": 0.09
+ },
+ "ambient": {
+ "normal": {
+ "bpm": 150,
+ "gain": 0.032,
+ "wave": "sawtooth",
+ "droneFreqs": [
+ 69.3,
+ 110,
+ 138.59
+ ],
+ "cutoffMin": 1200,
+ "cutoffMax": 5500,
+ "attack": 0.02,
+ "release": 0.08,
+ "melody": [
+ {
+ "freq": 69.3,
+ "dur": 0.17,
+ "step": 0.2
+ },
+ {
+ "freq": 82.41205306968857,
+ "dur": 0.17,
+ "step": 0.2
+ },
+ {
+ "freq": 98.00499987245549,
+ "dur": 0.17,
+ "step": 0.2
+ },
+ {
+ "freq": 123.47856233425104,
+ "dur": 0.17,
+ "step": 0.2
+ },
+ {
+ "freq": 138.59,
+ "dur": 1.536,
+ "step": 0.544
+ },
+ {
+ "freq": 164.81221406822712,
+ "dur": 0.992,
+ "step": 0.528
+ },
+ {
+ "freq": 207.6503777843393,
+ "dur": 0.48,
+ "step": 0.528
+ },
+ {
+ "freq": 138.59,
+ "dur": 0.17,
+ "step": 0.2
+ },
+ {
+ "freq": 164.81221406822712,
+ "dur": 0.17,
+ "step": 0.2
+ },
+ {
+ "freq": 195.99585760928727,
+ "dur": 0.17,
+ "step": 0.2
+ },
+ {
+ "freq": 246.93930669413928,
+ "dur": 0.17,
+ "step": 0.2
+ },
+ {
+ "freq": 277.18,
+ "dur": 0.17,
+ "step": 0.2
+ },
+ {
+ "freq": 329.62442813645424,
+ "dur": 0.17,
+ "step": 0.2
+ },
+ {
+ "freq": 391.99171521857454,
+ "dur": 0.17,
+ "step": 0.2
+ },
+ {
+ "freq": 493.87861338827855,
+ "dur": 0.17,
+ "step": 0.2
+ },
+ {
+ "freq": 82.41,
+ "dur": 0.17,
+ "step": 0.2
+ },
+ {
+ "freq": 98.00255834737423,
+ "dur": 0.17,
+ "step": 0.2
+ },
+ {
+ "freq": 116.54533967516677,
+ "dur": 0.17,
+ "step": 0.2
+ },
+ {
+ "freq": 146.83792672389072,
+ "dur": 0.17,
+ "step": 0.2
+ },
+ {
+ "freq": 164.81,
+ "dur": 1.536,
+ "step": 0.544
+ },
+ {
+ "freq": 195.99322462359845,
+ "dur": 0.992,
+ "step": 0.528
+ },
+ {
+ "freq": 246.9359893400459,
+ "dur": 0.48,
+ "step": 0.528
+ },
+ {
+ "freq": 164.81,
+ "dur": 0.17,
+ "step": 0.2
+ },
+ {
+ "freq": 195.99322462359845,
+ "dur": 0.17,
+ "step": 0.2
+ },
+ {
+ "freq": 233.07653721470982,
+ "dur": 0.17,
+ "step": 0.2
+ },
+ {
+ "freq": 293.6580354734187,
+ "dur": 0.17,
+ "step": 0.2
+ },
+ {
+ "freq": 329.63,
+ "dur": 0.17,
+ "step": 0.2
+ },
+ {
+ "freq": 391.99834131834695,
+ "dur": 0.17,
+ "step": 0.2
+ },
+ {
+ "freq": 466.16721656504336,
+ "dur": 0.17,
+ "step": 0.2
+ },
+ {
+ "freq": 587.3338889212001,
+ "dur": 0.17,
+ "step": 0.2
+ },
+ {
+ "freq": 58.27,
+ "dur": 0.17,
+ "step": 0.2
+ },
+ {
+ "freq": 69.29509859120856,
+ "dur": 0.17,
+ "step": 0.2
+ },
+ {
+ "freq": 82.40622427948026,
+ "dur": 0.17,
+ "step": 0.2
+ },
+ {
+ "freq": 103.82533661207516,
+ "dur": 0.17,
+ "step": 0.2
+ },
+ {
+ "freq": 116.54,
+ "dur": 1.536,
+ "step": 0.544
+ },
+ {
+ "freq": 146.8311991547485,
+ "dur": 0.992,
+ "step": 0.528
+ },
+ {
+ "freq": 174.61270673920848,
+ "dur": 0.48,
+ "step": 0.528
+ },
+ {
+ "freq": 116.54,
+ "dur": 0.17,
+ "step": 0.2
+ },
+ {
+ "freq": 138.5901971824171,
+ "dur": 0.17,
+ "step": 0.2
+ },
+ {
+ "freq": 164.8124485589605,
+ "dur": 0.17,
+ "step": 0.2
+ },
+ {
+ "freq": 207.65067322415032,
+ "dur": 0.17,
+ "step": 0.2
+ },
+ {
+ "freq": 233.08,
+ "dur": 0.17,
+ "step": 0.2
+ },
+ {
+ "freq": 277.1803943648342,
+ "dur": 0.17,
+ "step": 0.2
+ },
+ {
+ "freq": 329.624897117921,
+ "dur": 0.17,
+ "step": 0.2
+ },
+ {
+ "freq": 415.30134644830065,
+ "dur": 0.17,
+ "step": 0.2
+ },
+ {
+ "freq": 73.42,
+ "dur": 0.17,
+ "step": 0.2
+ },
+ {
+ "freq": 87.31158638349979,
+ "dur": 0.17,
+ "step": 0.2
+ },
+ {
+ "freq": 103.83155974943264,
+ "dur": 0.17,
+ "step": 0.2
+ },
+ {
+ "freq": 130.81956777172744,
+ "dur": 0.17,
+ "step": 0.2
+ },
+ {
+ "freq": 146.83,
+ "dur": 1.536,
+ "step": 0.544
+ },
+ {
+ "freq": 174.61128069584953,
+ "dur": 0.992,
+ "step": 0.528
+ },
+ {
+ "freq": 219.99642809780318,
+ "dur": 0.48,
+ "step": 0.528
+ },
+ {
+ "freq": 146.83,
+ "dur": 0.17,
+ "step": 0.2
+ },
+ {
+ "freq": 174.61128069584953,
+ "dur": 0.17,
+ "step": 0.2
+ },
+ {
+ "freq": 207.64897736324158,
+ "dur": 0.17,
+ "step": 0.2
+ },
+ {
+ "freq": 261.62131756909207,
+ "dur": 0.17,
+ "step": 0.2
+ },
+ {
+ "freq": 293.66,
+ "dur": 0.17,
+ "step": 0.2
+ },
+ {
+ "freq": 349.22256139169906,
+ "dur": 0.17,
+ "step": 0.2
+ },
+ {
+ "freq": 415.29795472648317,
+ "dur": 0.17,
+ "step": 0.2
+ },
+ {
+ "freq": 523.2426351381841,
+ "dur": 0.17,
+ "step": 0.2
+ }
+ ],
+ "drums": [
+ "kick",
+ "_",
+ "hat",
+ "kick",
+ "_",
+ "snare",
+ "kick",
+ "_",
+ "_",
+ "kick",
+ "hat",
+ "_",
+ "snare",
+ "_",
+ "kick",
+ "hat"
+ ]
+ },
+ "wild": {
+ "bpm": 190,
+ "gain": 0.075,
+ "wave": "sawtooth",
+ "droneFreqs": [
+ 69.3,
+ 138.59,
+ 220,
+ 277.18
+ ],
+ "cutoffMin": 2400,
+ "cutoffMax": 7500,
+ "attack": 0.02,
+ "release": 0.04,
+ "detuneCents": 22,
+ "melody": [
+ {
+ "freq": 138.59,
+ "dur": 0.1343,
+ "step": 0.158
+ },
+ {
+ "freq": 164.81221406822712,
+ "dur": 0.1343,
+ "step": 0.158
+ },
+ {
+ "freq": 195.99585760928727,
+ "dur": 0.1343,
+ "step": 0.158
+ },
+ {
+ "freq": 246.93930669413928,
+ "dur": 0.1343,
+ "step": 0.158
+ },
+ {
+ "freq": 277.18,
+ "dur": 0.1343,
+ "step": 0.158
+ },
+ {
+ "freq": 329.62442813645424,
+ "dur": 0.1343,
+ "step": 0.158
+ },
+ {
+ "freq": 391.99171521857454,
+ "dur": 0.1343,
+ "step": 0.158
+ },
+ {
+ "freq": 493.87861338827855,
+ "dur": 0.1343,
+ "step": 0.158
+ },
+ {
+ "freq": 554.37,
+ "dur": 0.1343,
+ "step": 0.158
+ },
+ {
+ "freq": 659.2607483440585,
+ "dur": 0.1343,
+ "step": 0.158
+ },
+ {
+ "freq": 783.9975725727728,
+ "dur": 0.1343,
+ "step": 0.158
+ },
+ {
+ "freq": 987.7750447509198,
+ "dur": 0.1343,
+ "step": 0.158
+ },
+ {
+ "freq": 1108.73,
+ "dur": 0.1343,
+ "step": 0.158
+ },
+ {
+ "freq": 1318.509604616967,
+ "dur": 0.1343,
+ "step": 0.158
+ },
+ {
+ "freq": 1567.9810030099218,
+ "dur": 0.1343,
+ "step": 0.158
+ },
+ {
+ "freq": 1975.532271527477,
+ "dur": 0.1343,
+ "step": 0.158
+ }
+ ],
+ "drums": [
+ "kick",
+ "_",
+ "hat",
+ "kick",
+ "_",
+ "snare",
+ "kick",
+ "_",
+ "_",
+ "kick",
+ "hat",
+ "_",
+ "snare",
+ "_",
+ "kick",
+ "hat"
+ ]
+ }
+ }
+}
diff --git a/internal/generator/templates/themes/brutalist/sounds.json b/internal/generator/templates/themes/brutalist/sounds.json
new file mode 100644
index 0000000..ffafee1
--- /dev/null
+++ b/internal/generator/templates/themes/brutalist/sounds.json
@@ -0,0 +1,342 @@
+{
+ "splash": {
+ "freqs": [
+ 261.63,
+ 329.63,
+ 392,
+ 523.25
+ ],
+ "spacing": 0.09,
+ "gain": 0.1,
+ "wave": "square"
+ },
+ "nav": {
+ "freq": 440,
+ "wave": "square",
+ "dur": 0.06,
+ "gain": 0.11
+ },
+ "open": {
+ "wave": "square",
+ "start": 440,
+ "end": 880,
+ "dur": 0.15,
+ "gain": 0.1
+ },
+ "close": {
+ "wave": "square",
+ "start": 660,
+ "end": 220,
+ "dur": 0.15,
+ "gain": 0.09
+ },
+ "bounce": {
+ "wave": "square",
+ "start": 200,
+ "end": 100,
+ "dur": 0.1,
+ "gain": 0.1
+ },
+ "ambient": {
+ "normal": {
+ "bpm": 140,
+ "gain": 0.032,
+ "wave": "sawtooth",
+ "droneFreqs": [
+ 65.41,
+ 98,
+ 130.81
+ ],
+ "cutoffMin": 1200,
+ "cutoffMax": 5500,
+ "attack": 0.02,
+ "release": 0.1,
+ "melody": [
+ {
+ "freq": 65.41,
+ "dur": 0.096525,
+ "step": 0.2145
+ },
+ {
+ "freq": 65.41,
+ "dur": 0.096525,
+ "step": 0.2145
+ },
+ {
+ "freq": 65.41,
+ "dur": 0.096525,
+ "step": 0.2145
+ },
+ {
+ "freq": 65.41,
+ "dur": 0.096525,
+ "step": 0.2145
+ },
+ {
+ "freq": 98.00426589850373,
+ "dur": 0.096525,
+ "step": 0.2145
+ },
+ {
+ "freq": 65.41,
+ "dur": 0.096525,
+ "step": 0.2145
+ },
+ {
+ "freq": 98.00426589850373,
+ "dur": 0.096525,
+ "step": 0.2145
+ },
+ {
+ "freq": 65.41,
+ "dur": 0.096525,
+ "step": 0.2145
+ },
+ {
+ "freq": 130.81,
+ "dur": 1.64736,
+ "step": 0.5834400000000001
+ },
+ {
+ "freq": 155.56018271350595,
+ "dur": 1.06392,
+ "step": 0.56628
+ },
+ {
+ "freq": 195.9935487262387,
+ "dur": 0.5147999999999999,
+ "step": 0.56628
+ },
+ {
+ "freq": 523.25,
+ "dur": 0.19734000000000002,
+ "step": 0.429
+ },
+ {
+ "freq": 622.25,
+ "dur": 0.19734000000000002,
+ "step": 0.429
+ },
+ {
+ "freq": 783.99,
+ "dur": 0.39468000000000003,
+ "step": 0.429
+ },
+ {
+ "freq": 622.25,
+ "dur": 0.39468000000000003,
+ "step": 0.429
+ },
+ {
+ "freq": 51.91,
+ "dur": 0.096525,
+ "step": 0.2145
+ },
+ {
+ "freq": 51.91,
+ "dur": 0.096525,
+ "step": 0.2145
+ },
+ {
+ "freq": 51.91,
+ "dur": 0.096525,
+ "step": 0.2145
+ },
+ {
+ "freq": 51.91,
+ "dur": 0.096525,
+ "step": 0.2145
+ },
+ {
+ "freq": 77.77712036066853,
+ "dur": 0.096525,
+ "step": 0.2145
+ },
+ {
+ "freq": 51.91,
+ "dur": 0.096525,
+ "step": 0.2145
+ },
+ {
+ "freq": 77.77712036066853,
+ "dur": 0.096525,
+ "step": 0.2145
+ },
+ {
+ "freq": 51.91,
+ "dur": 0.096525,
+ "step": 0.2145
+ },
+ {
+ "freq": 103.83,
+ "dur": 1.64736,
+ "step": 0.5834400000000001
+ },
+ {
+ "freq": 130.81760261058466,
+ "dur": 1.06392,
+ "step": 0.56628
+ },
+ {
+ "freq": 155.56922379210584,
+ "dur": 0.5147999999999999,
+ "step": 0.56628
+ },
+ {
+ "freq": 415.3,
+ "dur": 0.19734000000000002,
+ "step": 0.429
+ },
+ {
+ "freq": 622.25,
+ "dur": 0.19734000000000002,
+ "step": 0.429
+ },
+ {
+ "freq": 830.61,
+ "dur": 0.39468000000000003,
+ "step": 0.429
+ },
+ {
+ "freq": 622.25,
+ "dur": 0.39468000000000003,
+ "step": 0.429
+ }
+ ],
+ "drums": [
+ "kick",
+ "kick",
+ "_",
+ "hat",
+ "snare",
+ "_",
+ "kick",
+ "hat",
+ "kick",
+ "_",
+ "_",
+ "hat",
+ "snare",
+ "kick",
+ "_",
+ "hat"
+ ]
+ },
+ "wild": {
+ "bpm": 180,
+ "gain": 0.075,
+ "wave": "sawtooth",
+ "droneFreqs": [
+ 65.41,
+ 98,
+ 130.81,
+ 196
+ ],
+ "cutoffMin": 2400,
+ "cutoffMax": 7500,
+ "attack": 0.02,
+ "release": 0.04,
+ "detuneCents": 20,
+ "melody": [
+ {
+ "freq": 130.81,
+ "dur": 0.084375,
+ "step": 0.1875
+ },
+ {
+ "freq": 130.81,
+ "dur": 0.084375,
+ "step": 0.1875
+ },
+ {
+ "freq": 130.81,
+ "dur": 0.084375,
+ "step": 0.1875
+ },
+ {
+ "freq": 130.81,
+ "dur": 0.084375,
+ "step": 0.1875
+ },
+ {
+ "freq": 195.9935487262387,
+ "dur": 0.084375,
+ "step": 0.1875
+ },
+ {
+ "freq": 130.81,
+ "dur": 0.084375,
+ "step": 0.1875
+ },
+ {
+ "freq": 195.9935487262387,
+ "dur": 0.084375,
+ "step": 0.1875
+ },
+ {
+ "freq": 130.81,
+ "dur": 0.084375,
+ "step": 0.1875
+ },
+ {
+ "freq": 1046.5,
+ "dur": 0.08625000000000001,
+ "step": 0.09375
+ },
+ {
+ "freq": 1244.5,
+ "dur": 0.08625000000000001,
+ "step": 0.09375
+ },
+ {
+ "freq": 1567.98,
+ "dur": 0.08625000000000001,
+ "step": 0.09375
+ },
+ {
+ "freq": 1046.5,
+ "dur": 0.08625000000000001,
+ "step": 0.09375
+ },
+ {
+ "freq": 1244.5,
+ "dur": 0.08625000000000001,
+ "step": 0.09375
+ },
+ {
+ "freq": 1046.5,
+ "dur": 0.08625000000000001,
+ "step": 0.09375
+ },
+ {
+ "freq": 830.61,
+ "dur": 0.08625000000000001,
+ "step": 0.09375
+ },
+ {
+ "freq": 622.25,
+ "dur": 0.08625000000000001,
+ "step": 0.09375
+ }
+ ],
+ "drums": [
+ "kick",
+ "kick",
+ "_",
+ "hat",
+ "snare",
+ "_",
+ "kick",
+ "hat",
+ "kick",
+ "_",
+ "_",
+ "hat",
+ "snare",
+ "kick",
+ "_",
+ "hat"
+ ]
+ }
+ }
+}
diff --git a/internal/generator/templates/themes/cathedral/sounds.json b/internal/generator/templates/themes/cathedral/sounds.json
new file mode 100644
index 0000000..8fab3fe
--- /dev/null
+++ b/internal/generator/templates/themes/cathedral/sounds.json
@@ -0,0 +1,572 @@
+{
+ "splash": {
+ "freqs": [
+ 261.63,
+ 329.63,
+ 392,
+ 523.25
+ ],
+ "spacing": 0.1,
+ "gain": 0.09,
+ "wave": "sine"
+ },
+ "nav": {
+ "freq": 196,
+ "wave": "triangle",
+ "dur": 0.09,
+ "gain": 0.1
+ },
+ "open": {
+ "wave": "triangle",
+ "start": 261.63,
+ "end": 523.25,
+ "dur": 0.2,
+ "gain": 0.1
+ },
+ "close": {
+ "wave": "sine",
+ "start": 392,
+ "end": 130.81,
+ "dur": 0.22,
+ "gain": 0.09
+ },
+ "bounce": {
+ "wave": "triangle",
+ "start": 160,
+ "end": 80,
+ "dur": 0.14,
+ "gain": 0.09
+ },
+ "ambient": {
+ "normal": {
+ "bpm": 150,
+ "gain": 0.032,
+ "wave": "triangle",
+ "droneFreqs": [
+ 65.41,
+ 98,
+ 130.81
+ ],
+ "cutoffMin": 1200,
+ "cutoffMax": 5500,
+ "attack": 0.02,
+ "release": 0.08,
+ "melody": [
+ {
+ "freq": 65.41,
+ "dur": 0.09000000000000001,
+ "step": 0.2
+ },
+ {
+ "freq": 65.41,
+ "dur": 0.09000000000000001,
+ "step": 0.2
+ },
+ {
+ "freq": 65.41,
+ "dur": 0.09000000000000001,
+ "step": 0.2
+ },
+ {
+ "freq": 65.41,
+ "dur": 0.09000000000000001,
+ "step": 0.2
+ },
+ {
+ "freq": 98.00426589850373,
+ "dur": 0.09000000000000001,
+ "step": 0.2
+ },
+ {
+ "freq": 65.41,
+ "dur": 0.09000000000000001,
+ "step": 0.2
+ },
+ {
+ "freq": 98.00426589850373,
+ "dur": 0.09000000000000001,
+ "step": 0.2
+ },
+ {
+ "freq": 65.41,
+ "dur": 0.09000000000000001,
+ "step": 0.2
+ },
+ {
+ "freq": 130.81,
+ "dur": 1.536,
+ "step": 0.544
+ },
+ {
+ "freq": 155.56018271350595,
+ "dur": 0.992,
+ "step": 0.528
+ },
+ {
+ "freq": 195.9935487262387,
+ "dur": 0.48,
+ "step": 0.528
+ },
+ {
+ "freq": 523.25,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 622.25,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 783.99,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 622.25,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 523.25,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 466.16,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 415.3,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 391.99,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 98,
+ "dur": 0.09000000000000001,
+ "step": 0.2
+ },
+ {
+ "freq": 98,
+ "dur": 0.09000000000000001,
+ "step": 0.2
+ },
+ {
+ "freq": 98,
+ "dur": 0.09000000000000001,
+ "step": 0.2
+ },
+ {
+ "freq": 98,
+ "dur": 0.09000000000000001,
+ "step": 0.2
+ },
+ {
+ "freq": 146.8340935339148,
+ "dur": 0.09000000000000001,
+ "step": 0.2
+ },
+ {
+ "freq": 98,
+ "dur": 0.09000000000000001,
+ "step": 0.2
+ },
+ {
+ "freq": 146.8340935339148,
+ "dur": 0.09000000000000001,
+ "step": 0.2
+ },
+ {
+ "freq": 98,
+ "dur": 0.09000000000000001,
+ "step": 0.2
+ },
+ {
+ "freq": 196,
+ "dur": 1.536,
+ "step": 0.544
+ },
+ {
+ "freq": 233.08459454053332,
+ "dur": 0.992,
+ "step": 0.528
+ },
+ {
+ "freq": 293.6681870678296,
+ "dur": 0.48,
+ "step": 0.528
+ },
+ {
+ "freq": 783.99,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 932.33,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 1174.66,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 932.33,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 783.99,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 698.46,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 622.25,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 587.33,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 51.91,
+ "dur": 0.09000000000000001,
+ "step": 0.2
+ },
+ {
+ "freq": 51.91,
+ "dur": 0.09000000000000001,
+ "step": 0.2
+ },
+ {
+ "freq": 51.91,
+ "dur": 0.09000000000000001,
+ "step": 0.2
+ },
+ {
+ "freq": 51.91,
+ "dur": 0.09000000000000001,
+ "step": 0.2
+ },
+ {
+ "freq": 77.77712036066853,
+ "dur": 0.09000000000000001,
+ "step": 0.2
+ },
+ {
+ "freq": 51.91,
+ "dur": 0.09000000000000001,
+ "step": 0.2
+ },
+ {
+ "freq": 77.77712036066853,
+ "dur": 0.09000000000000001,
+ "step": 0.2
+ },
+ {
+ "freq": 51.91,
+ "dur": 0.09000000000000001,
+ "step": 0.2
+ },
+ {
+ "freq": 103.83,
+ "dur": 1.536,
+ "step": 0.544
+ },
+ {
+ "freq": 130.81760261058466,
+ "dur": 0.992,
+ "step": 0.528
+ },
+ {
+ "freq": 155.56922379210584,
+ "dur": 0.48,
+ "step": 0.528
+ },
+ {
+ "freq": 415.3,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 523.25,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 622.25,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 523.25,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 415.3,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 391.99,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 369.99,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 311.13,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 58.27,
+ "dur": 0.09000000000000001,
+ "step": 0.2
+ },
+ {
+ "freq": 58.27,
+ "dur": 0.09000000000000001,
+ "step": 0.2
+ },
+ {
+ "freq": 58.27,
+ "dur": 0.09000000000000001,
+ "step": 0.2
+ },
+ {
+ "freq": 58.27,
+ "dur": 0.09000000000000001,
+ "step": 0.2
+ },
+ {
+ "freq": 87.30635336960424,
+ "dur": 0.09000000000000001,
+ "step": 0.2
+ },
+ {
+ "freq": 58.27,
+ "dur": 0.09000000000000001,
+ "step": 0.2
+ },
+ {
+ "freq": 87.30635336960424,
+ "dur": 0.09000000000000001,
+ "step": 0.2
+ },
+ {
+ "freq": 58.27,
+ "dur": 0.09000000000000001,
+ "step": 0.2
+ },
+ {
+ "freq": 116.54,
+ "dur": 1.536,
+ "step": 0.544
+ },
+ {
+ "freq": 146.8311991547485,
+ "dur": 0.992,
+ "step": 0.528
+ },
+ {
+ "freq": 174.61270673920848,
+ "dur": 0.48,
+ "step": 0.528
+ },
+ {
+ "freq": 466.16,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 587.33,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 698.46,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 587.33,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 466.16,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 415.3,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 391.99,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 349.23,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ }
+ ],
+ "drums": [
+ "kick",
+ "kick",
+ "_",
+ "kick",
+ "snare",
+ "_",
+ "kick",
+ "_",
+ "kick",
+ "kick",
+ "_",
+ "kick",
+ "snare",
+ "kick",
+ "kick",
+ "kick"
+ ]
+ },
+ "wild": {
+ "bpm": 180,
+ "gain": 0.07,
+ "wave": "sawtooth",
+ "droneFreqs": [
+ 65.41,
+ 130.81,
+ 196,
+ 261.63
+ ],
+ "cutoffMin": 2400,
+ "cutoffMax": 7500,
+ "attack": 0.02,
+ "release": 0.05,
+ "detuneCents": 14,
+ "melody": [
+ {
+ "freq": 130.81,
+ "dur": 0.074925,
+ "step": 0.1665
+ },
+ {
+ "freq": 130.81,
+ "dur": 0.074925,
+ "step": 0.1665
+ },
+ {
+ "freq": 130.81,
+ "dur": 0.074925,
+ "step": 0.1665
+ },
+ {
+ "freq": 130.81,
+ "dur": 0.074925,
+ "step": 0.1665
+ },
+ {
+ "freq": 195.9935487262387,
+ "dur": 0.074925,
+ "step": 0.1665
+ },
+ {
+ "freq": 130.81,
+ "dur": 0.074925,
+ "step": 0.1665
+ },
+ {
+ "freq": 195.9935487262387,
+ "dur": 0.074925,
+ "step": 0.1665
+ },
+ {
+ "freq": 130.81,
+ "dur": 0.074925,
+ "step": 0.1665
+ },
+ {
+ "freq": 1046.5,
+ "dur": 0.07659,
+ "step": 0.08325
+ },
+ {
+ "freq": 1244.5,
+ "dur": 0.07659,
+ "step": 0.08325
+ },
+ {
+ "freq": 1567.98,
+ "dur": 0.07659,
+ "step": 0.08325
+ },
+ {
+ "freq": 1244.5,
+ "dur": 0.07659,
+ "step": 0.08325
+ },
+ {
+ "freq": 1046.5,
+ "dur": 0.07659,
+ "step": 0.08325
+ },
+ {
+ "freq": 932.33,
+ "dur": 0.07659,
+ "step": 0.08325
+ },
+ {
+ "freq": 783.99,
+ "dur": 0.07659,
+ "step": 0.08325
+ },
+ {
+ "freq": 622.25,
+ "dur": 0.07659,
+ "step": 0.08325
+ }
+ ],
+ "drums": [
+ "kick",
+ "kick",
+ "_",
+ "kick",
+ "snare",
+ "_",
+ "kick",
+ "_",
+ "kick",
+ "kick",
+ "_",
+ "kick",
+ "snare",
+ "kick",
+ "kick",
+ "kick"
+ ]
+ }
+ }
+}
diff --git a/internal/generator/templates/themes/cosmos/sounds.json b/internal/generator/templates/themes/cosmos/sounds.json
new file mode 100644
index 0000000..3387d82
--- /dev/null
+++ b/internal/generator/templates/themes/cosmos/sounds.json
@@ -0,0 +1,497 @@
+{
+ "splash": {
+ "freqs": [
+ 293.66,
+ 369.99,
+ 440,
+ 523.25
+ ],
+ "spacing": 0.08,
+ "gain": 0.09,
+ "wave": "sine"
+ },
+ "nav": {
+ "freq": 220,
+ "wave": "triangle",
+ "dur": 0.08,
+ "gain": 0.1
+ },
+ "open": {
+ "wave": "triangle",
+ "start": 293.66,
+ "end": 587.33,
+ "dur": 0.16,
+ "gain": 0.1
+ },
+ "close": {
+ "wave": "sine",
+ "start": 440,
+ "end": 146.83,
+ "dur": 0.18,
+ "gain": 0.09
+ },
+ "bounce": {
+ "wave": "triangle",
+ "start": 150,
+ "end": 75,
+ "dur": 0.12,
+ "gain": 0.09
+ },
+ "ambient": {
+ "normal": {
+ "bpm": 150,
+ "gain": 0.032,
+ "wave": "sawtooth",
+ "droneFreqs": [
+ 73.42,
+ 110,
+ 146.83
+ ],
+ "cutoffMin": 1200,
+ "cutoffMax": 5500,
+ "attack": 0.02,
+ "release": 0.08,
+ "melody": [
+ {
+ "freq": 73.42,
+ "dur": 0.09000000000000001,
+ "step": 0.2
+ },
+ {
+ "freq": 73.42,
+ "dur": 0.09000000000000001,
+ "step": 0.2
+ },
+ {
+ "freq": 73.42,
+ "dur": 0.09000000000000001,
+ "step": 0.2
+ },
+ {
+ "freq": 73.42,
+ "dur": 0.09000000000000001,
+ "step": 0.2
+ },
+ {
+ "freq": 110.00570558428596,
+ "dur": 0.09000000000000001,
+ "step": 0.2
+ },
+ {
+ "freq": 73.42,
+ "dur": 0.09000000000000001,
+ "step": 0.2
+ },
+ {
+ "freq": 110.00570558428596,
+ "dur": 0.09000000000000001,
+ "step": 0.2
+ },
+ {
+ "freq": 73.42,
+ "dur": 0.09000000000000001,
+ "step": 0.2
+ },
+ {
+ "freq": 146.83,
+ "dur": 1.536,
+ "step": 0.544
+ },
+ {
+ "freq": 174.61128069584953,
+ "dur": 0.992,
+ "step": 0.528
+ },
+ {
+ "freq": 219.99642809780318,
+ "dur": 0.48,
+ "step": 0.528
+ },
+ {
+ "freq": 587.33,
+ "dur": 0.2760000000000001,
+ "step": 0.30000000000000004
+ },
+ {
+ "freq": 587.33,
+ "dur": 0.09200000000000001,
+ "step": 0.1
+ },
+ {
+ "freq": 587.33,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 880,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 698.46,
+ "dur": 0.09200000000000001,
+ "step": 0.1
+ },
+ {
+ "freq": 659.25,
+ "dur": 0.09200000000000001,
+ "step": 0.1
+ },
+ {
+ "freq": 622.25,
+ "dur": 0.09200000000000001,
+ "step": 0.1
+ },
+ {
+ "freq": 587.33,
+ "dur": 0.09200000000000001,
+ "step": 0.1
+ },
+ {
+ "freq": 880,
+ "dur": 0.36800000000000005,
+ "step": 0.4
+ },
+ {
+ "freq": 58.27,
+ "dur": 0.09000000000000001,
+ "step": 0.2
+ },
+ {
+ "freq": 58.27,
+ "dur": 0.09000000000000001,
+ "step": 0.2
+ },
+ {
+ "freq": 58.27,
+ "dur": 0.09000000000000001,
+ "step": 0.2
+ },
+ {
+ "freq": 58.27,
+ "dur": 0.09000000000000001,
+ "step": 0.2
+ },
+ {
+ "freq": 87.30635336960424,
+ "dur": 0.09000000000000001,
+ "step": 0.2
+ },
+ {
+ "freq": 58.27,
+ "dur": 0.09000000000000001,
+ "step": 0.2
+ },
+ {
+ "freq": 87.30635336960424,
+ "dur": 0.09000000000000001,
+ "step": 0.2
+ },
+ {
+ "freq": 58.27,
+ "dur": 0.09000000000000001,
+ "step": 0.2
+ },
+ {
+ "freq": 116.54,
+ "dur": 1.536,
+ "step": 0.544
+ },
+ {
+ "freq": 146.8311991547485,
+ "dur": 0.992,
+ "step": 0.528
+ },
+ {
+ "freq": 174.61270673920848,
+ "dur": 0.48,
+ "step": 0.528
+ },
+ {
+ "freq": 466.16,
+ "dur": 0.2760000000000001,
+ "step": 0.30000000000000004
+ },
+ {
+ "freq": 466.16,
+ "dur": 0.09200000000000001,
+ "step": 0.1
+ },
+ {
+ "freq": 466.16,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 698.46,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 554.37,
+ "dur": 0.09200000000000001,
+ "step": 0.1
+ },
+ {
+ "freq": 523.25,
+ "dur": 0.09200000000000001,
+ "step": 0.1
+ },
+ {
+ "freq": 493.88,
+ "dur": 0.09200000000000001,
+ "step": 0.1
+ },
+ {
+ "freq": 466.16,
+ "dur": 0.09200000000000001,
+ "step": 0.1
+ },
+ {
+ "freq": 698.46,
+ "dur": 0.36800000000000005,
+ "step": 0.4
+ },
+ {
+ "freq": 65.41,
+ "dur": 0.09000000000000001,
+ "step": 0.2
+ },
+ {
+ "freq": 65.41,
+ "dur": 0.09000000000000001,
+ "step": 0.2
+ },
+ {
+ "freq": 65.41,
+ "dur": 0.09000000000000001,
+ "step": 0.2
+ },
+ {
+ "freq": 65.41,
+ "dur": 0.09000000000000001,
+ "step": 0.2
+ },
+ {
+ "freq": 98.00426589850373,
+ "dur": 0.09000000000000001,
+ "step": 0.2
+ },
+ {
+ "freq": 65.41,
+ "dur": 0.09000000000000001,
+ "step": 0.2
+ },
+ {
+ "freq": 98.00426589850373,
+ "dur": 0.09000000000000001,
+ "step": 0.2
+ },
+ {
+ "freq": 65.41,
+ "dur": 0.09000000000000001,
+ "step": 0.2
+ },
+ {
+ "freq": 130.81,
+ "dur": 1.536,
+ "step": 0.544
+ },
+ {
+ "freq": 155.56018271350595,
+ "dur": 0.992,
+ "step": 0.528
+ },
+ {
+ "freq": 195.9935487262387,
+ "dur": 0.48,
+ "step": 0.528
+ },
+ {
+ "freq": 523.25,
+ "dur": 0.2760000000000001,
+ "step": 0.30000000000000004
+ },
+ {
+ "freq": 523.25,
+ "dur": 0.09200000000000001,
+ "step": 0.1
+ },
+ {
+ "freq": 523.25,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 783.99,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 622.25,
+ "dur": 0.09200000000000001,
+ "step": 0.1
+ },
+ {
+ "freq": 587.33,
+ "dur": 0.09200000000000001,
+ "step": 0.1
+ },
+ {
+ "freq": 554.37,
+ "dur": 0.09200000000000001,
+ "step": 0.1
+ },
+ {
+ "freq": 523.25,
+ "dur": 0.09200000000000001,
+ "step": 0.1
+ },
+ {
+ "freq": 783.99,
+ "dur": 0.36800000000000005,
+ "step": 0.4
+ }
+ ],
+ "drums": [
+ "kick",
+ "_",
+ "_",
+ "_",
+ "snare",
+ "_",
+ "_",
+ "_",
+ "kick",
+ "_",
+ "_",
+ "_",
+ "snare",
+ "_",
+ "_",
+ "_"
+ ]
+ },
+ "wild": {
+ "bpm": 180,
+ "gain": 0.07,
+ "wave": "sawtooth",
+ "droneFreqs": [
+ 73.42,
+ 146.83,
+ 220,
+ 293.66
+ ],
+ "cutoffMin": 2400,
+ "cutoffMax": 7500,
+ "attack": 0.02,
+ "release": 0.05,
+ "detuneCents": 16,
+ "melody": [
+ {
+ "freq": 146.83,
+ "dur": 0.074925,
+ "step": 0.1665
+ },
+ {
+ "freq": 146.83,
+ "dur": 0.074925,
+ "step": 0.1665
+ },
+ {
+ "freq": 146.83,
+ "dur": 0.074925,
+ "step": 0.1665
+ },
+ {
+ "freq": 146.83,
+ "dur": 0.074925,
+ "step": 0.1665
+ },
+ {
+ "freq": 219.99642809780318,
+ "dur": 0.074925,
+ "step": 0.1665
+ },
+ {
+ "freq": 146.83,
+ "dur": 0.074925,
+ "step": 0.1665
+ },
+ {
+ "freq": 219.99642809780318,
+ "dur": 0.074925,
+ "step": 0.1665
+ },
+ {
+ "freq": 146.83,
+ "dur": 0.074925,
+ "step": 0.1665
+ },
+ {
+ "freq": 1174.66,
+ "dur": 0.07659,
+ "step": 0.08325
+ },
+ {
+ "freq": 1174.66,
+ "dur": 0.07659,
+ "step": 0.08325
+ },
+ {
+ "freq": 1396.92,
+ "dur": 0.15318,
+ "step": 0.1665
+ },
+ {
+ "freq": 1760,
+ "dur": 0.15318,
+ "step": 0.1665
+ },
+ {
+ "freq": 2349.32,
+ "dur": 0.15318,
+ "step": 0.1665
+ },
+ {
+ "freq": 2093,
+ "dur": 0.07659,
+ "step": 0.08325
+ },
+ {
+ "freq": 1760,
+ "dur": 0.07659,
+ "step": 0.08325
+ },
+ {
+ "freq": 1396.92,
+ "dur": 0.15318,
+ "step": 0.1665
+ },
+ {
+ "freq": 1174.66,
+ "dur": 0.15318,
+ "step": 0.1665
+ }
+ ],
+ "drums": [
+ "kick",
+ "kick",
+ "_",
+ "kick",
+ "snare",
+ "_",
+ "kick",
+ "_",
+ "kick",
+ "kick",
+ "_",
+ "kick",
+ "snare",
+ "kick",
+ "kick",
+ "kick"
+ ]
+ }
+ }
+}
diff --git a/internal/generator/templates/themes/dos/sounds.json b/internal/generator/templates/themes/dos/sounds.json
new file mode 100644
index 0000000..f418ad1
--- /dev/null
+++ b/internal/generator/templates/themes/dos/sounds.json
@@ -0,0 +1,367 @@
+{
+ "splash": {
+ "freqs": [
+ 261.63,
+ 329.63,
+ 392,
+ 523.25
+ ],
+ "spacing": 0.06,
+ "gain": 0.08,
+ "wave": "square"
+ },
+ "nav": {
+ "freq": 440,
+ "wave": "square",
+ "dur": 0.05,
+ "gain": 0.11
+ },
+ "open": {
+ "wave": "square",
+ "start": 440,
+ "end": 880,
+ "dur": 0.14,
+ "gain": 0.1
+ },
+ "close": {
+ "wave": "square",
+ "start": 660,
+ "end": 220,
+ "dur": 0.15,
+ "gain": 0.09
+ },
+ "bounce": {
+ "wave": "square",
+ "start": 180,
+ "end": 90,
+ "dur": 0.1,
+ "gain": 0.1
+ },
+ "ambient": {
+ "normal": {
+ "bpm": 130,
+ "gain": 0.032,
+ "wave": "square",
+ "droneFreqs": [
+ 82.41,
+ 164.81,
+ 246.94
+ ],
+ "cutoffMin": 1200,
+ "cutoffMax": 5500,
+ "attack": 0.01,
+ "release": 0.08,
+ "melody": [
+ {
+ "freq": 82.41,
+ "dur": 0.10395,
+ "step": 0.231
+ },
+ {
+ "freq": 82.41,
+ "dur": 0.10395,
+ "step": 0.231
+ },
+ {
+ "freq": 82.41,
+ "dur": 0.10395,
+ "step": 0.231
+ },
+ {
+ "freq": 82.41,
+ "dur": 0.10395,
+ "step": 0.231
+ },
+ {
+ "freq": 123.47548620540732,
+ "dur": 0.10395,
+ "step": 0.231
+ },
+ {
+ "freq": 82.41,
+ "dur": 0.10395,
+ "step": 0.231
+ },
+ {
+ "freq": 123.47548620540732,
+ "dur": 0.10395,
+ "step": 0.231
+ },
+ {
+ "freq": 82.41,
+ "dur": 0.10395,
+ "step": 0.231
+ },
+ {
+ "freq": 164.81,
+ "dur": 1.77408,
+ "step": 0.6283200000000001
+ },
+ {
+ "freq": 246.94,
+ "dur": 1.1457600000000001,
+ "step": 0.60984
+ },
+ {
+ "freq": 329.63,
+ "dur": 0.5544,
+ "step": 0.60984
+ },
+ {
+ "freq": 329.63,
+ "dur": 0.21252000000000001,
+ "step": 0.231
+ },
+ {
+ "freq": 329.63,
+ "dur": 0.21252000000000001,
+ "step": 0.231
+ },
+ {
+ "freq": 392,
+ "dur": 0.21252000000000001,
+ "step": 0.231
+ },
+ {
+ "freq": 440,
+ "dur": 0.21252000000000001,
+ "step": 0.231
+ },
+ {
+ "freq": 329.63,
+ "dur": 0.21252000000000001,
+ "step": 0.231
+ },
+ {
+ "freq": 329.63,
+ "dur": 0.21252000000000001,
+ "step": 0.231
+ },
+ {
+ "freq": 392,
+ "dur": 0.21252000000000001,
+ "step": 0.231
+ },
+ {
+ "freq": 440,
+ "dur": 0.21252000000000001,
+ "step": 0.231
+ },
+ {
+ "freq": 493.88,
+ "dur": 0.21252000000000001,
+ "step": 0.231
+ },
+ {
+ "freq": 440,
+ "dur": 0.21252000000000001,
+ "step": 0.231
+ },
+ {
+ "freq": 392,
+ "dur": 0.21252000000000001,
+ "step": 0.231
+ },
+ {
+ "freq": 329.63,
+ "dur": 0.21252000000000001,
+ "step": 0.231
+ },
+ {
+ "freq": 466.16,
+ "dur": 0.21252000000000001,
+ "step": 0.231
+ },
+ {
+ "freq": 440,
+ "dur": 0.21252000000000001,
+ "step": 0.231
+ },
+ {
+ "freq": 392,
+ "dur": 0.21252000000000001,
+ "step": 0.231
+ },
+ {
+ "freq": 329.63,
+ "dur": 0.21252000000000001,
+ "step": 0.231
+ }
+ ],
+ "drums": [
+ "kick",
+ "_",
+ "hat",
+ "_",
+ "snare",
+ "_",
+ "hat",
+ "_",
+ "kick",
+ "_",
+ "hat",
+ "_",
+ "snare",
+ "_",
+ "hat",
+ "kick"
+ ]
+ },
+ "wild": {
+ "bpm": 160,
+ "gain": 0.07,
+ "wave": "square",
+ "droneFreqs": [
+ 82.41,
+ 164.81,
+ 246.94,
+ 329.63
+ ],
+ "cutoffMin": 2400,
+ "cutoffMax": 8000,
+ "attack": 0.01,
+ "release": 0.04,
+ "detuneCents": 12,
+ "melody": [
+ {
+ "freq": 164.81,
+ "dur": 0.084375,
+ "step": 0.1875
+ },
+ {
+ "freq": 164.81,
+ "dur": 0.084375,
+ "step": 0.1875
+ },
+ {
+ "freq": 164.81,
+ "dur": 0.084375,
+ "step": 0.1875
+ },
+ {
+ "freq": 164.81,
+ "dur": 0.084375,
+ "step": 0.1875
+ },
+ {
+ "freq": 246.9359893400459,
+ "dur": 0.084375,
+ "step": 0.1875
+ },
+ {
+ "freq": 164.81,
+ "dur": 0.084375,
+ "step": 0.1875
+ },
+ {
+ "freq": 246.9359893400459,
+ "dur": 0.084375,
+ "step": 0.1875
+ },
+ {
+ "freq": 164.81,
+ "dur": 0.084375,
+ "step": 0.1875
+ },
+ {
+ "freq": 659.26,
+ "dur": 0.08625000000000001,
+ "step": 0.09375
+ },
+ {
+ "freq": 659.26,
+ "dur": 0.08625000000000001,
+ "step": 0.09375
+ },
+ {
+ "freq": 784,
+ "dur": 0.08625000000000001,
+ "step": 0.09375
+ },
+ {
+ "freq": 880,
+ "dur": 0.08625000000000001,
+ "step": 0.09375
+ },
+ {
+ "freq": 659.26,
+ "dur": 0.08625000000000001,
+ "step": 0.09375
+ },
+ {
+ "freq": 659.26,
+ "dur": 0.08625000000000001,
+ "step": 0.09375
+ },
+ {
+ "freq": 784,
+ "dur": 0.08625000000000001,
+ "step": 0.09375
+ },
+ {
+ "freq": 880,
+ "dur": 0.08625000000000001,
+ "step": 0.09375
+ },
+ {
+ "freq": 987.76,
+ "dur": 0.08625000000000001,
+ "step": 0.09375
+ },
+ {
+ "freq": 880,
+ "dur": 0.08625000000000001,
+ "step": 0.09375
+ },
+ {
+ "freq": 784,
+ "dur": 0.08625000000000001,
+ "step": 0.09375
+ },
+ {
+ "freq": 659.26,
+ "dur": 0.08625000000000001,
+ "step": 0.09375
+ },
+ {
+ "freq": 932.32,
+ "dur": 0.08625000000000001,
+ "step": 0.09375
+ },
+ {
+ "freq": 880,
+ "dur": 0.08625000000000001,
+ "step": 0.09375
+ },
+ {
+ "freq": 784,
+ "dur": 0.08625000000000001,
+ "step": 0.09375
+ },
+ {
+ "freq": 659.26,
+ "dur": 0.08625000000000001,
+ "step": 0.09375
+ }
+ ],
+ "drums": [
+ "kick",
+ "kick",
+ "hat",
+ "kick",
+ "snare",
+ "_",
+ "hat",
+ "kick",
+ "kick",
+ "kick",
+ "hat",
+ "kick",
+ "snare",
+ "_",
+ "hat",
+ "kick"
+ ]
+ }
+ }
+}
diff --git a/internal/generator/templates/themes/matrix/sounds.json b/internal/generator/templates/themes/matrix/sounds.json
new file mode 100644
index 0000000..5087473
--- /dev/null
+++ b/internal/generator/templates/themes/matrix/sounds.json
@@ -0,0 +1,283 @@
+{
+ "splash": {
+ "freqs": [
+ 261.63,
+ 311.13,
+ 392,
+ 466.16
+ ],
+ "spacing": 0.08,
+ "gain": 0.1,
+ "wave": "square"
+ },
+ "nav": {
+ "freq": 440,
+ "wave": "square",
+ "dur": 0.055,
+ "gain": 0.11
+ },
+ "open": {
+ "wave": "square",
+ "start": 440,
+ "end": 880,
+ "dur": 0.13,
+ "gain": 0.1
+ },
+ "close": {
+ "wave": "square",
+ "start": 660,
+ "end": 220,
+ "dur": 0.15,
+ "gain": 0.09
+ },
+ "bounce": {
+ "wave": "square",
+ "start": 180,
+ "end": 90,
+ "dur": 0.1,
+ "gain": 0.1
+ },
+ "ambient": {
+ "normal": {
+ "bpm": 170,
+ "gain": 0.03,
+ "wave": "sawtooth",
+ "droneFreqs": [
+ 32.7,
+ 65.41,
+ 130.81
+ ],
+ "cutoffMin": 1000,
+ "cutoffMax": 5500,
+ "attack": 0.02,
+ "release": 0.1,
+ "detuneCents": 6,
+ "melody": [
+ {
+ "freq": 41.2,
+ "dur": 1.3414,
+ "step": 1.412
+ },
+ {
+ "freq": 130.81,
+ "dur": 1.3555199999999998,
+ "step": 0.48008
+ },
+ {
+ "freq": 155.56018271350595,
+ "dur": 0.87544,
+ "step": 0.46596
+ },
+ {
+ "freq": 195.9935487262387,
+ "dur": 0.4236,
+ "step": 0.46596
+ },
+ {
+ "freq": 783.99,
+ "dur": 0.08119,
+ "step": 0.1765
+ },
+ {
+ "freq": 783.99,
+ "dur": 0.16238,
+ "step": 0.1765
+ },
+ {
+ "freq": 932.33,
+ "dur": 0.16238,
+ "step": 0.353
+ },
+ {
+ "freq": 1046.5,
+ "dur": 0.16238,
+ "step": 0.1765
+ },
+ {
+ "freq": 932.33,
+ "dur": 0.32476,
+ "step": 0.353
+ },
+ {
+ "freq": 34.65,
+ "dur": 1.3414,
+ "step": 1.412
+ },
+ {
+ "freq": 103.83,
+ "dur": 1.3555199999999998,
+ "step": 0.48008
+ },
+ {
+ "freq": 130.81760261058466,
+ "dur": 0.87544,
+ "step": 0.46596
+ },
+ {
+ "freq": 155.56922379210584,
+ "dur": 0.4236,
+ "step": 0.46596
+ },
+ {
+ "freq": 622.25,
+ "dur": 0.08119,
+ "step": 0.1765
+ },
+ {
+ "freq": 622.25,
+ "dur": 0.16238,
+ "step": 0.1765
+ },
+ {
+ "freq": 783.99,
+ "dur": 0.16238,
+ "step": 0.353
+ },
+ {
+ "freq": 932.33,
+ "dur": 0.16238,
+ "step": 0.1765
+ },
+ {
+ "freq": 783.99,
+ "dur": 0.32476,
+ "step": 0.353
+ }
+ ],
+ "drums": [
+ "kick",
+ "_",
+ "hat",
+ "kick",
+ "snare",
+ "hat",
+ "_",
+ "snare",
+ "_",
+ "kick",
+ "hat",
+ "_",
+ "snare",
+ "_",
+ "hat",
+ "kick"
+ ]
+ },
+ "wild": {
+ "bpm": 180,
+ "gain": 0.07,
+ "wave": "sawtooth",
+ "droneFreqs": [
+ 65.41,
+ 130.81,
+ 196,
+ 261.63
+ ],
+ "cutoffMin": 2200,
+ "cutoffMax": 8000,
+ "attack": 0.02,
+ "release": 0.04,
+ "detuneCents": 18,
+ "melody": [
+ {
+ "freq": 65.41,
+ "dur": 0.074925,
+ "step": 0.1665
+ },
+ {
+ "freq": 65.41,
+ "dur": 0.074925,
+ "step": 0.1665
+ },
+ {
+ "freq": 65.41,
+ "dur": 0.074925,
+ "step": 0.1665
+ },
+ {
+ "freq": 65.41,
+ "dur": 0.074925,
+ "step": 0.1665
+ },
+ {
+ "freq": 98.00426589850373,
+ "dur": 0.074925,
+ "step": 0.1665
+ },
+ {
+ "freq": 65.41,
+ "dur": 0.074925,
+ "step": 0.1665
+ },
+ {
+ "freq": 98.00426589850373,
+ "dur": 0.074925,
+ "step": 0.1665
+ },
+ {
+ "freq": 65.41,
+ "dur": 0.074925,
+ "step": 0.1665
+ },
+ {
+ "freq": 1046.5,
+ "dur": 0.07659,
+ "step": 0.08325
+ },
+ {
+ "freq": 1244.5,
+ "dur": 0.07659,
+ "step": 0.08325
+ },
+ {
+ "freq": 1567.98,
+ "dur": 0.07659,
+ "step": 0.08325
+ },
+ {
+ "freq": 1244.5,
+ "dur": 0.07659,
+ "step": 0.08325
+ },
+ {
+ "freq": 1864.66,
+ "dur": 0.07659,
+ "step": 0.08325
+ },
+ {
+ "freq": 1567.98,
+ "dur": 0.07659,
+ "step": 0.08325
+ },
+ {
+ "freq": 1244.5,
+ "dur": 0.07659,
+ "step": 0.08325
+ },
+ {
+ "freq": 1046.5,
+ "dur": 0.07659,
+ "step": 0.08325
+ }
+ ],
+ "drums": [
+ "kick",
+ "_",
+ "hat",
+ "kick",
+ "snare",
+ "hat",
+ "_",
+ "snare",
+ "_",
+ "kick",
+ "hat",
+ "_",
+ "snare",
+ "_",
+ "hat",
+ "kick"
+ ]
+ }
+ }
+}
diff --git a/internal/generator/templates/themes/neon/sounds.json b/internal/generator/templates/themes/neon/sounds.json
new file mode 100644
index 0000000..a7a29cf
--- /dev/null
+++ b/internal/generator/templates/themes/neon/sounds.json
@@ -0,0 +1,337 @@
+{
+ "splash": {
+ "freqs": [
+ 523.25,
+ 659.25,
+ 783.99,
+ 1046.5
+ ],
+ "spacing": 0.055,
+ "gain": 0.09,
+ "wave": "sine"
+ },
+ "nav": {
+ "freq": 330,
+ "wave": "square",
+ "dur": 0.055,
+ "gain": 0.11
+ },
+ "open": {
+ "wave": "triangle",
+ "start": 523.25,
+ "end": 1046.5,
+ "dur": 0.13,
+ "gain": 0.1
+ },
+ "close": {
+ "wave": "sine",
+ "start": 880,
+ "end": 261.63,
+ "dur": 0.16,
+ "gain": 0.09
+ },
+ "bounce": {
+ "wave": "square",
+ "start": 180,
+ "end": 90,
+ "dur": 0.12,
+ "gain": 0.1
+ },
+ "ambient": {
+ "normal": {
+ "bpm": 150,
+ "gain": 0.03,
+ "wave": "square",
+ "droneFreqs": [
+ 130.81,
+ 196,
+ 261.63
+ ],
+ "cutoffMin": 1200,
+ "cutoffMax": 5000,
+ "attack": 0.02,
+ "release": 0.15,
+ "melody": [
+ {
+ "freq": 130.81,
+ "dur": 0.34,
+ "step": 0.4
+ },
+ {
+ "freq": 261.62,
+ "dur": 0.34,
+ "step": 0.4
+ },
+ {
+ "freq": 130.81,
+ "dur": 0.34,
+ "step": 0.4
+ },
+ {
+ "freq": 195.9935487262387,
+ "dur": 0.34,
+ "step": 0.4
+ },
+ {
+ "freq": 261.63,
+ "dur": 1.536,
+ "step": 0.544
+ },
+ {
+ "freq": 329.6331442839956,
+ "dur": 0.992,
+ "step": 0.528
+ },
+ {
+ "freq": 392.0020805232462,
+ "dur": 0.48,
+ "step": 0.528
+ },
+ {
+ "freq": 1046.5,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 783.99,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 659.25,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 1046.5,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 880,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 783.99,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 659.25,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 523.25,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 174.61,
+ "dur": 0.34,
+ "step": 0.4
+ },
+ {
+ "freq": 349.22,
+ "dur": 0.34,
+ "step": 0.4
+ },
+ {
+ "freq": 174.61,
+ "dur": 0.34,
+ "step": 0.4
+ },
+ {
+ "freq": 261.6193986934374,
+ "dur": 0.34,
+ "step": 0.4
+ },
+ {
+ "freq": 349.23,
+ "dur": 1.536,
+ "step": 0.544
+ },
+ {
+ "freq": 440.00222825478653,
+ "dur": 0.992,
+ "step": 0.528
+ },
+ {
+ "freq": 523.2537804576435,
+ "dur": 0.48,
+ "step": 0.528
+ },
+ {
+ "freq": 1396.92,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 1046.5,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 880,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 1396.92,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 1174.66,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 1046.5,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 880,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 698.46,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ }
+ ],
+ "drums": [
+ "kick",
+ "_",
+ "hat",
+ "kick",
+ "snare",
+ "_",
+ "hat",
+ "_",
+ "kick",
+ "kick",
+ "hat",
+ "_",
+ "snare",
+ "_",
+ "hat",
+ "clap"
+ ]
+ },
+ "wild": {
+ "bpm": 220,
+ "gain": 0.06,
+ "wave": "square",
+ "droneFreqs": [
+ 130.81,
+ 261.63,
+ 392,
+ 523.25
+ ],
+ "cutoffMin": 2000,
+ "cutoffMax": 7000,
+ "attack": 0.02,
+ "release": 0.08,
+ "detuneCents": 12,
+ "melody": [
+ {
+ "freq": 261.63,
+ "dur": 0.23205,
+ "step": 0.273
+ },
+ {
+ "freq": 523.26,
+ "dur": 0.23205,
+ "step": 0.273
+ },
+ {
+ "freq": 261.63,
+ "dur": 0.23205,
+ "step": 0.273
+ },
+ {
+ "freq": 392.0020805232462,
+ "dur": 0.23205,
+ "step": 0.273
+ },
+ {
+ "freq": 523.25,
+ "dur": 1.0483200000000001,
+ "step": 0.37128000000000005
+ },
+ {
+ "freq": 659.2536893574922,
+ "dur": 0.6770400000000001,
+ "step": 0.36036000000000007
+ },
+ {
+ "freq": 783.9891779757236,
+ "dur": 0.3276,
+ "step": 0.36036000000000007
+ },
+ {
+ "freq": 1046.5,
+ "dur": 0.06279000000000001,
+ "step": 0.06825
+ },
+ {
+ "freq": 1318.5,
+ "dur": 0.06279000000000001,
+ "step": 0.06825
+ },
+ {
+ "freq": 1567.98,
+ "dur": 0.06279000000000001,
+ "step": 0.06825
+ },
+ {
+ "freq": 2093,
+ "dur": 0.06279000000000001,
+ "step": 0.06825
+ },
+ {
+ "freq": 1567.98,
+ "dur": 0.06279000000000001,
+ "step": 0.06825
+ },
+ {
+ "freq": 1318.5,
+ "dur": 0.06279000000000001,
+ "step": 0.06825
+ },
+ {
+ "freq": 1046.5,
+ "dur": 0.06279000000000001,
+ "step": 0.06825
+ },
+ {
+ "freq": 783.99,
+ "dur": 0.06279000000000001,
+ "step": 0.06825
+ }
+ ],
+ "drums": [
+ "kick",
+ "_",
+ "hat",
+ "kick",
+ "snare",
+ "_",
+ "hat",
+ "_",
+ "kick",
+ "kick",
+ "hat",
+ "_",
+ "snare",
+ "_",
+ "hat",
+ "clap"
+ ]
+ }
+ }
+}
diff --git a/internal/generator/templates/themes/noir/sounds.json b/internal/generator/templates/themes/noir/sounds.json
new file mode 100644
index 0000000..67a5273
--- /dev/null
+++ b/internal/generator/templates/themes/noir/sounds.json
@@ -0,0 +1,472 @@
+{
+ "splash": {
+ "freqs": [
+ 293.66,
+ 349.23,
+ 440,
+ 523.25
+ ],
+ "spacing": 0.09,
+ "gain": 0.09,
+ "wave": "sine"
+ },
+ "nav": {
+ "freq": 196,
+ "wave": "square",
+ "dur": 0.055,
+ "gain": 0.11
+ },
+ "open": {
+ "wave": "triangle",
+ "start": 293.66,
+ "end": 587.33,
+ "dur": 0.16,
+ "gain": 0.1
+ },
+ "close": {
+ "wave": "sine",
+ "start": 440,
+ "end": 146.83,
+ "dur": 0.18,
+ "gain": 0.09
+ },
+ "bounce": {
+ "wave": "square",
+ "start": 130,
+ "end": 65,
+ "dur": 0.12,
+ "gain": 0.09
+ },
+ "ambient": {
+ "normal": {
+ "bpm": 150,
+ "gain": 0.032,
+ "wave": "triangle",
+ "droneFreqs": [
+ 73.42,
+ 110,
+ 146.83
+ ],
+ "cutoffMin": 1200,
+ "cutoffMax": 5500,
+ "attack": 0.02,
+ "release": 0.08,
+ "melody": [
+ {
+ "freq": 73.42,
+ "dur": 0.36800000000000005,
+ "step": 0.4
+ },
+ {
+ "freq": 92.50340348328157,
+ "dur": 0.36800000000000005,
+ "step": 0.4
+ },
+ {
+ "freq": 110.00570558428596,
+ "dur": 0.36800000000000005,
+ "step": 0.4
+ },
+ {
+ "freq": 92.50340348328157,
+ "dur": 0.36800000000000005,
+ "step": 0.4
+ },
+ {
+ "freq": 146.83,
+ "dur": 1.536,
+ "step": 0.544
+ },
+ {
+ "freq": 174.61128069584953,
+ "dur": 0.992,
+ "step": 0.528
+ },
+ {
+ "freq": 219.99642809780318,
+ "dur": 0.48,
+ "step": 0.528
+ },
+ {
+ "freq": 880,
+ "dur": 0.12,
+ "step": 0.2
+ },
+ {
+ "freq": 830.6093951598903,
+ "dur": 0.12,
+ "step": 0.2
+ },
+ {
+ "freq": 783.9908719634985,
+ "dur": 0.12,
+ "step": 0.2
+ },
+ {
+ "freq": 739.9888454232689,
+ "dur": 0.12,
+ "step": 0.2
+ },
+ {
+ "freq": 698.4564628660079,
+ "dur": 0.12,
+ "step": 0.2
+ },
+ {
+ "freq": 659.2551138257398,
+ "dur": 0.12,
+ "step": 0.2
+ },
+ {
+ "freq": 622.2539674441617,
+ "dur": 0.12,
+ "step": 0.2
+ },
+ {
+ "freq": 587.3295358348151,
+ "dur": 0.12,
+ "step": 0.2
+ },
+ {
+ "freq": 98,
+ "dur": 0.36800000000000005,
+ "step": 0.4
+ },
+ {
+ "freq": 123.47226288969755,
+ "dur": 0.36800000000000005,
+ "step": 0.4
+ },
+ {
+ "freq": 146.8340935339148,
+ "dur": 0.36800000000000005,
+ "step": 0.4
+ },
+ {
+ "freq": 123.47226288969755,
+ "dur": 0.36800000000000005,
+ "step": 0.4
+ },
+ {
+ "freq": 196,
+ "dur": 1.536,
+ "step": 0.544
+ },
+ {
+ "freq": 233.08459454053332,
+ "dur": 0.992,
+ "step": 0.528
+ },
+ {
+ "freq": 293.6681870678296,
+ "dur": 0.48,
+ "step": 0.528
+ },
+ {
+ "freq": 739.99,
+ "dur": 0.12,
+ "step": 0.2
+ },
+ {
+ "freq": 698.4575526413263,
+ "dur": 0.12,
+ "step": 0.2
+ },
+ {
+ "freq": 659.2561424366696,
+ "dur": 0.12,
+ "step": 0.2
+ },
+ {
+ "freq": 622.2549383235963,
+ "dur": 0.12,
+ "step": 0.2
+ },
+ {
+ "freq": 587.3304522229741,
+ "dur": 0.12,
+ "step": 0.2
+ },
+ {
+ "freq": 554.3661269089878,
+ "dur": 0.12,
+ "step": 0.2
+ },
+ {
+ "freq": 523.2519470102333,
+ "dur": 0.12,
+ "step": 0.2
+ },
+ {
+ "freq": 493.8840718436419,
+ "dur": 0.12,
+ "step": 0.2
+ },
+ {
+ "freq": 110,
+ "dur": 0.36800000000000005,
+ "step": 0.4
+ },
+ {
+ "freq": 138.59131548843604,
+ "dur": 0.36800000000000005,
+ "step": 0.4
+ },
+ {
+ "freq": 164.81377845643496,
+ "dur": 0.36800000000000005,
+ "step": 0.4
+ },
+ {
+ "freq": 138.59131548843604,
+ "dur": 0.36800000000000005,
+ "step": 0.4
+ },
+ {
+ "freq": 220,
+ "dur": 1.536,
+ "step": 0.544
+ },
+ {
+ "freq": 277.1826309768721,
+ "dur": 0.992,
+ "step": 0.528
+ },
+ {
+ "freq": 329.6275569128699,
+ "dur": 0.48,
+ "step": 0.528
+ },
+ {
+ "freq": 659.25,
+ "dur": 0.12,
+ "step": 0.2
+ },
+ {
+ "freq": 622.2491406354064,
+ "dur": 0.12,
+ "step": 0.2
+ },
+ {
+ "freq": 587.3249799340186,
+ "dur": 0.12,
+ "step": 0.2
+ },
+ {
+ "freq": 554.3609617560113,
+ "dur": 0.12,
+ "step": 0.2
+ },
+ {
+ "freq": 523.2470717550178,
+ "dur": 0.12,
+ "step": 0.2
+ },
+ {
+ "freq": 493.87947021547615,
+ "dur": 0.12,
+ "step": 0.2
+ },
+ {
+ "freq": 466.16014549723144,
+ "dur": 0.12,
+ "step": 0.2
+ },
+ {
+ "freq": 439.9965869307976,
+ "dur": 0.12,
+ "step": 0.2
+ },
+ {
+ "freq": 73.42,
+ "dur": 0.36800000000000005,
+ "step": 0.4
+ },
+ {
+ "freq": 92.50340348328157,
+ "dur": 0.36800000000000005,
+ "step": 0.4
+ },
+ {
+ "freq": 110.00570558428596,
+ "dur": 0.36800000000000005,
+ "step": 0.4
+ },
+ {
+ "freq": 92.50340348328157,
+ "dur": 0.36800000000000005,
+ "step": 0.4
+ },
+ {
+ "freq": 146.83,
+ "dur": 1.536,
+ "step": 0.544
+ },
+ {
+ "freq": 174.61128069584953,
+ "dur": 0.992,
+ "step": 0.528
+ },
+ {
+ "freq": 219.99642809780318,
+ "dur": 0.48,
+ "step": 0.528
+ },
+ {
+ "freq": 587.33,
+ "dur": 0.12,
+ "step": 0.2
+ },
+ {
+ "freq": 554.365700067339,
+ "dur": 0.12,
+ "step": 0.2
+ },
+ {
+ "freq": 523.2515441253655,
+ "dur": 0.12,
+ "step": 0.2
+ },
+ {
+ "freq": 493.88369157096423,
+ "dur": 0.12,
+ "step": 0.2
+ },
+ {
+ "freq": 466.1641299262414,
+ "dur": 0.12,
+ "step": 0.2
+ },
+ {
+ "freq": 440.0003477309907,
+ "dur": 0.12,
+ "step": 0.2
+ },
+ {
+ "freq": 415.305025794295,
+ "dur": 0.12,
+ "step": 0.2
+ },
+ {
+ "freq": 391.99574577484316,
+ "dur": 0.12,
+ "step": 0.2
+ }
+ ],
+ "drums": [
+ "kick",
+ "_",
+ "_",
+ "hat",
+ "snare",
+ "_",
+ "_",
+ "hat",
+ "_",
+ "_",
+ "kick",
+ "hat",
+ "snare",
+ "_",
+ "kick",
+ "hat"
+ ]
+ },
+ "wild": {
+ "bpm": 190,
+ "gain": 0.07,
+ "wave": "sawtooth",
+ "droneFreqs": [
+ 73.42,
+ 146.83,
+ 196,
+ 293.66
+ ],
+ "cutoffMin": 2200,
+ "cutoffMax": 7500,
+ "attack": 0.02,
+ "release": 0.05,
+ "detuneCents": 14,
+ "melody": [
+ {
+ "freq": 146.83,
+ "dur": 0.29072000000000003,
+ "step": 0.316
+ },
+ {
+ "freq": 184.9942077560642,
+ "dur": 0.29072000000000003,
+ "step": 0.316
+ },
+ {
+ "freq": 219.99642809780318,
+ "dur": 0.29072000000000003,
+ "step": 0.316
+ },
+ {
+ "freq": 184.9942077560642,
+ "dur": 0.29072000000000003,
+ "step": 0.316
+ },
+ {
+ "freq": 1318.5,
+ "dur": 0.0948,
+ "step": 0.158
+ },
+ {
+ "freq": 1244.4982812708129,
+ "dur": 0.0948,
+ "step": 0.158
+ },
+ {
+ "freq": 1174.6499598680373,
+ "dur": 0.0948,
+ "step": 0.158
+ },
+ {
+ "freq": 1108.7219235120226,
+ "dur": 0.0948,
+ "step": 0.158
+ },
+ {
+ "freq": 1046.4941435100357,
+ "dur": 0.0948,
+ "step": 0.158
+ },
+ {
+ "freq": 987.7589404309523,
+ "dur": 0.0948,
+ "step": 0.158
+ },
+ {
+ "freq": 932.3202909944629,
+ "dur": 0.0948,
+ "step": 0.158
+ },
+ {
+ "freq": 879.9931738615952,
+ "dur": 0.0948,
+ "step": 0.158
+ }
+ ],
+ "drums": [
+ "kick",
+ "_",
+ "_",
+ "hat",
+ "snare",
+ "_",
+ "_",
+ "hat",
+ "_",
+ "_",
+ "kick",
+ "hat",
+ "snare",
+ "_",
+ "kick",
+ "hat"
+ ]
+ }
+ }
+}
diff --git a/internal/generator/templates/themes/nukem/sounds.json b/internal/generator/templates/themes/nukem/sounds.json
new file mode 100644
index 0000000..42b9a82
--- /dev/null
+++ b/internal/generator/templates/themes/nukem/sounds.json
@@ -0,0 +1,367 @@
+{
+ "splash": {
+ "freqs": [
+ 164.81,
+ 329.63,
+ 440,
+ 659.25
+ ],
+ "spacing": 0.06,
+ "gain": 0.1,
+ "wave": "sawtooth"
+ },
+ "nav": {
+ "freq": 440,
+ "wave": "square",
+ "dur": 0.05,
+ "gain": 0.12
+ },
+ "open": {
+ "wave": "sawtooth",
+ "start": 329.63,
+ "end": 659.25,
+ "dur": 0.14,
+ "gain": 0.11
+ },
+ "close": {
+ "wave": "square",
+ "start": 659.25,
+ "end": 164.81,
+ "dur": 0.16,
+ "gain": 0.1
+ },
+ "bounce": {
+ "wave": "sawtooth",
+ "start": 220,
+ "end": 110,
+ "dur": 0.1,
+ "gain": 0.1
+ },
+ "ambient": {
+ "normal": {
+ "bpm": 140,
+ "gain": 0.035,
+ "wave": "sawtooth",
+ "droneFreqs": [
+ 82.41,
+ 164.81,
+ 246.94
+ ],
+ "cutoffMin": 1400,
+ "cutoffMax": 6000,
+ "attack": 0.01,
+ "release": 0.08,
+ "melody": [
+ {
+ "freq": 82.41,
+ "dur": 0.096525,
+ "step": 0.2145
+ },
+ {
+ "freq": 82.41,
+ "dur": 0.096525,
+ "step": 0.2145
+ },
+ {
+ "freq": 82.41,
+ "dur": 0.096525,
+ "step": 0.2145
+ },
+ {
+ "freq": 82.41,
+ "dur": 0.096525,
+ "step": 0.2145
+ },
+ {
+ "freq": 123.47548620540732,
+ "dur": 0.096525,
+ "step": 0.2145
+ },
+ {
+ "freq": 82.41,
+ "dur": 0.096525,
+ "step": 0.2145
+ },
+ {
+ "freq": 123.47548620540732,
+ "dur": 0.096525,
+ "step": 0.2145
+ },
+ {
+ "freq": 82.41,
+ "dur": 0.096525,
+ "step": 0.2145
+ },
+ {
+ "freq": 164.81,
+ "dur": 1.64736,
+ "step": 0.5834400000000001
+ },
+ {
+ "freq": 246.94,
+ "dur": 1.06392,
+ "step": 0.56628
+ },
+ {
+ "freq": 329.63,
+ "dur": 0.5147999999999999,
+ "step": 0.56628
+ },
+ {
+ "freq": 329.63,
+ "dur": 0.19734000000000002,
+ "step": 0.2145
+ },
+ {
+ "freq": 329.63,
+ "dur": 0.19734000000000002,
+ "step": 0.2145
+ },
+ {
+ "freq": 392,
+ "dur": 0.19734000000000002,
+ "step": 0.2145
+ },
+ {
+ "freq": 440,
+ "dur": 0.19734000000000002,
+ "step": 0.2145
+ },
+ {
+ "freq": 329.63,
+ "dur": 0.19734000000000002,
+ "step": 0.2145
+ },
+ {
+ "freq": 329.63,
+ "dur": 0.19734000000000002,
+ "step": 0.2145
+ },
+ {
+ "freq": 392,
+ "dur": 0.19734000000000002,
+ "step": 0.2145
+ },
+ {
+ "freq": 440,
+ "dur": 0.19734000000000002,
+ "step": 0.2145
+ },
+ {
+ "freq": 493.88,
+ "dur": 0.19734000000000002,
+ "step": 0.2145
+ },
+ {
+ "freq": 440,
+ "dur": 0.19734000000000002,
+ "step": 0.2145
+ },
+ {
+ "freq": 392,
+ "dur": 0.19734000000000002,
+ "step": 0.2145
+ },
+ {
+ "freq": 329.63,
+ "dur": 0.19734000000000002,
+ "step": 0.2145
+ },
+ {
+ "freq": 466.16,
+ "dur": 0.19734000000000002,
+ "step": 0.2145
+ },
+ {
+ "freq": 440,
+ "dur": 0.19734000000000002,
+ "step": 0.2145
+ },
+ {
+ "freq": 392,
+ "dur": 0.19734000000000002,
+ "step": 0.2145
+ },
+ {
+ "freq": 329.63,
+ "dur": 0.19734000000000002,
+ "step": 0.2145
+ }
+ ],
+ "drums": [
+ "kick",
+ "_",
+ "hat",
+ "_",
+ "snare",
+ "_",
+ "hat",
+ "_",
+ "kick",
+ "_",
+ "hat",
+ "_",
+ "snare",
+ "_",
+ "hat",
+ "kick"
+ ]
+ },
+ "wild": {
+ "bpm": 180,
+ "gain": 0.075,
+ "wave": "sawtooth",
+ "droneFreqs": [
+ 82.41,
+ 164.81,
+ 329.63,
+ 440
+ ],
+ "cutoffMin": 2800,
+ "cutoffMax": 8500,
+ "attack": 0.01,
+ "release": 0.04,
+ "detuneCents": 14,
+ "melody": [
+ {
+ "freq": 164.81,
+ "dur": 0.074925,
+ "step": 0.1665
+ },
+ {
+ "freq": 164.81,
+ "dur": 0.074925,
+ "step": 0.1665
+ },
+ {
+ "freq": 164.81,
+ "dur": 0.074925,
+ "step": 0.1665
+ },
+ {
+ "freq": 164.81,
+ "dur": 0.074925,
+ "step": 0.1665
+ },
+ {
+ "freq": 246.9359893400459,
+ "dur": 0.074925,
+ "step": 0.1665
+ },
+ {
+ "freq": 164.81,
+ "dur": 0.074925,
+ "step": 0.1665
+ },
+ {
+ "freq": 246.9359893400459,
+ "dur": 0.074925,
+ "step": 0.1665
+ },
+ {
+ "freq": 164.81,
+ "dur": 0.074925,
+ "step": 0.1665
+ },
+ {
+ "freq": 659.26,
+ "dur": 0.07659,
+ "step": 0.08325
+ },
+ {
+ "freq": 659.26,
+ "dur": 0.07659,
+ "step": 0.08325
+ },
+ {
+ "freq": 784,
+ "dur": 0.07659,
+ "step": 0.08325
+ },
+ {
+ "freq": 880,
+ "dur": 0.07659,
+ "step": 0.08325
+ },
+ {
+ "freq": 659.26,
+ "dur": 0.07659,
+ "step": 0.08325
+ },
+ {
+ "freq": 659.26,
+ "dur": 0.07659,
+ "step": 0.08325
+ },
+ {
+ "freq": 784,
+ "dur": 0.07659,
+ "step": 0.08325
+ },
+ {
+ "freq": 880,
+ "dur": 0.07659,
+ "step": 0.08325
+ },
+ {
+ "freq": 987.76,
+ "dur": 0.07659,
+ "step": 0.08325
+ },
+ {
+ "freq": 880,
+ "dur": 0.07659,
+ "step": 0.08325
+ },
+ {
+ "freq": 784,
+ "dur": 0.07659,
+ "step": 0.08325
+ },
+ {
+ "freq": 659.26,
+ "dur": 0.07659,
+ "step": 0.08325
+ },
+ {
+ "freq": 932.32,
+ "dur": 0.07659,
+ "step": 0.08325
+ },
+ {
+ "freq": 880,
+ "dur": 0.07659,
+ "step": 0.08325
+ },
+ {
+ "freq": 784,
+ "dur": 0.07659,
+ "step": 0.08325
+ },
+ {
+ "freq": 659.26,
+ "dur": 0.07659,
+ "step": 0.08325
+ }
+ ],
+ "drums": [
+ "kick",
+ "kick",
+ "hat",
+ "kick",
+ "snare",
+ "_",
+ "hat",
+ "kick",
+ "kick",
+ "kick",
+ "hat",
+ "kick",
+ "snare",
+ "_",
+ "hat",
+ "kick"
+ ]
+ }
+ }
+}
diff --git a/internal/generator/templates/themes/ocean/sounds.json b/internal/generator/templates/themes/ocean/sounds.json
new file mode 100644
index 0000000..543ce0c
--- /dev/null
+++ b/internal/generator/templates/themes/ocean/sounds.json
@@ -0,0 +1,427 @@
+{
+ "splash": {
+ "freqs": [
+ 329.63,
+ 392,
+ 493.88,
+ 587.33
+ ],
+ "spacing": 0.09,
+ "gain": 0.095,
+ "wave": "triangle"
+ },
+ "nav": {
+ "freq": 220,
+ "wave": "sine",
+ "dur": 0.08,
+ "gain": 0.1
+ },
+ "open": {
+ "wave": "triangle",
+ "start": 329.63,
+ "end": 659.25,
+ "dur": 0.18,
+ "gain": 0.1
+ },
+ "close": {
+ "wave": "sine",
+ "start": 493.88,
+ "end": 164.81,
+ "dur": 0.18,
+ "gain": 0.09
+ },
+ "bounce": {
+ "wave": "triangle",
+ "start": 140,
+ "end": 70,
+ "dur": 0.12,
+ "gain": 0.09
+ },
+ "ambient": {
+ "normal": {
+ "bpm": 140,
+ "gain": 0.032,
+ "wave": "triangle",
+ "droneFreqs": [
+ 82.41,
+ 130.81,
+ 164.81
+ ],
+ "cutoffMin": 1500,
+ "cutoffMax": 6000,
+ "attack": 0.02,
+ "release": 0.08,
+ "melody": [
+ {
+ "freq": 82.41,
+ "dur": 0.096525,
+ "step": 0.2145
+ },
+ {
+ "freq": 82.41,
+ "dur": 0.096525,
+ "step": 0.2145
+ },
+ {
+ "freq": 82.41,
+ "dur": 0.096525,
+ "step": 0.2145
+ },
+ {
+ "freq": 82.41,
+ "dur": 0.096525,
+ "step": 0.2145
+ },
+ {
+ "freq": 123.47548620540732,
+ "dur": 0.096525,
+ "step": 0.2145
+ },
+ {
+ "freq": 82.41,
+ "dur": 0.096525,
+ "step": 0.2145
+ },
+ {
+ "freq": 123.47548620540732,
+ "dur": 0.096525,
+ "step": 0.2145
+ },
+ {
+ "freq": 82.41,
+ "dur": 0.096525,
+ "step": 0.2145
+ },
+ {
+ "freq": 164.81,
+ "dur": 1.64736,
+ "step": 0.5834400000000001
+ },
+ {
+ "freq": 195.99322462359845,
+ "dur": 1.06392,
+ "step": 0.56628
+ },
+ {
+ "freq": 246.9359893400459,
+ "dur": 0.5147999999999999,
+ "step": 0.56628
+ },
+ {
+ "freq": 659.25,
+ "dur": 0.09867000000000001,
+ "step": 0.10725
+ },
+ {
+ "freq": 698.46,
+ "dur": 0.09867000000000001,
+ "step": 0.10725
+ },
+ {
+ "freq": 783.99,
+ "dur": 0.09867000000000001,
+ "step": 0.10725
+ },
+ {
+ "freq": 698.46,
+ "dur": 0.09867000000000001,
+ "step": 0.10725
+ },
+ {
+ "freq": 659.25,
+ "dur": 0.09867000000000001,
+ "step": 0.10725
+ },
+ {
+ "freq": 622.25,
+ "dur": 0.09867000000000001,
+ "step": 0.10725
+ },
+ {
+ "freq": 587.33,
+ "dur": 0.09867000000000001,
+ "step": 0.10725
+ },
+ {
+ "freq": 523.25,
+ "dur": 0.09867000000000001,
+ "step": 0.10725
+ },
+ {
+ "freq": 493.88,
+ "dur": 0.19734000000000002,
+ "step": 0.2145
+ },
+ {
+ "freq": 587.33,
+ "dur": 0.19734000000000002,
+ "step": 0.2145
+ },
+ {
+ "freq": 659.25,
+ "dur": 0.39468000000000003,
+ "step": 0.429
+ },
+ {
+ "freq": 73.42,
+ "dur": 0.096525,
+ "step": 0.2145
+ },
+ {
+ "freq": 73.42,
+ "dur": 0.096525,
+ "step": 0.2145
+ },
+ {
+ "freq": 73.42,
+ "dur": 0.096525,
+ "step": 0.2145
+ },
+ {
+ "freq": 73.42,
+ "dur": 0.096525,
+ "step": 0.2145
+ },
+ {
+ "freq": 110.00570558428596,
+ "dur": 0.096525,
+ "step": 0.2145
+ },
+ {
+ "freq": 73.42,
+ "dur": 0.096525,
+ "step": 0.2145
+ },
+ {
+ "freq": 110.00570558428596,
+ "dur": 0.096525,
+ "step": 0.2145
+ },
+ {
+ "freq": 73.42,
+ "dur": 0.096525,
+ "step": 0.2145
+ },
+ {
+ "freq": 146.83,
+ "dur": 1.64736,
+ "step": 0.5834400000000001
+ },
+ {
+ "freq": 184.9942077560642,
+ "dur": 1.06392,
+ "step": 0.56628
+ },
+ {
+ "freq": 219.99642809780318,
+ "dur": 0.5147999999999999,
+ "step": 0.56628
+ },
+ {
+ "freq": 587.33,
+ "dur": 0.09867000000000001,
+ "step": 0.10725
+ },
+ {
+ "freq": 622.25,
+ "dur": 0.09867000000000001,
+ "step": 0.10725
+ },
+ {
+ "freq": 698.46,
+ "dur": 0.09867000000000001,
+ "step": 0.10725
+ },
+ {
+ "freq": 622.25,
+ "dur": 0.09867000000000001,
+ "step": 0.10725
+ },
+ {
+ "freq": 587.33,
+ "dur": 0.09867000000000001,
+ "step": 0.10725
+ },
+ {
+ "freq": 523.25,
+ "dur": 0.09867000000000001,
+ "step": 0.10725
+ },
+ {
+ "freq": 493.88,
+ "dur": 0.09867000000000001,
+ "step": 0.10725
+ },
+ {
+ "freq": 440,
+ "dur": 0.09867000000000001,
+ "step": 0.10725
+ },
+ {
+ "freq": 493.88,
+ "dur": 0.19734000000000002,
+ "step": 0.2145
+ },
+ {
+ "freq": 587.33,
+ "dur": 0.19734000000000002,
+ "step": 0.2145
+ },
+ {
+ "freq": 659.25,
+ "dur": 0.39468000000000003,
+ "step": 0.429
+ }
+ ],
+ "drums": [
+ "kick",
+ "_",
+ "hat",
+ "_",
+ "snare",
+ "_",
+ "hat",
+ "_",
+ "kick",
+ "_",
+ "hat",
+ "_",
+ "snare",
+ "_",
+ "hat",
+ "kick"
+ ]
+ },
+ "wild": {
+ "bpm": 170,
+ "gain": 0.065,
+ "wave": "sawtooth",
+ "droneFreqs": [
+ 82.41,
+ 164.81,
+ 246.94,
+ 329.63
+ ],
+ "cutoffMin": 2400,
+ "cutoffMax": 7500,
+ "attack": 0.02,
+ "release": 0.04,
+ "detuneCents": 14,
+ "melody": [
+ {
+ "freq": 164.81,
+ "dur": 0.079425,
+ "step": 0.1765
+ },
+ {
+ "freq": 164.81,
+ "dur": 0.079425,
+ "step": 0.1765
+ },
+ {
+ "freq": 164.81,
+ "dur": 0.079425,
+ "step": 0.1765
+ },
+ {
+ "freq": 164.81,
+ "dur": 0.079425,
+ "step": 0.1765
+ },
+ {
+ "freq": 246.9359893400459,
+ "dur": 0.079425,
+ "step": 0.1765
+ },
+ {
+ "freq": 164.81,
+ "dur": 0.079425,
+ "step": 0.1765
+ },
+ {
+ "freq": 246.9359893400459,
+ "dur": 0.079425,
+ "step": 0.1765
+ },
+ {
+ "freq": 164.81,
+ "dur": 0.079425,
+ "step": 0.1765
+ },
+ {
+ "freq": 1318.5,
+ "dur": 0.040595,
+ "step": 0.044125
+ },
+ {
+ "freq": 1396.92,
+ "dur": 0.040595,
+ "step": 0.044125
+ },
+ {
+ "freq": 1567.98,
+ "dur": 0.040595,
+ "step": 0.044125
+ },
+ {
+ "freq": 1396.92,
+ "dur": 0.040595,
+ "step": 0.044125
+ },
+ {
+ "freq": 1318.5,
+ "dur": 0.040595,
+ "step": 0.044125
+ },
+ {
+ "freq": 1244.5,
+ "dur": 0.040595,
+ "step": 0.044125
+ },
+ {
+ "freq": 1174.66,
+ "dur": 0.040595,
+ "step": 0.044125
+ },
+ {
+ "freq": 1046.5,
+ "dur": 0.040595,
+ "step": 0.044125
+ },
+ {
+ "freq": 987.77,
+ "dur": 0.08119,
+ "step": 0.08825
+ },
+ {
+ "freq": 1174.66,
+ "dur": 0.08119,
+ "step": 0.08825
+ },
+ {
+ "freq": 1318.5,
+ "dur": 0.16238,
+ "step": 0.1765
+ }
+ ],
+ "drums": [
+ "kick",
+ "kick",
+ "hat",
+ "kick",
+ "snare",
+ "_",
+ "hat",
+ "kick",
+ "kick",
+ "kick",
+ "hat",
+ "kick",
+ "snare",
+ "_",
+ "hat",
+ "kick"
+ ]
+ }
+ }
+}
diff --git a/internal/generator/templates/themes/plasma/sounds.json b/internal/generator/templates/themes/plasma/sounds.json
new file mode 100644
index 0000000..8d429ae
--- /dev/null
+++ b/internal/generator/templates/themes/plasma/sounds.json
@@ -0,0 +1,372 @@
+{
+ "splash": {
+ "freqs": [
+ 369.99,
+ 493.88,
+ 587.33,
+ 739.99
+ ],
+ "spacing": 0.055,
+ "gain": 0.09,
+ "wave": "sine"
+ },
+ "nav": {
+ "freq": 246.94,
+ "wave": "square",
+ "dur": 0.055,
+ "gain": 0.11
+ },
+ "open": {
+ "wave": "sine",
+ "start": 370,
+ "end": 740,
+ "dur": 0.14,
+ "gain": 0.1
+ },
+ "close": {
+ "wave": "square",
+ "start": 740,
+ "end": 246.94,
+ "dur": 0.17,
+ "gain": 0.09
+ },
+ "bounce": {
+ "wave": "square",
+ "start": 120,
+ "end": 60,
+ "dur": 0.1,
+ "gain": 0.1
+ },
+ "ambient": {
+ "normal": {
+ "bpm": 150,
+ "gain": 0.032,
+ "wave": "square",
+ "droneFreqs": [
+ 46.25,
+ 92.5,
+ 138.59
+ ],
+ "cutoffMin": 800,
+ "cutoffMax": 5500,
+ "attack": 0.01,
+ "release": 0.08,
+ "melody": [
+ {
+ "freq": 46.25,
+ "dur": 0.09000000000000001,
+ "step": 0.2
+ },
+ {
+ "freq": 46.25,
+ "dur": 0.09000000000000001,
+ "step": 0.2
+ },
+ {
+ "freq": 46.25,
+ "dur": 0.09000000000000001,
+ "step": 0.2
+ },
+ {
+ "freq": 46.25,
+ "dur": 0.09000000000000001,
+ "step": 0.2
+ },
+ {
+ "freq": 69.29670230554652,
+ "dur": 0.09000000000000001,
+ "step": 0.2
+ },
+ {
+ "freq": 46.25,
+ "dur": 0.09000000000000001,
+ "step": 0.2
+ },
+ {
+ "freq": 69.29670230554652,
+ "dur": 0.09000000000000001,
+ "step": 0.2
+ },
+ {
+ "freq": 46.25,
+ "dur": 0.09000000000000001,
+ "step": 0.2
+ },
+ {
+ "freq": 92.5,
+ "dur": 1.536,
+ "step": 0.544
+ },
+ {
+ "freq": 110.00165813775169,
+ "dur": 0.992,
+ "step": 0.528
+ },
+ {
+ "freq": 138.59340461109304,
+ "dur": 0.48,
+ "step": 0.528
+ },
+ {
+ "freq": 369.99,
+ "dur": 0.18400000000000002,
+ "step": 0.4
+ },
+ {
+ "freq": 369.99,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 440,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 554.37,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 440,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 369.99,
+ "dur": 0.36800000000000005,
+ "step": 0.4
+ },
+ {
+ "freq": 46.25,
+ "dur": 0.09000000000000001,
+ "step": 0.2
+ },
+ {
+ "freq": 46.25,
+ "dur": 0.09000000000000001,
+ "step": 0.2
+ },
+ {
+ "freq": 46.25,
+ "dur": 0.09000000000000001,
+ "step": 0.2
+ },
+ {
+ "freq": 46.25,
+ "dur": 0.09000000000000001,
+ "step": 0.2
+ },
+ {
+ "freq": 69.29670230554652,
+ "dur": 0.09000000000000001,
+ "step": 0.2
+ },
+ {
+ "freq": 46.25,
+ "dur": 0.09000000000000001,
+ "step": 0.2
+ },
+ {
+ "freq": 69.29670230554652,
+ "dur": 0.09000000000000001,
+ "step": 0.2
+ },
+ {
+ "freq": 46.25,
+ "dur": 0.09000000000000001,
+ "step": 0.2
+ },
+ {
+ "freq": 92.5,
+ "dur": 1.536,
+ "step": 0.544
+ },
+ {
+ "freq": 110.00165813775169,
+ "dur": 0.992,
+ "step": 0.528
+ },
+ {
+ "freq": 138.59340461109304,
+ "dur": 0.48,
+ "step": 0.528
+ },
+ {
+ "freq": 369.99,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 440,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 554.37,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 739.99,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 659.25,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 554.37,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 440,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 369.99,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ }
+ ],
+ "drums": [
+ "kick",
+ "kick",
+ "_",
+ "kick",
+ "snare",
+ "_",
+ "kick",
+ "_",
+ "kick",
+ "kick",
+ "_",
+ "kick",
+ "snare",
+ "kick",
+ "kick",
+ "kick"
+ ]
+ },
+ "wild": {
+ "bpm": 180,
+ "gain": 0.07,
+ "wave": "square",
+ "droneFreqs": [
+ 46.25,
+ 92.5,
+ 138.59,
+ 277.18
+ ],
+ "cutoffMin": 2400,
+ "cutoffMax": 8000,
+ "attack": 0.01,
+ "release": 0.04,
+ "detuneCents": 22,
+ "melody": [
+ {
+ "freq": 92.5,
+ "dur": 0.074925,
+ "step": 0.1665
+ },
+ {
+ "freq": 92.5,
+ "dur": 0.074925,
+ "step": 0.1665
+ },
+ {
+ "freq": 92.5,
+ "dur": 0.074925,
+ "step": 0.1665
+ },
+ {
+ "freq": 92.5,
+ "dur": 0.074925,
+ "step": 0.1665
+ },
+ {
+ "freq": 138.59340461109304,
+ "dur": 0.074925,
+ "step": 0.1665
+ },
+ {
+ "freq": 92.5,
+ "dur": 0.074925,
+ "step": 0.1665
+ },
+ {
+ "freq": 138.59340461109304,
+ "dur": 0.074925,
+ "step": 0.1665
+ },
+ {
+ "freq": 92.5,
+ "dur": 0.074925,
+ "step": 0.1665
+ },
+ {
+ "freq": 739.99,
+ "dur": 0.07659,
+ "step": 0.08325
+ },
+ {
+ "freq": 880,
+ "dur": 0.07659,
+ "step": 0.08325
+ },
+ {
+ "freq": 1108.73,
+ "dur": 0.07659,
+ "step": 0.08325
+ },
+ {
+ "freq": 1480,
+ "dur": 0.07659,
+ "step": 0.08325
+ },
+ {
+ "freq": 1108.73,
+ "dur": 0.07659,
+ "step": 0.08325
+ },
+ {
+ "freq": 880,
+ "dur": 0.07659,
+ "step": 0.08325
+ },
+ {
+ "freq": 739.99,
+ "dur": 0.07659,
+ "step": 0.08325
+ },
+ {
+ "freq": 554.37,
+ "dur": 0.07659,
+ "step": 0.08325
+ }
+ ],
+ "drums": [
+ "kick",
+ "kick",
+ "_",
+ "kick",
+ "snare",
+ "_",
+ "kick",
+ "_",
+ "kick",
+ "kick",
+ "_",
+ "kick",
+ "snare",
+ "kick",
+ "kick",
+ "kick"
+ ]
+ }
+ }
+}
diff --git a/internal/generator/templates/themes/retro/sounds.json b/internal/generator/templates/themes/retro/sounds.json
new file mode 100644
index 0000000..f0e21a0
--- /dev/null
+++ b/internal/generator/templates/themes/retro/sounds.json
@@ -0,0 +1,612 @@
+{
+ "splash": {
+ "freqs": [
+ 220,
+ 261.63,
+ 329.63,
+ 440
+ ],
+ "spacing": 0.08,
+ "gain": 0.09,
+ "wave": "sine"
+ },
+ "nav": {
+ "freq": 164.81,
+ "wave": "triangle",
+ "dur": 0.085,
+ "gain": 0.1
+ },
+ "open": {
+ "wave": "triangle",
+ "start": 220,
+ "end": 440,
+ "dur": 0.16,
+ "gain": 0.1
+ },
+ "close": {
+ "wave": "sine",
+ "start": 330,
+ "end": 110,
+ "dur": 0.16,
+ "gain": 0.09
+ },
+ "bounce": {
+ "wave": "triangle",
+ "start": 150,
+ "end": 75,
+ "dur": 0.12,
+ "gain": 0.09
+ },
+ "ambient": {
+ "normal": {
+ "bpm": 150,
+ "gain": 0.032,
+ "wave": "square",
+ "droneFreqs": [
+ 55,
+ 110,
+ 220
+ ],
+ "cutoffMin": 1500,
+ "cutoffMax": 6500,
+ "attack": 0.01,
+ "release": 0.05,
+ "melody": [
+ {
+ "freq": 110,
+ "dur": 0.34,
+ "step": 0.4
+ },
+ {
+ "freq": 220,
+ "dur": 0.34,
+ "step": 0.4
+ },
+ {
+ "freq": 110,
+ "dur": 0.34,
+ "step": 0.4
+ },
+ {
+ "freq": 164.81377845643496,
+ "dur": 0.34,
+ "step": 0.4
+ },
+ {
+ "freq": 220,
+ "dur": 0.17,
+ "step": 0.2
+ },
+ {
+ "freq": 261.6255653005986,
+ "dur": 0.17,
+ "step": 0.2
+ },
+ {
+ "freq": 329.6275569128699,
+ "dur": 0.17,
+ "step": 0.2
+ },
+ {
+ "freq": 440,
+ "dur": 0.17,
+ "step": 0.2
+ },
+ {
+ "freq": 329.6275569128699,
+ "dur": 0.17,
+ "step": 0.2
+ },
+ {
+ "freq": 261.6255653005986,
+ "dur": 0.17,
+ "step": 0.2
+ },
+ {
+ "freq": 220,
+ "dur": 0.17,
+ "step": 0.2
+ },
+ {
+ "freq": 261.6255653005986,
+ "dur": 0.17,
+ "step": 0.2
+ },
+ {
+ "freq": 880,
+ "dur": 0.09200000000000001,
+ "step": 0.1
+ },
+ {
+ "freq": 1046.5,
+ "dur": 0.09200000000000001,
+ "step": 0.1
+ },
+ {
+ "freq": 1318.5,
+ "dur": 0.09200000000000001,
+ "step": 0.1
+ },
+ {
+ "freq": 1760,
+ "dur": 0.09200000000000001,
+ "step": 0.1
+ },
+ {
+ "freq": 1318.5,
+ "dur": 0.09200000000000001,
+ "step": 0.1
+ },
+ {
+ "freq": 1046.5,
+ "dur": 0.09200000000000001,
+ "step": 0.1
+ },
+ {
+ "freq": 880,
+ "dur": 0.09200000000000001,
+ "step": 0.1
+ },
+ {
+ "freq": 659.25,
+ "dur": 0.09200000000000001,
+ "step": 0.1
+ },
+ {
+ "freq": 87.31,
+ "dur": 0.34,
+ "step": 0.4
+ },
+ {
+ "freq": 174.62,
+ "dur": 0.34,
+ "step": 0.4
+ },
+ {
+ "freq": 87.31,
+ "dur": 0.34,
+ "step": 0.4
+ },
+ {
+ "freq": 130.81719088210306,
+ "dur": 0.34,
+ "step": 0.4
+ },
+ {
+ "freq": 174.61,
+ "dur": 0.17,
+ "step": 0.2
+ },
+ {
+ "freq": 219.9948145221438,
+ "dur": 0.17,
+ "step": 0.2
+ },
+ {
+ "freq": 261.6193986934374,
+ "dur": 0.17,
+ "step": 0.2
+ },
+ {
+ "freq": 349.22,
+ "dur": 0.17,
+ "step": 0.2
+ },
+ {
+ "freq": 261.6193986934374,
+ "dur": 0.17,
+ "step": 0.2
+ },
+ {
+ "freq": 219.9948145221438,
+ "dur": 0.17,
+ "step": 0.2
+ },
+ {
+ "freq": 174.61,
+ "dur": 0.17,
+ "step": 0.2
+ },
+ {
+ "freq": 219.9948145221438,
+ "dur": 0.17,
+ "step": 0.2
+ },
+ {
+ "freq": 698.46,
+ "dur": 0.09200000000000001,
+ "step": 0.1
+ },
+ {
+ "freq": 880,
+ "dur": 0.09200000000000001,
+ "step": 0.1
+ },
+ {
+ "freq": 1046.5,
+ "dur": 0.09200000000000001,
+ "step": 0.1
+ },
+ {
+ "freq": 1396.92,
+ "dur": 0.09200000000000001,
+ "step": 0.1
+ },
+ {
+ "freq": 1046.5,
+ "dur": 0.09200000000000001,
+ "step": 0.1
+ },
+ {
+ "freq": 880,
+ "dur": 0.09200000000000001,
+ "step": 0.1
+ },
+ {
+ "freq": 698.46,
+ "dur": 0.09200000000000001,
+ "step": 0.1
+ },
+ {
+ "freq": 523.25,
+ "dur": 0.09200000000000001,
+ "step": 0.1
+ },
+ {
+ "freq": 98,
+ "dur": 0.34,
+ "step": 0.4
+ },
+ {
+ "freq": 196,
+ "dur": 0.34,
+ "step": 0.4
+ },
+ {
+ "freq": 98,
+ "dur": 0.34,
+ "step": 0.4
+ },
+ {
+ "freq": 146.8340935339148,
+ "dur": 0.34,
+ "step": 0.4
+ },
+ {
+ "freq": 196,
+ "dur": 0.17,
+ "step": 0.2
+ },
+ {
+ "freq": 246.9445257793951,
+ "dur": 0.17,
+ "step": 0.2
+ },
+ {
+ "freq": 293.6681870678296,
+ "dur": 0.17,
+ "step": 0.2
+ },
+ {
+ "freq": 392,
+ "dur": 0.17,
+ "step": 0.2
+ },
+ {
+ "freq": 293.6681870678296,
+ "dur": 0.17,
+ "step": 0.2
+ },
+ {
+ "freq": 246.9445257793951,
+ "dur": 0.17,
+ "step": 0.2
+ },
+ {
+ "freq": 196,
+ "dur": 0.17,
+ "step": 0.2
+ },
+ {
+ "freq": 246.9445257793951,
+ "dur": 0.17,
+ "step": 0.2
+ },
+ {
+ "freq": 783.99,
+ "dur": 0.09200000000000001,
+ "step": 0.1
+ },
+ {
+ "freq": 987.77,
+ "dur": 0.09200000000000001,
+ "step": 0.1
+ },
+ {
+ "freq": 1174.66,
+ "dur": 0.09200000000000001,
+ "step": 0.1
+ },
+ {
+ "freq": 1567.98,
+ "dur": 0.09200000000000001,
+ "step": 0.1
+ },
+ {
+ "freq": 1174.66,
+ "dur": 0.09200000000000001,
+ "step": 0.1
+ },
+ {
+ "freq": 987.77,
+ "dur": 0.09200000000000001,
+ "step": 0.1
+ },
+ {
+ "freq": 783.99,
+ "dur": 0.09200000000000001,
+ "step": 0.1
+ },
+ {
+ "freq": 587.33,
+ "dur": 0.09200000000000001,
+ "step": 0.1
+ },
+ {
+ "freq": 82.41,
+ "dur": 0.34,
+ "step": 0.4
+ },
+ {
+ "freq": 164.82,
+ "dur": 0.34,
+ "step": 0.4
+ },
+ {
+ "freq": 82.41,
+ "dur": 0.34,
+ "step": 0.4
+ },
+ {
+ "freq": 123.47548620540732,
+ "dur": 0.34,
+ "step": 0.4
+ },
+ {
+ "freq": 164.81,
+ "dur": 0.17,
+ "step": 0.2
+ },
+ {
+ "freq": 195.99322462359845,
+ "dur": 0.17,
+ "step": 0.2
+ },
+ {
+ "freq": 246.9359893400459,
+ "dur": 0.17,
+ "step": 0.2
+ },
+ {
+ "freq": 329.62,
+ "dur": 0.17,
+ "step": 0.2
+ },
+ {
+ "freq": 246.9359893400459,
+ "dur": 0.17,
+ "step": 0.2
+ },
+ {
+ "freq": 195.99322462359845,
+ "dur": 0.17,
+ "step": 0.2
+ },
+ {
+ "freq": 164.81,
+ "dur": 0.17,
+ "step": 0.2
+ },
+ {
+ "freq": 195.99322462359845,
+ "dur": 0.17,
+ "step": 0.2
+ },
+ {
+ "freq": 659.25,
+ "dur": 0.09200000000000001,
+ "step": 0.1
+ },
+ {
+ "freq": 783.99,
+ "dur": 0.09200000000000001,
+ "step": 0.1
+ },
+ {
+ "freq": 987.77,
+ "dur": 0.09200000000000001,
+ "step": 0.1
+ },
+ {
+ "freq": 1318.5,
+ "dur": 0.09200000000000001,
+ "step": 0.1
+ },
+ {
+ "freq": 987.77,
+ "dur": 0.09200000000000001,
+ "step": 0.1
+ },
+ {
+ "freq": 783.99,
+ "dur": 0.09200000000000001,
+ "step": 0.1
+ },
+ {
+ "freq": 659.25,
+ "dur": 0.09200000000000001,
+ "step": 0.1
+ },
+ {
+ "freq": 493.88,
+ "dur": 0.09200000000000001,
+ "step": 0.1
+ }
+ ],
+ "drums": [
+ "kick",
+ "snare",
+ "kick",
+ "snare",
+ "kick",
+ "snare",
+ "kick",
+ "snare",
+ "kick",
+ "snare",
+ "kick",
+ "snare",
+ "kick",
+ "snare",
+ "kick",
+ "snare"
+ ]
+ },
+ "wild": {
+ "bpm": 190,
+ "gain": 0.07,
+ "wave": "square",
+ "droneFreqs": [
+ 110,
+ 220,
+ 329.63,
+ 440
+ ],
+ "cutoffMin": 2500,
+ "cutoffMax": 8000,
+ "attack": 0.005,
+ "release": 0.03,
+ "detuneCents": 8,
+ "melody": [
+ {
+ "freq": 220,
+ "dur": 0.2686,
+ "step": 0.316
+ },
+ {
+ "freq": 440,
+ "dur": 0.2686,
+ "step": 0.316
+ },
+ {
+ "freq": 220,
+ "dur": 0.2686,
+ "step": 0.316
+ },
+ {
+ "freq": 329.6275569128699,
+ "dur": 0.2686,
+ "step": 0.316
+ },
+ {
+ "freq": 1760,
+ "dur": 0.036340000000000004,
+ "step": 0.0395
+ },
+ {
+ "freq": 2093,
+ "dur": 0.036340000000000004,
+ "step": 0.0395
+ },
+ {
+ "freq": 2637,
+ "dur": 0.036340000000000004,
+ "step": 0.0395
+ },
+ {
+ "freq": 3520,
+ "dur": 0.036340000000000004,
+ "step": 0.0395
+ },
+ {
+ "freq": 2637,
+ "dur": 0.036340000000000004,
+ "step": 0.0395
+ },
+ {
+ "freq": 2093,
+ "dur": 0.036340000000000004,
+ "step": 0.0395
+ },
+ {
+ "freq": 1760,
+ "dur": 0.036340000000000004,
+ "step": 0.0395
+ },
+ {
+ "freq": 1318.5,
+ "dur": 0.036340000000000004,
+ "step": 0.0395
+ },
+ {
+ "freq": 880,
+ "dur": 0.036340000000000004,
+ "step": 0.0395
+ },
+ {
+ "freq": 1046.5,
+ "dur": 0.036340000000000004,
+ "step": 0.0395
+ },
+ {
+ "freq": 1318.5,
+ "dur": 0.036340000000000004,
+ "step": 0.0395
+ },
+ {
+ "freq": 1760,
+ "dur": 0.036340000000000004,
+ "step": 0.0395
+ },
+ {
+ "freq": 1318.5,
+ "dur": 0.036340000000000004,
+ "step": 0.0395
+ },
+ {
+ "freq": 1046.5,
+ "dur": 0.036340000000000004,
+ "step": 0.0395
+ },
+ {
+ "freq": 880,
+ "dur": 0.036340000000000004,
+ "step": 0.0395
+ },
+ {
+ "freq": 659.25,
+ "dur": 0.036340000000000004,
+ "step": 0.0395
+ }
+ ],
+ "drums": [
+ "kick",
+ "snare",
+ "kick",
+ "snare",
+ "kick",
+ "snare",
+ "kick",
+ "snare",
+ "kick",
+ "snare",
+ "kick",
+ "snare",
+ "kick",
+ "snare",
+ "kick",
+ "snare"
+ ]
+ }
+ }
+}
diff --git a/internal/generator/templates/themes/retrofuture/sounds.json b/internal/generator/templates/themes/retrofuture/sounds.json
new file mode 100644
index 0000000..3cced12
--- /dev/null
+++ b/internal/generator/templates/themes/retrofuture/sounds.json
@@ -0,0 +1,322 @@
+{
+ "splash": {
+ "freqs": [
+ 329.63,
+ 415.3,
+ 493.88,
+ 659.25
+ ],
+ "spacing": 0.09,
+ "gain": 0.095,
+ "wave": "triangle"
+ },
+ "nav": {
+ "freq": 246.94,
+ "wave": "sine",
+ "dur": 0.085,
+ "gain": 0.1
+ },
+ "open": {
+ "wave": "triangle",
+ "start": 329.63,
+ "end": 659.25,
+ "dur": 0.18,
+ "gain": 0.1
+ },
+ "close": {
+ "wave": "sine",
+ "start": 493.88,
+ "end": 164.81,
+ "dur": 0.2,
+ "gain": 0.09
+ },
+ "bounce": {
+ "wave": "triangle",
+ "start": 160,
+ "end": 80,
+ "dur": 0.14,
+ "gain": 0.09
+ },
+ "ambient": {
+ "normal": {
+ "bpm": 150,
+ "gain": 0.032,
+ "wave": "square",
+ "droneFreqs": [
+ 82.41,
+ 164.81,
+ 246.94
+ ],
+ "cutoffMin": 1200,
+ "cutoffMax": 5500,
+ "attack": 0.02,
+ "release": 0.08,
+ "melody": [
+ {
+ "freq": 82.41,
+ "dur": 0.34,
+ "step": 0.4
+ },
+ {
+ "freq": 164.82,
+ "dur": 0.34,
+ "step": 0.4
+ },
+ {
+ "freq": 82.41,
+ "dur": 0.34,
+ "step": 0.4
+ },
+ {
+ "freq": 123.47548620540732,
+ "dur": 0.34,
+ "step": 0.4
+ },
+ {
+ "freq": 164.81,
+ "dur": 1.536,
+ "step": 0.544
+ },
+ {
+ "freq": 207.64758823317402,
+ "dur": 0.992,
+ "step": 0.528
+ },
+ {
+ "freq": 246.9359893400459,
+ "dur": 0.48,
+ "step": 0.528
+ },
+ {
+ "freq": 659.25,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 659.25,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 783.99,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 987.77,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 987.77,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 783.99,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 659.25,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 493.88,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 110,
+ "dur": 0.34,
+ "step": 0.4
+ },
+ {
+ "freq": 220,
+ "dur": 0.34,
+ "step": 0.4
+ },
+ {
+ "freq": 110,
+ "dur": 0.34,
+ "step": 0.4
+ },
+ {
+ "freq": 164.81377845643496,
+ "dur": 0.34,
+ "step": 0.4
+ },
+ {
+ "freq": 220,
+ "dur": 1.536,
+ "step": 0.544
+ },
+ {
+ "freq": 277.1826309768721,
+ "dur": 0.992,
+ "step": 0.528
+ },
+ {
+ "freq": 329.6275569128699,
+ "dur": 0.48,
+ "step": 0.528
+ },
+ {
+ "freq": 880,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 880,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 1046.5,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 1318.5,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 1046.5,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 880,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 659.25,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 493.88,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ }
+ ],
+ "drums": [
+ "kick",
+ "_",
+ "hat",
+ "_",
+ "kick",
+ "_",
+ "hat",
+ "_",
+ "kick",
+ "_",
+ "hat",
+ "_",
+ "kick",
+ "_",
+ "hat",
+ "_"
+ ]
+ },
+ "wild": {
+ "bpm": 190,
+ "gain": 0.07,
+ "wave": "sawtooth",
+ "droneFreqs": [
+ 82.41,
+ 164.81,
+ 329.63,
+ 493.88
+ ],
+ "cutoffMin": 2400,
+ "cutoffMax": 7500,
+ "attack": 0.01,
+ "release": 0.04,
+ "detuneCents": 14,
+ "melody": [
+ {
+ "freq": 164.81,
+ "dur": 0.2686,
+ "step": 0.316
+ },
+ {
+ "freq": 329.62,
+ "dur": 0.2686,
+ "step": 0.316
+ },
+ {
+ "freq": 164.81,
+ "dur": 0.2686,
+ "step": 0.316
+ },
+ {
+ "freq": 246.9359893400459,
+ "dur": 0.2686,
+ "step": 0.316
+ },
+ {
+ "freq": 1318.5,
+ "dur": 0.07268000000000001,
+ "step": 0.079
+ },
+ {
+ "freq": 1567.98,
+ "dur": 0.07268000000000001,
+ "step": 0.079
+ },
+ {
+ "freq": 1864.66,
+ "dur": 0.07268000000000001,
+ "step": 0.079
+ },
+ {
+ "freq": 1318.5,
+ "dur": 0.07268000000000001,
+ "step": 0.079
+ },
+ {
+ "freq": 1567.98,
+ "dur": 0.07268000000000001,
+ "step": 0.079
+ },
+ {
+ "freq": 1864.66,
+ "dur": 0.07268000000000001,
+ "step": 0.079
+ },
+ {
+ "freq": 1318.5,
+ "dur": 0.07268000000000001,
+ "step": 0.079
+ },
+ {
+ "freq": 1046.5,
+ "dur": 0.07268000000000001,
+ "step": 0.079
+ }
+ ],
+ "drums": [
+ "kick",
+ "_",
+ "hat",
+ "_",
+ "kick",
+ "_",
+ "hat",
+ "_",
+ "kick",
+ "_",
+ "hat",
+ "_",
+ "kick",
+ "_",
+ "hat",
+ "_"
+ ]
+ }
+ }
+}
diff --git a/internal/generator/templates/themes/spaceage/sounds.json b/internal/generator/templates/themes/spaceage/sounds.json
new file mode 100644
index 0000000..0165dca
--- /dev/null
+++ b/internal/generator/templates/themes/spaceage/sounds.json
@@ -0,0 +1,472 @@
+{
+ "splash": {
+ "freqs": [
+ 392,
+ 493.88,
+ 587.33,
+ 783.99
+ ],
+ "spacing": 0.1,
+ "gain": 0.1,
+ "wave": "sine"
+ },
+ "nav": {
+ "freq": 261.63,
+ "wave": "triangle",
+ "dur": 0.085,
+ "gain": 0.1
+ },
+ "open": {
+ "wave": "triangle",
+ "start": 392,
+ "end": 784,
+ "dur": 0.17,
+ "gain": 0.1
+ },
+ "close": {
+ "wave": "sine",
+ "start": 587,
+ "end": 196,
+ "dur": 0.19,
+ "gain": 0.09
+ },
+ "bounce": {
+ "wave": "triangle",
+ "start": 130,
+ "end": 65,
+ "dur": 0.12,
+ "gain": 0.09
+ },
+ "ambient": {
+ "normal": {
+ "bpm": 150,
+ "gain": 0.032,
+ "wave": "triangle",
+ "droneFreqs": [
+ 98,
+ 130.81,
+ 196
+ ],
+ "cutoffMin": 1200,
+ "cutoffMax": 5500,
+ "attack": 0.02,
+ "release": 0.08,
+ "melody": [
+ {
+ "freq": 98,
+ "dur": 0.34,
+ "step": 0.4
+ },
+ {
+ "freq": 196,
+ "dur": 0.34,
+ "step": 0.4
+ },
+ {
+ "freq": 98,
+ "dur": 0.34,
+ "step": 0.4
+ },
+ {
+ "freq": 146.8340935339148,
+ "dur": 0.34,
+ "step": 0.4
+ },
+ {
+ "freq": 196,
+ "dur": 1.536,
+ "step": 0.544
+ },
+ {
+ "freq": 246.9445257793951,
+ "dur": 0.992,
+ "step": 0.528
+ },
+ {
+ "freq": 293.6681870678296,
+ "dur": 0.48,
+ "step": 0.528
+ },
+ {
+ "freq": 783.99,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 987.77,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 1174.66,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 1567.98,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 1318.5,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 1174.66,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 987.77,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 783.99,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 82.41,
+ "dur": 0.34,
+ "step": 0.4
+ },
+ {
+ "freq": 164.82,
+ "dur": 0.34,
+ "step": 0.4
+ },
+ {
+ "freq": 82.41,
+ "dur": 0.34,
+ "step": 0.4
+ },
+ {
+ "freq": 123.47548620540732,
+ "dur": 0.34,
+ "step": 0.4
+ },
+ {
+ "freq": 164.81,
+ "dur": 1.536,
+ "step": 0.544
+ },
+ {
+ "freq": 195.99322462359845,
+ "dur": 0.992,
+ "step": 0.528
+ },
+ {
+ "freq": 246.9359893400459,
+ "dur": 0.48,
+ "step": 0.528
+ },
+ {
+ "freq": 659.25,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 783.99,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 987.77,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 1318.5,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 1174.66,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 987.77,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 783.99,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 659.25,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 110,
+ "dur": 0.34,
+ "step": 0.4
+ },
+ {
+ "freq": 220,
+ "dur": 0.34,
+ "step": 0.4
+ },
+ {
+ "freq": 110,
+ "dur": 0.34,
+ "step": 0.4
+ },
+ {
+ "freq": 164.81377845643496,
+ "dur": 0.34,
+ "step": 0.4
+ },
+ {
+ "freq": 220,
+ "dur": 1.536,
+ "step": 0.544
+ },
+ {
+ "freq": 261.6255653005986,
+ "dur": 0.992,
+ "step": 0.528
+ },
+ {
+ "freq": 329.6275569128699,
+ "dur": 0.48,
+ "step": 0.528
+ },
+ {
+ "freq": 880,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 1046.5,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 1318.5,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 1760,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 1396.92,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 1318.5,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 1046.5,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 880,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 73.42,
+ "dur": 0.34,
+ "step": 0.4
+ },
+ {
+ "freq": 146.84,
+ "dur": 0.34,
+ "step": 0.4
+ },
+ {
+ "freq": 73.42,
+ "dur": 0.34,
+ "step": 0.4
+ },
+ {
+ "freq": 110.00570558428596,
+ "dur": 0.34,
+ "step": 0.4
+ },
+ {
+ "freq": 146.83,
+ "dur": 1.536,
+ "step": 0.544
+ },
+ {
+ "freq": 184.9942077560642,
+ "dur": 0.992,
+ "step": 0.528
+ },
+ {
+ "freq": 219.99642809780318,
+ "dur": 0.48,
+ "step": 0.528
+ },
+ {
+ "freq": 587.33,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 880,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 1108.73,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 1318.5,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 1567.98,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 1318.5,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 1108.73,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 880,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ }
+ ],
+ "drums": [
+ "kick",
+ "_",
+ "hat",
+ "kick",
+ "snare",
+ "_",
+ "hat",
+ "_",
+ "kick",
+ "kick",
+ "hat",
+ "_",
+ "snare",
+ "_",
+ "hat",
+ "clap"
+ ]
+ },
+ "wild": {
+ "bpm": 180,
+ "gain": 0.065,
+ "wave": "sawtooth",
+ "droneFreqs": [
+ 98,
+ 196,
+ 293.66,
+ 392
+ ],
+ "cutoffMin": 2200,
+ "cutoffMax": 7500,
+ "attack": 0.02,
+ "release": 0.05,
+ "detuneCents": 12,
+ "melody": [
+ {
+ "freq": 196,
+ "dur": 0.28305,
+ "step": 0.333
+ },
+ {
+ "freq": 392,
+ "dur": 0.28305,
+ "step": 0.333
+ },
+ {
+ "freq": 196,
+ "dur": 0.28305,
+ "step": 0.333
+ },
+ {
+ "freq": 293.6681870678296,
+ "dur": 0.28305,
+ "step": 0.333
+ },
+ {
+ "freq": 1567.98,
+ "dur": 0.07659,
+ "step": 0.08325
+ },
+ {
+ "freq": 1975.53,
+ "dur": 0.07659,
+ "step": 0.08325
+ },
+ {
+ "freq": 2349.32,
+ "dur": 0.07659,
+ "step": 0.08325
+ },
+ {
+ "freq": 3135.96,
+ "dur": 0.07659,
+ "step": 0.08325
+ },
+ {
+ "freq": 2637,
+ "dur": 0.07659,
+ "step": 0.08325
+ },
+ {
+ "freq": 2349.32,
+ "dur": 0.07659,
+ "step": 0.08325
+ },
+ {
+ "freq": 1975.53,
+ "dur": 0.07659,
+ "step": 0.08325
+ },
+ {
+ "freq": 1567.98,
+ "dur": 0.07659,
+ "step": 0.08325
+ }
+ ],
+ "drums": [
+ "kick",
+ "_",
+ "hat",
+ "kick",
+ "snare",
+ "_",
+ "hat",
+ "_",
+ "kick",
+ "kick",
+ "hat",
+ "_",
+ "snare",
+ "_",
+ "hat",
+ "clap"
+ ]
+ }
+ }
+}
diff --git a/internal/generator/templates/themes/surveillance/sounds.json b/internal/generator/templates/themes/surveillance/sounds.json
new file mode 100644
index 0000000..7e99456
--- /dev/null
+++ b/internal/generator/templates/themes/surveillance/sounds.json
@@ -0,0 +1,451 @@
+{
+ "splash": {
+ "freqs": [
+ 440,
+ 554.37,
+ 659.25
+ ],
+ "spacing": 0.06,
+ "gain": 0.08,
+ "wave": "square"
+ },
+ "nav": {
+ "freq": 880,
+ "wave": "square",
+ "dur": 0.04,
+ "gain": 0.1
+ },
+ "open": {
+ "wave": "square",
+ "start": 660,
+ "end": 1320,
+ "dur": 0.12,
+ "gain": 0.09
+ },
+ "close": {
+ "wave": "square",
+ "start": 990,
+ "end": 330,
+ "dur": 0.14,
+ "gain": 0.085
+ },
+ "bounce": {
+ "wave": "square",
+ "start": 280,
+ "end": 140,
+ "dur": 0.09,
+ "gain": 0.09
+ },
+ "ambient": {
+ "normal": {
+ "bpm": 150,
+ "gain": 0.032,
+ "wave": "triangle",
+ "droneFreqs": [
+ 82.41,
+ 123.47,
+ 164.81
+ ],
+ "cutoffMin": 1200,
+ "cutoffMax": 5500,
+ "attack": 0.02,
+ "release": 0.08,
+ "melody": [
+ {
+ "freq": 82.41,
+ "dur": 0.36800000000000005,
+ "step": 0.4
+ },
+ {
+ "freq": 103.83009372183648,
+ "dur": 0.36800000000000005,
+ "step": 0.4
+ },
+ {
+ "freq": 123.47548620540732,
+ "dur": 0.36800000000000005,
+ "step": 0.4
+ },
+ {
+ "freq": 103.83009372183648,
+ "dur": 0.36800000000000005,
+ "step": 0.4
+ },
+ {
+ "freq": 164.81,
+ "dur": 1.536,
+ "step": 0.544
+ },
+ {
+ "freq": 195.99322462359845,
+ "dur": 0.992,
+ "step": 0.528
+ },
+ {
+ "freq": 246.9359893400459,
+ "dur": 0.48,
+ "step": 0.528
+ },
+ {
+ "freq": 329.63,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 392,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 493.88,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 392,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 659.25,
+ "dur": 0.36800000000000005,
+ "step": 0.4
+ },
+ {
+ "freq": 622.25,
+ "dur": 0.36800000000000005,
+ "step": 0.4
+ },
+ {
+ "freq": 110,
+ "dur": 0.36800000000000005,
+ "step": 0.4
+ },
+ {
+ "freq": 138.59131548843604,
+ "dur": 0.36800000000000005,
+ "step": 0.4
+ },
+ {
+ "freq": 164.81377845643496,
+ "dur": 0.36800000000000005,
+ "step": 0.4
+ },
+ {
+ "freq": 138.59131548843604,
+ "dur": 0.36800000000000005,
+ "step": 0.4
+ },
+ {
+ "freq": 220,
+ "dur": 1.536,
+ "step": 0.544
+ },
+ {
+ "freq": 277.1826309768721,
+ "dur": 0.992,
+ "step": 0.528
+ },
+ {
+ "freq": 329.6275569128699,
+ "dur": 0.48,
+ "step": 0.528
+ },
+ {
+ "freq": 987.77,
+ "dur": 0.12,
+ "step": 0.2
+ },
+ {
+ "freq": 932.3307298375963,
+ "dur": 0.12,
+ "step": 0.2
+ },
+ {
+ "freq": 880.0030268174829,
+ "dur": 0.12,
+ "step": 0.2
+ },
+ {
+ "freq": 830.6122520951617,
+ "dur": 0.12,
+ "step": 0.2
+ },
+ {
+ "freq": 783.9935685513143,
+ "dur": 0.12,
+ "step": 0.2
+ },
+ {
+ "freq": 739.9913906632398,
+ "dur": 0.12,
+ "step": 0.2
+ },
+ {
+ "freq": 698.458865252636,
+ "dur": 0.12,
+ "step": 0.2
+ },
+ {
+ "freq": 659.2573813767674,
+ "dur": 0.12,
+ "step": 0.2
+ },
+ {
+ "freq": 82.41,
+ "dur": 0.36800000000000005,
+ "step": 0.4
+ },
+ {
+ "freq": 103.83009372183648,
+ "dur": 0.36800000000000005,
+ "step": 0.4
+ },
+ {
+ "freq": 123.47548620540732,
+ "dur": 0.36800000000000005,
+ "step": 0.4
+ },
+ {
+ "freq": 103.83009372183648,
+ "dur": 0.36800000000000005,
+ "step": 0.4
+ },
+ {
+ "freq": 164.81,
+ "dur": 1.536,
+ "step": 0.544
+ },
+ {
+ "freq": 195.99322462359845,
+ "dur": 0.992,
+ "step": 0.528
+ },
+ {
+ "freq": 246.9359893400459,
+ "dur": 0.48,
+ "step": 0.528
+ },
+ {
+ "freq": 329.63,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 392,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 493.88,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 392,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 740,
+ "dur": 0.36800000000000005,
+ "step": 0.4
+ },
+ {
+ "freq": 698.46,
+ "dur": 0.36800000000000005,
+ "step": 0.4
+ },
+ {
+ "freq": 123.47,
+ "dur": 0.36800000000000005,
+ "step": 0.4
+ },
+ {
+ "freq": 155.56245203051998,
+ "dur": 0.36800000000000005,
+ "step": 0.4
+ },
+ {
+ "freq": 184.99597478196387,
+ "dur": 0.36800000000000005,
+ "step": 0.4
+ },
+ {
+ "freq": 155.56245203051998,
+ "dur": 0.36800000000000005,
+ "step": 0.4
+ },
+ {
+ "freq": 246.94,
+ "dur": 1.536,
+ "step": 0.544
+ },
+ {
+ "freq": 311.12490406103996,
+ "dur": 0.992,
+ "step": 0.528
+ },
+ {
+ "freq": 369.99194956392773,
+ "dur": 0.48,
+ "step": 0.528
+ },
+ {
+ "freq": 880,
+ "dur": 0.12,
+ "step": 0.2
+ },
+ {
+ "freq": 830.6093951598903,
+ "dur": 0.12,
+ "step": 0.2
+ },
+ {
+ "freq": 783.9908719634985,
+ "dur": 0.12,
+ "step": 0.2
+ },
+ {
+ "freq": 739.9888454232689,
+ "dur": 0.12,
+ "step": 0.2
+ },
+ {
+ "freq": 698.4564628660079,
+ "dur": 0.12,
+ "step": 0.2
+ },
+ {
+ "freq": 659.2551138257398,
+ "dur": 0.12,
+ "step": 0.2
+ },
+ {
+ "freq": 622.2539674441617,
+ "dur": 0.12,
+ "step": 0.2
+ },
+ {
+ "freq": 587.3295358348151,
+ "dur": 0.12,
+ "step": 0.2
+ }
+ ],
+ "drums": [
+ "kick",
+ "_",
+ "hat",
+ "_",
+ "_",
+ "snare",
+ "hat",
+ "_",
+ "kick",
+ "kick",
+ "hat",
+ "_",
+ "snare",
+ "_",
+ "hat",
+ "snare"
+ ]
+ },
+ "wild": {
+ "bpm": 190,
+ "gain": 0.075,
+ "wave": "sawtooth",
+ "droneFreqs": [
+ 164.81,
+ 246.94,
+ 329.63,
+ 493.88
+ ],
+ "cutoffMin": 2400,
+ "cutoffMax": 7500,
+ "attack": 0.02,
+ "release": 0.04,
+ "detuneCents": 18,
+ "melody": [
+ {
+ "freq": 164.81,
+ "dur": 0.29072000000000003,
+ "step": 0.316
+ },
+ {
+ "freq": 207.64758823317402,
+ "dur": 0.29072000000000003,
+ "step": 0.316
+ },
+ {
+ "freq": 246.9359893400459,
+ "dur": 0.29072000000000003,
+ "step": 0.316
+ },
+ {
+ "freq": 207.64758823317402,
+ "dur": 0.29072000000000003,
+ "step": 0.316
+ },
+ {
+ "freq": 1318.5,
+ "dur": 0.0948,
+ "step": 0.158
+ },
+ {
+ "freq": 1244.4982812708129,
+ "dur": 0.0948,
+ "step": 0.158
+ },
+ {
+ "freq": 1174.6499598680373,
+ "dur": 0.0948,
+ "step": 0.158
+ },
+ {
+ "freq": 1108.7219235120226,
+ "dur": 0.0948,
+ "step": 0.158
+ },
+ {
+ "freq": 1046.4941435100357,
+ "dur": 0.0948,
+ "step": 0.158
+ },
+ {
+ "freq": 987.7589404309523,
+ "dur": 0.0948,
+ "step": 0.158
+ },
+ {
+ "freq": 932.3202909944629,
+ "dur": 0.0948,
+ "step": 0.158
+ },
+ {
+ "freq": 879.9931738615952,
+ "dur": 0.0948,
+ "step": 0.158
+ }
+ ],
+ "drums": [
+ "kick",
+ "_",
+ "hat",
+ "_",
+ "_",
+ "snare",
+ "hat",
+ "_",
+ "kick",
+ "kick",
+ "hat",
+ "_",
+ "snare",
+ "_",
+ "hat",
+ "snare"
+ ]
+ }
+ }
+}
diff --git a/internal/generator/templates/themes/synthwave/sounds.json b/internal/generator/templates/themes/synthwave/sounds.json
new file mode 100644
index 0000000..082d781
--- /dev/null
+++ b/internal/generator/templates/themes/synthwave/sounds.json
@@ -0,0 +1,472 @@
+{
+ "splash": {
+ "freqs": [
+ 196,
+ 246.94,
+ 293.66,
+ 349.23
+ ],
+ "spacing": 0.1,
+ "gain": 0.1,
+ "wave": "sine"
+ },
+ "nav": {
+ "freq": 164.81,
+ "wave": "triangle",
+ "dur": 0.09,
+ "gain": 0.1
+ },
+ "open": {
+ "wave": "sine",
+ "start": 220,
+ "end": 440,
+ "dur": 0.18,
+ "gain": 0.1
+ },
+ "close": {
+ "wave": "sine",
+ "start": 440,
+ "end": 110,
+ "dur": 0.17,
+ "gain": 0.09
+ },
+ "bounce": {
+ "wave": "sine",
+ "start": 150,
+ "end": 75,
+ "dur": 0.14,
+ "gain": 0.09
+ },
+ "ambient": {
+ "normal": {
+ "bpm": 150,
+ "gain": 0.032,
+ "wave": "sawtooth",
+ "droneFreqs": [
+ 110,
+ 174.61,
+ 220
+ ],
+ "cutoffMin": 1200,
+ "cutoffMax": 5500,
+ "attack": 0.02,
+ "release": 0.08,
+ "melody": [
+ {
+ "freq": 110,
+ "dur": 0.34,
+ "step": 0.4
+ },
+ {
+ "freq": 220,
+ "dur": 0.34,
+ "step": 0.4
+ },
+ {
+ "freq": 110,
+ "dur": 0.34,
+ "step": 0.4
+ },
+ {
+ "freq": 164.81377845643496,
+ "dur": 0.34,
+ "step": 0.4
+ },
+ {
+ "freq": 220,
+ "dur": 1.536,
+ "step": 0.544
+ },
+ {
+ "freq": 261.6255653005986,
+ "dur": 0.992,
+ "step": 0.528
+ },
+ {
+ "freq": 329.6275569128699,
+ "dur": 0.48,
+ "step": 0.528
+ },
+ {
+ "freq": 880,
+ "dur": 0.09200000000000001,
+ "step": 0.1
+ },
+ {
+ "freq": 1046.5,
+ "dur": 0.09200000000000001,
+ "step": 0.1
+ },
+ {
+ "freq": 1318.5,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 1046.5,
+ "dur": 0.09200000000000001,
+ "step": 0.1
+ },
+ {
+ "freq": 880,
+ "dur": 0.09200000000000001,
+ "step": 0.1
+ },
+ {
+ "freq": 659.25,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 880,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 1046.5,
+ "dur": 0.36800000000000005,
+ "step": 0.4
+ },
+ {
+ "freq": 87.31,
+ "dur": 0.34,
+ "step": 0.4
+ },
+ {
+ "freq": 174.62,
+ "dur": 0.34,
+ "step": 0.4
+ },
+ {
+ "freq": 87.31,
+ "dur": 0.34,
+ "step": 0.4
+ },
+ {
+ "freq": 130.81719088210306,
+ "dur": 0.34,
+ "step": 0.4
+ },
+ {
+ "freq": 174.61,
+ "dur": 1.536,
+ "step": 0.544
+ },
+ {
+ "freq": 219.9948145221438,
+ "dur": 0.992,
+ "step": 0.528
+ },
+ {
+ "freq": 261.6193986934374,
+ "dur": 0.48,
+ "step": 0.528
+ },
+ {
+ "freq": 698.46,
+ "dur": 0.09200000000000001,
+ "step": 0.1
+ },
+ {
+ "freq": 880,
+ "dur": 0.09200000000000001,
+ "step": 0.1
+ },
+ {
+ "freq": 1046.5,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 880,
+ "dur": 0.09200000000000001,
+ "step": 0.1
+ },
+ {
+ "freq": 698.46,
+ "dur": 0.09200000000000001,
+ "step": 0.1
+ },
+ {
+ "freq": 523.25,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 698.46,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 880,
+ "dur": 0.36800000000000005,
+ "step": 0.4
+ },
+ {
+ "freq": 130.81,
+ "dur": 0.34,
+ "step": 0.4
+ },
+ {
+ "freq": 261.62,
+ "dur": 0.34,
+ "step": 0.4
+ },
+ {
+ "freq": 130.81,
+ "dur": 0.34,
+ "step": 0.4
+ },
+ {
+ "freq": 195.9935487262387,
+ "dur": 0.34,
+ "step": 0.4
+ },
+ {
+ "freq": 261.63,
+ "dur": 1.536,
+ "step": 0.544
+ },
+ {
+ "freq": 329.6331442839956,
+ "dur": 0.992,
+ "step": 0.528
+ },
+ {
+ "freq": 392.0020805232462,
+ "dur": 0.48,
+ "step": 0.528
+ },
+ {
+ "freq": 1046.5,
+ "dur": 0.09200000000000001,
+ "step": 0.1
+ },
+ {
+ "freq": 1318.5,
+ "dur": 0.09200000000000001,
+ "step": 0.1
+ },
+ {
+ "freq": 1567.98,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 1318.5,
+ "dur": 0.09200000000000001,
+ "step": 0.1
+ },
+ {
+ "freq": 1046.5,
+ "dur": 0.09200000000000001,
+ "step": 0.1
+ },
+ {
+ "freq": 783.99,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 1046.5,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 1318.5,
+ "dur": 0.36800000000000005,
+ "step": 0.4
+ },
+ {
+ "freq": 98,
+ "dur": 0.34,
+ "step": 0.4
+ },
+ {
+ "freq": 196,
+ "dur": 0.34,
+ "step": 0.4
+ },
+ {
+ "freq": 98,
+ "dur": 0.34,
+ "step": 0.4
+ },
+ {
+ "freq": 146.8340935339148,
+ "dur": 0.34,
+ "step": 0.4
+ },
+ {
+ "freq": 196,
+ "dur": 1.536,
+ "step": 0.544
+ },
+ {
+ "freq": 246.9445257793951,
+ "dur": 0.992,
+ "step": 0.528
+ },
+ {
+ "freq": 293.6681870678296,
+ "dur": 0.48,
+ "step": 0.528
+ },
+ {
+ "freq": 783.99,
+ "dur": 0.09200000000000001,
+ "step": 0.1
+ },
+ {
+ "freq": 987.77,
+ "dur": 0.09200000000000001,
+ "step": 0.1
+ },
+ {
+ "freq": 1174.66,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 987.77,
+ "dur": 0.09200000000000001,
+ "step": 0.1
+ },
+ {
+ "freq": 783.99,
+ "dur": 0.09200000000000001,
+ "step": 0.1
+ },
+ {
+ "freq": 587.33,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 783.99,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 987.77,
+ "dur": 0.36800000000000005,
+ "step": 0.4
+ }
+ ],
+ "drums": [
+ "kick",
+ "_",
+ "_",
+ "_",
+ "clap",
+ "_",
+ "hat",
+ "_",
+ "kick",
+ "kick",
+ "_",
+ "_",
+ "clap",
+ "_",
+ "hat",
+ "snare"
+ ]
+ },
+ "wild": {
+ "bpm": 190,
+ "gain": 0.065,
+ "wave": "sawtooth",
+ "droneFreqs": [
+ 220,
+ 349.23,
+ 440,
+ 523.25
+ ],
+ "cutoffMin": 2400,
+ "cutoffMax": 7500,
+ "attack": 0.02,
+ "release": 0.05,
+ "detuneCents": 14,
+ "melody": [
+ {
+ "freq": 220,
+ "dur": 0.2686,
+ "step": 0.316
+ },
+ {
+ "freq": 440,
+ "dur": 0.2686,
+ "step": 0.316
+ },
+ {
+ "freq": 220,
+ "dur": 0.2686,
+ "step": 0.316
+ },
+ {
+ "freq": 329.6275569128699,
+ "dur": 0.2686,
+ "step": 0.316
+ },
+ {
+ "freq": 1760,
+ "dur": 0.07268000000000001,
+ "step": 0.079
+ },
+ {
+ "freq": 2093,
+ "dur": 0.07268000000000001,
+ "step": 0.079
+ },
+ {
+ "freq": 2637,
+ "dur": 0.07268000000000001,
+ "step": 0.079
+ },
+ {
+ "freq": 2093,
+ "dur": 0.07268000000000001,
+ "step": 0.079
+ },
+ {
+ "freq": 1760,
+ "dur": 0.07268000000000001,
+ "step": 0.079
+ },
+ {
+ "freq": 1318.5,
+ "dur": 0.07268000000000001,
+ "step": 0.079
+ },
+ {
+ "freq": 1760,
+ "dur": 0.07268000000000001,
+ "step": 0.079
+ },
+ {
+ "freq": 2093,
+ "dur": 0.07268000000000001,
+ "step": 0.079
+ }
+ ],
+ "drums": [
+ "kick",
+ "_",
+ "_",
+ "_",
+ "clap",
+ "_",
+ "hat",
+ "_",
+ "kick",
+ "kick",
+ "_",
+ "_",
+ "clap",
+ "_",
+ "hat",
+ "snare"
+ ]
+ }
+ }
+}
diff --git a/internal/generator/templates/themes/terminal/sounds.json b/internal/generator/templates/themes/terminal/sounds.json
new file mode 100644
index 0000000..e6ddff2
--- /dev/null
+++ b/internal/generator/templates/themes/terminal/sounds.json
@@ -0,0 +1,381 @@
+{
+ "splash": {
+ "freqs": [
+ 523.25,
+ 659.25,
+ 783.99
+ ],
+ "spacing": 0.09,
+ "gain": 0.11,
+ "wave": "square"
+ },
+ "nav": {
+ "freq": 800,
+ "wave": "square",
+ "dur": 0.045,
+ "gain": 0.12
+ },
+ "open": {
+ "wave": "square",
+ "start": 600,
+ "end": 1200,
+ "dur": 0.12,
+ "gain": 0.1
+ },
+ "close": {
+ "wave": "square",
+ "start": 900,
+ "end": 400,
+ "dur": 0.14,
+ "gain": 0.09
+ },
+ "bounce": {
+ "wave": "square",
+ "start": 200,
+ "end": 100,
+ "dur": 0.1,
+ "gain": 0.1
+ },
+ "ambient": {
+ "normal": {
+ "bpm": 160,
+ "gain": 0.03,
+ "wave": "sawtooth",
+ "droneFreqs": [
+ 82.41,
+ 123.47,
+ 164.81
+ ],
+ "cutoffMin": 1000,
+ "cutoffMax": 5000,
+ "attack": 0.02,
+ "release": 0.1,
+ "melody": [
+ {
+ "freq": 82.41,
+ "dur": 0.084375,
+ "step": 0.1875
+ },
+ {
+ "freq": 82.41,
+ "dur": 0.084375,
+ "step": 0.1875
+ },
+ {
+ "freq": 82.41,
+ "dur": 0.084375,
+ "step": 0.1875
+ },
+ {
+ "freq": 82.41,
+ "dur": 0.084375,
+ "step": 0.1875
+ },
+ {
+ "freq": 123.47548620540732,
+ "dur": 0.084375,
+ "step": 0.1875
+ },
+ {
+ "freq": 82.41,
+ "dur": 0.084375,
+ "step": 0.1875
+ },
+ {
+ "freq": 123.47548620540732,
+ "dur": 0.084375,
+ "step": 0.1875
+ },
+ {
+ "freq": 82.41,
+ "dur": 0.084375,
+ "step": 0.1875
+ },
+ {
+ "freq": 164.81,
+ "dur": 1.44,
+ "step": 0.51
+ },
+ {
+ "freq": 195.99322462359845,
+ "dur": 0.9299999999999999,
+ "step": 0.495
+ },
+ {
+ "freq": 246.9359893400459,
+ "dur": 0.44999999999999996,
+ "step": 0.495
+ },
+ {
+ "freq": 329.63,
+ "dur": 0.17250000000000001,
+ "step": 0.1875
+ },
+ {
+ "freq": 392,
+ "dur": 0.17250000000000001,
+ "step": 0.1875
+ },
+ {
+ "freq": 466.16,
+ "dur": 0.17250000000000001,
+ "step": 0.1875
+ },
+ {
+ "freq": 329.63,
+ "dur": 0.17250000000000001,
+ "step": 0.1875
+ },
+ {
+ "freq": 466.16,
+ "dur": 0.17250000000000001,
+ "step": 0.1875
+ },
+ {
+ "freq": 622.25,
+ "dur": 0.17250000000000001,
+ "step": 0.1875
+ },
+ {
+ "freq": 466.16,
+ "dur": 0.17250000000000001,
+ "step": 0.1875
+ },
+ {
+ "freq": 329.63,
+ "dur": 0.17250000000000001,
+ "step": 0.1875
+ },
+ {
+ "freq": 110,
+ "dur": 0.084375,
+ "step": 0.1875
+ },
+ {
+ "freq": 110,
+ "dur": 0.084375,
+ "step": 0.1875
+ },
+ {
+ "freq": 110,
+ "dur": 0.084375,
+ "step": 0.1875
+ },
+ {
+ "freq": 110,
+ "dur": 0.084375,
+ "step": 0.1875
+ },
+ {
+ "freq": 164.81377845643496,
+ "dur": 0.084375,
+ "step": 0.1875
+ },
+ {
+ "freq": 110,
+ "dur": 0.084375,
+ "step": 0.1875
+ },
+ {
+ "freq": 164.81377845643496,
+ "dur": 0.084375,
+ "step": 0.1875
+ },
+ {
+ "freq": 110,
+ "dur": 0.084375,
+ "step": 0.1875
+ },
+ {
+ "freq": 220,
+ "dur": 1.44,
+ "step": 0.51
+ },
+ {
+ "freq": 261.6255653005986,
+ "dur": 0.9299999999999999,
+ "step": 0.495
+ },
+ {
+ "freq": 329.6275569128699,
+ "dur": 0.44999999999999996,
+ "step": 0.495
+ },
+ {
+ "freq": 440,
+ "dur": 0.17250000000000001,
+ "step": 0.1875
+ },
+ {
+ "freq": 523.25,
+ "dur": 0.17250000000000001,
+ "step": 0.1875
+ },
+ {
+ "freq": 622.25,
+ "dur": 0.17250000000000001,
+ "step": 0.1875
+ },
+ {
+ "freq": 440,
+ "dur": 0.17250000000000001,
+ "step": 0.1875
+ },
+ {
+ "freq": 622.25,
+ "dur": 0.17250000000000001,
+ "step": 0.1875
+ },
+ {
+ "freq": 783.99,
+ "dur": 0.17250000000000001,
+ "step": 0.1875
+ },
+ {
+ "freq": 622.25,
+ "dur": 0.17250000000000001,
+ "step": 0.1875
+ },
+ {
+ "freq": 440,
+ "dur": 0.17250000000000001,
+ "step": 0.1875
+ }
+ ],
+ "drums": [
+ "kick",
+ "kick",
+ "_",
+ "hat",
+ "snare",
+ "_",
+ "kick",
+ "hat",
+ "kick",
+ "_",
+ "_",
+ "hat",
+ "snare",
+ "kick",
+ "_",
+ "hat"
+ ]
+ },
+ "wild": {
+ "bpm": 170,
+ "gain": 0.065,
+ "wave": "sawtooth",
+ "droneFreqs": [
+ 82.41,
+ 164.81,
+ 246.94,
+ 329.63
+ ],
+ "cutoffMin": 2000,
+ "cutoffMax": 7000,
+ "attack": 0.02,
+ "release": 0.05,
+ "detuneCents": 18,
+ "melody": [
+ {
+ "freq": 164.81,
+ "dur": 0.079425,
+ "step": 0.1765
+ },
+ {
+ "freq": 164.81,
+ "dur": 0.079425,
+ "step": 0.1765
+ },
+ {
+ "freq": 164.81,
+ "dur": 0.079425,
+ "step": 0.1765
+ },
+ {
+ "freq": 164.81,
+ "dur": 0.079425,
+ "step": 0.1765
+ },
+ {
+ "freq": 246.9359893400459,
+ "dur": 0.079425,
+ "step": 0.1765
+ },
+ {
+ "freq": 164.81,
+ "dur": 0.079425,
+ "step": 0.1765
+ },
+ {
+ "freq": 246.9359893400459,
+ "dur": 0.079425,
+ "step": 0.1765
+ },
+ {
+ "freq": 164.81,
+ "dur": 0.079425,
+ "step": 0.1765
+ },
+ {
+ "freq": 659.25,
+ "dur": 0.08119,
+ "step": 0.08825
+ },
+ {
+ "freq": 783.99,
+ "dur": 0.08119,
+ "step": 0.08825
+ },
+ {
+ "freq": 932.33,
+ "dur": 0.08119,
+ "step": 0.08825
+ },
+ {
+ "freq": 659.25,
+ "dur": 0.08119,
+ "step": 0.08825
+ },
+ {
+ "freq": 932.33,
+ "dur": 0.08119,
+ "step": 0.08825
+ },
+ {
+ "freq": 1244.51,
+ "dur": 0.08119,
+ "step": 0.08825
+ },
+ {
+ "freq": 932.33,
+ "dur": 0.08119,
+ "step": 0.08825
+ },
+ {
+ "freq": 659.25,
+ "dur": 0.08119,
+ "step": 0.08825
+ }
+ ],
+ "drums": [
+ "kick",
+ "kick",
+ "_",
+ "hat",
+ "snare",
+ "_",
+ "kick",
+ "hat",
+ "kick",
+ "_",
+ "_",
+ "hat",
+ "snare",
+ "kick",
+ "_",
+ "hat"
+ ]
+ }
+ }
+}
diff --git a/internal/generator/templates/themes/tropicale/sounds.json b/internal/generator/templates/themes/tropicale/sounds.json
new file mode 100644
index 0000000..8fdbd38
--- /dev/null
+++ b/internal/generator/templates/themes/tropicale/sounds.json
@@ -0,0 +1,382 @@
+{
+ "splash": {
+ "freqs": [
+ 349.23,
+ 440,
+ 523.25,
+ 698.46
+ ],
+ "spacing": 0.09,
+ "gain": 0.095,
+ "wave": "triangle"
+ },
+ "nav": {
+ "freq": 233.08,
+ "wave": "sine",
+ "dur": 0.085,
+ "gain": 0.1
+ },
+ "open": {
+ "wave": "triangle",
+ "start": 349.23,
+ "end": 698.46,
+ "dur": 0.18,
+ "gain": 0.1
+ },
+ "close": {
+ "wave": "sine",
+ "start": 523.25,
+ "end": 174.61,
+ "dur": 0.2,
+ "gain": 0.09
+ },
+ "bounce": {
+ "wave": "triangle",
+ "start": 170,
+ "end": 85,
+ "dur": 0.12,
+ "gain": 0.09
+ },
+ "ambient": {
+ "normal": {
+ "bpm": 120,
+ "gain": 0.03,
+ "wave": "sawtooth",
+ "droneFreqs": [
+ 87.31,
+ 174.61,
+ 261.63
+ ],
+ "cutoffMin": 1200,
+ "cutoffMax": 5500,
+ "attack": 0.02,
+ "release": 0.15,
+ "melody": [
+ {
+ "freq": 87.31,
+ "dur": 0.7,
+ "step": 0.75
+ },
+ {
+ "freq": 130.81719088210306,
+ "dur": 0.225,
+ "step": 0.25
+ },
+ {
+ "freq": 87.31,
+ "dur": 0.7,
+ "step": 0.75
+ },
+ {
+ "freq": 130.81719088210306,
+ "dur": 0.225,
+ "step": 0.25
+ },
+ {
+ "freq": 174.61,
+ "dur": 1.92,
+ "step": 0.68
+ },
+ {
+ "freq": 219.9948145221438,
+ "dur": 1.24,
+ "step": 0.66
+ },
+ {
+ "freq": 261.6193986934374,
+ "dur": 0.6,
+ "step": 0.66
+ },
+ {
+ "freq": 698.46,
+ "dur": 0.23,
+ "step": 0.375
+ },
+ {
+ "freq": 880,
+ "dur": 0.115,
+ "step": 0.125
+ },
+ {
+ "freq": 1046.5,
+ "dur": 0.23,
+ "step": 0.25
+ },
+ {
+ "freq": 880,
+ "dur": 0.23,
+ "step": 0.25
+ },
+ {
+ "freq": 698.46,
+ "dur": 0.23,
+ "step": 0.25
+ },
+ {
+ "freq": 880,
+ "dur": 0.23,
+ "step": 0.25
+ },
+ {
+ "freq": 1046.5,
+ "dur": 0.46,
+ "step": 0.5
+ },
+ {
+ "freq": 116.54,
+ "dur": 0.7,
+ "step": 0.75
+ },
+ {
+ "freq": 174.61270673920848,
+ "dur": 0.225,
+ "step": 0.25
+ },
+ {
+ "freq": 116.54,
+ "dur": 0.7,
+ "step": 0.75
+ },
+ {
+ "freq": 174.61270673920848,
+ "dur": 0.225,
+ "step": 0.25
+ },
+ {
+ "freq": 233.08,
+ "dur": 1.92,
+ "step": 0.68
+ },
+ {
+ "freq": 293.662398309497,
+ "dur": 1.24,
+ "step": 0.66
+ },
+ {
+ "freq": 349.22541347841695,
+ "dur": 0.6,
+ "step": 0.66
+ },
+ {
+ "freq": 932.33,
+ "dur": 0.23,
+ "step": 0.375
+ },
+ {
+ "freq": 1174.66,
+ "dur": 0.115,
+ "step": 0.125
+ },
+ {
+ "freq": 1396.92,
+ "dur": 0.23,
+ "step": 0.25
+ },
+ {
+ "freq": 1174.66,
+ "dur": 0.23,
+ "step": 0.25
+ },
+ {
+ "freq": 932.33,
+ "dur": 0.23,
+ "step": 0.25
+ },
+ {
+ "freq": 1174.66,
+ "dur": 0.23,
+ "step": 0.25
+ },
+ {
+ "freq": 1396.92,
+ "dur": 0.46,
+ "step": 0.5
+ },
+ {
+ "freq": 130.81,
+ "dur": 0.7,
+ "step": 0.75
+ },
+ {
+ "freq": 195.9935487262387,
+ "dur": 0.225,
+ "step": 0.25
+ },
+ {
+ "freq": 130.81,
+ "dur": 0.7,
+ "step": 0.75
+ },
+ {
+ "freq": 195.9935487262387,
+ "dur": 0.225,
+ "step": 0.25
+ },
+ {
+ "freq": 261.63,
+ "dur": 1.92,
+ "step": 0.68
+ },
+ {
+ "freq": 329.6331442839956,
+ "dur": 1.24,
+ "step": 0.66
+ },
+ {
+ "freq": 392.0020805232462,
+ "dur": 0.6,
+ "step": 0.66
+ },
+ {
+ "freq": 1046.5,
+ "dur": 0.23,
+ "step": 0.375
+ },
+ {
+ "freq": 1318.5,
+ "dur": 0.115,
+ "step": 0.125
+ },
+ {
+ "freq": 1567.98,
+ "dur": 0.23,
+ "step": 0.25
+ },
+ {
+ "freq": 1318.5,
+ "dur": 0.23,
+ "step": 0.25
+ },
+ {
+ "freq": 1046.5,
+ "dur": 0.23,
+ "step": 0.25
+ },
+ {
+ "freq": 1318.5,
+ "dur": 0.23,
+ "step": 0.25
+ },
+ {
+ "freq": 1567.98,
+ "dur": 0.46,
+ "step": 0.5
+ }
+ ],
+ "drums": [
+ "kick",
+ "hat",
+ "_",
+ "hat",
+ "snare",
+ "kick",
+ "hat",
+ "_",
+ "kick",
+ "hat",
+ "_",
+ "hat",
+ "snare",
+ "_",
+ "hat",
+ "kick"
+ ]
+ },
+ "wild": {
+ "bpm": 170,
+ "gain": 0.065,
+ "wave": "sawtooth",
+ "droneFreqs": [
+ 87.31,
+ 174.61,
+ 261.63,
+ 349.23
+ ],
+ "cutoffMin": 2200,
+ "cutoffMax": 7500,
+ "attack": 0.02,
+ "release": 0.06,
+ "detuneCents": 12,
+ "melody": [
+ {
+ "freq": 174.61,
+ "dur": 0.4941999999999999,
+ "step": 0.5295
+ },
+ {
+ "freq": 261.6193986934374,
+ "dur": 0.15885,
+ "step": 0.1765
+ },
+ {
+ "freq": 174.61,
+ "dur": 0.4941999999999999,
+ "step": 0.5295
+ },
+ {
+ "freq": 261.6193986934374,
+ "dur": 0.15885,
+ "step": 0.1765
+ },
+ {
+ "freq": 1396.92,
+ "dur": 0.08119,
+ "step": 0.08825
+ },
+ {
+ "freq": 1760,
+ "dur": 0.08119,
+ "step": 0.08825
+ },
+ {
+ "freq": 2093,
+ "dur": 0.08119,
+ "step": 0.08825
+ },
+ {
+ "freq": 1760,
+ "dur": 0.08119,
+ "step": 0.08825
+ },
+ {
+ "freq": 2349.32,
+ "dur": 0.08119,
+ "step": 0.08825
+ },
+ {
+ "freq": 2093,
+ "dur": 0.08119,
+ "step": 0.08825
+ },
+ {
+ "freq": 1760,
+ "dur": 0.08119,
+ "step": 0.08825
+ },
+ {
+ "freq": 1396.92,
+ "dur": 0.08119,
+ "step": 0.08825
+ }
+ ],
+ "drums": [
+ "kick",
+ "hat",
+ "_",
+ "hat",
+ "snare",
+ "kick",
+ "hat",
+ "_",
+ "kick",
+ "hat",
+ "_",
+ "hat",
+ "snare",
+ "_",
+ "hat",
+ "kick"
+ ]
+ }
+ }
+}
diff --git a/internal/generator/templates/themes/volcano/sounds.json b/internal/generator/templates/themes/volcano/sounds.json
new file mode 100644
index 0000000..2b22e9d
--- /dev/null
+++ b/internal/generator/templates/themes/volcano/sounds.json
@@ -0,0 +1,322 @@
+{
+ "splash": {
+ "freqs": [
+ 293.66,
+ 369.99,
+ 440,
+ 587.33
+ ],
+ "spacing": 0.09,
+ "gain": 0.095,
+ "wave": "triangle"
+ },
+ "nav": {
+ "freq": 196,
+ "wave": "triangle",
+ "dur": 0.085,
+ "gain": 0.1
+ },
+ "open": {
+ "wave": "triangle",
+ "start": 293.66,
+ "end": 587.33,
+ "dur": 0.16,
+ "gain": 0.1
+ },
+ "close": {
+ "wave": "sine",
+ "start": 440,
+ "end": 146.83,
+ "dur": 0.18,
+ "gain": 0.09
+ },
+ "bounce": {
+ "wave": "triangle",
+ "start": 130,
+ "end": 65,
+ "dur": 0.12,
+ "gain": 0.09
+ },
+ "ambient": {
+ "normal": {
+ "bpm": 150,
+ "gain": 0.032,
+ "wave": "sawtooth",
+ "droneFreqs": [
+ 73.42,
+ 110,
+ 146.83
+ ],
+ "cutoffMin": 1200,
+ "cutoffMax": 5500,
+ "attack": 0.01,
+ "release": 0.08,
+ "melody": [
+ {
+ "freq": 36.71,
+ "dur": 0.34,
+ "step": 0.2
+ },
+ {
+ "freq": 73.42,
+ "dur": 0.18000000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 36.71,
+ "dur": 0.34,
+ "step": 0.2
+ },
+ {
+ "freq": 73.42,
+ "dur": 0.18000000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 36.71,
+ "dur": 0.34,
+ "step": 0.2
+ },
+ {
+ "freq": 73.42,
+ "dur": 0.18000000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 36.71,
+ "dur": 0.34,
+ "step": 0.2
+ },
+ {
+ "freq": 73.42,
+ "dur": 0.18000000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 587.33,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 698.46,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 880,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 1174.66,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 880,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 698.46,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 587.33,
+ "dur": 0.36800000000000005,
+ "step": 0.4
+ },
+ {
+ "freq": 29.135,
+ "dur": 0.34,
+ "step": 0.2
+ },
+ {
+ "freq": 58.27,
+ "dur": 0.18000000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 29.135,
+ "dur": 0.34,
+ "step": 0.2
+ },
+ {
+ "freq": 58.27,
+ "dur": 0.18000000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 43.655,
+ "dur": 0.34,
+ "step": 0.2
+ },
+ {
+ "freq": 87.31,
+ "dur": 0.18000000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 32.705,
+ "dur": 0.34,
+ "step": 0.2
+ },
+ {
+ "freq": 65.41,
+ "dur": 0.18000000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 466.16,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 587.33,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 698.46,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 880,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 698.46,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 587.33,
+ "dur": 0.18400000000000002,
+ "step": 0.2
+ },
+ {
+ "freq": 466.16,
+ "dur": 0.36800000000000005,
+ "step": 0.4
+ }
+ ],
+ "drums": [
+ "kick",
+ "_",
+ "_",
+ "kick",
+ "kick",
+ "_",
+ "_",
+ "kick",
+ "kick",
+ "_",
+ "_",
+ "kick",
+ "kick",
+ "kick",
+ "_",
+ "kick"
+ ]
+ },
+ "wild": {
+ "bpm": 180,
+ "gain": 0.07,
+ "wave": "sawtooth",
+ "droneFreqs": [
+ 73.42,
+ 110,
+ 146.83,
+ 220
+ ],
+ "cutoffMin": 2400,
+ "cutoffMax": 8000,
+ "attack": 0.01,
+ "release": 0.04,
+ "detuneCents": 18,
+ "melody": [
+ {
+ "freq": 73.415,
+ "dur": 0.28305,
+ "step": 0.1665
+ },
+ {
+ "freq": 146.83,
+ "dur": 0.14985,
+ "step": 0.1665
+ },
+ {
+ "freq": 73.415,
+ "dur": 0.28305,
+ "step": 0.1665
+ },
+ {
+ "freq": 146.83,
+ "dur": 0.14985,
+ "step": 0.1665
+ },
+ {
+ "freq": 1174.66,
+ "dur": 0.07659,
+ "step": 0.08325
+ },
+ {
+ "freq": 1396.92,
+ "dur": 0.07659,
+ "step": 0.08325
+ },
+ {
+ "freq": 1760,
+ "dur": 0.07659,
+ "step": 0.08325
+ },
+ {
+ "freq": 2349.32,
+ "dur": 0.07659,
+ "step": 0.08325
+ },
+ {
+ "freq": 1760,
+ "dur": 0.07659,
+ "step": 0.08325
+ },
+ {
+ "freq": 1396.92,
+ "dur": 0.07659,
+ "step": 0.08325
+ },
+ {
+ "freq": 1174.66,
+ "dur": 0.07659,
+ "step": 0.08325
+ },
+ {
+ "freq": 880,
+ "dur": 0.07659,
+ "step": 0.08325
+ }
+ ],
+ "drums": [
+ "kick",
+ "_",
+ "_",
+ "kick",
+ "kick",
+ "_",
+ "_",
+ "kick",
+ "kick",
+ "_",
+ "_",
+ "kick",
+ "kick",
+ "kick",
+ "_",
+ "kick"
+ ]
+ }
+ }
+}
diff --git a/internal/generator/theme_sounds.go b/internal/generator/theme_sounds.go
index 234a964..788a76a 100644
--- a/internal/generator/theme_sounds.go
+++ b/internal/generator/theme_sounds.go
@@ -2,8 +2,11 @@ package generator
import (
"encoding/json"
+ "fmt"
"html/template"
- "math"
+ "sync"
+
+ "codeberg.org/snonux/snonux/internal/generator/templates"
)
// melodyNote is a single note in a looping ambient melody.
@@ -79,1179 +82,64 @@ type themeSounds struct {
Ambient ambientSounds `json:"ambient,omitempty"`
}
-// ── basic note + chord helpers ─────────────────────────────────────
-
-// ns builds a note that rings for 'dur' but advances the sequencer by 'step',
-// so multiple voices appended back-to-back can overlap when dur > step.
-func ns(freq, dur, step float64) melodyNote {
- return melodyNote{Freq: freq, Dur: dur, Step: step}
-}
-
+// soundCache holds unmarshalled themeSounds indexed by theme name. It is
+// populated lazily on first access so repeated calls to loadThemeSounds are
+// essentially free.
var (
- intMajor3rd = math.Pow(2, 4.0/12)
- intMinor3rd = math.Pow(2, 3.0/12)
- intPerf5th = math.Pow(2, 7.0/12)
- intMinor7th = math.Pow(2, 10.0/12)
+ soundCache map[string]themeSounds
+ soundCacheMu sync.RWMutex
)
-func major(freq float64) [3]float64 {
- return [3]float64{freq, freq * intMajor3rd, freq * intPerf5th}
-}
-func minor(freq float64) [3]float64 {
- return [3]float64{freq, freq * intMinor3rd, freq * intPerf5th}
-}
-
-// ── voice builders ────────────────────────────────────────────────
-// Each builder returns a slice of notes appended back-to-back into a melody.
-// Because the engine advances time by note.Step (not note.Dur), notes with
-// dur > step ring through the next entries — that is how distinct "voices"
-// (bass, pad, lead) are stacked into one flat array.
-
-// hook turns explicit (freq, beats) pairs into a melodic phrase. A pair with
-// freq <= 0 OR beats <= 0 is treated as a rest, and its duration is folded
-// into the preceding note's step so the next real note triggers later. We
-// can't emit a zero-frequency rest entry because the JS engine substitutes
-// 440 Hz for falsy freq values, which would turn rests into audible tones.
-//
-// beat = seconds-per-quarter-note. dur multiplier of 1.0 = quarter note.
-func hook(beat float64, pairs ...float64) []melodyNote {
- out := make([]melodyNote, 0, len(pairs)/2)
- leadIn := 0.0
- for i := 0; i+1 < len(pairs); i += 2 {
- f, b := pairs[i], pairs[i+1]
- if f <= 0 || b <= 0 {
- silence := math.Abs(b) * beat
- if len(out) == 0 {
- leadIn += silence
- } else {
- out[len(out)-1].Step += silence
- }
+// initSoundCache eagerly loads every sounds.json from the embedded theme FS.
+// It is called lazily under soundCacheMu.
+func initSoundCache() {
+ soundCache = make(map[string]themeSounds)
+ for name := range getThemeSet() {
+ b, err := templates.ThemeSounds(name)
+ if err != nil {
continue
}
- step := b * beat
- // 0.92 leaves a small gap so repeated notes re-trigger cleanly.
- out = append(out, ns(f, step*0.92, step))
- }
- // A leading rest in a looped phrase is equivalent to a trailing delay on
- // the last note (the loop wraps), so push it onto the final note's step.
- if leadIn > 0 && len(out) > 0 {
- out[len(out)-1].Step += leadIn
- }
- return out
-}
-
-// padHold lays a chord triad as a long sustained pad. The three notes are
-// emitted back-to-back but each rings for almost the full duration, so they
-// pile into a held chord.
-func padHold(chord [3]float64, totalBeats, beat float64) []melodyNote {
- dur := totalBeats * beat
- return []melodyNote{
- ns(chord[0], dur*0.96, dur*0.34),
- ns(chord[1], dur*0.62, dur*0.33),
- ns(chord[2], dur*0.30, dur*0.33),
- }
-}
-
-// octaveBass: pumping synth-pop bassline — root, octave, root, fifth — over 4
-// quarter-notes. Iconic Outrun / "Take On Me" feel.
-func octaveBass(root, beat float64) []melodyNote {
- fifth := root * intPerf5th
- return []melodyNote{
- ns(root, beat*0.85, beat),
- ns(root*2, beat*0.85, beat),
- ns(root, beat*0.85, beat),
- ns(fifth, beat*0.85, beat),
- }
-}
-
-// palmMute: 8 chugging eighth-notes alternating root and fifth — heavy-metal
-// palm-mute feel (think Doom Eternal / Megadeth).
-func palmMute(root, beat float64) []melodyNote {
- out := make([]melodyNote, 0, 8)
- half := beat * 0.5
- fifth := root * intPerf5th
- for i := 0; i < 8; i++ {
- f := root
- if i == 4 || i == 6 {
- f = fifth
+ var s themeSounds
+ if err := json.Unmarshal(b, &s); err != nil {
+ continue
}
- out = append(out, ns(f, half*0.45, half))
- }
- return out
-}
-
-// arpUpDown: chord up-and-down across 8 sixteenths (1-3-5-8-5-3-1-3) — Mario
-// chiptune feel.
-func arpUpDown(chord [3]float64, beat float64) []melodyNote {
- s := beat * 0.5
- return []melodyNote{
- ns(chord[0], s*0.85, s), ns(chord[1], s*0.85, s),
- ns(chord[2], s*0.85, s), ns(chord[0]*2, s*0.85, s),
- ns(chord[2], s*0.85, s), ns(chord[1], s*0.85, s),
- ns(chord[0], s*0.85, s), ns(chord[1], s*0.85, s),
- }
-}
-
-// walkBass: jazz quarter-note walking pattern root → 3rd → 5th → 3rd.
-func walkBass(root, beat float64) []melodyNote {
- return []melodyNote{
- ns(root, beat*0.92, beat),
- ns(root*intMajor3rd, beat*0.92, beat),
- ns(root*intPerf5th, beat*0.92, beat),
- ns(root*intMajor3rd, beat*0.92, beat),
- }
-}
-
-// chromDesc: 8-note chromatic descent from 'top' — Bond / Pink Panther feel.
-func chromDesc(top, beat float64) []melodyNote {
- out := make([]melodyNote, 0, 8)
- step := beat * 0.5
- for i := 0; i < 8; i++ {
- f := top * math.Pow(2, -float64(i)/12.0)
- out = append(out, ns(f, step*0.6, step))
- }
- return out
-}
-
-// fanfareStab: a punchy orchestral chord-hit held across 'beats' beats.
-// Three voices land together because each rings for most of the duration.
-func fanfareStab(chord [3]float64, beats, beat float64) []melodyNote {
- dur := beats * beat
- return []melodyNote{
- ns(chord[0], dur*0.9, dur*0.34),
- ns(chord[1], dur*0.7, dur*0.33),
- ns(chord[2], dur*0.5, dur*0.33),
- }
-}
-
-// reverseKick: hardstyle reverse-bass effect — a sub-octave thump followed by
-// a short octave-up snap (the "wub" before the kick).
-func reverseKick(root, beat float64) []melodyNote {
- return []melodyNote{
- ns(root/2, beat*0.85, beat*0.5),
- ns(root, beat*0.45, beat*0.5),
- }
-}
-
-// bossaBass: bossa nova bass — dotted-quarter root, eighth fifth, repeat.
-func bossaBass(root, beat float64) []melodyNote {
- fifth := root * intPerf5th
- return []melodyNote{
- ns(root, beat*1.4, beat*1.5),
- ns(fifth, beat*0.45, beat*0.5),
- ns(root, beat*1.4, beat*1.5),
- ns(fifth, beat*0.45, beat*0.5),
- }
-}
-
-// dubSwell: very long sustained bass — held across the whole bar. Caller
-// passes the actual played frequency (no implicit octave-down) so we don't
-// drop below ~30 Hz, where most speakers reproduce nothing but clicks.
-func dubSwell(freq, beats, beat float64) []melodyNote {
- return []melodyNote{ns(freq, beats*beat*0.95, beats*beat)}
-}
-
-// alienSlide: 4 sliding atonal arpeggio notes spaced by minor-3rds and tritones.
-func alienSlide(root, beat float64) []melodyNote {
- tritone := math.Pow(2, 6.0/12)
- s := beat * 0.5
- return []melodyNote{
- ns(root, s*0.85, s),
- ns(root*intMinor3rd, s*0.85, s),
- ns(root*tritone, s*0.85, s),
- ns(root*intMinor7th, s*0.85, s),
- }
-}
-
-// concat flattens several voices into one note slice.
-func concat(parts ...[]melodyNote) []melodyNote {
- var out []melodyNote
- for _, p := range parts {
- out = append(out, p...)
- }
- return out
-}
-
-// ── drum patterns ─────────────────────────────────────────────────
-// Each is a 16-step bar (one entry per 16th-note at the preset BPM).
-
-func pat(names ...string) []string { return names }
-
-var (
- // Synth-pop punch — kick on 1+4+8, claps on 16.
- drumPop = pat("kick", "_", "hat", "kick", "snare", "_", "hat", "_", "kick", "kick", "hat", "_", "snare", "_", "hat", "clap")
- // Four-on-the-floor dance — kick every quarter, hat offbeat.
- drumFour = pat("kick", "_", "hat", "_", "kick", "_", "hat", "_", "kick", "_", "hat", "_", "kick", "_", "hat", "_")
- // Heavy rock — straight 4/4 with offbeat hats (Duke Nukem feel).
- drumRock = pat("kick", "_", "hat", "_", "snare", "_", "hat", "_", "kick", "_", "hat", "_", "snare", "_", "hat", "kick")
- // Industrial pulse — hammering double-kick, syncopated snare.
- drumPulse = pat("kick", "kick", "_", "hat", "snare", "_", "kick", "hat", "kick", "_", "_", "hat", "snare", "kick", "_", "hat")
- // Hardstyle — kick on every beat plus the offbeats (gabber).
- drumHardstyle = pat("kick", "_", "_", "kick", "kick", "_", "_", "kick", "kick", "_", "_", "kick", "kick", "kick", "_", "kick")
- // DnB amen-break — kick on 1+11, snare with ghosted "skips" on 4.
- drumDnb = pat("kick", "_", "hat", "kick", "snare", "hat", "_", "snare", "_", "kick", "hat", "_", "snare", "_", "hat", "kick")
- // Bossa nova clave (3-2 son) — Latin syncopation.
- drumBossa = pat("kick", "_", "hat", "_", "_", "_", "hat", "snare", "_", "kick", "hat", "_", "snare", "_", "hat", "_")
- // Boom-bap — hip-hop / film-noir groove.
- drumBoom = pat("kick", "_", "_", "hat", "snare", "_", "_", "hat", "_", "_", "kick", "hat", "snare", "_", "kick", "hat")
- // Dub — kick on 1, snare on 9, hi-hat on 16. Spacious.
- drumDub = pat("kick", "_", "_", "_", "_", "_", "_", "_", "snare", "_", "_", "_", "_", "_", "_", "hat")
- // Ambient — single soft kick + sparse clap. Mostly silence.
- drumAmbient = pat("kick", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "clap", "_", "_", "_")
- // March — kick/snare alternate, no hat (cosmos military feel).
- drumMarch = pat("kick", "_", "_", "_", "snare", "_", "_", "_", "kick", "_", "_", "_", "snare", "_", "_", "_")
- // Bell tolls — only deep kicks, very sparse (cathedral).
- drumBell = pat("kick", "_", "_", "_", "_", "_", "_", "_", "kick", "_", "_", "_", "_", "_", "_", "_")
- // Latin funk — busy clave with conga-like accents.
- drumLatin = pat("kick", "hat", "_", "hat", "snare", "kick", "hat", "_", "kick", "hat", "_", "hat", "snare", "_", "hat", "kick")
- // Chiptune — bouncy NES drum-machine: kick+snare on every other 16th.
- drumChip = pat("kick", "snare", "kick", "snare", "kick", "snare", "kick", "snare", "kick", "snare", "kick", "snare", "kick", "snare", "kick", "snare")
- // Spy — sneaky offbeat snare with double-kick pickup.
- drumSpy = pat("kick", "_", "hat", "_", "_", "snare", "hat", "_", "kick", "kick", "hat", "_", "snare", "_", "hat", "snare")
- // Organic / biomech — irregular limb-like accents.
- drumOrganic = pat("kick", "_", "hat", "kick", "_", "snare", "kick", "_", "_", "kick", "hat", "_", "snare", "_", "kick", "hat")
- // Metal chug — double-kick galloping metal rhythm (plasma normal).
- drumChug = pat("kick", "kick", "_", "kick", "snare", "_", "kick", "_", "kick", "kick", "_", "kick", "snare", "kick", "kick", "kick")
- // Gated 80s electro — tight punchy clap on 5+13 (synthwave).
- drumElectro = pat("kick", "_", "_", "_", "clap", "_", "hat", "_", "kick", "kick", "_", "_", "clap", "_", "hat", "snare")
- // Wild rock — extra-busy version of drumRock for wild mode.
- drumRockWild = pat("kick", "kick", "hat", "kick", "snare", "_", "hat", "kick", "kick", "kick", "hat", "kick", "snare", "_", "hat", "kick")
-)
-
-// ── theme songs ───────────────────────────────────────────────────
-//
-// Each theme builds two ambient presets (normal + wild). Wild is the same
-// musical character as normal but faster, denser, brighter — never a
-// different song, so the listener always hears "the theme" intensifying.
-
-// ════════════════════════════════════════════════════════════════════
-// NEON – synth-pop banger, C major, Outrun pumping octave bass
-// ════════════════════════════════════════════════════════════════════
-func soundsNeon() themeSounds {
- var s themeSounds
- s.Splash.Freqs = []float64{523.25, 659.25, 783.99, 1046.5}
- s.Splash.Spacing, s.Splash.Gain, s.Splash.Wave = 0.055, 0.09, "sine"
- s.Nav.Freq, s.Nav.Wave, s.Nav.Dur, s.Nav.Gain = 330, "square", 0.055, 0.11
- s.Open.Wave, s.Open.Start, s.Open.End, s.Open.Dur, s.Open.Gain = "triangle", 523.25, 1046.5, 0.13, 0.1
- s.Close.Wave, s.Close.Start, s.Close.End, s.Close.Dur, s.Close.Gain = "sine", 880, 261.63, 0.16, 0.09
- s.Bounce.Wave, s.Bounce.Start, s.Bounce.End, s.Bounce.Dur, s.Bounce.Gain = "square", 180, 90, 0.12, 0.1
-
- // Hook: sparkly major arpeggio that resolves down — C-E-G-C-A-G-E-C feel.
- beat := 0.4 // 150 BPM quarter
- mel := concat(
- octaveBass(130.81, beat), padHold(major(261.63), 4, beat),
- hook(beat, 1046.5, 0.5, 783.99, 0.5, 659.25, 0.5, 1046.5, 0.5,
- 880.00, 0.5, 783.99, 0.5, 659.25, 0.5, 523.25, 0.5),
- octaveBass(174.61, beat), padHold(major(349.23), 4, beat),
- hook(beat, 1396.92, 0.5, 1046.5, 0.5, 880.00, 0.5, 1396.92, 0.5,
- 1174.66, 0.5, 1046.5, 0.5, 880.00, 0.5, 698.46, 0.5),
- )
- wbeat := 0.273 // 220 BPM
- wmel := concat(
- octaveBass(261.63, wbeat), padHold(major(523.25), 4, wbeat),
- hook(wbeat, 1046.5, 0.25, 1318.5, 0.25, 1567.98, 0.25, 2093.0, 0.25,
- 1567.98, 0.25, 1318.5, 0.25, 1046.5, 0.25, 783.99, 0.25),
- )
- s.Ambient.Normal = ambientPreset{
- Gain: 0.03, BPM: 150, Wave: "square",
- DroneFreqs: []float64{130.81, 196.00, 261.63}, Attack: 0.02, Release: 0.15,
- CutoffMin: 1200, CutoffMax: 5000, Drums: drumPop, Melody: mel,
- }
- s.Ambient.Wild = ambientPreset{
- Gain: 0.06, BPM: 220, Wave: "square",
- DroneFreqs: []float64{130.81, 261.63, 392.00, 523.25}, Attack: 0.02, Release: 0.08,
- CutoffMin: 2000, CutoffMax: 7000, DetuneCents: 12, Drums: drumPop, Melody: wmel,
- }
- return s
-}
-
-// ════════════════════════════════════════════════════════════════════
-// TERMINAL – industrial techno, E minor, hammering pulse
-// ════════════════════════════════════════════════════════════════════
-func soundsTerminal() themeSounds {
- var s themeSounds
- s.Splash.Freqs = []float64{523.25, 659.25, 783.99}
- s.Splash.Spacing, s.Splash.Gain, s.Splash.Wave = 0.09, 0.11, "square"
- s.Nav.Freq, s.Nav.Wave, s.Nav.Dur, s.Nav.Gain = 800, "square", 0.045, 0.12
- s.Open.Wave, s.Open.Start, s.Open.End, s.Open.Dur, s.Open.Gain = "square", 600, 1200, 0.12, 0.1
- s.Close.Wave, s.Close.Start, s.Close.End, s.Close.Dur, s.Close.Gain = "square", 900, 400, 0.14, 0.09
- s.Bounce.Wave, s.Bounce.Start, s.Bounce.End, s.Bounce.Dur, s.Bounce.Gain = "square", 200, 100, 0.1, 0.1
-
- // Hook: dissonant rising tritone stab — Hotline Miami / industrial menace.
- beat := 0.375 // 160 BPM
- mel := concat(
- palmMute(82.41, beat), padHold(minor(164.81), 4, beat),
- hook(beat, 329.63, 0.5, 392.00, 0.5, 466.16, 0.5, 329.63, 0.5,
- 466.16, 0.5, 622.25, 0.5, 466.16, 0.5, 329.63, 0.5),
- palmMute(110.00, beat), padHold(minor(220.00), 4, beat),
- hook(beat, 440.00, 0.5, 523.25, 0.5, 622.25, 0.5, 440.00, 0.5,
- 622.25, 0.5, 783.99, 0.5, 622.25, 0.5, 440.00, 0.5),
- )
- wbeat := 0.353 // 170 BPM, but denser stabs
- wmel := concat(
- palmMute(164.81, wbeat),
- hook(wbeat, 659.25, 0.25, 783.99, 0.25, 932.33, 0.25, 659.25, 0.25,
- 932.33, 0.25, 1244.51, 0.25, 932.33, 0.25, 659.25, 0.25),
- )
- s.Ambient.Normal = ambientPreset{
- Gain: 0.03, BPM: 160, Wave: "sawtooth",
- DroneFreqs: []float64{82.41, 123.47, 164.81}, Attack: 0.02, Release: 0.1,
- CutoffMin: 1000, CutoffMax: 5000, Drums: drumPulse, Melody: mel,
- }
- s.Ambient.Wild = ambientPreset{
- Gain: 0.065, BPM: 170, Wave: "sawtooth",
- DroneFreqs: []float64{82.41, 164.81, 246.94, 329.63}, Attack: 0.02, Release: 0.05,
- CutoffMin: 2000, CutoffMax: 7000, DetuneCents: 18, Drums: drumPulse, Melody: wmel,
- }
- return s
-}
-
-// ════════════════════════════════════════════════════════════════════
-// SYNTHWAVE – Carpenter Brut "Turbo Killer" anthem rock, A minor
-// ════════════════════════════════════════════════════════════════════
-func soundsSynthwave() themeSounds {
- var s themeSounds
- s.Splash.Freqs = []float64{196, 246.94, 293.66, 349.23}
- s.Splash.Spacing, s.Splash.Gain, s.Splash.Wave = 0.1, 0.1, "sine"
- s.Nav.Freq, s.Nav.Wave, s.Nav.Dur, s.Nav.Gain = 164.81, "triangle", 0.09, 0.1
- s.Open.Wave, s.Open.Start, s.Open.End, s.Open.Dur, s.Open.Gain = "sine", 220, 440, 0.18, 0.1
- s.Close.Wave, s.Close.Start, s.Close.End, s.Close.Dur, s.Close.Gain = "sine", 440, 110, 0.17, 0.09
- s.Bounce.Wave, s.Bounce.Start, s.Bounce.End, s.Bounce.Dur, s.Bounce.Gain = "sine", 150, 75, 0.14, 0.09
-
- // Driving Am-F-C-G with a sawtooth-stab lead riff. Action-rock not chill.
- beat := 0.4 // 150 BPM — punchy synth-anthem
- mel := concat(
- octaveBass(110.00, beat), padHold(minor(220.00), 4, beat),
- hook(beat, 880.00, 0.25, 1046.5, 0.25, 1318.5, 0.5, 1046.5, 0.25, 880.00, 0.25,
- 659.25, 0.5, 880.00, 0.5, 1046.5, 1.0),
- octaveBass(87.31, beat), padHold(major(174.61), 4, beat),
- hook(beat, 698.46, 0.25, 880.00, 0.25, 1046.5, 0.5, 880.00, 0.25, 698.46, 0.25,
- 523.25, 0.5, 698.46, 0.5, 880.00, 1.0),
- octaveBass(130.81, beat), padHold(major(261.63), 4, beat),
- hook(beat, 1046.5, 0.25, 1318.5, 0.25, 1567.98, 0.5, 1318.5, 0.25, 1046.5, 0.25,
- 783.99, 0.5, 1046.5, 0.5, 1318.5, 1.0),
- octaveBass(98.00, beat), padHold(major(196.00), 4, beat),
- hook(beat, 783.99, 0.25, 987.77, 0.25, 1174.66, 0.5, 987.77, 0.25, 783.99, 0.25,
- 587.33, 0.5, 783.99, 0.5, 987.77, 1.0),
- )
- wbeat := 0.316 // 190 BPM
- wmel := concat(
- octaveBass(220.00, wbeat),
- hook(wbeat, 1760.00, 0.25, 2093.0, 0.25, 2637.0, 0.25, 2093.0, 0.25,
- 1760.00, 0.25, 1318.5, 0.25, 1760.00, 0.25, 2093.0, 0.25),
- )
- s.Ambient.Normal = ambientPreset{
- Gain: 0.032, BPM: 150, Wave: "sawtooth",
- DroneFreqs: []float64{110.00, 174.61, 220.00}, Attack: 0.02, Release: 0.08,
- CutoffMin: 1200, CutoffMax: 5500, Drums: drumElectro, Melody: mel,
- }
- s.Ambient.Wild = ambientPreset{
- Gain: 0.065, BPM: 190, Wave: "sawtooth",
- DroneFreqs: []float64{220.00, 349.23, 440.00, 523.25}, Attack: 0.02, Release: 0.05,
- CutoffMin: 2400, CutoffMax: 7500, DetuneCents: 14, Drums: drumElectro, Melody: wmel,
- }
- return s
-}
-
-// ════════════════════════════════════════════════════════════════════
-// PLASMA – Doom Eternal djent, F# minor, drop-tuned palm-mute chug
-// ════════════════════════════════════════════════════════════════════
-func soundsPlasma() themeSounds {
- var s themeSounds
- s.Splash.Freqs = []float64{369.99, 493.88, 587.33, 739.99}
- s.Splash.Spacing, s.Splash.Gain, s.Splash.Wave = 0.055, 0.09, "sine"
- s.Nav.Freq, s.Nav.Wave, s.Nav.Dur, s.Nav.Gain = 246.94, "square", 0.055, 0.11
- s.Open.Wave, s.Open.Start, s.Open.End, s.Open.Dur, s.Open.Gain = "sine", 370, 740, 0.14, 0.1
- s.Close.Wave, s.Close.Start, s.Close.End, s.Close.Dur, s.Close.Gain = "square", 740, 246.94, 0.17, 0.09
- s.Bounce.Wave, s.Bounce.Start, s.Bounce.End, s.Bounce.Dur, s.Bounce.Gain = "square", 120, 60, 0.1, 0.1
-
- // Djent: low palm-mute chugs against a screaming high lead.
- beat := 0.4 // 150 BPM — heavy not blistering
- mel := concat(
- palmMute(46.25, beat), padHold(minor(92.50), 4, beat),
- hook(beat, 369.99, 0.5, 0, 0.5, 369.99, 0.5, 440.00, 0.5,
- 554.37, 0.5, 440.00, 0.5, 369.99, 1.0),
- palmMute(46.25, beat), padHold(minor(92.50), 4, beat),
- hook(beat, 369.99, 0.5, 440.00, 0.5, 554.37, 0.5, 739.99, 0.5,
- 659.25, 0.5, 554.37, 0.5, 440.00, 0.5, 369.99, 0.5),
- )
- wbeat := 0.333 // 180 BPM thrash
- wmel := concat(
- palmMute(92.50, wbeat),
- hook(wbeat, 739.99, 0.25, 880.00, 0.25, 1108.73, 0.25, 1480.00, 0.25,
- 1108.73, 0.25, 880.00, 0.25, 739.99, 0.25, 554.37, 0.25),
- )
- s.Ambient.Normal = ambientPreset{
- Gain: 0.032, BPM: 150, Wave: "square",
- DroneFreqs: []float64{46.25, 92.50, 138.59}, Attack: 0.01, Release: 0.08,
- CutoffMin: 800, CutoffMax: 5500, Drums: drumChug, Melody: mel,
- }
- s.Ambient.Wild = ambientPreset{
- Gain: 0.07, BPM: 180, Wave: "square",
- DroneFreqs: []float64{46.25, 92.50, 138.59, 277.18}, Attack: 0.01, Release: 0.04,
- CutoffMin: 2400, CutoffMax: 8000, DetuneCents: 22, Drums: drumChug, Melody: wmel,
- }
- return s
-}
-
-// ════════════════════════════════════════════════════════════════════
-// BRUTALIST – Akira-style minimalist techno, C minor, concrete pulse
-// ════════════════════════════════════════════════════════════════════
-func soundsBrutalist() themeSounds {
- var s themeSounds
- s.Splash.Freqs = []float64{261.63, 329.63, 392.00, 523.25}
- s.Splash.Spacing, s.Splash.Gain, s.Splash.Wave = 0.09, 0.1, "square"
- s.Nav.Freq, s.Nav.Wave, s.Nav.Dur, s.Nav.Gain = 440, "square", 0.06, 0.11
- s.Open.Wave, s.Open.Start, s.Open.End, s.Open.Dur, s.Open.Gain = "square", 440, 880, 0.15, 0.1
- s.Close.Wave, s.Close.Start, s.Close.End, s.Close.Dur, s.Close.Gain = "square", 660, 220, 0.15, 0.09
- s.Bounce.Wave, s.Bounce.Start, s.Bounce.End, s.Bounce.Dur, s.Bounce.Gain = "square", 200, 100, 0.1, 0.1
-
- // Hook: pulse-step bass with metallic stab leads. Cm-Ab-Gm-Fm.
- beat := 0.429 // 140 BPM driving
- mel := concat(
- palmMute(65.41, beat), padHold(minor(130.81), 4, beat),
- hook(beat, 523.25, 0.5, 0, 0.5, 622.25, 0.5, 0, 0.5,
- 783.99, 1.0, 622.25, 1.0),
- palmMute(51.91, beat), padHold(major(103.83), 4, beat),
- hook(beat, 415.30, 0.5, 0, 0.5, 622.25, 0.5, 0, 0.5,
- 830.61, 1.0, 622.25, 1.0),
- )
- wbeat := 0.375 // 160 BPM
- wmel := concat(
- palmMute(130.81, wbeat),
- hook(wbeat, 1046.5, 0.25, 1244.5, 0.25, 1567.98, 0.25, 1046.5, 0.25,
- 1244.5, 0.25, 1046.5, 0.25, 830.61, 0.25, 622.25, 0.25),
- )
- s.Ambient.Normal = ambientPreset{
- Gain: 0.032, BPM: 140, Wave: "sawtooth",
- DroneFreqs: []float64{65.41, 98.00, 130.81}, Attack: 0.02, Release: 0.1,
- CutoffMin: 1200, CutoffMax: 5500, Drums: drumPulse, Melody: mel,
- }
- s.Ambient.Wild = ambientPreset{
- Gain: 0.075, BPM: 180, Wave: "sawtooth",
- DroneFreqs: []float64{65.41, 98.00, 130.81, 196.00}, Attack: 0.02, Release: 0.04,
- CutoffMin: 2400, CutoffMax: 7500, DetuneCents: 20, Drums: drumPulse, Melody: wmel,
- }
- return s
-}
-
-// ════════════════════════════════════════════════════════════════════
-// VOLCANO – hardstyle / gabber, D minor, reverse-bass kicks
-// ════════════════════════════════════════════════════════════════════
-func soundsVolcano() themeSounds {
- var s themeSounds
- s.Splash.Freqs = []float64{293.66, 369.99, 440.00, 587.33}
- s.Splash.Spacing, s.Splash.Gain, s.Splash.Wave = 0.09, 0.095, "triangle"
- s.Nav.Freq, s.Nav.Wave, s.Nav.Dur, s.Nav.Gain = 196, "triangle", 0.085, 0.1
- s.Open.Wave, s.Open.Start, s.Open.End, s.Open.Dur, s.Open.Gain = "triangle", 293.66, 587.33, 0.16, 0.1
- s.Close.Wave, s.Close.Start, s.Close.End, s.Close.Dur, s.Close.Gain = "sine", 440, 146.83, 0.18, 0.09
- s.Bounce.Wave, s.Bounce.Start, s.Bounce.End, s.Bounce.Dur, s.Bounce.Gain = "triangle", 130, 65, 0.12, 0.09
-
- // Reverse-bass + screech lead. Dm-Bb-F-C — classic hardstyle.
- beat := 0.4 // 150 BPM
- mel := concat(
- reverseKick(73.42, beat), reverseKick(73.42, beat),
- reverseKick(73.42, beat), reverseKick(73.42, beat),
- hook(beat, 587.33, 0.5, 698.46, 0.5, 880.00, 0.5, 1174.66, 0.5,
- 880.00, 0.5, 698.46, 0.5, 587.33, 1.0),
- reverseKick(58.27, beat), reverseKick(58.27, beat),
- reverseKick(87.31, beat), reverseKick(65.41, beat),
- hook(beat, 466.16, 0.5, 587.33, 0.5, 698.46, 0.5, 880.00, 0.5,
- 698.46, 0.5, 587.33, 0.5, 466.16, 1.0),
- )
- wbeat := 0.333 // 180 BPM
- wmel := concat(
- reverseKick(146.83, wbeat), reverseKick(146.83, wbeat),
- hook(wbeat, 1174.66, 0.25, 1396.92, 0.25, 1760.00, 0.25, 2349.32, 0.25,
- 1760.00, 0.25, 1396.92, 0.25, 1174.66, 0.25, 880.00, 0.25),
- )
- s.Ambient.Normal = ambientPreset{
- Gain: 0.032, BPM: 150, Wave: "sawtooth",
- DroneFreqs: []float64{73.42, 110.00, 146.83}, Attack: 0.01, Release: 0.08,
- CutoffMin: 1200, CutoffMax: 5500, Drums: drumHardstyle, Melody: mel,
- }
- s.Ambient.Wild = ambientPreset{
- Gain: 0.07, BPM: 180, Wave: "sawtooth",
- DroneFreqs: []float64{73.42, 110.00, 146.83, 220.00}, Attack: 0.01, Release: 0.04,
- CutoffMin: 2400, CutoffMax: 8000, DetuneCents: 18, Drums: drumHardstyle, Melody: wmel,
- }
- return s
-}
-
-// ════════════════════════════════════════════════════════════════════
-// AURORA – arctic anthem rock, G major, soaring stadium lead
-// ════════════════════════════════════════════════════════════════════
-func soundsAurora() themeSounds {
- var s themeSounds
- s.Splash.Freqs = []float64{392.00, 493.88, 587.33, 783.99}
- s.Splash.Spacing, s.Splash.Gain, s.Splash.Wave = 0.08, 0.09, "sine"
- s.Nav.Freq, s.Nav.Wave, s.Nav.Dur, s.Nav.Gain = 261.63, "triangle", 0.085, 0.1
- s.Open.Wave, s.Open.Start, s.Open.End, s.Open.Dur, s.Open.Gain = "sine", 390, 780, 0.16, 0.1
- s.Close.Wave, s.Close.Start, s.Close.End, s.Close.Dur, s.Close.Gain = "sine", 523, 196, 0.18, 0.09
- s.Bounce.Wave, s.Bounce.Start, s.Bounce.End, s.Bounce.Dur, s.Bounce.Gain = "triangle", 180, 90, 0.12, 0.09
-
- // Driving G-major anthem (G-Em-C-D) with a soaring fist-pump lead hook.
- beat := 0.462 // 130 BPM
- mel := concat(
- octaveBass(98.00, beat), padHold(major(196.00), 4, beat),
- hook(beat, 783.99, 0.5, 880.00, 0.5, 987.77, 0.5, 1174.66, 0.5,
- 987.77, 0.5, 880.00, 1.0, 783.99, 0.5),
- octaveBass(82.41, beat), padHold(minor(164.81), 4, beat),
- hook(beat, 659.25, 0.5, 783.99, 0.5, 880.00, 0.5, 987.77, 0.5,
- 880.00, 0.5, 783.99, 1.0, 659.25, 0.5),
- octaveBass(65.41, beat), padHold(major(130.81), 4, beat),
- hook(beat, 783.99, 0.5, 880.00, 0.5, 987.77, 0.5, 1174.66, 0.5,
- 1318.5, 1.0, 1174.66, 1.0),
- octaveBass(73.42, beat), padHold(major(146.83), 4, beat),
- hook(beat, 880.00, 0.5, 987.77, 0.5, 1174.66, 0.5, 1318.5, 0.5,
- 1174.66, 0.5, 987.77, 1.0, 880.00, 0.5),
- )
- wbeat := 0.353 // 170 BPM thrash anthem
- wmel := concat(
- octaveBass(196.00, wbeat),
- hook(wbeat, 1567.98, 0.25, 1760.00, 0.25, 1975.53, 0.25, 2349.32, 0.25,
- 1975.53, 0.25, 1760.00, 0.25, 1567.98, 0.25, 1318.5, 0.25),
- )
- s.Ambient.Normal = ambientPreset{
- Gain: 0.032, BPM: 130, Wave: "triangle",
- DroneFreqs: []float64{98.00, 146.83, 196.00}, Attack: 0.02, Release: 0.1,
- CutoffMin: 1200, CutoffMax: 5500, Drums: drumPop, Melody: mel,
- }
- s.Ambient.Wild = ambientPreset{
- Gain: 0.065, BPM: 170, Wave: "sawtooth",
- DroneFreqs: []float64{98.00, 196.00, 293.66, 392.00}, Attack: 0.02, Release: 0.05,
- CutoffMin: 2200, CutoffMax: 7500, DetuneCents: 12, Drums: drumPop, Melody: wmel,
- }
- return s
-}
-
-// ════════════════════════════════════════════════════════════════════
-// MATRIX – liquid drum-and-bass, C minor, sub-bass + amen-break stabs
-// ════════════════════════════════════════════════════════════════════
-func soundsMatrix() themeSounds {
- var s themeSounds
- s.Splash.Freqs = []float64{261.63, 311.13, 392.00, 466.16}
- s.Splash.Spacing, s.Splash.Gain, s.Splash.Wave = 0.08, 0.1, "square"
- s.Nav.Freq, s.Nav.Wave, s.Nav.Dur, s.Nav.Gain = 440, "square", 0.055, 0.11
- s.Open.Wave, s.Open.Start, s.Open.End, s.Open.Dur, s.Open.Gain = "square", 440, 880, 0.13, 0.1
- s.Close.Wave, s.Close.Start, s.Close.End, s.Close.Dur, s.Close.Gain = "square", 660, 220, 0.15, 0.09
- s.Bounce.Wave, s.Bounce.Start, s.Bounce.End, s.Bounce.Dur, s.Bounce.Gain = "square", 180, 90, 0.1, 0.1
-
- // Reese-bass + glitchy stabs. Cm-Ab-Bb-Cm.
- beat := 0.353 // 170 BPM DnB
- mel := concat(
- dubSwell(41.20, 4, beat), padHold(minor(130.81), 4, beat),
- hook(beat, 783.99, 0.25, 0, 0.25, 783.99, 0.5, 932.33, 0.5,
- 0, 0.5, 1046.5, 0.5, 932.33, 1.0),
- dubSwell(34.65, 4, beat), padHold(major(103.83), 4, beat),
- hook(beat, 622.25, 0.25, 0, 0.25, 622.25, 0.5, 783.99, 0.5,
- 0, 0.5, 932.33, 0.5, 783.99, 1.0),
- )
- wbeat := 0.333 // 180 BPM neurofunk
- wmel := concat(
- palmMute(65.41, wbeat),
- hook(wbeat, 1046.5, 0.25, 1244.5, 0.25, 1567.98, 0.25, 1244.5, 0.25,
- 1864.66, 0.25, 1567.98, 0.25, 1244.5, 0.25, 1046.5, 0.25),
- )
- s.Ambient.Normal = ambientPreset{
- Gain: 0.03, BPM: 170, Wave: "sawtooth",
- DroneFreqs: []float64{32.70, 65.41, 130.81}, Attack: 0.02, Release: 0.1,
- CutoffMin: 1000, CutoffMax: 5500, DetuneCents: 6, Drums: drumDnb, Melody: mel,
- }
- s.Ambient.Wild = ambientPreset{
- Gain: 0.07, BPM: 180, Wave: "sawtooth",
- DroneFreqs: []float64{65.41, 130.81, 196.00, 261.63}, Attack: 0.02, Release: 0.04,
- CutoffMin: 2200, CutoffMax: 8000, DetuneCents: 18, Drums: drumDnb, Melody: wmel,
- }
- return s
-}
-
-// ════════════════════════════════════════════════════════════════════
-// OCEAN – surf rock, E minor, Dick Dale tremolo guitar
-// ════════════════════════════════════════════════════════════════════
-func soundsOcean() themeSounds {
- var s themeSounds
- s.Splash.Freqs = []float64{329.63, 392.00, 493.88, 587.33}
- s.Splash.Spacing, s.Splash.Gain, s.Splash.Wave = 0.09, 0.095, "triangle"
- s.Nav.Freq, s.Nav.Wave, s.Nav.Dur, s.Nav.Gain = 220, "sine", 0.08, 0.1
- s.Open.Wave, s.Open.Start, s.Open.End, s.Open.Dur, s.Open.Gain = "triangle", 329.63, 659.25, 0.18, 0.1
- s.Close.Wave, s.Close.Start, s.Close.End, s.Close.Dur, s.Close.Gain = "sine", 493.88, 164.81, 0.18, 0.09
- s.Bounce.Wave, s.Bounce.Start, s.Bounce.End, s.Bounce.Dur, s.Bounce.Gain = "triangle", 140, 70, 0.12, 0.09
-
- // "Misirlou"-style tremolo-picked surf riff over driving rock drums.
- // Em-D-C-B7 with a chromatic descending phrygian lead.
- beat := 0.429 // 140 BPM
- mel := concat(
- palmMute(82.41, beat), padHold(minor(164.81), 4, beat),
- hook(beat, 659.25, 0.25, 698.46, 0.25, 783.99, 0.25, 698.46, 0.25,
- 659.25, 0.25, 622.25, 0.25, 587.33, 0.25, 523.25, 0.25,
- 493.88, 0.5, 587.33, 0.5, 659.25, 1.0),
- palmMute(73.42, beat), padHold(major(146.83), 4, beat),
- hook(beat, 587.33, 0.25, 622.25, 0.25, 698.46, 0.25, 622.25, 0.25,
- 587.33, 0.25, 523.25, 0.25, 493.88, 0.25, 440.00, 0.25,
- 493.88, 0.5, 587.33, 0.5, 659.25, 1.0),
- )
- wbeat := 0.353 // 170 BPM
- wmel := concat(
- palmMute(164.81, wbeat),
- hook(wbeat, 1318.5, 0.125, 1396.92, 0.125, 1567.98, 0.125, 1396.92, 0.125,
- 1318.5, 0.125, 1244.5, 0.125, 1174.66, 0.125, 1046.5, 0.125,
- 987.77, 0.25, 1174.66, 0.25, 1318.5, 0.5),
- )
- s.Ambient.Normal = ambientPreset{
- Gain: 0.032, BPM: 140, Wave: "triangle",
- DroneFreqs: []float64{82.41, 130.81, 164.81}, Attack: 0.02, Release: 0.08,
- CutoffMin: 1500, CutoffMax: 6000, Drums: drumRock, Melody: mel,
- }
- s.Ambient.Wild = ambientPreset{
- Gain: 0.065, BPM: 170, Wave: "sawtooth",
- DroneFreqs: []float64{82.41, 164.81, 246.94, 329.63}, Attack: 0.02, Release: 0.04,
- CutoffMin: 2400, CutoffMax: 7500, DetuneCents: 14, Drums: drumRockWild, Melody: wmel,
- }
- return s
-}
-
-// ════════════════════════════════════════════════════════════════════
-// DOS – Duke Nukem 3D "Grabbag" lick, E minor, palm-muted metal
-// ════════════════════════════════════════════════════════════════════
-func soundsDos() themeSounds {
- var s themeSounds
- s.Splash.Freqs = []float64{261.63, 329.63, 392.00, 523.25}
- s.Splash.Spacing, s.Splash.Gain, s.Splash.Wave = 0.06, 0.08, "square"
- s.Nav.Freq, s.Nav.Wave, s.Nav.Dur, s.Nav.Gain = 440, "square", 0.05, 0.11
- s.Open.Wave, s.Open.Start, s.Open.End, s.Open.Dur, s.Open.Gain = "square", 440, 880, 0.14, 0.1
- s.Close.Wave, s.Close.Start, s.Close.End, s.Close.Dur, s.Close.Gain = "square", 660, 220, 0.15, 0.09
- s.Bounce.Wave, s.Bounce.Start, s.Bounce.End, s.Bounce.Dur, s.Bounce.Gain = "square", 180, 90, 0.1, 0.1
-
- // THE Lee Jackson Grabbag riff: E5 E5 G5 A5 | E5 E5 G5 A5 Bb5 A5 G5 E5
- // then drop down B4 D5 E5 ... Iconic 1996 PC-DOS metal.
- beat := 0.462 // 130 BPM
- const (
- E2, E3, B3 = 82.41, 164.81, 246.94
- E4, G4, A4 = 329.63, 392.00, 440.00
- Bb4, B4 = 466.16, 493.88
- )
- riff := []float64{
- E4, 0.5, E4, 0.5, G4, 0.5, A4, 0.5, // bar 1a
- E4, 0.5, E4, 0.5, G4, 0.5, A4, 0.5, // bar 1b
- B4, 0.5, A4, 0.5, G4, 0.5, E4, 0.5, // bar 2 — the climbs-then-drops hook
- Bb4, 0.5, A4, 0.5, G4, 0.5, E4, 0.5,
+ soundCache[name] = s
}
- mel := concat(
- palmMute(E2, beat), padHold([3]float64{E3, B3, E4}, 4, beat),
- hook(beat, riff...),
- )
- wbeat := 0.375 // 160 BPM thrash
- wmel := concat(
- palmMute(E3, wbeat),
- hook(wbeat, E4*2, 0.25, E4*2, 0.25, G4*2, 0.25, A4*2, 0.25,
- E4*2, 0.25, E4*2, 0.25, G4*2, 0.25, A4*2, 0.25,
- B4*2, 0.25, A4*2, 0.25, G4*2, 0.25, E4*2, 0.25,
- Bb4*2, 0.25, A4*2, 0.25, G4*2, 0.25, E4*2, 0.25),
- )
- s.Ambient.Normal = ambientPreset{
- Gain: 0.032, BPM: 130, Wave: "square",
- DroneFreqs: []float64{82.41, 164.81, 246.94}, Attack: 0.01, Release: 0.08,
- CutoffMin: 1200, CutoffMax: 5500, Drums: drumRock, Melody: mel,
- }
- s.Ambient.Wild = ambientPreset{
- Gain: 0.07, BPM: 160, Wave: "square",
- DroneFreqs: []float64{82.41, 164.81, 246.94, 329.63}, Attack: 0.01, Release: 0.04,
- CutoffMin: 2400, CutoffMax: 8000, DetuneCents: 12, Drums: drumRockWild, Melody: wmel,
- }
- return s
-}
-
-// ════════════════════════════════════════════════════════════════════
-// RETRO – 8-bit chiptune Mario bounce, A minor, NES arpeggios
-// ════════════════════════════════════════════════════════════════════
-func soundsRetro() themeSounds {
- var s themeSounds
- s.Splash.Freqs = []float64{220.00, 261.63, 329.63, 440.00}
- s.Splash.Spacing, s.Splash.Gain, s.Splash.Wave = 0.08, 0.09, "sine"
- s.Nav.Freq, s.Nav.Wave, s.Nav.Dur, s.Nav.Gain = 164.81, "triangle", 0.085, 0.1
- s.Open.Wave, s.Open.Start, s.Open.End, s.Open.Dur, s.Open.Gain = "triangle", 220, 440, 0.16, 0.1
- s.Close.Wave, s.Close.Start, s.Close.End, s.Close.Dur, s.Close.Gain = "sine", 330, 110, 0.16, 0.09
- s.Bounce.Wave, s.Bounce.Start, s.Bounce.End, s.Bounce.Dur, s.Bounce.Gain = "triangle", 150, 75, 0.12, 0.09
-
- // Bouncy Am-F-G-Em arp lead — Mega Man action-platformer pace.
- beat := 0.4 // 150 BPM
- mel := concat(
- octaveBass(110.00, beat), arpUpDown(minor(220.00), beat),
- hook(beat, 880.00, 0.25, 1046.5, 0.25, 1318.5, 0.25, 1760.00, 0.25,
- 1318.5, 0.25, 1046.5, 0.25, 880.00, 0.25, 659.25, 0.25),
- octaveBass(87.31, beat), arpUpDown(major(174.61), beat),
- hook(beat, 698.46, 0.25, 880.00, 0.25, 1046.5, 0.25, 1396.92, 0.25,
- 1046.5, 0.25, 880.00, 0.25, 698.46, 0.25, 523.25, 0.25),
- octaveBass(98.00, beat), arpUpDown(major(196.00), beat),
- hook(beat, 783.99, 0.25, 987.77, 0.25, 1174.66, 0.25, 1567.98, 0.25,
- 1174.66, 0.25, 987.77, 0.25, 783.99, 0.25, 587.33, 0.25),
- octaveBass(82.41, beat), arpUpDown(minor(164.81), beat),
- hook(beat, 659.25, 0.25, 783.99, 0.25, 987.77, 0.25, 1318.5, 0.25,
- 987.77, 0.25, 783.99, 0.25, 659.25, 0.25, 493.88, 0.25),
- )
- wbeat := 0.316 // 190 BPM
- wmel := concat(
- octaveBass(220.00, wbeat),
- hook(wbeat, 1760.00, 0.125, 2093.0, 0.125, 2637.0, 0.125, 3520.0, 0.125,
- 2637.0, 0.125, 2093.0, 0.125, 1760.00, 0.125, 1318.5, 0.125,
- 880.00, 0.125, 1046.5, 0.125, 1318.5, 0.125, 1760.00, 0.125,
- 1318.5, 0.125, 1046.5, 0.125, 880.00, 0.125, 659.25, 0.125),
- )
- s.Ambient.Normal = ambientPreset{
- Gain: 0.032, BPM: 150, Wave: "square",
- DroneFreqs: []float64{55.00, 110.00, 220.00}, Attack: 0.01, Release: 0.05,
- CutoffMin: 1500, CutoffMax: 6500, Drums: drumChip, Melody: mel,
- }
- s.Ambient.Wild = ambientPreset{
- Gain: 0.07, BPM: 190, Wave: "square",
- DroneFreqs: []float64{110.00, 220.00, 329.63, 440.00}, Attack: 0.005, Release: 0.03,
- CutoffMin: 2500, CutoffMax: 8000, DetuneCents: 8, Drums: drumChip, Melody: wmel,
- }
- return s
-}
-
-// ════════════════════════════════════════════════════════════════════
-// COSMOS – Imperial March stomp, D minor, action fanfare
-// ════════════════════════════════════════════════════════════════════
-func soundsCosmos() themeSounds {
- var s themeSounds
- s.Splash.Freqs = []float64{293.66, 369.99, 440.00, 523.25}
- s.Splash.Spacing, s.Splash.Gain, s.Splash.Wave = 0.08, 0.09, "sine"
- s.Nav.Freq, s.Nav.Wave, s.Nav.Dur, s.Nav.Gain = 220, "triangle", 0.08, 0.1
- s.Open.Wave, s.Open.Start, s.Open.End, s.Open.Dur, s.Open.Gain = "triangle", 293.66, 587.33, 0.16, 0.1
- s.Close.Wave, s.Close.Start, s.Close.End, s.Close.Dur, s.Close.Gain = "sine", 440, 146.83, 0.18, 0.09
- s.Bounce.Wave, s.Bounce.Start, s.Bounce.End, s.Bounce.Dur, s.Bounce.Gain = "triangle", 150, 75, 0.12, 0.09
-
- // Imperial-March-style stomping brass fanfare at action tempo.
- beat := 0.4 // 150 BPM driving
- mel := concat(
- palmMute(73.42, beat), padHold(minor(146.83), 4, beat),
- hook(beat, 587.33, 0.75, 587.33, 0.25, 587.33, 0.5, 880.00, 0.5,
- 698.46, 0.25, 659.25, 0.25, 622.25, 0.25, 587.33, 0.25, 880.00, 1.0),
- palmMute(58.27, beat), padHold(major(116.54), 4, beat),
- hook(beat, 466.16, 0.75, 466.16, 0.25, 466.16, 0.5, 698.46, 0.5,
- 554.37, 0.25, 523.25, 0.25, 493.88, 0.25, 466.16, 0.25, 698.46, 1.0),
- palmMute(65.41, beat), padHold(minor(130.81), 4, beat),
- hook(beat, 523.25, 0.75, 523.25, 0.25, 523.25, 0.5, 783.99, 0.5,
- 622.25, 0.25, 587.33, 0.25, 554.37, 0.25, 523.25, 0.25, 783.99, 1.0),
- )
- wbeat := 0.333 // 180 BPM
- wmel := concat(
- palmMute(146.83, wbeat),
- hook(wbeat, 1174.66, 0.25, 1174.66, 0.25, 1396.92, 0.5, 1760.00, 0.5,
- 2349.32, 0.5, 2093.0, 0.25, 1760.00, 0.25, 1396.92, 0.5, 1174.66, 0.5),
- )
- s.Ambient.Normal = ambientPreset{
- Gain: 0.032, BPM: 150, Wave: "sawtooth",
- DroneFreqs: []float64{73.42, 110.00, 146.83}, Attack: 0.02, Release: 0.08,
- CutoffMin: 1200, CutoffMax: 5500, Drums: drumMarch, Melody: mel,
- }
- s.Ambient.Wild = ambientPreset{
- Gain: 0.07, BPM: 180, Wave: "sawtooth",
- DroneFreqs: []float64{73.42, 146.83, 220.00, 293.66}, Attack: 0.02, Release: 0.05,
- CutoffMin: 2400, CutoffMax: 7500, DetuneCents: 16, Drums: drumChug, Melody: wmel,
- }
- return s
}
-// ════════════════════════════════════════════════════════════════════
-// RETROFUTURE – Tron / Daft Punk filter-square, E major
-// ════════════════════════════════════════════════════════════════════
-func soundsRetrofuture() themeSounds {
- var s themeSounds
- s.Splash.Freqs = []float64{329.63, 415.30, 493.88, 659.25}
- s.Splash.Spacing, s.Splash.Gain, s.Splash.Wave = 0.09, 0.095, "triangle"
- s.Nav.Freq, s.Nav.Wave, s.Nav.Dur, s.Nav.Gain = 246.94, "sine", 0.085, 0.1
- s.Open.Wave, s.Open.Start, s.Open.End, s.Open.Dur, s.Open.Gain = "triangle", 329.63, 659.25, 0.18, 0.1
- s.Close.Wave, s.Close.Start, s.Close.End, s.Close.Dur, s.Close.Gain = "sine", 493.88, 164.81, 0.2, 0.09
- s.Bounce.Wave, s.Bounce.Start, s.Bounce.End, s.Bounce.Dur, s.Bounce.Gain = "triangle", 160, 80, 0.14, 0.09
-
- // Filtered square bass + locked-grid analog lead. E-A-B-E.
- beat := 0.4 // 150 BPM driving Daft Punk action-disco
- mel := concat(
- octaveBass(82.41, beat), padHold(major(164.81), 4, beat),
- hook(beat, 659.25, 0.5, 659.25, 0.5, 783.99, 0.5, 987.77, 0.5,
- 987.77, 0.5, 783.99, 0.5, 659.25, 0.5, 493.88, 0.5),
- octaveBass(110.00, beat), padHold(major(220.00), 4, beat),
- hook(beat, 880.00, 0.5, 880.00, 0.5, 1046.5, 0.5, 1318.5, 0.5,
- 1046.5, 0.5, 880.00, 0.5, 659.25, 0.5, 493.88, 0.5),
- )
- wbeat := 0.316 // 190 BPM
- wmel := concat(
- octaveBass(164.81, wbeat),
- hook(wbeat, 1318.5, 0.25, 1567.98, 0.25, 1864.66, 0.25, 1318.5, 0.25,
- 1567.98, 0.25, 1864.66, 0.25, 1318.5, 0.25, 1046.5, 0.25),
- )
- s.Ambient.Normal = ambientPreset{
- Gain: 0.032, BPM: 150, Wave: "square",
- DroneFreqs: []float64{82.41, 164.81, 246.94}, Attack: 0.02, Release: 0.08,
- CutoffMin: 1200, CutoffMax: 5500, Drums: drumFour, Melody: mel,
- }
- s.Ambient.Wild = ambientPreset{
- Gain: 0.07, BPM: 190, Wave: "sawtooth",
- DroneFreqs: []float64{82.41, 164.81, 329.63, 493.88}, Attack: 0.01, Release: 0.04,
- CutoffMin: 2400, CutoffMax: 7500, DetuneCents: 14, Drums: drumFour, Melody: wmel,
+// loadThemeSounds returns the unmarshaled sound preset for a theme.
+// On cache miss it falls back to the empty zero value.
+func loadThemeSounds(themeName string) (themeSounds, error) {
+ soundCacheMu.RLock()
+ cached, ok := soundCache[themeName]
+ soundCacheMu.RUnlock()
+ if ok {
+ return cached, nil
}
- return s
-}
-
-// ════════════════════════════════════════════════════════════════════
-// SPACEAGE – Star Trek action theme, G major, hero-fanfare drive
-// ════════════════════════════════════════════════════════════════════
-func soundsSpaceage() themeSounds {
- var s themeSounds
- s.Splash.Freqs = []float64{392.00, 493.88, 587.33, 783.99}
- s.Splash.Spacing, s.Splash.Gain, s.Splash.Wave = 0.1, 0.1, "sine"
- s.Nav.Freq, s.Nav.Wave, s.Nav.Dur, s.Nav.Gain = 261.63, "triangle", 0.085, 0.1
- s.Open.Wave, s.Open.Start, s.Open.End, s.Open.Dur, s.Open.Gain = "triangle", 392, 784, 0.17, 0.1
- s.Close.Wave, s.Close.Start, s.Close.End, s.Close.Dur, s.Close.Gain = "sine", 587, 196, 0.19, 0.09
- s.Bounce.Wave, s.Bounce.Start, s.Bounce.End, s.Bounce.Dur, s.Bounce.Gain = "triangle", 130, 65, 0.12, 0.09
- // Heroic ascending fanfare at action tempo — "to boldly go" energy.
- beat := 0.4 // 150 BPM
- mel := concat(
- octaveBass(98.00, beat), padHold(major(196.00), 4, beat),
- hook(beat, 783.99, 0.5, 987.77, 0.5, 1174.66, 0.5, 1567.98, 0.5,
- 1318.5, 0.5, 1174.66, 0.5, 987.77, 0.5, 783.99, 0.5),
- octaveBass(82.41, beat), padHold(minor(164.81), 4, beat),
- hook(beat, 659.25, 0.5, 783.99, 0.5, 987.77, 0.5, 1318.5, 0.5,
- 1174.66, 0.5, 987.77, 0.5, 783.99, 0.5, 659.25, 0.5),
- octaveBass(110.00, beat), padHold(minor(220.00), 4, beat),
- hook(beat, 880.00, 0.5, 1046.5, 0.5, 1318.5, 0.5, 1760.00, 0.5,
- 1396.92, 0.5, 1318.5, 0.5, 1046.5, 0.5, 880.00, 0.5),
- octaveBass(73.42, beat), padHold(major(146.83), 4, beat),
- hook(beat, 587.33, 0.5, 880.00, 0.5, 1108.73, 0.5, 1318.5, 0.5,
- 1567.98, 0.5, 1318.5, 0.5, 1108.73, 0.5, 880.00, 0.5),
- )
- wbeat := 0.333 // 180 BPM
- wmel := concat(
- octaveBass(196.00, wbeat),
- hook(wbeat, 1567.98, 0.25, 1975.53, 0.25, 2349.32, 0.25, 3135.96, 0.25,
- 2637.0, 0.25, 2349.32, 0.25, 1975.53, 0.25, 1567.98, 0.25),
- )
- s.Ambient.Normal = ambientPreset{
- Gain: 0.032, BPM: 150, Wave: "triangle",
- DroneFreqs: []float64{98.00, 130.81, 196.00}, Attack: 0.02, Release: 0.08,
- CutoffMin: 1200, CutoffMax: 5500, Drums: drumPop, Melody: mel,
- }
- s.Ambient.Wild = ambientPreset{
- Gain: 0.065, BPM: 180, Wave: "sawtooth",
- DroneFreqs: []float64{98.00, 196.00, 293.66, 392.00}, Attack: 0.02, Release: 0.05,
- CutoffMin: 2200, CutoffMax: 7500, DetuneCents: 12, Drums: drumPop, Melody: wmel,
- }
- return s
-}
-
-// ════════════════════════════════════════════════════════════════════
-// TROPICALE – Latin afro-funk, F major, conga clave + brass stabs
-// ════════════════════════════════════════════════════════════════════
-func soundsTropical() themeSounds {
- var s themeSounds
- s.Splash.Freqs = []float64{349.23, 440.00, 523.25, 698.46}
- s.Splash.Spacing, s.Splash.Gain, s.Splash.Wave = 0.09, 0.095, "triangle"
- s.Nav.Freq, s.Nav.Wave, s.Nav.Dur, s.Nav.Gain = 233.08, "sine", 0.085, 0.1
- s.Open.Wave, s.Open.Start, s.Open.End, s.Open.Dur, s.Open.Gain = "triangle", 349.23, 698.46, 0.18, 0.1
- s.Close.Wave, s.Close.Start, s.Close.End, s.Close.Dur, s.Close.Gain = "sine", 523.25, 174.61, 0.2, 0.09
- s.Bounce.Wave, s.Bounce.Start, s.Bounce.End, s.Bounce.Dur, s.Bounce.Gain = "triangle", 170, 85, 0.12, 0.09
-
- // Tito Puente brass-stab energy, F-Bb-C-F.
- beat := 0.5 // 120 BPM
- mel := concat(
- bossaBass(87.31, beat), padHold(major(174.61), 4, beat),
- hook(beat, 698.46, 0.5, 0, 0.25, 880.00, 0.25, 1046.5, 0.5, 880.00, 0.5,
- 698.46, 0.5, 880.00, 0.5, 1046.5, 1.0),
- bossaBass(116.54, beat), padHold(major(233.08), 4, beat),
- hook(beat, 932.33, 0.5, 0, 0.25, 1174.66, 0.25, 1396.92, 0.5, 1174.66, 0.5,
- 932.33, 0.5, 1174.66, 0.5, 1396.92, 1.0),
- bossaBass(130.81, beat), padHold(major(261.63), 4, beat),
- hook(beat, 1046.5, 0.5, 0, 0.25, 1318.5, 0.25, 1567.98, 0.5, 1318.5, 0.5,
- 1046.5, 0.5, 1318.5, 0.5, 1567.98, 1.0),
- )
- wbeat := 0.353 // 170 BPM
- wmel := concat(
- bossaBass(174.61, wbeat),
- hook(wbeat, 1396.92, 0.25, 1760.00, 0.25, 2093.0, 0.25, 1760.00, 0.25,
- 2349.32, 0.25, 2093.0, 0.25, 1760.00, 0.25, 1396.92, 0.25),
- )
- s.Ambient.Normal = ambientPreset{
- Gain: 0.03, BPM: 120, Wave: "sawtooth",
- DroneFreqs: []float64{87.31, 174.61, 261.63}, Attack: 0.02, Release: 0.15,
- CutoffMin: 1200, CutoffMax: 5500, Drums: drumLatin, Melody: mel,
- }
- s.Ambient.Wild = ambientPreset{
- Gain: 0.065, BPM: 170, Wave: "sawtooth",
- DroneFreqs: []float64{87.31, 174.61, 261.63, 349.23}, Attack: 0.02, Release: 0.06,
- CutoffMin: 2200, CutoffMax: 7500, DetuneCents: 12, Drums: drumLatin, Melody: wmel,
- }
- return s
-}
-
-// ════════════════════════════════════════════════════════════════════
-// NOIR – rockabilly chase, D minor, slap-bass + chromatic guitar
-// ════════════════════════════════════════════════════════════════════
-func soundsNoir() themeSounds {
- var s themeSounds
- s.Splash.Freqs = []float64{293.66, 349.23, 440.00, 523.25}
- s.Splash.Spacing, s.Splash.Gain, s.Splash.Wave = 0.09, 0.09, "sine"
- s.Nav.Freq, s.Nav.Wave, s.Nav.Dur, s.Nav.Gain = 196, "square", 0.055, 0.11
- s.Open.Wave, s.Open.Start, s.Open.End, s.Open.Dur, s.Open.Gain = "triangle", 293.66, 587.33, 0.16, 0.1
- s.Close.Wave, s.Close.Start, s.Close.End, s.Close.Dur, s.Close.Gain = "sine", 440, 146.83, 0.18, 0.09
- s.Bounce.Wave, s.Bounce.Start, s.Bounce.End, s.Bounce.Dur, s.Bounce.Gain = "square", 130, 65, 0.12, 0.09
-
- // Rockabilly chase — Stray Cats slap-bass walking + Pulp-Fiction-style
- // surf-rock chromatic guitar lead at action tempo. Dm-Gm-A7-Dm.
- beat := 0.4 // 150 BPM rockabilly
- mel := concat(
- walkBass(73.42, beat), padHold(minor(146.83), 4, beat),
- chromDesc(880.00, beat),
- walkBass(98.00, beat), padHold(minor(196.00), 4, beat),
- chromDesc(739.99, beat),
- walkBass(110.00, beat), padHold(major(220.00), 4, beat),
- chromDesc(659.25, beat),
- walkBass(73.42, beat), padHold(minor(146.83), 4, beat),
- chromDesc(587.33, beat),
- )
- wbeat := 0.316 // 190 BPM
- wmel := concat(
- walkBass(146.83, wbeat),
- chromDesc(1318.5, wbeat),
- )
- s.Ambient.Normal = ambientPreset{
- Gain: 0.032, BPM: 150, Wave: "triangle",
- DroneFreqs: []float64{73.42, 110.00, 146.83}, Attack: 0.02, Release: 0.08,
- CutoffMin: 1200, CutoffMax: 5500, Drums: drumBoom, Melody: mel,
- }
- s.Ambient.Wild = ambientPreset{
- Gain: 0.07, BPM: 190, Wave: "sawtooth",
- DroneFreqs: []float64{73.42, 146.83, 196.00, 293.66}, Attack: 0.02, Release: 0.05,
- CutoffMin: 2200, CutoffMax: 7500, DetuneCents: 14, Drums: drumBoom, Melody: wmel,
- }
- return s
-}
-
-// ════════════════════════════════════════════════════════════════════
-// CATHEDRAL – gothic metal organ, C minor, Type-O-Negative drive
-// ════════════════════════════════════════════════════════════════════
-func soundsCathedral() themeSounds {
- var s themeSounds
- s.Splash.Freqs = []float64{261.63, 329.63, 392.00, 523.25}
- s.Splash.Spacing, s.Splash.Gain, s.Splash.Wave = 0.1, 0.09, "sine"
- s.Nav.Freq, s.Nav.Wave, s.Nav.Dur, s.Nav.Gain = 196, "triangle", 0.09, 0.1
- s.Open.Wave, s.Open.Start, s.Open.End, s.Open.Dur, s.Open.Gain = "triangle", 261.63, 523.25, 0.2, 0.1
- s.Close.Wave, s.Close.Start, s.Close.End, s.Close.Dur, s.Close.Gain = "sine", 392, 130.81, 0.22, 0.09
- s.Bounce.Wave, s.Bounce.Start, s.Bounce.End, s.Bounce.Dur, s.Bounce.Gain = "triangle", 160, 80, 0.14, 0.09
-
- // Gothic-metal organ pedal + driven Toccata-style lead. Cm-Gm-Ab-Bb.
- beat := 0.4 // 150 BPM driving gothic
- mel := concat(
- palmMute(65.41, beat), padHold(minor(130.81), 4, beat),
- hook(beat, 523.25, 0.5, 622.25, 0.5, 783.99, 0.5, 622.25, 0.5,
- 523.25, 0.5, 466.16, 0.5, 415.30, 0.5, 391.99, 0.5),
- palmMute(98.00, beat), padHold(minor(196.00), 4, beat),
- hook(beat, 783.99, 0.5, 932.33, 0.5, 1174.66, 0.5, 932.33, 0.5,
- 783.99, 0.5, 698.46, 0.5, 622.25, 0.5, 587.33, 0.5),
- palmMute(51.91, beat), padHold(major(103.83), 4, beat),
- hook(beat, 415.30, 0.5, 523.25, 0.5, 622.25, 0.5, 523.25, 0.5,
- 415.30, 0.5, 391.99, 0.5, 369.99, 0.5, 311.13, 0.5),
- palmMute(58.27, beat), padHold(major(116.54), 4, beat),
- hook(beat, 466.16, 0.5, 587.33, 0.5, 698.46, 0.5, 587.33, 0.5,
- 466.16, 0.5, 415.30, 0.5, 391.99, 0.5, 349.23, 0.5),
- )
- wbeat := 0.333 // 180 BPM
- wmel := concat(
- palmMute(130.81, wbeat),
- hook(wbeat, 1046.5, 0.25, 1244.5, 0.25, 1567.98, 0.25, 1244.5, 0.25,
- 1046.5, 0.25, 932.33, 0.25, 783.99, 0.25, 622.25, 0.25),
- )
- s.Ambient.Normal = ambientPreset{
- Gain: 0.032, BPM: 150, Wave: "triangle",
- DroneFreqs: []float64{65.41, 98.00, 130.81}, Attack: 0.02, Release: 0.08,
- CutoffMin: 1200, CutoffMax: 5500, Drums: drumChug, Melody: mel,
- }
- s.Ambient.Wild = ambientPreset{
- Gain: 0.07, BPM: 180, Wave: "sawtooth",
- DroneFreqs: []float64{65.41, 130.81, 196.00, 261.63}, Attack: 0.02, Release: 0.05,
- CutoffMin: 2400, CutoffMax: 7500, DetuneCents: 14, Drums: drumChug, Melody: wmel,
- }
- return s
-}
-
-// ════════════════════════════════════════════════════════════════════
-// SURVEILLANCE – John Barry spy theme, E minor, chromatic sneak
-// ════════════════════════════════════════════════════════════════════
-func soundsSurveillance() themeSounds {
- var s themeSounds
- s.Splash.Freqs = []float64{440, 554.37, 659.25}
- s.Splash.Spacing, s.Splash.Gain, s.Splash.Wave = 0.06, 0.08, "square"
- s.Nav.Freq, s.Nav.Wave, s.Nav.Dur, s.Nav.Gain = 880, "square", 0.04, 0.1
- s.Open.Wave, s.Open.Start, s.Open.End, s.Open.Dur, s.Open.Gain = "square", 660, 1320, 0.12, 0.09
- s.Close.Wave, s.Close.Start, s.Close.End, s.Close.Dur, s.Close.Gain = "square", 990, 330, 0.14, 0.085
- s.Bounce.Wave, s.Bounce.Start, s.Bounce.End, s.Bounce.Dur, s.Bounce.Gain = "square", 280, 140, 0.09, 0.09
-
- // Bond "dum-da-da-dum" + chromatic descend lead at chase tempo.
- beat := 0.4 // 150 BPM action
- mel := concat(
- walkBass(82.41, beat), padHold(minor(164.81), 4, beat),
- hook(beat, 329.63, 0.5, 392.00, 0.5, 493.88, 0.5, 392.00, 0.5,
- 659.25, 1.0, 622.25, 1.0),
- walkBass(110.00, beat), padHold(major(220.00), 4, beat),
- chromDesc(987.77, beat),
- walkBass(82.41, beat), padHold(minor(164.81), 4, beat),
- hook(beat, 329.63, 0.5, 392.00, 0.5, 493.88, 0.5, 392.00, 0.5,
- 740.00, 1.0, 698.46, 1.0),
- walkBass(123.47, beat), padHold(major(246.94), 4, beat),
- chromDesc(880.00, beat),
- )
- wbeat := 0.316 // 190 BPM chase
- wmel := concat(
- walkBass(164.81, wbeat),
- chromDesc(1318.5, wbeat),
- )
- s.Ambient.Normal = ambientPreset{
- Gain: 0.032, BPM: 150, Wave: "triangle",
- DroneFreqs: []float64{82.41, 123.47, 164.81}, Attack: 0.02, Release: 0.08,
- CutoffMin: 1200, CutoffMax: 5500, Drums: drumSpy, Melody: mel,
- }
- s.Ambient.Wild = ambientPreset{
- Gain: 0.075, BPM: 190, Wave: "sawtooth",
- DroneFreqs: []float64{164.81, 246.94, 329.63, 493.88}, Attack: 0.02, Release: 0.04,
- CutoffMin: 2400, CutoffMax: 7500, DetuneCents: 18, Drums: drumSpy, Melody: wmel,
- }
- return s
-}
-
-// ════════════════════════════════════════════════════════════════════
-// BIOMECH – alien organic, C# minor, atonal sliding arpeggios
-// ════════════════════════════════════════════════════════════════════
-func soundsBiomech() themeSounds {
- var s themeSounds
- s.Splash.Freqs = []float64{164.81, 246.94, 311.13, 466.16}
- s.Splash.Spacing, s.Splash.Gain, s.Splash.Wave = 0.09, 0.095, "triangle"
- s.Nav.Freq, s.Nav.Wave, s.Nav.Dur, s.Nav.Gain = 233.08, "sine", 0.085, 0.1
- s.Open.Wave, s.Open.Start, s.Open.End, s.Open.Dur, s.Open.Gain = "triangle", 220, 523.25, 0.18, 0.095
- s.Close.Wave, s.Close.Start, s.Close.End, s.Close.Dur, s.Close.Gain = "sine", 392, 130.81, 0.2, 0.09
- s.Bounce.Wave, s.Bounce.Start, s.Bounce.End, s.Bounce.Dur, s.Bounce.Gain = "triangle", 160, 80, 0.14, 0.09
-
- // Alien arpeggios with tritone slide — Giger-style organic action.
- beat := 0.4 // 150 BPM
- mel := concat(
- alienSlide(69.30, beat), padHold(minor(138.59), 4, beat),
- alienSlide(138.59, beat), alienSlide(277.18, beat),
- alienSlide(82.41, beat), padHold(minor(164.81), 4, beat),
- alienSlide(164.81, beat), alienSlide(329.63, beat),
- alienSlide(58.27, beat), padHold(major(116.54), 4, beat),
- alienSlide(116.54, beat), alienSlide(233.08, beat),
- alienSlide(73.42, beat), padHold(minor(146.83), 4, beat),
- alienSlide(146.83, beat), alienSlide(293.66, beat),
- )
- wbeat := 0.316 // 190 BPM
- wmel := concat(
- alienSlide(138.59, wbeat), alienSlide(277.18, wbeat),
- alienSlide(554.37, wbeat), alienSlide(1108.73, wbeat),
- )
- s.Ambient.Normal = ambientPreset{
- Gain: 0.032, BPM: 150, Wave: "sawtooth",
- DroneFreqs: []float64{69.30, 110.00, 138.59}, Attack: 0.02, Release: 0.08,
- CutoffMin: 1200, CutoffMax: 5500, Drums: drumOrganic, Melody: mel,
- }
- s.Ambient.Wild = ambientPreset{
- Gain: 0.075, BPM: 190, Wave: "sawtooth",
- DroneFreqs: []float64{69.30, 138.59, 220.00, 277.18}, Attack: 0.02, Release: 0.04,
- CutoffMin: 2400, CutoffMax: 7500, DetuneCents: 22, Drums: drumOrganic, Melody: wmel,
- }
- return s
-}
-
-// ════════════════════════════════════════════════════════════════════
-// NUKEM – action-hero hard rock, E minor, Grabbag-inspired power riffs
-// ════════════════════════════════════════════════════════════════════
-func soundsNukem() themeSounds {
- var s themeSounds
- s.Splash.Freqs = []float64{164.81, 329.63, 440.00, 659.25}
- s.Splash.Spacing, s.Splash.Gain, s.Splash.Wave = 0.06, 0.1, "sawtooth"
- s.Nav.Freq, s.Nav.Wave, s.Nav.Dur, s.Nav.Gain = 440, "square", 0.05, 0.12
- s.Open.Wave, s.Open.Start, s.Open.End, s.Open.Dur, s.Open.Gain = "sawtooth", 329.63, 659.25, 0.14, 0.11
- s.Close.Wave, s.Close.Start, s.Close.End, s.Close.Dur, s.Close.Gain = "square", 659.25, 164.81, 0.16, 0.1
- s.Bounce.Wave, s.Bounce.Start, s.Bounce.End, s.Bounce.Dur, s.Bounce.Gain = "sawtooth", 220, 110, 0.1, 0.1
-
- // THE Grabbag riff (Lee Jackson) — E5 E5 G5 A5 | E5 E5 G5 A5 Bb5 A5 G5 E5
- // Heavier sawtooth rendition at 140 BPM with palm-muted bass chugging.
- beat := 0.429 // 140 BPM hard rock
- const (
- E2, E3, B3 = 82.41, 164.81, 246.94
- E4, G4, A4 = 329.63, 392.00, 440.00
- Bb4, B4 = 466.16, 493.88
- )
- riff := []float64{
- E4, 0.5, E4, 0.5, G4, 0.5, A4, 0.5, // bar 1a
- E4, 0.5, E4, 0.5, G4, 0.5, A4, 0.5, // bar 1b
- B4, 0.5, A4, 0.5, G4, 0.5, E4, 0.5, // bar 2 — climbs then drops
- Bb4, 0.5, A4, 0.5, G4, 0.5, E4, 0.5,
- }
- mel := concat(
- palmMute(E2, beat), padHold([3]float64{E3, B3, E4}, 4, beat),
- hook(beat, riff...),
- )
- wbeat := 0.333 // 180 BPM thrash
- wmel := concat(
- palmMute(E3, wbeat),
- hook(wbeat, E4*2, 0.25, E4*2, 0.25, G4*2, 0.25, A4*2, 0.25,
- E4*2, 0.25, E4*2, 0.25, G4*2, 0.25, A4*2, 0.25,
- B4*2, 0.25, A4*2, 0.25, G4*2, 0.25, E4*2, 0.25,
- Bb4*2, 0.25, A4*2, 0.25, G4*2, 0.25, E4*2, 0.25),
- )
- s.Ambient.Normal = ambientPreset{
- Gain: 0.035, BPM: 140, Wave: "sawtooth",
- DroneFreqs: []float64{82.41, 164.81, 246.94}, Attack: 0.01, Release: 0.08,
- CutoffMin: 1400, CutoffMax: 6000, Drums: drumRock, Melody: mel,
- }
- s.Ambient.Wild = ambientPreset{
- Gain: 0.075, BPM: 180, Wave: "sawtooth",
- DroneFreqs: []float64{82.41, 164.81, 329.63, 440.00}, Attack: 0.01, Release: 0.04,
- CutoffMin: 2800, CutoffMax: 8500, DetuneCents: 14, Drums: drumRockWild, Melody: wmel,
+ soundCacheMu.Lock()
+ defer soundCacheMu.Unlock()
+ if soundCache == nil {
+ initSoundCache()
+ if s, ok := soundCache[themeName]; ok {
+ return s, nil
+ }
}
- return s
+ return themeSounds{}, fmt.Errorf("no sounds.json for theme %q", themeName)
}
-// ── public entry points ───────────────────────────────────────────
-
+// defaultSounds returns the default theme (neon) sound preset.
func defaultSounds() themeSounds {
- return soundsNeon()
+ s, _ := loadThemeSounds("neon")
+ return s
}
// themeSoundsJSON returns a JS object literal for embedding in <script> (safe JSON).
func themeSoundsJSON(themeName string) template.JS {
- p := defaultSounds()
- if x, ok := themeSoundPresets[themeName]; ok {
- p = x
- }
- b, err := json.Marshal(p)
+ s, _ := loadThemeSounds(themeName)
+ b, err := json.Marshal(s)
if err != nil {
- b, _ = json.Marshal(defaultSounds())
+ b, _ = json.Marshal(themeSounds{})
}
return template.JS(b) //nolint:gosec // JSON from fixed structs
}
-
-var themeSoundPresets = map[string]themeSounds{
- "neon": soundsNeon(),
- "terminal": soundsTerminal(),
- "synthwave": soundsSynthwave(),
- "plasma": soundsPlasma(),
- "brutalist": soundsBrutalist(),
- "volcano": soundsVolcano(),
- "aurora": soundsAurora(),
- "matrix": soundsMatrix(),
- "ocean": soundsOcean(),
- "dos": soundsDos(),
- "retro": soundsRetro(),
- "cosmos": soundsCosmos(),
- "retrofuture": soundsRetrofuture(),
- "spaceage": soundsSpaceage(),
- "tropicale": soundsTropical(),
- "noir": soundsNoir(),
- "cathedral": soundsCathedral(),
- "surveillance": soundsSurveillance(),
- "biomech": soundsBiomech(),
- "nukem": soundsNukem(),
-}