Skip to content

Commit

Permalink
Merge pull request #19 from jfhamlin/f/features-features
Browse files Browse the repository at this point in the history
Knobs, tidal cycles-like DSL, and play-buf rename
  • Loading branch information
jfhamlin authored Jun 2, 2024
2 parents ea49622 + d7fb947 commit 81fc943
Show file tree
Hide file tree
Showing 38 changed files with 887 additions and 270 deletions.
24 changes: 24 additions & 0 deletions app.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import (
"github.com/jfhamlin/muscrat/pkg/conf"
"github.com/jfhamlin/muscrat/pkg/mrat"
"github.com/jfhamlin/muscrat/pkg/pubsub"
"github.com/jfhamlin/muscrat/pkg/ugen"

"github.com/wailsapp/wails/v2/pkg/runtime"
)

Expand Down Expand Up @@ -76,6 +78,24 @@ func (a *App) startup(ctx context.Context) {
}
})

pubsub.Subscribe(ugen.KnobsChangedEvent, func(event string, data any) {
// send the new knobs to the UI
go func() {
runtime.EventsEmit(ctx, "knobs-changed", ugen.GetKnobs())
}()
})

// forward knob value changes from the UI to the pubsub
runtime.EventsOn(ctx, "knob-value-change", func(data ...any) {
id := data[0].(float64)
value := data[1].(float64)
update := ugen.KnobUpdate{
ID: uint64(id),
Value: value,
}
pubsub.Publish(ugen.KnobValueChangeEvent, update)
})

pubsub.Subscribe("console.log", func(event string, data any) {
go runtime.EventsEmit(ctx, "console.log", data)
})
Expand Down Expand Up @@ -187,3 +207,7 @@ func (a *App) stopFile() {
func (a *App) GetNSPublics() []mrat.Symbol {
return mrat.GetNSPublics()
}

func (a *App) GetKnobs() []*ugen.Knob {
return ugen.GetKnobs()
}
12 changes: 10 additions & 2 deletions examples/bitcrush.glj
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
(ns user
(:require [mrat.core :refer :all]))

(def metro (impulse (knob "metro" 4 1 10)))

(def cutoff (knob "cutoff" 300 200 10000))

(play (-> (saw [100 150 202 304 606] :mul 0.5 :iphase [0.2 0 0.5])
(bitcrush :bits (step (impulse 8) [3 2 16 5]))
(rlpf 15000 :mul 0.25)
(bitcrush :bits (step metro [3 2 16 5]))
sum
(rlpf (env metro [5000 cutoff cutoff 5000] [0.01 0.01 0.1])
(- 1 (* 0.9 (env-perc metro [0.01 0.1])))
:mul 0.25)
(* 0.6)
(* (env-perc metro [0.01 0.1]))
(freeverb :room-size (knob "room-size" 0.5 0 1))
limiter))
2 changes: 1 addition & 1 deletion examples/calculating.glj
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@

(play (-> (sin freq :duty (sin 4.1 :mul 0.4 :add 0.5))
(* metro)
(combc 2 0.01 3)
(combc 2 0.018 3)
(rlpf (* freq 8) 1)
(* 0.1)))
4 changes: 2 additions & 2 deletions examples/compus.glj
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,10 @@
(def trig4 (impulse (/ 1 (* 4 dur))))

(def loopr
(play-buf compus :trigger trig4 :rate (choose trig4 [0.5 1 1 1 1 2])))
(smp compus :trigger trig4 :rate (choose trig4 [0.5 1 1 1 1 2])))

(def bass
(play-buf :bass_voxy_c
(smp :bass_voxy_c
:trigger (choose trig [0 0 0 1])
:rate (choose trig [0.5 0.5 1 1 2 4])))

Expand Down
2 changes: 1 addition & 1 deletion examples/drumcircle.glj
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,6 @@
(combc 2 0.014 1)
(* 0.5)
(rlpf 300 0.3)
(+ (-> (play-buf :loop_amen_full :rate (step trig [0.4 1 0.1 2 1.5 0.6 0.25]) :trigger trig :mul 0.1)
(+ (-> (smp :loop_amen_full :rate (step trig [0.4 1 0.1 2 1.5 0.6 0.25]) :trigger trig :mul 0.1)
(rhpf 1400 0.15 :mul 0.2)))
(freeverb :room-size 0.1)))
64 changes: 20 additions & 44 deletions examples/fm.glj
Original file line number Diff line number Diff line change
@@ -1,63 +1,39 @@
(ns examples.fm
(:require [mrat.core :refer :all]))

(defn fm-op
"Creates a simple FM 'operator' in the style of the Yamaha DX series."
[freq envelope input & {:keys [feedback]}]
(let [phase (phasor freq)
feedback (or feedback 0)
;; log2 is used to scale the feedback amount
;; todo: add log2 to the core namespace
feedback (math.Log2 (+ feedback 1))
has-feedback (> feedback 0)
fb (if has-feedback (pipe) 0)
osc (sin :phase (+ phase input fb)) ;; todo: sync with the trigger so that the phase is reset
out (* osc envelope)]
(if has-feedback (pipeset! fb (* feedback out)))
out))
(:use [mrat.core]))

(def impulse-rate 6)
(def gate (lfpulse impulse-rate :duty 0.2))

(def freq
(let [offset (choose gate [0 0 0 0 0 0 12 12 12 24])]
(let [offset (step gate [0 0 0 0 0 0 12 12 12 24])]
(step gate
(->> mixolydian
(map #(+ D2 % offset))
(->> locrian
(map #(+ A2 % offset))
(map mtof)))))

(def op-conf
;; freq-ratio amp adsr mod-indexes feedback carrier
[[1 0.8 [0.001 0.15 1 0.15] [1] 0.1 true]
[2 0.5 [0.001 0.15 0.1 0.15] [2] 0 false]
[7 0.3 [0.1 0.15 1 0.01] nil 0.4 false]
[2 0.5 [0.01 0.15 0.1 0.15] [2] 0.0 false]
[7 0.3 [0.01 0.15 1 0.01] nil 0.4 false]
[0.5 1 [0.1 0.15 0.5 0.001] [1 2] (knob "fb" 0 0 1) true]
])

(def fm-out
(let [ops (mapv (fn [[r a e m f c]]
(let [input (if-not (empty? m) (pipe) 0)
op (fm-op (* freq r)
(* a (env-adsr gate e))
input
:feedback f)]
{:op op
:mods m
:input input
:carrier c}))
op-conf)]
;; wire up the modulators
(doseq [{:keys [op mods input]} ops
:when (not (empty? mods))]
(let [in-sum (sum (map #(:op (nth ops %)) mods))]
(pipeset! input in-sum)))
(sum (->> ops
(filter :carrier)
(map :op)))))
(println (double (/ BUFFER-SIZE SAMPLE-RATE)))

(def trig (impulse 6))

(def kick (smp :kick :trigger (pulse-div trig 2) :mul 0.7))
(def kick-amp (amplitude kick))
(play kick)

(def sig
(-> fm-out
(combc 0.5 0.5 3)
(* 0.25)
(-> (fm-synth op-conf trig (step trig (map (comp mtof #(+ % 2)) [C3 E3 B4 E3 C3 E3 G3])))
(combc 0.5 (knob "delay" 0.25 0.1 1) 3)
(* 0.75)
tanh
(* 0.3)
(* (- 1 kick-amp))
limiter))

;; (wavout sig "fm.wav")
Expand Down
8 changes: 4 additions & 4 deletions examples/ihylp.glj
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
(ns examples.ihylpr
"A cover of 'I heard you like polyrhythms' by Virtual Riot
https://www.youtube.com/watch?v=SthcxWPXG_E"
(:require [mrat.core :refer :all]))
(:use [mrat.core]))

(def bps 1.0)

(def speed-factor 0.005)
(def speed-factor (knob "speed-factor" 0.005 0.001 0.5 0.001))

(def offset (choose (impulse (/ bps 10)) [-9 -5 0 3 7 12]))

Expand All @@ -24,7 +24,7 @@

(defn synth
[rate note]
(let [osc (sin (mtof note) :duty 0.2)
(let [osc (sin (mtof note) :duty 0.6)
trig (impulse rate :iphase (.Float64 mrand))
amp (env trig [0 1 1 0] [0.01 0.02 0.1])]
(* osc amp)))
Expand All @@ -34,6 +34,6 @@
(pan2 (/ %1 (count notes)))) (range (count notes)) notes)
(sum)
(* (/ 4 (inc (count notes))))
(freeverb :room-size 0.5)))
(freeverb :room-size (knob "room-size" 0.5 0 1))))

(play ihylpr)
19 changes: 10 additions & 9 deletions examples/karplus_strong.glj
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,26 @@

(def fade-in-time 60)

(def metro (impulse 10))
(def metro (impulse 8))

(def burst (-> (pink-noise)
(* (env-adsr metro [0.001 0.001 1 0.001]))
(def burst (-> (saw 50)
(* (env-adsr metro [0.001 0.001 1 0.1]))
(* 1)))

(def feedback (pipe))

(def delay-filter
(-> feedback
(delayc 0.5 (step metro [0.0001 0.002 0.001 0.01 0.0015 0.0019]))
(lores 1000 0)
(* (sin 4 :mul 0.02 :add 0.98))))
(lores 400 0)
(* 0.98)))

(pipeset! feedback (+ burst delay-filter))

(play (-> feedback
wfold
(loshelf 20 :db -20)
(rhpf 1200)
(hishelf 12000 :db -90)
(* 0.1)
tanh
;; (loshelf 20 :db -20)
(rlpf 500 0.2)
;; (hishelf 12000 :db -90)
limiter))
4 changes: 2 additions & 2 deletions examples/kick.glj
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

(defugen kick
[trig 0]
(let [[hi lo] [700 54]
(let [[hi lo] [(knob "high-freq" 700 100 2000) 54]
freq (env-perc trig [0 0.13] :curve -6)
freq (linexp freq 0 1 lo hi)
;; another little layer
Expand All @@ -18,4 +18,4 @@
snd))


(play (kick (impulse 2) :mul 0.5))
(play (kick (impulse (knob "bps" 2 1 10)) :mul 0.5))
8 changes: 4 additions & 4 deletions examples/scriabin.glj
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
(ns examples.scriabin
(:require [mrat.core :refer :all] :reload
[mrat.abc :as abc] :reload))
(:require [mrat.core :refer :all]
[mrat.abc :as abc]))

(def tempo-in (midi-in "tempo" :cc :controller 70 :default 0.5))
(def tempo (* 2 72 tempo-in)) ;; 72 quarter notes per minute default
Expand Down Expand Up @@ -62,10 +62,10 @@
(def envelope-bass (mkenv metro-bass dur-bass))

(def tune
(let [sig (-> (saw (* root (semitones (sin 6 :mul 0.05))) :duty 0.8)
(let [sig (-> (saw (* root (semitones (sin 8 :mul 0.05))) :duty 0.8)
(lores (* root (semitones 7)) 0.8)
(* envelope))
sig-bass (-> (saw (* root-bass (semitones (sin 6 :mul 0.1))))
sig-bass (-> (sin (* root-bass (semitones (sin 6 :mul 0.1))) :duty 0.8)
(lores (* root-bass 3) 0.9)
(* envelope-bass))]
(-> (+ sig (* (dbamp -5) sig-bass))
Expand Down
2 changes: 1 addition & 1 deletion examples/st.glj
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
(def melody-freq-seq (env 1 [4 16 32]
[melody-cf1-time
melody-cf2-dur]
:interp :hold))
:curve :hold))

(def duty-env (env 1 [0.8 0.8 0.2 0.2] [30 2 100]))

Expand Down
18 changes: 9 additions & 9 deletions examples/sunset.glj
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
(ns examples.sunset
(:require [mrat.core :refer :all]))

(def melody-amp (* 0.3 (midi-in "melody" :cc :controller 70 :default 0.5)))
(def drone-amp (midi-in "drone" :cc :controller 74 :default 0.6))
(def amp (* 0.8 (midi-in "amp" :cc :controller 73 :default 0.5)))
(def melody-amp (* 0.3 (knob "melody" 0.5 0 1)))
(def drone-amp (knob "drone" 0.6 0 1))
(def amp (* 0.8 (knob "amp" 0.5 0 1)))

(def split-cutoff-midi (+ 40 36 (* 40 (midi-in "split" :cc :controller 71 :default 0.5))))
(def split-cutoff-midi (+ 40 36 (* 40 (knob "split" 0.5 0 1))))

(def res (* 0.95 (midi-in "res" :cc :controller 75 :default 0.6)))
(def res (* 0.95 (knob "res" 0.6 0 1)))

(def hpcutoff (mtof (+ 40 (* 90 (midi-in "hpcutoff" :cc :controller 76 :default 0)))))
(def lpcutoff (mtof (+ 20 (* 110 (midi-in "lpcutoff" :cc :controller 77 :default 1)))))
(def hpcutoff (mtof (+ 40 (* 90 (knob "hpcutoff" 0 0 1)))))
(def lpcutoff (mtof (+ 20 (* 110 (knob "lpcutoff" 1 0 1)))))

(def intervals [0 7 0 5 0 10
0 5 0 3 0 7
Expand All @@ -19,9 +19,9 @@
0 0 0 0 0 0
])

(def root-midi 50)
(def root-midi (knob "root-midi" 40 30 70 1))

(def metro (impulse 6))
(def metro (impulse (knob "metro" 4 4 6 1)))

(def metro-slo (impulse 0.1))

Expand Down
Loading

0 comments on commit 81fc943

Please sign in to comment.