├── .gitignore ├── AUTHORS ├── CONTRIBUTING ├── Dockerfile ├── HACKING.md ├── LICENSE ├── Makefile ├── README.md ├── UGENS.md ├── _config.yml ├── allpass.go ├── allpass_test.go ├── arrayspec.go ├── balance2.go ├── balance2_test.go ├── ball.go ├── ball_test.go ├── ballpass.go ├── ballpass_test.go ├── bar_test.go ├── blip.go ├── blip_test.go ├── blowpass.go ├── blowpass_test.go ├── bpf.go ├── bpf_test.go ├── brf.go ├── brf_test.go ├── brownnoise.go ├── brownnoise_test.go ├── buffer.go ├── buffer_test.go ├── c.go ├── c_test.go ├── cascade_test.go ├── caw_test.go ├── client.go ├── client_buffer.go ├── client_test.go ├── clipnoise.go ├── clipnoise_test.go ├── coingate.go ├── coingate_test.go ├── comb.go ├── comb_test.go ├── control.go ├── controlrate.go ├── conv.go ├── conv_test.go ├── cosc.go ├── cosc_test.go ├── crackle.go ├── crackle_test.go ├── dc.go ├── dc_test.go ├── decay.go ├── decay2.go ├── decay2_test.go ├── decodeb2.go ├── defs.go ├── delay.go ├── delay_test.go ├── detect_silence.go ├── detectsilence_test.go ├── doc.go ├── dust.go ├── dust2.go ├── dust2_test.go ├── dust_test.go ├── env.go ├── env_test.go ├── envelope.go ├── envgen.go ├── envgen_test.go ├── fft.go ├── fft_test.go ├── foo_test.go ├── formant.go ├── formant_test.go ├── formlet.go ├── formlet_test.go ├── freeverb.go ├── freeverb_test.go ├── fsinosc.go ├── fsinosc_test.go ├── gate.go ├── gate_test.go ├── gendy1.go ├── gendy1_test.go ├── gendy2.go ├── gendy2_test.go ├── gendy3.go ├── gendy3_test.go ├── grainbuf.go ├── grainbuf_test.go ├── grainfm.go ├── grainfm_test.go ├── grainin.go ├── grainin_test.go ├── grainsin.go ├── grainsin_test.go ├── graynoise.go ├── group.go ├── gverb.go ├── gverb_test.go ├── hasher.go ├── hasher_test.go ├── hpf.go ├── hpf_test.go ├── ifft.go ├── impulse.go ├── impulse_test.go ├── in.go ├── in_test.go ├── init.go ├── input.go ├── input_test.go ├── integrator.go ├── integrator_test.go ├── interpolation.go ├── jpverb.go ├── kalimba_mono.wav ├── klang.go ├── klang_test.go ├── klank.go ├── klank_test.go ├── lag.go ├── lag_test.go ├── latch.go ├── latch_test.go ├── leakdc.go ├── leakdc_test.go ├── lfclipnoise.go ├── lfclipnoise_test.go ├── lfcub.go ├── lfcub_test.go ├── lfdclipnoise.go ├── lfdclipnoise_test.go ├── lfdnoise.go ├── lfgauss.go ├── lfgauss_test.go ├── lfnoise.go ├── lfnoise_test.go ├── lfo.go ├── lfpar.go ├── lfpar_test.go ├── lfpulse.go ├── lfpulse_test.go ├── lfsaw.go ├── lfsaw_test.go ├── lftri.go ├── lftri_test.go ├── limiter.go ├── line.go ├── line_test.go ├── linpan2.go ├── linpan2_test.go ├── linxfade2.go ├── linxfade2_test.go ├── localbuf.go ├── lpf.go ├── lpf_test.go ├── maxlocalbufs.go ├── median.go ├── median_test.go ├── mix.go ├── mix_test.go ├── moddif.go ├── mousex.go ├── mousey.go ├── multiInput.go ├── multi_test.go ├── notes ├── num_outout_buses.go ├── offset_out.go ├── onepole.go ├── onepole_test.go ├── onezero.go ├── onezero_test.go ├── operators.go ├── operators_test.go ├── osc.go ├── osc_test.go ├── oscn.go ├── oscn_test.go ├── out.go ├── out_test.go ├── output.go ├── pan2.go ├── pan2_test.go ├── pan4.go ├── pan4_test.go ├── panaz.go ├── panaz_test.go ├── panb2.go ├── panb2_test.go ├── param.go ├── paramName.go ├── param_test.go ├── pinknoise.go ├── playbuf.go ├── playbuf_test.go ├── pmosc.go ├── pmosc_test.go ├── psingrain.go ├── psingrain_test.go ├── pstring.go ├── pulse.go ├── pulse_count.go ├── pulse_count_test.go ├── pulse_divider.go ├── pulse_divider_test.go ├── pulse_test.go ├── pv_brickwall.go ├── rand.go ├── rate.go ├── resonz.go ├── resonz_test.go ├── ringz.go ├── ringz_test.go ├── rlpf.go ├── rlpf_test.go ├── rotate2.go ├── runningsum.go ├── runningsum_test.go ├── sampledur.go ├── samplerate.go ├── saw.go ├── select.go ├── server.go ├── server_darwin.go ├── server_linux.go ├── shaper.go ├── shaper_test.go ├── silent.go ├── silent_test.go ├── sinosc.go ├── sinosc_test.go ├── sinoscfb.go ├── sinoscfb_test.go ├── slew.go ├── slew_test.go ├── slope.go ├── slope_test.go ├── soundin.go ├── soundin_test.go ├── spring.go ├── spring_test.go ├── stack.go ├── stack_test.go ├── status.go ├── sums.go ├── sums_test.go ├── sweep.go ├── sweep_test.go ├── syncsaw.go ├── syncsaw_test.go ├── synth.go ├── synthdef.go ├── synthdef_read.go ├── synthdef_test.go ├── synthdef_write.go ├── tdelay.go ├── tdelay_test.go ├── testdata ├── AllpassExample.scsyndef ├── AllpassnExample.scsyndef ├── BAllPassExample.scsyndef ├── BLowPassTest.scsyndef ├── BPFExample.scsyndef ├── BRFExample.scsyndef ├── Balance2Test.scsyndef ├── BallTest.scsyndef ├── Beats.scsyndef ├── BlipExample.scsyndef ├── BrownNoiseTest.scsyndef ├── COscTest.scsyndef ├── Cascade.scsyndef ├── CascadeExample.scsyndef ├── ClipNoiseTest.scsyndef ├── CoinGateTest.scsyndef ├── CombCTest.scsyndef ├── CombLTest.scsyndef ├── CombNTest.scsyndef ├── CrackleTest.scsyndef ├── DCTest.scsyndef ├── Decay2Test.scsyndef ├── DelayCTest.scsyndef ├── DelayLTest.scsyndef ├── DelayNTest.scsyndef ├── DetectSilence.scsyndef ├── Dust2Test.scsyndef ├── DustTest.scsyndef ├── Envgen1.scsyndef ├── EnvgenTest.scsyndef ├── FFTTest.scsyndef ├── FSinOscExample.scsyndef ├── FittonBubbles.scsyndef ├── FormantTest.scsyndef ├── FormletTest.scsyndef ├── FreeVerbExample.scsyndef ├── FreeVerbTest.scsyndef ├── GVerbExample.scsyndef ├── GateTest.scsyndef ├── Gendy1Test.scsyndef ├── Gendy2Test.scsyndef ├── Gendy3Test.scsyndef ├── GrainBufTest.scsyndef ├── GrainFMExample.scsyndef ├── GrainFMTest.scsyndef ├── GrainInTest.scsyndef ├── GrainSinTest.scsyndef ├── HPFExample.scsyndef ├── HasherTest.scsyndef ├── ImpulseExample.scsyndef ├── InTest.scsyndef ├── IntegratorExample.scsyndef ├── KlangTest.scsyndef ├── KlankTest1.scsyndef ├── LFClipNoiseTest.scsyndef ├── LFCubTest.scsyndef ├── LFDClipNoiseTest.scsyndef ├── LFGaussTest.scsyndef ├── LFNoise1Example.scsyndef ├── LFParTest.scsyndef ├── LFPulseTest.scsyndef ├── LFSawExample.scsyndef ├── LFTriExample.scsyndef ├── LPFExample.scsyndef ├── LagTest.scsyndef ├── LatchTest.scsyndef ├── LeakDCTest.scsyndef ├── LinPan2Test.scsyndef ├── LinXFade2Test.scsyndef ├── LineTest.scsyndef ├── MedianTest.scsyndef ├── MixTest.scsyndef ├── OnePoleTest.scsyndef ├── OneZeroTest.scsyndef ├── OscNTest.scsyndef ├── OscTest.scsyndef ├── PMOscTest.scsyndef ├── PSinGrainTest.scsyndef ├── Pan2Test.scsyndef ├── Pan4Test.scsyndef ├── PanAzTest.scsyndef ├── PanB2Test.scsyndef ├── PlayBufExample.scsyndef ├── PulseCountTest.scsyndef ├── PulseDividerTest.scsyndef ├── PulseTest.scsyndef ├── RLPFTest.scsyndef ├── ResonzTest.scsyndef ├── RingzTest.scsyndef ├── RunningSumTest.scsyndef ├── SameSame.scsyndef ├── SawTone1.scsyndef ├── SelectTest.scsyndef ├── ShaperTest.scsyndef ├── SilentTest.scsyndef ├── SimpleMulti.scsyndef ├── SinOscFBTest.scsyndef ├── SineTone.scsyndef ├── SineTone2.scsyndef ├── SineTone3.scsyndef ├── SineTone4.scsyndef ├── SlewTest.scsyndef ├── SlopeTest.scsyndef ├── SoundInTest0.scsyndef ├── SoundInTest00.scsyndef ├── SoundInTest01.scsyndef ├── SoundInTest02.scsyndef ├── SoundInTest12.scsyndef ├── SoundInTest20.scsyndef ├── SpringTest.scsyndef ├── Sum3Test.scsyndef ├── SweepTest.scsyndef ├── SyncSawTest.scsyndef ├── TDelayTest.scsyndef ├── TGrainsExample.scsyndef ├── THX.scsyndef ├── TestEnvADSR.scsyndef ├── Trig1Test.scsyndef ├── TrigTest.scsyndef ├── UseParam.scsyndef ├── VOsc3Test.scsyndef ├── VOscTest.scsyndef ├── VarSawTest.scsyndef ├── VibratoTest.scsyndef ├── Warp1Example.scsyndef ├── XFade2Test.scsyndef ├── XLineTest.scsyndef ├── absExample.scsyndef ├── absdifExample.scsyndef ├── acosExample.scsyndef ├── amclipExample.scsyndef ├── ampdbExample.scsyndef ├── asinExample.scsyndef ├── atan2Example.scsyndef ├── atanExample.scsyndef ├── bar.scsyndef ├── baz.scsyndef ├── bilinrandExample.scsyndef ├── ceilExample.scsyndef ├── clip2Example.scsyndef ├── coinExample.scsyndef ├── cosExample.scsyndef ├── coshExample.scsyndef ├── cpsmidiExample.scsyndef ├── cpsoctExample.scsyndef ├── cubedExample.scsyndef ├── dbampExample.scsyndef ├── defWith2Params.scsyndef ├── difsqrExample.scsyndef ├── distortExample.scsyndef ├── divExample.scsyndef ├── excessExample.scsyndef ├── expExample.scsyndef ├── exponExample.scsyndef ├── floorExample.scsyndef ├── fold2Example.scsyndef ├── foo.scsyndef ├── fracExample.scsyndef ├── gcdExample.scsyndef ├── gtExample.scsyndef ├── gteExample.scsyndef ├── hypotExample.scsyndef ├── hypotapxExample.scsyndef ├── lcmExample.scsyndef ├── linrandExample.scsyndef ├── log10Example.scsyndef ├── log2Example.scsyndef ├── logExample.scsyndef ├── ltExample.scsyndef ├── lteExample.scsyndef ├── midiratioExample.scsyndef ├── minExample.scsyndef ├── moddifExample.scsyndef ├── moduloExample.scsyndef ├── negExample.scsyndef ├── octcpsExample.scsyndef ├── powExample.scsyndef ├── rand2Example.scsyndef ├── randExample.scsyndef ├── ratiomidiExample.scsyndef ├── reciprocalExample.scsyndef ├── ring1Example.scsyndef ├── ring2Example.scsyndef ├── ring3Example.scsyndef ├── ring4Example.scsyndef ├── roundExample.scsyndef ├── scalenegExample.scsyndef ├── signExample.scsyndef ├── sinExample.scsyndef ├── sinhExample.scsyndef ├── sqrdifExample.scsyndef ├── sqrsumExample.scsyndef ├── sqrtExample.scsyndef ├── squaredExample.scsyndef ├── sub.scsyndef ├── sum3randExample.scsyndef ├── sumsqrExample.scsyndef ├── synthdefs.sc ├── tanExample.scsyndef ├── tanhExample.scsyndef ├── threshExample.scsyndef ├── truncExample.scsyndef └── wrap2Example.scsyndef ├── tgrains.go ├── tgrains_test.go ├── toggleff.go ├── trand.go ├── translate-synthdefs.md ├── trig.go ├── trig1.go ├── trig1_test.go ├── trig_test.go ├── ugen.go ├── ugenFunc.go ├── ugenInput.go ├── ugenNode_test.go ├── variant.go ├── varsaw.go ├── varsaw_test.go ├── vibrato.go ├── vibrato_test.go ├── vosc.go ├── vosc3.go ├── vosc3_test.go ├── vosc_test.go ├── warp1.go ├── warp1_test.go ├── whitenoise.go ├── xfade2.go ├── xfade2_test.go ├── xline.go └── xline_test.go /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | *.gosyndef 3 | *.svg 4 | *.dot 5 | *.log 6 | *.xml 7 | *.json 8 | core 9 | 10 | # makefile cache 11 | .fixtures 12 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | Brian Sorahan 2 | Blake Wenzel 3 | Paul Lucas 4 | -------------------------------------------------------------------------------- /CONTRIBUTING: -------------------------------------------------------------------------------- 1 | All development activity takes place on github. 2 | 3 | If you think you've discovered a bug, or you would like 4 | to make a feature request please do this through github. 5 | 6 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:14.04 2 | RUN sudo add-apt-repository ppa:supercollider/ppa 3 | RUN sudo apt-get update 4 | RUN sudo apt-get install supercollider 5 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Get the path to sclang 2 | PLATFORM = $(shell uname -s) 3 | 4 | ifeq ($(PLATFORM),Darwin) 5 | SCLANG = /Applications/SuperCollider.app/Contents/MacOS/sclang 6 | endif 7 | 8 | ifeq ($(PLATFORM),Linux) 9 | SCLANG = /usr/bin/sclang 10 | endif 11 | 12 | # HACK for running sclang w/o a GUI on linux 13 | ifeq ($(GUI),no) 14 | SCLANG = /usr/bin/xvfb-run --server-args="-screen 0, 1280x800x24" $(SCLANG) 15 | endif 16 | 17 | # Default target 18 | all: 19 | @go install 20 | 21 | fixtures: .fixtures 22 | .fixtures: testdata/synthdefs.sc 23 | @cd testdata && $(SCLANG) synthdefs.sc 24 | @touch $@ 25 | 26 | lint: 27 | @gometalinter 28 | 29 | coverage: 30 | @rm -f cover.out cover.html 31 | @go test -coverprofile cover.out && go tool cover -html cover.out -o cover.html 32 | 33 | clean: 34 | @rm -rf *~ *.gosyndef *.svg *.dot *.json *.xml .fixtures 35 | 36 | test: .fixtures 37 | @go test 38 | 39 | .PHONY: all clean fixtures test 40 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-hacker -------------------------------------------------------------------------------- /allpass_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import "testing" 4 | 5 | // Out.ar(0, AllpassC.ar(Decay.ar(Dust.ar(1,0.5), 0.2, WhiteNoise.ar), 0.2, 0.2, 3)); 6 | func TestAllpassnExample(t *testing.T) { 7 | const defName = "AllpassExample" 8 | 9 | compareAndWrite(t, defName, NewSynthdef(defName, func(p Params) Ugen { 10 | var ( 11 | noise = WhiteNoise{}.Rate(AR) 12 | dust = Dust{C(1)}.Rate(AR).Mul(C(0.5)) 13 | decay = Decay{dust, C(0.2)}.Rate(AR).Mul(noise) 14 | sig = Allpass{ 15 | Interpolation: InterpolationCubic, 16 | In: decay, 17 | MaxDelayTime: C(0.2), 18 | DelayTime: C(0.2), 19 | DecayTime: C(3), 20 | }.Rate(AR) 21 | ) 22 | return Out{ 23 | Bus: C(0), 24 | Channels: sig, 25 | }.Rate(AR) 26 | })) 27 | } 28 | -------------------------------------------------------------------------------- /balance2.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // Balance2 equal power panner 4 | type Balance2 struct { 5 | // L is the left input signal 6 | L Input 7 | // R is the right input signal 8 | R Input 9 | // Pos stereo position where -1 is hard left and +1 is hard right 10 | Pos Input 11 | // Level gain [0, 1] 12 | Level Input 13 | } 14 | 15 | func (bal *Balance2) defaults() { 16 | if bal.Pos == nil { 17 | bal.Pos = C(0) 18 | } 19 | if bal.Level == nil { 20 | bal.Level = C(1) 21 | } 22 | } 23 | 24 | // Rate creates a new ugen at a specific rate. 25 | // If rate is an unsupported value this method will cause 26 | // a runtime panic. 27 | func (bal Balance2) Rate(rate int8) Input { 28 | if bal.L == nil || bal.R == nil { 29 | panic("Balance2 expects L and R to not be nil") 30 | } 31 | CheckRate(rate) 32 | (&bal).defaults() 33 | return NewInput("Balance2", rate, 0, 2, bal.L, bal.R, bal.Pos, bal.Level) 34 | } 35 | -------------------------------------------------------------------------------- /balance2_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestBalance2(t *testing.T) { 8 | defName := "Balance2Test" 9 | def := NewSynthdef(defName, func(p Params) Ugen { 10 | var ( 11 | bus = C(0) 12 | gain = C(0.1) 13 | l = LFSaw{Freq: C(44)}.Rate(AR) 14 | r = Pulse{Freq: C(33)}.Rate(AR) 15 | pos = FSinOsc{Freq: C(0.5)}.Rate(KR) 16 | sig = Balance2{L: l, R: r, Pos: pos, Level: gain}.Rate(AR) 17 | ) 18 | return Out{bus, sig}.Rate(AR) 19 | }) 20 | compareAndWrite(t, defName, def) 21 | } 22 | -------------------------------------------------------------------------------- /ball.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // Ball models the path of a bouncing object that is reflected by a vibrating surface. 4 | type Ball struct { 5 | In Input 6 | Gravity Input 7 | Damp Input 8 | Friction Input 9 | } 10 | 11 | func (b *Ball) defaults() { 12 | if b.In == nil { 13 | b.In = C(0) 14 | } 15 | if b.Gravity == nil { 16 | b.Gravity = C(1) 17 | } 18 | if b.Damp == nil { 19 | b.Damp = C(0) 20 | } 21 | if b.Friction == nil { 22 | b.Friction = C(0.01) 23 | } 24 | } 25 | 26 | // Rate creates a new ugen at a specific rate. 27 | // If rate is an unsupported value this method will cause a runtime panic. 28 | func (b Ball) Rate(rate int8) Input { 29 | CheckRate(rate) 30 | (&b).defaults() 31 | return NewInput("Ball", rate, 0, 1, b.In, b.Gravity, b.Damp, b.Friction) 32 | } 33 | -------------------------------------------------------------------------------- /ball_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestBall(t *testing.T) { 8 | const defName = "BallTest" 9 | 10 | // var sf = LFNoise0.ar(MouseX.kr(1, 100, 1)); 11 | // var g = MouseY.kr(0.1, 10, 1); 12 | // var f = Ball.ar(sf, g, 0.01, 0.01); 13 | // f = f * 140 + 500; 14 | // SinOsc.ar(f, 0, 0.2) 15 | compareAndWriteStructure(t, defName, NewSynthdef(defName, func(p Params) Ugen { 16 | sf := A(LFNoise{ 17 | Interpolation: NoiseStep, 18 | Freq: K(MouseX{ 19 | Min: C(1), 20 | Max: C(100), 21 | Warp: WarpExp, 22 | }), 23 | }) 24 | g := K(MouseY{ 25 | Min: C(0.1), 26 | Max: C(10), 27 | Warp: WarpExp, 28 | }) 29 | f := A(Ball{ 30 | In: sf, 31 | Gravity: g, 32 | Damp: C(0.01), 33 | Friction: C(0.01), 34 | }) 35 | f = f.MulAdd(C(140), C(500)) 36 | 37 | return Out{ 38 | Bus: C(0), 39 | Channels: SinOsc{Freq: f}.Rate(AR).Mul(C(0.2)), 40 | }.Rate(AR) 41 | })) 42 | } 43 | -------------------------------------------------------------------------------- /ballpass_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import "testing" 4 | 5 | func TestBAllPass(t *testing.T) { 6 | const defName = "BAllPassExample" 7 | 8 | compareAndWrite(t, defName, NewSynthdef(defName, func(p Params) Ugen { 9 | mousex := MouseX{ 10 | Min: C(10), 11 | Max: C(18000), 12 | Warp: C(1), 13 | }.Rate(KR) 14 | 15 | saw := Saw{}.Rate(AR) 16 | 17 | sig := BAllPass{ 18 | In: saw, 19 | Freq: mousex, 20 | RQ: C(0.8), 21 | }.Rate(AR) 22 | 23 | return Out{ 24 | Bus: C(0), 25 | Channels: sig, 26 | }.Rate(AR) 27 | })) 28 | } 29 | -------------------------------------------------------------------------------- /bar_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // FIXME 4 | // import "testing" 5 | 6 | // func TestBar(t *testing.T) { 7 | // name := "bar" 8 | // def := NewSynthdef(name, func(p Params) Ugen { 9 | // bus := C(0) 10 | // blip := Blip{}.Rate(AR) 11 | // sine := SinOsc{}.Rate(AR) 12 | // return Out{bus, sine.Mul(blip)}.Rate(AR) 13 | // }) 14 | // if def == nil { 15 | // t.Fatalf("nil synthdef") 16 | // } 17 | // compareAndWrite(t, name, def) 18 | // } 19 | -------------------------------------------------------------------------------- /blip.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // Blip band-limited impulse generator 4 | type Blip struct { 5 | // Freq frequency in Hz 6 | Freq Input 7 | // Harm the number of harmonics 8 | Harm Input 9 | } 10 | 11 | func (blip *Blip) defaults() { 12 | if blip.Freq == nil { 13 | blip.Freq = C(440) 14 | } 15 | if blip.Harm == nil { 16 | blip.Harm = C(200) 17 | } 18 | } 19 | 20 | // Rate creates a new ugen at a specific rate. 21 | // If rate is an unsupported value this method will cause 22 | // a runtime panic. 23 | func (blip Blip) Rate(rate int8) Input { 24 | CheckRate(rate) 25 | (&blip).defaults() 26 | return NewInput("Blip", rate, 0, 1, blip.Freq, blip.Harm) 27 | } 28 | -------------------------------------------------------------------------------- /blip_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestBlip(t *testing.T) { 8 | def := NewSynthdef("BlipExample", func(p Params) Ugen { 9 | start, end, dur, done := C(20000), C(200), C(6), 0 10 | freq := XLine{start, end, dur, done}.Rate(KR) 11 | bus, harms, gain := C(0), C(100), C(0.2) 12 | sig := Blip{freq, harms}.Rate(AR).Mul(gain) 13 | return Out{bus, sig}.Rate(AR) 14 | }) 15 | same, err := def.CompareToFile("testdata/BlipExample.scsyndef") 16 | if err != nil { 17 | t.Fatal(err) 18 | } 19 | if !same { 20 | t.Fatalf("synthdef is different from sclang version") 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /blowpass.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // BLowPass is a lowpass filter based on the Second Order Section 4 | // biquad UGen. 5 | type BLowPass struct { 6 | // In is the input signal. 7 | In Input 8 | // Freq is frequency in Hz. 9 | Freq Input 10 | // RQ is the reciprocal of Q, bandwidth / cutoff. 11 | RQ Input 12 | } 13 | 14 | func (blp *BLowPass) defaults() { 15 | if blp.In == nil { 16 | panic("BLowPass needs an input") 17 | } 18 | if blp.Freq == nil { 19 | blp.Freq = C(1200) 20 | } 21 | if blp.RQ == nil { 22 | blp.RQ = C(1) 23 | } 24 | } 25 | 26 | // Rate creates a new ugen at a specific rate. 27 | // If rate is an unsupported value this method will cause 28 | // a runtime panic. 29 | func (blp BLowPass) Rate(rate int8) Input { 30 | CheckRate(rate) 31 | (&blp).defaults() 32 | return NewInput("BLowPass", rate, 0, 1, blp.In, blp.Freq, blp.RQ) 33 | } 34 | -------------------------------------------------------------------------------- /blowpass_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestBLowPass(t *testing.T) { 8 | defName := "BLowPassTest" 9 | 10 | // Out.ar(0, BLowPass.ar(Blip.ar(400, 4), 300, 0.5)); 11 | compareAndWriteStructure(t, defName, NewSynthdef(defName, func(p Params) Ugen { 12 | return Out{ 13 | Bus: C(0), 14 | Channels: BLowPass{ 15 | In: A(Blip{ 16 | Freq: C(400), 17 | Harm: C(4), 18 | }), 19 | Freq: C(300), 20 | RQ: C(0.5), 21 | }.Rate(AR), 22 | }.Rate(AR) 23 | })) 24 | } 25 | -------------------------------------------------------------------------------- /bpf.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // BPF a resonant low pass filter 4 | type BPF struct { 5 | // In is the input signal 6 | In Input 7 | // Freq cutoff in Hz 8 | Freq Input 9 | // RQ Reciprocal of Q 10 | RQ Input 11 | } 12 | 13 | func (bpf *BPF) defaults() { 14 | if bpf.Freq == nil { 15 | bpf.Freq = C(440) 16 | } 17 | if bpf.RQ == nil { 18 | bpf.RQ = C(1) 19 | } 20 | } 21 | 22 | // Rate creates a new ugen at a specific rate. 23 | // If rate is an unsupported value this method will cause 24 | // a runtime panic. 25 | func (bpf BPF) Rate(rate int8) Input { 26 | if bpf.In == nil { 27 | panic("BPF expects In to not be nil") 28 | } 29 | CheckRate(rate) 30 | (&bpf).defaults() 31 | return NewInput("BPF", rate, 0, 1, bpf.In, bpf.Freq, bpf.RQ) 32 | } 33 | -------------------------------------------------------------------------------- /bpf_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // FIXME 4 | // import ( 5 | // "testing" 6 | // ) 7 | 8 | // func TestBPF(t *testing.T) { 9 | // def := NewSynthdef("BPFExample", func(p Params) Ugen { 10 | // line := XLine{C(0.7), C(300), C(20), 0}.Rate(KR) 11 | // saw := Saw{C(200)}.Rate(AR).Mul(C(0.5)) 12 | // sine := FSinOsc{line, C(0)}.Rate(KR).MulAdd(C(3600), C(4000)) 13 | // bpf := BPF{saw, sine, C(0.3)}.Rate(AR) 14 | // return Out{C(0), bpf}.Rate(AR) 15 | // }) 16 | // same, err := def.Compare(`{ 17 | // var line = XLine.kr(0.7, 300, 20); 18 | // var saw = Saw.ar(200, 0.5); 19 | // var sine = FSinOsc.kr(line, 0, 3600, 4000); 20 | // Out.ar(0, BPF.ar(saw, sine, 0.3)); 21 | // }`) 22 | // if err != nil { 23 | // t.Fatal(err) 24 | // } 25 | // if !same { 26 | // t.Fatalf("synthdef is not the same as sclang version") 27 | // } 28 | // } 29 | -------------------------------------------------------------------------------- /brf.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // BRF a second order band reject filter 4 | type BRF struct { 5 | // In is the input signal 6 | In Input 7 | // Freq cutoff in Hz 8 | Freq Input 9 | // RQ Reciprocal of Q 10 | RQ Input 11 | } 12 | 13 | func (brf *BRF) defaults() { 14 | if brf.Freq == nil { 15 | brf.Freq = C(440) 16 | } 17 | if brf.RQ == nil { 18 | brf.RQ = C(1) 19 | } 20 | } 21 | 22 | // Rate creates a new ugen at a specific rate. 23 | // If rate is an unsupported value this method will cause 24 | // a runtime panic. 25 | func (brf BRF) Rate(rate int8) Input { 26 | if brf.In == nil { 27 | panic("BRF expects In to not be nil") 28 | } 29 | CheckRate(rate) 30 | (&brf).defaults() 31 | return NewInput("BRF", rate, 0, 1, brf.In, brf.Freq, brf.RQ) 32 | } 33 | -------------------------------------------------------------------------------- /brf_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // FIXME 4 | // import ( 5 | // "testing" 6 | // ) 7 | 8 | // func TestBRF(t *testing.T) { 9 | // def := NewSynthdef("BRFExample", func(p Params) Ugen { 10 | // line := XLine{C(0.7), C(300), C(20), 0}.Rate(KR) 11 | // saw := Saw{C(200)}.Rate(AR).Mul(C(0.5)) 12 | // sine := FSinOsc{line, C(0)}.Rate(KR).MulAdd(C(3800), C(4000)) 13 | // bpf := BRF{saw, sine, C(0.3)}.Rate(AR) 14 | // return Out{C(0), bpf}.Rate(AR) 15 | // }) 16 | // same, err := def.Compare(`{ 17 | // var line = XLine.kr(0.7, 300, 20); 18 | // var saw = Saw.ar(200, 0.5); 19 | // var sine = FSinOsc.kr(line, 0, 3800, 4000); 20 | // Out.ar(0, BRF.ar(saw, sine, 0.3)); 21 | // }`) 22 | // if err != nil { 23 | // t.Fatal(err) 24 | // } 25 | // if !same { 26 | // t.Fatalf("synthdef is different from sclang version") 27 | // } 28 | // } 29 | -------------------------------------------------------------------------------- /brownnoise.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // BrownNoise generates noise whose spectrum falls off in power by 6 dB per octave 4 | type BrownNoise struct{} 5 | 6 | // Rate creates a new ugen at a specific rate. 7 | // If rate is an unsupported value this method will cause a runtime panic. 8 | func (brown BrownNoise) Rate(rate int8) Input { 9 | CheckRate(rate) 10 | return NewInput("BrownNoise", rate, 0, 1) 11 | } 12 | -------------------------------------------------------------------------------- /brownnoise_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestBrownNoise(t *testing.T) { 8 | defName := "BrownNoiseTest" 9 | def := NewSynthdef(defName, func(p Params) Ugen { 10 | bus, gain := C(0), C(0.1) 11 | noise := BrownNoise{}.Rate(AR).MulAdd(C(100), C(200)) 12 | sig := SinOsc{Freq: noise}.Rate(AR) 13 | return Out{bus, sig.Mul(gain)}.Rate(AR) 14 | }) 15 | same, err := def.CompareToFile("testdata/BrownNoiseTest.scsyndef") 16 | if err != nil { 17 | t.Fatal(err) 18 | } 19 | if !same { 20 | t.Fatalf("synthdef different from sclang version") 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /buffer_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import ( 4 | "testing" 5 | "time" 6 | ) 7 | 8 | func TestBuffer(t *testing.T) { 9 | c, err := NewClient("udp", "127.0.0.1:57112", "127.0.0.1:57120", 5*time.Second) 10 | if err != nil { 11 | t.Fatal(err) 12 | } 13 | defer func() { _ = c.Close() }() // Best effort. 14 | 15 | buf := newReadBuffer("foo", 0, c) 16 | if buf.Num != 0 { 17 | t.Fatalf("expected 0, but got %d", buf.Num) 18 | } 19 | buf = newReadBuffer("bar", 1, c) 20 | if buf.Num != 1 { 21 | t.Fatalf("expected 1, but got %d", buf.Num) 22 | } 23 | // should return the first buffer 24 | newBuf := newReadBuffer("foo", 0, c) 25 | if newBuf.Num != 0 { 26 | t.Fatalf("expected 0, but got %d", newBuf.Num) 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /c_test.go: -------------------------------------------------------------------------------- 1 | package sc_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/scgolang/sc" 7 | ) 8 | 9 | func TestTruncf(t *testing.T) { 10 | for i, c := range []struct { 11 | in [2]float32 12 | out float32 13 | }{ 14 | { 15 | in: [2]float32{4, 2}, 16 | out: 4, 17 | }, 18 | } { 19 | if expected, got := c.out, sc.Truncf(c.in[0], c.in[1]); expected != got { 20 | t.Fatalf("[%d] expected %f, got %f", i, expected, got) 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /cascade_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestCascade(t *testing.T) { 8 | const defName = "CascadeExample" 9 | 10 | compareAndWrite(t, defName, NewSynthdef(defName, func(p Params) Ugen { 11 | var ( 12 | freq = Multi(C(440), C(441)) 13 | mod1 = SinOsc{Freq: freq}.Rate(AR) 14 | mod2 = SinOsc{Freq: mod1}.Rate(AR) 15 | ) 16 | return Out{ 17 | Bus: C(0), 18 | Channels: SinOsc{ 19 | Freq: mod2, 20 | }.Rate(AR), 21 | }.Rate(AR) 22 | })) 23 | } 24 | -------------------------------------------------------------------------------- /caw_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "path/filepath" 7 | "testing" 8 | ) 9 | 10 | func compareAndWriteStructure(t *testing.T, name string, def *Synthdef) { 11 | f, err := os.Create(fmt.Sprintf("%s.gosyndef", name)) 12 | if err != nil { 13 | t.Fatal(err) 14 | } 15 | if err := def.Write(f); err != nil { 16 | t.Fatal(err) 17 | } 18 | scf, err := os.Open(filepath.Join("testdata", fmt.Sprintf("%s.scsyndef", name))) 19 | if err != nil { 20 | t.Fatal(err) 21 | } 22 | sclangVersion, err := ReadSynthdef(scf) 23 | if err != nil { 24 | t.Fatal(err) 25 | } 26 | for _, msgs := range def.Diff(sclangVersion) { 27 | t.Error(msgs[0] + ", " + msgs[1]) 28 | } 29 | } 30 | 31 | func compareAndWrite(t *testing.T, name string, def *Synthdef) { 32 | f, err := os.Create(fmt.Sprintf("%s.gosyndef", name)) 33 | if err != nil { 34 | t.Fatal(err) 35 | } 36 | if err := def.Write(f); err != nil { 37 | t.Fatal(err) 38 | } 39 | same, err := def.CompareToFile(fmt.Sprintf("testdata/%s.scsyndef", name)) 40 | if err != nil { 41 | t.Fatal(err) 42 | } 43 | if !same { 44 | t.Fatalf("%s is not the same as sclang version", name) 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /clipnoise.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // ClipNoise generates noise whose values are either -1 or 1. 4 | // This produces the maximum energy for the least peak to peak amplitude. 5 | type ClipNoise struct{} 6 | 7 | // Rate creates a new ugen at a specific rate. 8 | // If rate is an unsupported value this method will cause 9 | // a runtime panic. 10 | func (cn ClipNoise) Rate(rate int8) Input { 11 | return NewInput("ClipNoise", rate, 0, 1) 12 | } 13 | -------------------------------------------------------------------------------- /clipnoise_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestClipNoise(t *testing.T) { 8 | defName := "ClipNoiseTest" 9 | def := NewSynthdef(defName, func(p Params) Ugen { 10 | bus, gain := C(0), C(0.2) 11 | sig := ClipNoise{}.Rate(AR).Mul(gain) 12 | return Out{bus, sig}.Rate(AR) 13 | }) 14 | compareAndWrite(t, defName, def) 15 | } 16 | -------------------------------------------------------------------------------- /coingate.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // CoinGate tosses a coin every time it receives a trigger 4 | // and either passes the trigger or doesn't. 5 | type CoinGate struct { 6 | // Value between 0.0 and 1.0 determines probability of either possibilities. 7 | Prob Input 8 | 9 | // Trigger signal. 10 | In Input 11 | } 12 | 13 | func (c *CoinGate) defaults() { 14 | if c.Prob == nil { 15 | c.Prob = C(0.5) 16 | } 17 | if c.In == nil { 18 | c.In = C(0) 19 | } 20 | } 21 | 22 | // Rate creates a new ugen at a specific rate. 23 | // If rate is an unsupported value this method will cause a runtime panic. 24 | func (c CoinGate) Rate(rate int8) Input { 25 | CheckRate(rate) 26 | (&c).defaults() 27 | return NewInput("CoinGate", rate, 0, 1, c.Prob, c.In) 28 | } 29 | -------------------------------------------------------------------------------- /coingate_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestCoinGate(t *testing.T) { 8 | const defName = "CoinGateTest" 9 | 10 | // arg out=0, prob=0.5; 11 | // var trig; 12 | // trig = CoinGate.kr(prob, Impulse.kr(10)); 13 | // Out.ar(out, 14 | // SinOsc.ar( 15 | // TRand.kr(300.0, 400.0, trig), 0, 0.2 16 | // ) 17 | // ) 18 | compareAndWriteStructure(t, defName, NewSynthdef(defName, func(p Params) Ugen { 19 | var ( 20 | out = p.Add("out", 0) 21 | prob = p.Add("prob", 0.5) 22 | ) 23 | trig := K(CoinGate{ 24 | Prob: prob, 25 | In: K(Impulse{ 26 | Freq: C(10), 27 | }), 28 | }) 29 | sine := A(SinOsc{ 30 | Freq: K(TRand{ 31 | Lo: C(300), 32 | Hi: C(400), 33 | Trig: trig, 34 | }), 35 | }) 36 | return Out{ 37 | Bus: out, 38 | Channels: sine.Mul(C(0.2)), 39 | }.Rate(AR) 40 | })) 41 | } 42 | -------------------------------------------------------------------------------- /control.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // NewControl creates a new Control. 4 | func NewControl(numOutputs int) *Ugen { 5 | outputs := make([]Output, numOutputs) 6 | o := Output(1) 7 | for i := 0; i < numOutputs; i++ { 8 | outputs[i] = o 9 | } 10 | return &Ugen{ 11 | Name: "Control", 12 | Rate: KR, 13 | SpecialIndex: 0, 14 | Outputs: outputs, 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /controlrate.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // ControlRate returns the current control rate of the server. 4 | type ControlRate struct{} 5 | 6 | // Rate creates a new ugen at a specific rate. 7 | // If rate is not IR this method will cause a runtime panic. 8 | func (s ControlRate) Rate(rate int8) Input { 9 | if rate != IR { 10 | panic("ControlRate only supports IR") 11 | } 12 | return NewInput("ControlRate", rate, 0, 1) 13 | } 14 | -------------------------------------------------------------------------------- /conv.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import ( 4 | "math" 5 | ) 6 | 7 | // Midicps converts midi note values to frequency in Hz 8 | func Midicps(note float32) float32 { 9 | return float32(440) * float32(math.Pow(2, float64(note-69)/12.0)) 10 | } 11 | 12 | // Cpsmidi converts frequency in Hz to midi note values. 13 | func Cpsmidi(cps float32) float32 { 14 | return float32((12 * math.Log2(float64(cps)/440)) + 69) 15 | } 16 | 17 | // Octcps converts decimal octaves to cycles per second. 18 | func Octcps(oct float32) float32 { 19 | return Midicps((oct + 1) * 12) 20 | } 21 | 22 | // Cpsoct converts cycles per second to decimal octaves. 23 | func Cpsoct(cps float32) float32 { 24 | return Cpsmidi((cps / 12) - 1) 25 | } 26 | -------------------------------------------------------------------------------- /conv_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestMidicps(t *testing.T) { 8 | val := Midicps(60) 9 | if int(val) != 261 { 10 | t.Fatalf("got %d, expected %d", int(val), 261) 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /cosc.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // COsc is a chorusing wavetable lookup oscillator. 4 | // Produces sum of 2 signals at 5 | // freq +- (beats / 2) 6 | // Due to summing, the peak amplitude is twice that of the wavetable. 7 | type COsc struct { 8 | // BufNum the number of a buffer filled in wavetable format 9 | BufNum Input 10 | // Freq frequency in Hz 11 | Freq Input 12 | // Beats beat frequency in Hz 13 | Beats Input 14 | } 15 | 16 | func (cosc *COsc) defaults() { 17 | if cosc.Freq == nil { 18 | cosc.Freq = C(440) 19 | } 20 | if cosc.Beats == nil { 21 | cosc.Beats = C(0.5) 22 | } 23 | } 24 | 25 | // Rate creates a new ugen at a specific rate. 26 | // If rate is an unsupported value this method will cause 27 | // a runtime panic. 28 | // There will also be a runtime panic if BufNum is nil. 29 | func (cosc COsc) Rate(rate int8) Input { 30 | CheckRate(rate) 31 | if cosc.BufNum == nil { 32 | panic("COsc requires a buffer number") 33 | } 34 | (&cosc).defaults() 35 | return NewInput("COsc", rate, 0, 1, cosc.BufNum, cosc.Freq, cosc.Beats) 36 | } 37 | -------------------------------------------------------------------------------- /cosc_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestCOsc(t *testing.T) { 8 | const defName = "COscTest" 9 | def := NewSynthdef(defName, func(p Params) Ugen { 10 | bus, bufnum := C(0), C(0) 11 | freq, beats := C(200), C(0.7) 12 | gain := C(0.25) 13 | sig := COsc{BufNum: bufnum, Freq: freq, Beats: beats}.Rate(AR) 14 | return Out{bus, sig.Mul(gain)}.Rate(AR) 15 | }) 16 | compareAndWrite(t, defName, def) 17 | } 18 | -------------------------------------------------------------------------------- /crackle.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // Crackle is a noise generator based on a chaotic function. 4 | type Crackle struct { 5 | Chaos Input 6 | } 7 | 8 | func (crackle *Crackle) defaults() { 9 | if crackle.Chaos == nil { 10 | crackle.Chaos = C(1.5) 11 | } 12 | } 13 | 14 | // Rate creates a new ugen at a specific rate. 15 | // If rate is an unsupported value this method will cause 16 | // a runtime panic. 17 | func (crackle Crackle) Rate(rate int8) Input { 18 | CheckRate(rate) 19 | (&crackle).defaults() 20 | return NewInput("Crackle", rate, 0, 1, crackle.Chaos) 21 | } 22 | -------------------------------------------------------------------------------- /crackle_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestCrackle(t *testing.T) { 8 | name := "CrackleTest" 9 | def := NewSynthdef(name, func(params Params) Ugen { 10 | bus, chaos := C(0), Line{C(1.0), C(2.0), C(3), DoNothing}.Rate(KR) 11 | sig := Crackle{chaos}.Rate(AR).MulAdd(C(0.5), C(0.5)) 12 | return Out{bus, sig}.Rate(AR) 13 | 14 | }) 15 | same, err := def.CompareToFile("testdata/CrackleTest.scsyndef") 16 | if err != nil { 17 | t.Fatal(err) 18 | } 19 | if !same { 20 | t.Fatalf("synthdef different from sclang version") 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /dc.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // DC creates a constant amplitude signal. 4 | type DC struct { 5 | In Input 6 | } 7 | 8 | func (dc *DC) defaults() { 9 | if dc.In == nil { 10 | dc.In = C(0) 11 | } 12 | } 13 | 14 | // Rate creates a new ugen at a specific rate. 15 | // If rate is an unsupported value this method will cause a runtime panic. 16 | func (dc DC) Rate(rate int8) Input { 17 | CheckRate(rate) 18 | (&dc).defaults() 19 | return NewInput("DC", rate, 0, 1, dc.In) 20 | } 21 | -------------------------------------------------------------------------------- /dc_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestDC(t *testing.T) { 8 | defName := "DCTest" 9 | def := NewSynthdef(defName, func(p Params) Ugen { 10 | return Out{ 11 | Bus: C(0), 12 | Channels: DC{}.Rate(AR), 13 | }.Rate(AR) 14 | }) 15 | compareAndWrite(t, defName, def) 16 | } 17 | -------------------------------------------------------------------------------- /decay.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // Decay is an exponential decay. 4 | type Decay struct { 5 | // In is the input signal 6 | In Input 7 | // Decay 60dB decay time in seconds 8 | Decay Input 9 | } 10 | 11 | func (decay *Decay) defaults() { 12 | if decay.Decay == nil { 13 | decay.Decay = C(1) 14 | } 15 | } 16 | 17 | // Rate creates a new ugen at a specific rate. 18 | // If an In signal is not provided this method will 19 | // trigger a runtime panic. 20 | func (decay Decay) Rate(rate int8) Input { 21 | CheckRate(rate) 22 | if decay.In == nil { 23 | panic("Decay expects In to not be nil") 24 | } 25 | (&decay).defaults() 26 | return NewInput("Decay", rate, 0, 1, decay.In, decay.Decay) 27 | } 28 | -------------------------------------------------------------------------------- /decay2.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // Decay2 is just like Decay, except it rounds off the attack 4 | // by subtracting one Decay from another. This fixes the sharp 5 | // attacks and clicks that can sometimes occur with Decay. 6 | type Decay2 struct { 7 | // In is the input signal 8 | In Input 9 | // Attack 60dB attack time in seconds 10 | Attack Input 11 | // Decay 60dB decay time in seconds 12 | Decay Input 13 | } 14 | 15 | func (decay2 *Decay2) defaults() { 16 | if decay2.Attack == nil { 17 | decay2.Attack = C(0.01) 18 | } 19 | if decay2.Decay == nil { 20 | decay2.Decay = C(1) 21 | } 22 | } 23 | 24 | // Rate creates a new ugen at a specific rate. 25 | // If an In signal is not provided this method will 26 | // trigger a runtime panic. 27 | func (decay2 Decay2) Rate(rate int8) Input { 28 | CheckRate(rate) 29 | if decay2.In == nil { 30 | panic("Decay2 expects In to not be nil") 31 | } 32 | (&decay2).defaults() 33 | return NewInput("Decay2", rate, 0, 1, decay2.In, decay2.Attack, decay2.Decay) 34 | } 35 | -------------------------------------------------------------------------------- /decay2_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // FIXME 4 | // import ( 5 | // "testing" 6 | // ) 7 | 8 | // func TestDecay2(t *testing.T) { 9 | // defName := "Decay2Test" 10 | // def := NewSynthdef(defName, func(p Params) Ugen { 11 | // bus := C(0) 12 | // line := XLine{Start: C(1), End: C(50), Dur: C(20)}.Rate(KR) 13 | // pulse := Impulse{Freq: line, Phase: C(0.25)}.Rate(AR) 14 | // sig := Decay2{In: pulse, Attack: C(0.01), Decay: C(0.2)}.Rate(AR) 15 | // gain := FSinOsc{Freq: C(600)}.Rate(AR) 16 | // return Out{bus, sig.Mul(gain)}.Rate(AR) 17 | // }) 18 | // compareAndWrite(t, defName, def) 19 | // } 20 | -------------------------------------------------------------------------------- /defs.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import ( 4 | "errors" 5 | "sync" 6 | ) 7 | 8 | // Synthdefs is a map of synthdefs. 9 | var Synthdefs = map[string]*Synthdef{} 10 | 11 | var synthdefsMu sync.RWMutex 12 | 13 | // RegisterSynthdef registers a synthdef with this package. 14 | // It returns an error if a synthdef is already registered with the provided name. 15 | func RegisterSynthdef(name string, f UgenFunc) error { 16 | synthdefsMu.Lock() 17 | defer synthdefsMu.Unlock() 18 | if _, ok := Synthdefs[name]; ok { 19 | return errors.New("synthdef already registered: " + name) 20 | } 21 | Synthdefs[name] = NewSynthdef(name, f) 22 | return nil 23 | } 24 | -------------------------------------------------------------------------------- /detect_silence.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // DetectSilence evaluates Done when input falls below a certain threshold. 4 | type DetectSilence struct { 5 | In Input // The input signal. 6 | Amp Input // Amplitude threshold. 7 | Time Input // The minimum duration for which amplitude must be below Amp before Done triggers. 8 | Done int // UGen done-action. 9 | } 10 | 11 | func (ds *DetectSilence) defaults() { 12 | if ds.Amp == nil { 13 | ds.Amp = C(0.0001) 14 | } 15 | if ds.Time == nil { 16 | ds.Time = C(0.1) 17 | } 18 | } 19 | 20 | // Rate creates a new ugen at a specific rate. 21 | // If rate is an unsupported value this method will cause a runtime panic. 22 | func (ds DetectSilence) Rate(rate int8) Input { 23 | if ds.In == nil { 24 | panic("DetectSilence expects In to not be nil") 25 | } 26 | CheckRate(rate) 27 | (&ds).defaults() 28 | return NewInput("DetectSilence", rate, 0, 1, ds.In, ds.Amp, ds.Time, C(float32(ds.Done))) 29 | } 30 | -------------------------------------------------------------------------------- /detectsilence_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import "testing" 4 | 5 | func TestDetectSilence(t *testing.T) { 6 | // TODO: need a way to compare synthdef blobs where the order of the constants doesn't matter 7 | t.SkipNow() 8 | 9 | const name = "DetectSilence" 10 | 11 | def := NewSynthdef(name, func(params Params) Ugen { 12 | out := params.Add("out", 0) 13 | 14 | noise := LFDNoise{ 15 | Interpolation: InterpolationCubic, 16 | Freq: C(8), 17 | }.Rate(KR).Max(C(0)) 18 | 19 | sine := SinOsc{ 20 | Freq: Rand{Lo: C(400), Hi: C(700)}.Rate(AR), 21 | Phase: C(0), 22 | }.Rate(AR).Mul(noise).SoftClip().Mul(C(0.3)) 23 | 24 | return Out{ 25 | Bus: out, 26 | Channels: DetectSilence{ 27 | In: sine, 28 | Done: FreeEnclosing, 29 | }.Rate(AR), 30 | }.Rate(AR) 31 | }) 32 | compareAndWrite(t, name, def) 33 | } 34 | -------------------------------------------------------------------------------- /doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Package sc is a SuperCollider client for Go. 3 | */ 4 | package sc 5 | -------------------------------------------------------------------------------- /dust.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // Dust generates random impulses from 0 to +1 4 | type Dust struct { 5 | // Density is the average number of impulses per second 6 | Density Input 7 | } 8 | 9 | func (dust *Dust) defaults() { 10 | if dust.Density == nil { 11 | dust.Density = C(0) 12 | } 13 | } 14 | 15 | // Rate creates a new ugen at a specific rate. 16 | // If rate is an unsupported value this method will cause a runtime panic. 17 | func (dust Dust) Rate(rate int8) Input { 18 | CheckRate(rate) 19 | (&dust).defaults() 20 | return NewInput("Dust", rate, 0, 1, dust.Density) 21 | } 22 | -------------------------------------------------------------------------------- /dust2.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // Dust2 generates random impulses from -1 to +1 4 | type Dust2 struct { 5 | // Density is the average number of impulses per second 6 | Density Input 7 | } 8 | 9 | func (dust2 *Dust2) defaults() { 10 | if dust2.Density == nil { 11 | dust2.Density = C(0) 12 | } 13 | } 14 | 15 | // Rate creates a new ugen at a specific rate. 16 | // If rate is an unsupported value this method will cause 17 | // a runtime panic. 18 | func (dust2 Dust2) Rate(rate int8) Input { 19 | CheckRate(rate) 20 | (&dust2).defaults() 21 | return NewInput("Dust2", rate, 0, 1, dust2.Density) 22 | } 23 | -------------------------------------------------------------------------------- /dust2_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // import ( 4 | // "testing" 5 | // ) 6 | 7 | // func TestDust2(t *testing.T) { 8 | // defName := "Dust2Test" 9 | // def := NewSynthdef(defName, func(p Params) Ugen { 10 | // // Out.ar(0, Dust2.ar(XLine.kr(20000, 2, 10), 0.5)); 11 | // bus, line := C(0), XLine{Start: C(20000), End: C(2), Dur: C(10)}.Rate(KR) 12 | // gain, sig := C(0.5), Dust2{Density: line}.Rate(AR) 13 | // return Out{bus, sig.Mul(gain)}.Rate(AR) 14 | // }) 15 | // compareAndWrite(t, defName, def) 16 | // } 17 | -------------------------------------------------------------------------------- /dust_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestDust(t *testing.T) { 8 | const defName = "DustTest" 9 | 10 | compareAndWrite(t, defName, NewSynthdef(defName, func(p Params) Ugen { 11 | // Out.ar(0, Dust.ar(XLine.kr(20000, 2, 10), 0.5)); 12 | bus, line := C(0), XLine{Start: C(20000), End: C(2), Dur: C(10)}.Rate(KR) 13 | gain, sig := C(0.5), Dust{Density: line}.Rate(AR) 14 | return Out{Bus: bus, Channels: sig.Mul(gain)}.Rate(AR) 15 | })) 16 | } 17 | -------------------------------------------------------------------------------- /envelope.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // Envelope is an interface that should be implemented by 4 | // types that define envelopes for EnvGen. 5 | type Envelope interface { 6 | // InputsArray provides EnvGen with the data it needs 7 | // to get a list of inputs. 8 | Inputs() []Input 9 | } 10 | -------------------------------------------------------------------------------- /envgen_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestEnvGen(t *testing.T) { 8 | def := NewSynthdef("EnvgenTest", func(p Params) Ugen { 9 | bus := C(0) 10 | attack, release := C(0.01), C(1) 11 | level, curvature := C(1), C(-4) 12 | perc := EnvPerc{attack, release, level, curvature} 13 | gate, levelScale, levelBias, timeScale := C(1), C(1), C(0), C(1) 14 | ampEnv := EnvGen{perc, gate, levelScale, levelBias, timeScale, FreeEnclosing}.Rate(KR) 15 | noise := PinkNoise{}.Rate(AR).Mul(ampEnv) 16 | return Out{bus, noise}.Rate(AR) 17 | }) 18 | same, err := def.CompareToFile("testdata/EnvgenTest.scsyndef") 19 | if err != nil { 20 | t.Fatal(err) 21 | } 22 | if !same { 23 | t.Fatalf("synthdef different from sclang version") 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /fft_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestFFT(t *testing.T) { 8 | const defName = "FFTTest" 9 | 10 | // var in, chain; 11 | // in = WhiteNoise.ar(0.2); 12 | // chain = FFT(LocalBuf(2048), in); 13 | // chain = PV_BrickWall(chain, SinOsc.kr(0.1)); 14 | // Out.ar(0, IFFT(chain)); 15 | compareAndWriteStructure(t, defName, NewSynthdef(defName, func(p Params) Ugen { 16 | chain := PVBrickWall{ 17 | Buffer: FFT{ 18 | Buffer: LocalBuf{NumFrames: C(2048)}.Rate(AR), 19 | In: WhiteNoise{}.Rate(AR).Mul(C(0.2)), 20 | }.Rate(AR), 21 | Wipe: SinOsc{Freq: C(0.1)}.Rate(KR), 22 | }.Rate(AR) 23 | 24 | return Out{ 25 | Bus: C(0), 26 | Channels: IFFT{Buffer: chain}.Rate(AR), 27 | }.Rate(AR) 28 | })) 29 | } 30 | -------------------------------------------------------------------------------- /foo_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import "testing" 4 | 5 | func TestFoo(t *testing.T) { 6 | name := "foo" 7 | def := NewSynthdef(name, func(p Params) Ugen { 8 | bus := C(0) 9 | blip := Blip{}.Rate(AR) 10 | sine := SinOsc{}.Rate(AR) 11 | return Out{bus, sine.Mul(blip)}.Rate(AR) 12 | }) 13 | same, err := def.CompareToFile("testdata/foo.scsyndef") 14 | if err != nil { 15 | t.Fatal(err) 16 | } 17 | if !same { 18 | t.Fatalf("synthdefs were different") 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /formant_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestFormant(t *testing.T) { 8 | defName := "FormantTest" 9 | 10 | // Out.ar(0, Formant.ar(XLine.kr(400,1000, 8), 2000, 800, 0.125)); 11 | def := NewSynthdef(defName, func(p Params) Ugen { 12 | line := XLine{ 13 | Start: C(400), 14 | End: C(1000), 15 | Dur: C(8), 16 | }.Rate(KR) 17 | 18 | return Out{ 19 | Bus: C(0), 20 | Channels: Formant{ 21 | FundFreq: line, 22 | FormantFreq: C(2000), 23 | BWFreq: C(800), 24 | }.Rate(AR).Mul(C(0.125)), 25 | }.Rate(AR) 26 | }) 27 | compareAndWriteStructure(t, defName, def) 28 | } 29 | -------------------------------------------------------------------------------- /formlet_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestFormlet(t *testing.T) { 8 | defName := "FormletTest" 9 | def := NewSynthdef(defName, func(p Params) Ugen { 10 | // var in = Blip.ar(SinOsc.kr(5, 0, 20, 300), 1000, 0.1); 11 | // Out.ar(0, Formlet.ar(in, XLine.kr(1500, 700, 8), 0.005, 0.4)); 12 | bus, sine := C(0), SinOsc{Freq: C(5)}.Rate(KR).MulAdd(C(20), C(300)) 13 | blip := Blip{Freq: sine, Harm: C(1000)}.Rate(AR).Mul(C(0.1)) 14 | line := XLine{Start: C(1500), End: C(700), Dur: C(8)}.Rate(KR) 15 | sig := Formlet{ 16 | In: blip, 17 | Freq: line, 18 | AttackTime: C(0.005), 19 | DecayTime: C(0.4), 20 | }.Rate(AR) 21 | return Out{bus, sig}.Rate(AR) 22 | }) 23 | compareAndWrite(t, defName, def) 24 | } 25 | -------------------------------------------------------------------------------- /freeverb.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // FreeVerb reverb implemented with faust 4 | type FreeVerb struct { 5 | // In the input signal 6 | In Input 7 | // Mix dry/wet balance [0, 1] 8 | Mix Input 9 | // Room room size [0, 1] 10 | Room Input 11 | // Damp high frequency damping [0, 1] 12 | Damp Input 13 | } 14 | 15 | func (fv *FreeVerb) defaults() { 16 | if fv.Mix == nil { 17 | fv.Mix = C(0.33) 18 | } 19 | if fv.Room == nil { 20 | fv.Room = C(0.5) 21 | } 22 | if fv.Damp == nil { 23 | fv.Damp = C(0.5) 24 | } 25 | } 26 | 27 | // Rate creates a new ugen at a specific rate. 28 | // If an In signal is not provided this method will 29 | // trigger a runtime panic. 30 | func (fv FreeVerb) Rate(rate int8) Input { 31 | CheckRate(rate) 32 | if fv.In == nil { 33 | panic("FreeVerb expects In to not be nil") 34 | } 35 | (&fv).defaults() 36 | return NewInput("FreeVerb", rate, 0, 1, fv.In, fv.Mix, fv.Room, fv.Damp) 37 | } 38 | -------------------------------------------------------------------------------- /fsinosc.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // FSinOsc is a very fast sine wave generator implemented using a 4 | // ringing filter. This generates a much cleaner sine wave than a 5 | // table lookup oscillator and is a lot faster. However, the 6 | // amplitude of the wave will vary with frequency. Generally the 7 | // amplitude will go down as you raise the frequency and go up 8 | // as you lower the frequency. 9 | type FSinOsc struct { 10 | // Freq is frequency in Hz 11 | Freq Input 12 | // Phase is the initial phase offset 13 | Phase Input 14 | } 15 | 16 | func (fso *FSinOsc) defaults() { 17 | if fso.Freq == nil { 18 | fso.Freq = C(440) 19 | } 20 | if fso.Phase == nil { 21 | fso.Phase = C(0) 22 | } 23 | } 24 | 25 | // Rate creates a new ugen at a specific rate. 26 | // If rate is an unsupported value this method will cause 27 | // a runtime panic. 28 | func (fso FSinOsc) Rate(rate int8) Input { 29 | CheckRate(rate) 30 | (&fso).defaults() 31 | return NewInput("FSinOsc", rate, 0, 1, fso.Freq, fso.Phase) 32 | } 33 | -------------------------------------------------------------------------------- /fsinosc_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestFSinOsc(t *testing.T) { 8 | def := NewSynthdef("FSinOscExample", func(p Params) Ugen { 9 | line := XLine{C(4), C(401), C(8), 0}.Rate(KR) 10 | sin1 := FSinOsc{line, C(0)}.Rate(AR).MulAdd(C(200), C(800)) 11 | sin2 := FSinOsc{Freq: sin1}.Rate(AR).Mul(C(0.2)) 12 | bus := C(0) 13 | return Out{bus, sin2}.Rate(AR) 14 | }) 15 | same, err := def.CompareToFile("testdata/FSinOscExample.scsyndef") 16 | if err != nil { 17 | t.Fatal(err) 18 | } 19 | if !same { 20 | t.Fatalf("synthdef different from sclang version") 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /gate.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // Gate allows an input signal value to pass when gate is 4 | // positive, otherwise holds last value. 5 | type Gate struct { 6 | // In is the input signal. 7 | In Input 8 | // Trig is the rigger signal. The output is held fixed when this is non-positive. 9 | Trig Input 10 | } 11 | 12 | func (gate *Gate) defaults() { 13 | if gate.Trig == nil { 14 | gate.Trig = C(0) 15 | } 16 | } 17 | 18 | // Rate creates a new ugen at a specific rate. 19 | // If an In signal is not provided this method will 20 | // trigger a runtime panic. 21 | func (gate Gate) Rate(rate int8) Input { 22 | CheckRate(rate) 23 | if gate.In == nil { 24 | panic("Gate expects In to not be nil") 25 | } 26 | (&gate).defaults() 27 | return NewInput("Gate", rate, 0, 1, gate.In, gate.Trig) 28 | } 29 | -------------------------------------------------------------------------------- /gate_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestGate(t *testing.T) { 8 | defName := "GateTest" 9 | def := NewSynthdef(defName, func(p Params) Ugen { 10 | // var noise = WhiteNoise.kr(1, 0); 11 | // var pulse = LFPulse.kr(1.333, 0.5); 12 | // Out.ar(0, Gate.ar(noise, pulse)); 13 | bus, noise := C(0), WhiteNoise{}.Rate(KR) 14 | pulse := LFPulse{Freq: C(1.333), IPhase: C(0.5)}.Rate(KR) 15 | sig := Gate{In: noise, Trig: pulse}.Rate(AR) 16 | return Out{bus, sig}.Rate(AR) 17 | }) 18 | compareAndWrite(t, defName, def) 19 | } 20 | -------------------------------------------------------------------------------- /gendy1_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestGendy1(t *testing.T) { 8 | const defName = "Gendy1Test" 9 | 10 | // Out.ar(0, Pan2.ar(Gendy1.ar)); 11 | compareAndWriteStructure(t, defName, NewSynthdef(defName, func(p Params) Ugen { 12 | return Out{ 13 | Bus: C(0), 14 | Channels: A(Pan2{ 15 | In: A(Gendy1{}), 16 | }), 17 | }.Rate(AR) 18 | })) 19 | } 20 | -------------------------------------------------------------------------------- /gendy2.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // Gendy2 is a dynamic stochastic synthesis generator. 4 | // See Gendy1 for background. 5 | // This variant of GENDYN is closer to that presented in Hoffmann, 6 | // Peter. (2000) The New GENDYN Program. Computer Music Journal 24:2, pp 31-38. 7 | type Gendy2 struct { 8 | Gendy1 9 | 10 | // Parameter for Lehmer random number generator perturbed by Xenakis as in ((old*a)+c)%1.0 11 | A Input 12 | 13 | // Parameter for Lehmer random number generator perturbed by Xenakis. 14 | C Input 15 | } 16 | 17 | func (g *Gendy2) defaults() { 18 | (&g.Gendy1).defaults() 19 | 20 | if g.A == nil { 21 | g.A = C(1.17) 22 | } 23 | if g.C == nil { 24 | g.C = C(0.31) 25 | } 26 | } 27 | 28 | // Rate creates a new ugen at a specific rate. 29 | // If rate is an unsupported value this method will cause a runtime panic. 30 | func (g Gendy2) Rate(rate int8) Input { 31 | CheckRate(rate) 32 | g.rate = rate 33 | (&g).defaults() 34 | return NewInput("Gendy2", rate, 0, 1, g.AmpDist, g.DurDist, g.ADParam, g.DDParam, g.MinFreq, g.MaxFreq, g.AmpScale, g.DurScale, g.InitCPs, g.KNum, g.A, g.C) 35 | } 36 | -------------------------------------------------------------------------------- /gendy2_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestGendy2(t *testing.T) { 8 | const defName = "Gendy2Test" 9 | 10 | // Out.ar(0, Pan2.ar(Gendy2.ar)); 11 | compareAndWriteStructure(t, defName, NewSynthdef(defName, func(p Params) Ugen { 12 | return Out{ 13 | Bus: C(0), 14 | Channels: A(Pan2{ 15 | In: A(Gendy2{}), 16 | }), 17 | }.Rate(AR) 18 | })) 19 | } 20 | -------------------------------------------------------------------------------- /gendy3_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestGendy3(t *testing.T) { 8 | const defName = "Gendy3Test" 9 | 10 | // Out.ar(0, Pan2.ar(Gendy3.ar)); 11 | compareAndWriteStructure(t, defName, NewSynthdef(defName, func(p Params) Ugen { 12 | return Out{ 13 | Bus: C(0), 14 | Channels: A(Pan2{ 15 | In: A(Gendy3{}), 16 | }), 17 | }.Rate(AR) 18 | })) 19 | } 20 | -------------------------------------------------------------------------------- /grainbuf_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestGrainBuf(t *testing.T) { 8 | defName := "GrainBufTest" 9 | def := NewSynthdef(defName, func(p Params) Ugen { 10 | bus, bufnum := C(0), C(0) 11 | channels := 1 12 | sig := GrainBuf{ 13 | NumChannels: channels, 14 | BufNum: bufnum, 15 | }.Rate(AR) 16 | return Out{bus, sig}.Rate(AR) 17 | }) 18 | compareAndWrite(t, defName, def) 19 | } 20 | -------------------------------------------------------------------------------- /graynoise.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // GrayNoise generates noise which results from flipping 4 | // random bits in a word. This type of noise has a high 5 | // RMS level relative to its peak to peak level. 6 | // The spectrum is emphasized towards lower frequencies. 7 | type GrayNoise struct { 8 | } 9 | 10 | // Rate creates a new ugen at a specific rate. 11 | // If rate is an unsupported value this method will cause 12 | // a runtime panic. 13 | func (gn GrayNoise) Rate(rate int8) Input { 14 | CheckRate(rate) 15 | return NewInput("GrayNoise", rate, 0, 1) 16 | } 17 | -------------------------------------------------------------------------------- /gverb_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import "testing" 4 | 5 | func TestGVerb(t *testing.T) { 6 | name := "GVerbExample" 7 | def := NewSynthdef(name, func(params Params) Ugen { 8 | bus, In := C(0), SinOsc{Freq: C(220)}.Rate(AR) 9 | src := GVerb{In: In}.Rate(AR) 10 | return Out{bus, src}.Rate(AR) 11 | }) 12 | same, err := def.CompareToFile("testdata/GVerbExample.scsyndef") 13 | if err != nil { 14 | t.Fatal(err) 15 | } 16 | if !same { 17 | t.Fatalf("synthdef different from sclang version") 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /hasher.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // Hasher returns a unique output value from -1 to +1 for each input value 4 | // according to a hash function. 5 | // The same input value will always produce the same output value. 6 | // The input need not be in the range -1 to +1. 7 | type Hasher struct { 8 | In Input 9 | } 10 | 11 | // Rate creates a new ugen at a specific rate. 12 | // If rate is an unsupported value this method will cause a runtime panic. 13 | // If the input signal is nil then this method will cause a runtime panic. 14 | func (hasher Hasher) Rate(rate int8) Input { 15 | CheckRate(rate) 16 | if hasher.In == nil { 17 | panic("Hasher requires an input signal") 18 | } 19 | return NewInput("Hasher", rate, 0, 1, hasher.In) 20 | } 21 | -------------------------------------------------------------------------------- /hasher_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestHasher(t *testing.T) { 8 | defName := "HasherTest" 9 | 10 | def := NewSynthdef(defName, func(p Params) Ugen { 11 | return Out{ 12 | Bus: C(0), 13 | Channels: SinOsc{ 14 | Freq: Hasher{ 15 | In: MouseX{Min: C(0), Max: C(10)}.Rate(KR), 16 | }.Rate(KR).MulAdd(C(300), C(500)), 17 | }.Rate(AR), 18 | }.Rate(AR) 19 | }) 20 | compareAndWrite(t, defName, def) 21 | } 22 | -------------------------------------------------------------------------------- /hpf.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // HPF is a 2nd order Butterworth highpass filter. 4 | type HPF struct { 5 | // In is the input signal 6 | In Input 7 | // Freq cutoff in Hz 8 | Freq Input 9 | } 10 | 11 | func (hpf *HPF) defaults() { 12 | if hpf.Freq == nil { 13 | hpf.Freq = C(440) 14 | } 15 | } 16 | 17 | // Rate creates a new ugen at a specific rate. 18 | // If rate is an unsupported value this method will cause 19 | // a runtime panic. 20 | func (hpf HPF) Rate(rate int8) Input { 21 | if hpf.In == nil { 22 | panic("HPF expects In to not be nil") 23 | } 24 | CheckRate(rate) 25 | (&hpf).defaults() 26 | return NewInput("HPF", rate, 0, 1, hpf.In, hpf.Freq) 27 | } 28 | -------------------------------------------------------------------------------- /hpf_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import "testing" 4 | 5 | func TestHPF(t *testing.T) { 6 | name := "HPFExample" 7 | def := NewSynthdef(name, func(params Params) Ugen { 8 | bus, In := C(0), SinOsc{Freq: C(220)}.Rate(AR) 9 | src := HPF{In: In}.Rate(AR) 10 | return Out{bus, src}.Rate(AR) 11 | }) 12 | same, err := def.CompareToFile("testdata/HPFExample.scsyndef") 13 | if err != nil { 14 | t.Fatal(err) 15 | } 16 | if !same { 17 | t.Fatalf("synthdef different from sclang version") 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /impulse.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // Impulse non-band-limited single-sample impulses 4 | type Impulse struct { 5 | // Freq frequency in Hz 6 | Freq Input 7 | // Phase offset in cycles [0, 1] 8 | Phase Input 9 | } 10 | 11 | func (impulse *Impulse) defaults() { 12 | if impulse.Freq == nil { 13 | impulse.Freq = C(440) 14 | } 15 | if impulse.Phase == nil { 16 | impulse.Phase = C(0) 17 | } 18 | } 19 | 20 | // Rate creates a new ugen at a specific rate. 21 | // If rate is an unsupported value this method will cause 22 | // a runtime panic. 23 | func (impulse Impulse) Rate(rate int8) Input { 24 | CheckRate(rate) 25 | (&impulse).defaults() 26 | return NewInput("Impulse", rate, 0, 1, impulse.Freq, impulse.Phase) 27 | } 28 | -------------------------------------------------------------------------------- /impulse_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestImpulse(t *testing.T) { 8 | def := NewSynthdef("ImpulseExample", func(p Params) Ugen { 9 | start, end, dur, done := C(800), C(100), C(5), 0 10 | freq := XLine{start, end, dur, done}.Rate(KR) 11 | bus, phase, gain := C(0), C(0), C(0.5) 12 | sig := Impulse{freq, phase}.Rate(AR).Mul(gain) 13 | return Out{bus, sig}.Rate(AR) 14 | }) 15 | same, err := def.CompareToFile("testdata/ImpulseExample.scsyndef") 16 | if err != nil { 17 | t.Fatal(err) 18 | } 19 | if !same { 20 | t.Fatalf("synthdef different from sclang version") 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /in.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // In reads signals from busses. 4 | type In struct { 5 | NumChannels int 6 | Bus Input 7 | } 8 | 9 | func (in *In) defaults() { 10 | if in.Bus == nil { 11 | in.Bus = C(0) 12 | } 13 | if in.NumChannels == 0 { 14 | in.NumChannels = 1 15 | } 16 | } 17 | 18 | // Rate returns an Input at the specified rate. 19 | // This method panics if rate is not a supported value. 20 | func (in In) Rate(rate int8) Input { 21 | CheckRate(rate) 22 | (&in).defaults() 23 | 24 | var ( 25 | uin = NewInput("In", rate, 0, in.NumChannels, in.Bus) 26 | ins = make([]Input, in.NumChannels) 27 | ) 28 | for i := range ins { 29 | ins[i] = uin 30 | } 31 | return Multi(ins...) 32 | } 33 | 34 | func defIn(params Params) Ugen { 35 | var ( 36 | in = params.Add("in", 0) 37 | out = params.Add("out", 0) 38 | ) 39 | return Out{ 40 | Bus: out, 41 | Channels: In{ 42 | NumChannels: 1, 43 | Bus: in, 44 | }.Rate(AR), 45 | }.Rate(AR) 46 | } 47 | -------------------------------------------------------------------------------- /in_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import ( 4 | "os" 5 | "testing" 6 | ) 7 | 8 | func TestIn(t *testing.T) { 9 | const name = "InTest" 10 | 11 | def := NewSynthdef(name, func(params Params) Ugen { 12 | var ( 13 | out = params.Add("out", 0) 14 | in = params.Add("in", 0) 15 | ) 16 | return Out{ 17 | Bus: out, 18 | Channels: SinOsc{ 19 | Freq: In{ 20 | Bus: in, 21 | NumChannels: 2, 22 | }.Rate(KR), 23 | }.Rate(AR).Mul(C(0.1)), 24 | }.Rate(AR) 25 | }) 26 | f, err := os.Create("testdata/" + name + ".gosyndef") 27 | if err != nil { 28 | t.Fatal(err) 29 | } 30 | if err := def.Write(f); err != nil { 31 | t.Fatal(err) 32 | } 33 | same, err := def.CompareToFile("testdata/" + name + ".scsyndef") 34 | if err != nil { 35 | t.Fatal(err) 36 | } 37 | if !same { 38 | t.Fatalf("synthdef different from sclang version") 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /init.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import ( 4 | "math/rand" 5 | "time" 6 | ) 7 | 8 | func init() { 9 | rand.Seed(time.Now().UnixNano()) 10 | } 11 | -------------------------------------------------------------------------------- /input_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import ( 4 | "reflect" 5 | "testing" 6 | ) 7 | 8 | func TestExpandInputs(t *testing.T) { 9 | a := []Input{Multi(C(1), C(2), C(3)), Multi(C(4), C(5))} 10 | b := expandInputs(a...) 11 | // should be [ [1,4], [2,5], [3,4] ] 12 | expect := [][]Input{ 13 | {C(1), C(4)}, 14 | {C(2), C(5)}, 15 | {C(3), C(4)}, 16 | } 17 | if !reflect.DeepEqual(expect, b) { 18 | t.Fatalf("expandInputs returned %v", b) 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /integrator.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // Integrator integrates an input signal with a leak. 4 | // The formula used is 5 | // 6 | // out(0) = in(0) + (coef * out(-1)) 7 | type Integrator struct { 8 | // In is the input signal 9 | In Input 10 | // Coef is the leak coefficient 11 | Coef Input 12 | } 13 | 14 | func (integrator *Integrator) defaults() { 15 | if integrator.Coef == nil { 16 | integrator.Coef = C(1) 17 | } 18 | } 19 | 20 | // Rate creates a new ugen at a specific rate. 21 | // If an In signal is not provided this method will 22 | // trigger a runtime panic. 23 | func (integrator Integrator) Rate(rate int8) Input { 24 | CheckRate(rate) 25 | if integrator.In == nil { 26 | panic("Integrator expects In to not be nil") 27 | } 28 | (&integrator).defaults() 29 | return NewInput("Integrator", rate, 0, 1, integrator.In, integrator.Coef) 30 | } 31 | -------------------------------------------------------------------------------- /integrator_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import "testing" 4 | 5 | func TestIntegrator(t *testing.T) { 6 | def := NewSynthdef("IntegratorExample", func(p Params) Ugen { 7 | pulse := LFPulse{C(375), C(0.2), C(0.1)}.Rate(AR) 8 | x := MouseX{C(0.01), C(0.999), C(1), C(0.2)}.Rate(KR) 9 | sig := Integrator{pulse, x}.Rate(AR) 10 | return Out{C(0), sig}.Rate(AR) 11 | }) 12 | same, err := def.CompareToFile("testdata/IntegratorExample.scsyndef") 13 | if err != nil { 14 | t.Fatal(err) 15 | } 16 | if !same { 17 | t.Fatalf("synthdef different from sclang version") 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /interpolation.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // Interpolation is a smoothing strategy for delay lines. 4 | // Possible values are 5 | // - InterpolationNone 6 | // - InterpolationLinear 7 | // - InterpolationCubic 8 | type Interpolation int 9 | 10 | // Interpolation types. 11 | const ( 12 | InterpolationNone Interpolation = iota 13 | InterpolationLinear 14 | InterpolationCubic 15 | ) 16 | -------------------------------------------------------------------------------- /kalimba_mono.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/kalimba_mono.wav -------------------------------------------------------------------------------- /klang_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestKlang(t *testing.T) { 8 | const defName = "KlangTest" 9 | 10 | // var sig = Pan2.ar( 11 | // Klang.ar(`[ Array.rand(12, 200.0, 2000.0), nil, nil ], 1, 0), 12 | // 1.0.rand 13 | // ); 14 | // Out.ar(0, sig * EnvGen.kr(Env.sine(4), 1, 0.02, doneAction: 2); 15 | compareAndWriteStructure(t, defName, NewSynthdef(defName, func(p Params) Ugen { 16 | freqs := []Input{ 17 | C(561.384644), 18 | C(1043.168701), 19 | C(237.107315), 20 | C(303.264008), 21 | C(927.150208), 22 | C(833.526123), 23 | C(509.927826), 24 | C(946.380005), 25 | C(752.409973), 26 | C(525.558716), 27 | C(1111.182129), 28 | C(715.820068), 29 | } 30 | sig := A(Pan2{ 31 | In: A(Klang{ 32 | Spec: ArraySpec{freqs, nil, nil}, 33 | }), 34 | Pos: C(0.307131), 35 | }) 36 | env := K(EnvGen{ 37 | Env: EnvSine{Dur: C(4)}, 38 | Gate: C(1), 39 | LevelScale: C(0.02), 40 | Done: FreeEnclosing, 41 | }) 42 | return Out{ 43 | Bus: C(0), 44 | Channels: sig.Mul(env), 45 | }.Rate(AR) 46 | })) 47 | } 48 | -------------------------------------------------------------------------------- /klank_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestKlank1(t *testing.T) { 8 | var defName = "KlankTest1" 9 | 10 | // Out.ar(0, Klank.ar(`[[800, 1071, 1353, 1723], nil, [1, 1, 1, 1]], PinkNoise.ar(0.007))); 11 | compareAndWriteStructure(t, defName, NewSynthdef(defName, func(p Params) Ugen { 12 | return Out{ 13 | Bus: C(0), 14 | Channels: A(Klank{ 15 | Spec: ArraySpec{ 16 | { 17 | C(800), 18 | C(1071), 19 | C(1353), 20 | C(1723), 21 | }, 22 | nil, 23 | Fill(4, C(1)), 24 | }, 25 | In: PinkNoise{}.Rate(AR).Mul(C(0.007)), 26 | }), 27 | }.Rate(AR) 28 | })) 29 | } 30 | -------------------------------------------------------------------------------- /lag.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // Lag is essentially the same as OnePole except that instead of 4 | // supplying the coefficient directly, it is calculated from a 60 dB lag time. 5 | // This is the time required for the filter to converge to within 0.01% of a value. 6 | // This is useful for smoothing out control signals. 7 | type Lag struct { 8 | // In is the input signal. 9 | In Input 10 | 11 | // LagTime is the 60 dB lag time in seconds. 12 | LagTime Input 13 | } 14 | 15 | func (l *Lag) defaults() { 16 | if l.LagTime == nil { 17 | l.LagTime = C(0.1) 18 | } 19 | } 20 | 21 | // Rate creates a new ugen at a specific rate. 22 | // If rate is an unsupported value this method will cause a runtime panic. 23 | // If the input signal is nil this method will panic. 24 | func (l Lag) Rate(rate int8) Input { 25 | CheckRate(rate) 26 | if l.In == nil { 27 | panic("Lag requires an input signal") 28 | } 29 | return NewInput("Lag", rate, 0, 1, l.In, l.LagTime) 30 | } 31 | -------------------------------------------------------------------------------- /lag_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestLag(t *testing.T) { 8 | defName := "LagTest" 9 | 10 | // Out.ar(0, SinOsc.ar( 11 | // Lag.kr( 12 | // LFPulse.kr(4, 0, 0.5, 50, 400), 13 | // Line.kr(0, 1, 15) 14 | // ), 15 | // 0, 16 | // 0.3 17 | // )); 18 | compareAndWriteStructure(t, defName, NewSynthdef(defName, func(p Params) Ugen { 19 | pulse := K(LFPulse{ 20 | Freq: C(4), 21 | IPhase: C(0), 22 | Width: C(0.5), 23 | }) 24 | line := K(Line{ 25 | Start: C(0), 26 | End: C(1), 27 | Dur: C(15), 28 | }) 29 | return Out{ 30 | Bus: C(0), 31 | Channels: A(SinOsc{ 32 | Freq: K(Lag{ 33 | In: pulse.MulAdd(C(50), C(400)), 34 | LagTime: line, 35 | }), 36 | }).Mul(C(0.3)), 37 | }.Rate(AR) 38 | })) 39 | } 40 | -------------------------------------------------------------------------------- /latch.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // Latch is a sample and hold. 4 | // It holds input signal value when triggered. 5 | // Latch will output 0 until it receives its first trigger. 6 | type Latch struct { 7 | // In is the input signal. 8 | In Input 9 | 10 | // Trig can be any signal. 11 | // A trigger happens when the signal changes from non-positive to positive. 12 | Trig Input 13 | } 14 | 15 | // Rate creates a new ugen at a specific rate. 16 | // If rate is an unsupported value this method will cause a runtime panic. 17 | // If the input signal is nil this method will panic. 18 | // If the trig signal is nil this method will panic. 19 | func (l Latch) Rate(rate int8) Input { 20 | CheckRate(rate) 21 | if l.In == nil { 22 | panic("Latch requires an input signal") 23 | } 24 | if l.Trig == nil { 25 | panic("Latch requires an trig signal") 26 | } 27 | return NewInput("Latch", rate, 0, 1, l.In, l.Trig) 28 | } 29 | -------------------------------------------------------------------------------- /latch_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestLatch(t *testing.T) { 8 | defName := "LatchTest" 9 | 10 | // Out.ar(0, Blip.ar(Latch.ar(WhiteNoise.ar, Impulse.ar(9)) * 400 + 500, 4, 0.2)); 11 | compareAndWriteStructure(t, defName, NewSynthdef(defName, func(p Params) Ugen { 12 | latch := Latch{ 13 | In: WhiteNoise{}.Rate(AR), 14 | Trig: Impulse{Freq: C(9)}.Rate(AR), 15 | }.Rate(AR) 16 | 17 | return Out{ 18 | Bus: C(0), 19 | Channels: Blip{ 20 | Freq: latch.MulAdd(C(400), C(500)), 21 | Harm: C(4), 22 | }.Rate(AR).Mul(C(0.2)), 23 | }.Rate(AR) 24 | })) 25 | } 26 | -------------------------------------------------------------------------------- /leakdc.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // LeakDC removes DC offset from a signal. 4 | type LeakDC struct { 5 | // In is the input signal. 6 | In Input 7 | 8 | // Coeff is the leak coefficient. 9 | Coeff Input 10 | 11 | rate int8 12 | } 13 | 14 | func (ldc *LeakDC) defaults() { 15 | if ldc.Coeff == nil { 16 | switch ldc.rate { 17 | case AR: 18 | ldc.Coeff = C(0.995) 19 | default: 20 | ldc.Coeff = C(0.9) 21 | } 22 | } 23 | } 24 | 25 | // Rate creates a new ugen at a specific rate. 26 | // If rate is an unsupported value this method will cause a runtime panic. 27 | // If the input signal is nil this method will cause a runtime panic. 28 | func (ldc LeakDC) Rate(rate int8) Input { 29 | CheckRate(rate) 30 | if ldc.In == nil { 31 | panic("LeakDC requires an input signal") 32 | } 33 | ldc.rate = rate 34 | (&ldc).defaults() 35 | return NewInput("LeakDC", rate, 0, 1, ldc.In, ldc.Coeff) 36 | } 37 | -------------------------------------------------------------------------------- /leakdc_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestLeakDC(t *testing.T) { 8 | defName := "LeakDCTest" 9 | 10 | def := NewSynthdef(defName, func(p Params) Ugen { 11 | return Out{ 12 | Bus: C(0), 13 | Channels: LeakDC{ 14 | In: LFPulse{ 15 | Freq: C(800), 16 | IPhase: C(0.5), 17 | Width: C(0.5), 18 | }.Rate(AR).Mul(C(0.5)), 19 | Coeff: C(0.995), 20 | }.Rate(AR), 21 | }.Rate(AR) 22 | }) 23 | compareAndWrite(t, defName, def) 24 | } 25 | -------------------------------------------------------------------------------- /lfclipnoise.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // LFClipNoise randomly generates the values -1 or +1 at a rate 4 | // given by the nearest integer division of the sample rate by the freqargument. 5 | // It is probably pretty hard on your speakers! 6 | type LFClipNoise struct { 7 | Freq Input 8 | } 9 | 10 | func (l *LFClipNoise) defaults() { 11 | if l.Freq == nil { 12 | l.Freq = C(500) 13 | } 14 | } 15 | 16 | // Rate creates a new ugen at a specific rate. 17 | // If rate is an unsupported value this method will cause a runtime panic. 18 | func (l LFClipNoise) Rate(rate int8) Input { 19 | CheckRate(rate) 20 | (&l).defaults() 21 | return NewInput("LFClipNoise", rate, 0, 1, l.Freq) 22 | } 23 | -------------------------------------------------------------------------------- /lfclipnoise_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestLFClipNoise(t *testing.T) { 8 | const defName = "LFClipNoiseTest" 9 | 10 | // Out.ar(0, SinOsc.ar( 11 | // LFClipNoise.ar(4, 200, 600), 12 | // 0, 0.2 13 | // )); 14 | compareAndWriteStructure(t, defName, NewSynthdef(defName, func(p Params) Ugen { 15 | noise := A(LFClipNoise{ 16 | Freq: C(4), 17 | }) 18 | sine := A(SinOsc{ 19 | Freq: noise.MulAdd(C(200), C(600)), 20 | }) 21 | return Out{ 22 | Bus: C(0), 23 | Channels: sine.Mul(C(0.2)), 24 | }.Rate(AR) 25 | })) 26 | } 27 | -------------------------------------------------------------------------------- /lfcub.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // LFCub is a sine-like shape made of two cubic pieces. 4 | // It is smoother than LFPar. 5 | type LFCub struct { 6 | // Freq frequency in Hz 7 | Freq Input 8 | // Iphase initial phase offset 9 | Iphase Input 10 | } 11 | 12 | func (lfcub *LFCub) defaults() { 13 | if lfcub.Freq == nil { 14 | lfcub.Freq = C(440) 15 | } 16 | if lfcub.Iphase == nil { 17 | lfcub.Iphase = C(0) 18 | } 19 | } 20 | 21 | // Rate creates a new ugen at a specific rate. 22 | // If rate is an unsupported value this method will cause 23 | // a runtime panic. 24 | func (lfcub LFCub) Rate(rate int8) Input { 25 | CheckRate(rate) 26 | (&lfcub).defaults() 27 | return NewInput("LFCub", rate, 0, 1, lfcub.Freq, lfcub.Iphase) 28 | } 29 | -------------------------------------------------------------------------------- /lfcub_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestLFCub(t *testing.T) { 8 | defName := "LFCubTest" 9 | def := NewSynthdef(defName, func(p Params) Ugen { 10 | // var freq = LFCub.kr(LFCub.kr(0.2, 0, 8, 10), 0, 400, 800); 11 | // var sig = LFCub.ar(freq, 0, 0.1); 12 | // Out.ar(0, sig); 13 | bus, gain := C(0), C(0.1) 14 | lfo1 := LFCub{Freq: C(0.2)}.Rate(KR).MulAdd(C(8), C(10)) 15 | lfo2 := LFCub{Freq: lfo1}.Rate(KR).MulAdd(C(400), C(800)) 16 | sig := LFCub{Freq: lfo2}.Rate(AR).Mul(gain) 17 | return Out{bus, sig}.Rate(AR) 18 | }) 19 | compareAndWrite(t, defName, def) 20 | } 21 | -------------------------------------------------------------------------------- /lfdclipnoise.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // LFDClipNoise is like LFClipNoise, except it generates the values -1 or +1 4 | // at a rate given by the freq argument, with two differences: 5 | // no time quantization 6 | // fast recovery from low freq values1 7 | // If you don't need very high or very low freqs, or use fixed freqs, 8 | // LFDClipNoise is more efficient. 9 | type LFDClipNoise struct { 10 | Freq Input 11 | } 12 | 13 | func (l *LFDClipNoise) defaults() { 14 | if l.Freq == nil { 15 | l.Freq = C(500) 16 | } 17 | } 18 | 19 | // Rate creates a new ugen at a specific rate. 20 | // If rate is an unsupported value this method will cause a runtime panic. 21 | func (l LFDClipNoise) Rate(rate int8) Input { 22 | CheckRate(rate) 23 | (&l).defaults() 24 | return NewInput("LFDClipNoise", rate, 0, 1, l.Freq) 25 | } 26 | -------------------------------------------------------------------------------- /lfdclipnoise_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestLFDClipNoise(t *testing.T) { 8 | const defName = "LFDClipNoiseTest" 9 | 10 | // Out.ar(0, SinOsc.ar( 11 | // LFDClipNoise.ar(4, 200, 600), 12 | // 0, 0.2 13 | // )); 14 | compareAndWriteStructure(t, defName, NewSynthdef(defName, func(p Params) Ugen { 15 | noise := A(LFDClipNoise{ 16 | Freq: C(4), 17 | }) 18 | sine := A(SinOsc{ 19 | Freq: noise.MulAdd(C(200), C(600)), 20 | }) 21 | return Out{ 22 | Bus: C(0), 23 | Channels: sine.Mul(C(0.2)), 24 | }.Rate(AR) 25 | })) 26 | } 27 | -------------------------------------------------------------------------------- /lfdnoise.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // LFDNoise generates random values at a rate given by the freq argument, with two 4 | // differences: no time quantization, and fast recovery from low freq values. 5 | type LFDNoise struct { 6 | Interpolation Interpolation 7 | Freq Input 8 | } 9 | 10 | func (lfdn *LFDNoise) defaults() { 11 | if lfdn.Freq == nil { 12 | lfdn.Freq = C(500) 13 | } 14 | } 15 | 16 | // Rate creates a new ugen at a specific rate. 17 | // If rate is an unsupported value this method will cause a runtime panic. 18 | func (lfdn LFDNoise) Rate(rate int8) Input { 19 | CheckRate(rate) 20 | (&lfdn).defaults() 21 | switch lfdn.Interpolation { 22 | case InterpolationNone: 23 | return NewInput("LFDNoise0", rate, 0, 1, lfdn.Freq) 24 | case InterpolationLinear: 25 | return NewInput("LFDNoise1", rate, 0, 1, lfdn.Freq) 26 | case InterpolationCubic: 27 | return NewInput("LFDNoise3", rate, 0, 1, lfdn.Freq) 28 | default: 29 | panic("unknown interpolation value") 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /lfgauss.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // LFGauss is a non-band-limited gaussian function oscillator. 4 | // Output ranges from minval to 1. 5 | // LFGauss implements the formula: 6 | // f(x) = exp(squared(x - iphase) / (-2.0 * squared(width))) 7 | // where x is to vary in the range -1 to 1 over the period dur. 8 | // minval is the initial value at -1. 9 | type LFGauss struct { 10 | Duration Input 11 | Width Input 12 | IPhase Input 13 | Loop Input 14 | Done int 15 | } 16 | 17 | func (l *LFGauss) defaults() { 18 | if l.Duration == nil { 19 | l.Duration = C(1) 20 | } 21 | if l.Width == nil { 22 | l.Width = C(0.1) 23 | } 24 | if l.IPhase == nil { 25 | l.IPhase = C(0) 26 | } 27 | if l.Loop == nil { 28 | l.Loop = C(1) 29 | } 30 | } 31 | 32 | // Rate creates a new ugen at a specific rate. 33 | // If rate is an unsupported value this method will cause a runtime panic. 34 | func (l LFGauss) Rate(rate int8) Input { 35 | CheckRate(rate) 36 | (&l).defaults() 37 | done := C(float32(l.Done)) 38 | return NewInput("LFGauss", rate, 0, 1, l.Duration, l.Width, l.IPhase, l.Loop, done) 39 | } 40 | -------------------------------------------------------------------------------- /lfgauss_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestLFGauss(t *testing.T) { 8 | const defName = "LFGaussTest" 9 | 10 | // Out.ar(0, LFGauss.ar(0.01, SampleDur.ir * MouseX.kr(10, 3000, 1)) * 0.2); 11 | compareAndWriteStructure(t, defName, NewSynthdef(defName, func(p Params) Ugen { 12 | return Out{ 13 | Bus: C(0), 14 | Channels: A(LFGauss{ 15 | Duration: C(0.01), 16 | Width: SampleDur{}.Rate(IR).Mul(K(MouseX{ 17 | Min: C(10), 18 | Max: C(3000), 19 | Warp: WarpExp, 20 | })), 21 | }).Mul(C(0.2)), 22 | }.Rate(AR) 23 | })) 24 | } 25 | -------------------------------------------------------------------------------- /lfnoise_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import "testing" 4 | 5 | func TestLFNoise1(t *testing.T) { 6 | def := NewSynthdef("LFNoise1Example", func(p Params) Ugen { 7 | start, end, dur, done := C(1000), C(10000), C(10), 0 8 | bus, gain := C(0), C(0.25) 9 | freq := XLine{start, end, dur, done}.Rate(KR) 10 | sig := LFNoise{Interpolation: NoiseLinear, Freq: freq}.Rate(AR).Mul(gain) 11 | return Out{bus, sig}.Rate(AR) 12 | }) 13 | same, err := def.CompareToFile("testdata/LFNoise1Example.scsyndef") 14 | if err != nil { 15 | t.Fatal(err) 16 | } 17 | if !same { 18 | t.Fatalf("synthdef different from sclang version") 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /lfo.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | func defLFO(params Params) Ugen { 4 | var ( 5 | freq = params.Add("freq", 1) 6 | out = params.Add("out", 0) 7 | saw = LFSaw{Freq: freq}.Rate(KR) 8 | sine = SinOsc{Freq: freq}.Rate(KR) 9 | square = LFPulse{Freq: freq}.Rate(KR) 10 | ) 11 | return Out{ 12 | Bus: out, 13 | Channels: Multi(saw, sine, square), 14 | }.Rate(KR) 15 | } 16 | -------------------------------------------------------------------------------- /lfpar.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // LFPar is a sine-like shape made of two parabolas and 4 | // the integral of a triangular wave. 5 | // It has audible odd harmonics and is non-band-limited. 6 | // Output ranges from -1 to +1. 7 | type LFPar struct { 8 | // Freq is frequency in Hz. 9 | Freq Input 10 | 11 | // IPhase is the initial phase (0..1). 12 | IPhase Input 13 | } 14 | 15 | func (l *LFPar) defaults() { 16 | if l.Freq == nil { 17 | l.Freq = C(440) 18 | } 19 | if l.IPhase == nil { 20 | l.IPhase = C(0) 21 | } 22 | } 23 | 24 | // Rate creates a new ugen at a specific rate. 25 | // If rate is an unsupported value this method will cause a runtime panic. 26 | func (l LFPar) Rate(rate int8) Input { 27 | CheckRate(rate) 28 | (&l).defaults() 29 | return NewInput("LFPar", rate, 0, 1, l.Freq, l.IPhase) 30 | } 31 | -------------------------------------------------------------------------------- /lfpar_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestLFPar(t *testing.T) { 8 | const defName = "LFParTest" 9 | 10 | // Out.ar(0, LFPar.ar(XLine.kr(100,8000,30),0,0.1)); 11 | compareAndWriteStructure(t, defName, NewSynthdef(defName, func(p Params) Ugen { 12 | return Out{ 13 | Bus: C(0), 14 | Channels: A(LFPar{ 15 | Freq: K(XLine{ 16 | Start: C(100), 17 | End: C(8000), 18 | Dur: C(30), 19 | }), 20 | }).Mul(C(0.1)), 21 | }.Rate(AR) 22 | })) 23 | } 24 | -------------------------------------------------------------------------------- /lfpulse_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestLFPulse(t *testing.T) { 8 | def := NewSynthdef("LFPulseTest", func(p Params) Ugen { 9 | lfoFreq, lfoPhase, lfoWidth := C(3), C(0), C(0.3) 10 | bus, gain := C(0), C(0.1) 11 | freq := LFPulse{lfoFreq, lfoPhase, lfoWidth}.Rate(KR).MulAdd(C(200), C(200)) 12 | iphase, width := C(0), C(0.2) 13 | sig := LFPulse{freq, iphase, width}.Rate(AR).Mul(gain) 14 | return Out{bus, sig}.Rate(AR) 15 | }) 16 | same, err := def.CompareToFile("testdata/LFPulseTest.scsyndef") 17 | if err != nil { 18 | t.Fatal(err) 19 | } 20 | if !same { 21 | t.Fatalf("synthdef different from sclang version") 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /lfsaw_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import "testing" 4 | 5 | func TestLFSaw(t *testing.T) { 6 | def := NewSynthdef("LFSawExample", func(p Params) Ugen { 7 | lfoFreq, lfoPhase := C(4), C(0) 8 | bus, gain := C(0), C(0.1) 9 | freq := LFSaw{lfoFreq, lfoPhase}.Rate(KR).MulAdd(C(200), C(400)) 10 | sig := LFSaw{freq, C(0)}.Rate(AR).Mul(gain) 11 | return Out{bus, sig}.Rate(AR) 12 | }) 13 | same, err := def.CompareToFile("testdata/LFSawExample.scsyndef") 14 | if err != nil { 15 | t.Fatal(err) 16 | } 17 | if !same { 18 | t.Fatalf("synthdef different from sclang version") 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /lftri.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // LFTri is a non-band-limited triangle oscillator. 4 | // Output is [-1, 1]. 5 | type LFTri struct { 6 | // Freq is the approximate rate at which to 7 | // generate random values 8 | Freq Input 9 | // Iphase initial phase offset in the range [0, 4] 10 | Iphase Input 11 | } 12 | 13 | func (lftri *LFTri) defaults() { 14 | if lftri.Freq == nil { 15 | lftri.Freq = C(500) 16 | } 17 | if lftri.Iphase == nil { 18 | lftri.Iphase = C(0) 19 | } 20 | } 21 | 22 | // Rate creates a new ugen at a specific rate. 23 | // If rate is an unsupported value this method will cause 24 | // a runtime panic. 25 | func (lftri LFTri) Rate(rate int8) Input { 26 | CheckRate(rate) 27 | (&lftri).defaults() 28 | return NewInput("LFTri", rate, 0, 1, lftri.Freq, lftri.Iphase) 29 | } 30 | -------------------------------------------------------------------------------- /lftri_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import "testing" 4 | 5 | func TestLFTri(t *testing.T) { 6 | def := NewSynthdef("LFTriExample", func(p Params) Ugen { 7 | bus := C(0) 8 | freq := LFTri{C(4), C(0)}.Rate(KR).MulAdd(C(200), C(400)) 9 | sig := LFTri{freq, C(0)}.Rate(AR).Mul(C(0.1)) 10 | return Out{bus, sig}.Rate(AR) 11 | }) 12 | same, err := def.CompareToFile("testdata/LFTriExample.scsyndef") 13 | if err != nil { 14 | t.Fatal(err) 15 | } 16 | if !same { 17 | t.Fatalf("synthdef different from sclang version") 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /line.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // Line generates a line from the start value to the end value 4 | type Line struct { 5 | Start Input 6 | End Input 7 | Dur Input 8 | Done int 9 | } 10 | 11 | func (line *Line) defaults() { 12 | if line.Start == nil { 13 | line.Start = C(0) 14 | } 15 | if line.End == nil { 16 | line.End = C(1) 17 | } 18 | if line.Dur == nil { 19 | line.Dur = C(1) 20 | } 21 | } 22 | 23 | // Rate creates a new ugen at a specific rate. 24 | // If rate is an unsupported value this method will cause 25 | // a runtime panic. 26 | func (line Line) Rate(rate int8) Input { 27 | CheckRate(rate) 28 | (&line).defaults() 29 | return NewInput("Line", rate, 0, 1, line.Start, line.End, line.Dur, C(float32(line.Done))) 30 | } 31 | -------------------------------------------------------------------------------- /line_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestLine(t *testing.T) { 8 | defName := "LineTest" 9 | 10 | // Out.ar(0, SinOsc.ar(Line.kr(200, 17000, 10), 0, 0.1)); 11 | def := NewSynthdef(defName, func(p Params) Ugen { 12 | line := Line{ 13 | Start: C(200), 14 | End: C(17000), 15 | Dur: C(10), 16 | }.Rate(KR) 17 | 18 | return Out{ 19 | Bus: C(0), 20 | Channels: SinOsc{Freq: line}.Rate(AR).Mul(C(0.1)), 21 | }.Rate(AR) 22 | }) 23 | compareAndWriteStructure(t, defName, def) 24 | } 25 | -------------------------------------------------------------------------------- /linpan2_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestLinPan2(t *testing.T) { 8 | const defName = "LinPan2Test" 9 | 10 | // Out.ar(0, LinPan2.ar(FSinOsc.ar(800, 0, 0.1), FSinOsc.kr(3))) 11 | compareAndWriteStructure(t, defName, NewSynthdef(defName, func(p Params) Ugen { 12 | sig := A(FSinOsc{ 13 | Freq: C(800), 14 | Phase: C(0), 15 | }) 16 | pos := K(FSinOsc{ 17 | Freq: C(3), 18 | }) 19 | return Out{ 20 | Bus: C(0), 21 | Channels: A(LinPan2{ 22 | In: sig.Mul(C(0.1)), 23 | Pos: pos, 24 | }), 25 | }.Rate(AR) 26 | })) 27 | } 28 | -------------------------------------------------------------------------------- /linxfade2.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // LinXFade2 is a two channel linear crossfader. 4 | type LinXFade2 struct { 5 | A Input 6 | B Input 7 | Pan Input // Cross fade position from -1 to +1. 8 | Level Input 9 | } 10 | 11 | func (x *LinXFade2) defaults() { 12 | if x.A == nil { 13 | x.A = C(0) 14 | } 15 | if x.B == nil { 16 | x.B = C(0) 17 | } 18 | if x.Pan == nil { 19 | x.Pan = C(0) 20 | } 21 | if x.Level == nil { 22 | x.Level = C(1) 23 | } 24 | } 25 | 26 | // Rate creates a new ugen at a specific rate. 27 | // If rate is an unsupported value this method will cause a runtime panic. 28 | func (x LinXFade2) Rate(rate int8) Input { 29 | CheckRate(rate) 30 | (&x).defaults() 31 | // Not sure why Level doesn't show up in sclang's synthdefs that use LinXFade2 32 | return NewInput("LinXFade2", rate, 0, 1, x.A, x.B, x.Pan) 33 | } 34 | -------------------------------------------------------------------------------- /linxfade2_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestLinXFade2(t *testing.T) { 8 | defName := "LinXFade2Test" 9 | 10 | // Out.ar(0, LinXFade2.ar( Saw.ar, SinOsc.ar , LFTri.kr(0.1) )); 11 | compareAndWriteStructure(t, defName, NewSynthdef(defName, func(p Params) Ugen { 12 | return Out{ 13 | Bus: C(0), 14 | Channels: A(LinXFade2{ 15 | A: Saw{}.Rate(AR), 16 | B: SinOsc{}.Rate(AR), 17 | Pan: K(LFTri{ 18 | Freq: C(0.1), 19 | }), 20 | }), 21 | }.Rate(AR) 22 | })) 23 | } 24 | -------------------------------------------------------------------------------- /localbuf.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // LocalBuf allocates a buffer local to a synth node. 4 | type LocalBuf struct { 5 | NumChannels Input 6 | NumFrames Input 7 | } 8 | 9 | func (lb *LocalBuf) defaults() { 10 | if lb.NumChannels == nil { 11 | lb.NumChannels = C(1) 12 | } 13 | if lb.NumFrames == nil { 14 | lb.NumFrames = C(1) 15 | } 16 | } 17 | 18 | // Rate creates a new ugen at a specific rate. 19 | // If rate is an unsupported value this method will cause a runtime panic. 20 | func (lb LocalBuf) Rate(rate int8) Input { 21 | CheckRate(rate) 22 | (&lb).defaults() 23 | mlb := maxLocalBufs{}.Rate(rate) 24 | return NewInput("LocalBuf", rate, 0, 1, lb.NumChannels, lb.NumFrames, mlb) 25 | } 26 | -------------------------------------------------------------------------------- /lpf.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // LPF is a second order low pass filter. 4 | type LPF struct { 5 | // In is the input signal 6 | In Input 7 | // Freq cutoff in Hz 8 | Freq Input 9 | } 10 | 11 | func (lpf *LPF) defaults() { 12 | if lpf.Freq == nil { 13 | lpf.Freq = C(440) 14 | } 15 | } 16 | 17 | // Rate creates a new ugen at a specific rate. 18 | // If rate is an unsupported value this method will cause 19 | // a runtime panic. 20 | func (lpf LPF) Rate(rate int8) Input { 21 | if lpf.In == nil { 22 | panic("LPF expects In to not be nil") 23 | } 24 | CheckRate(rate) 25 | (&lpf).defaults() 26 | return NewInput("LPF", rate, 0, 1, lpf.In, lpf.Freq) 27 | } 28 | -------------------------------------------------------------------------------- /lpf_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import "testing" 4 | 5 | func TestLPF(t *testing.T) { 6 | name := "LPFExample" 7 | def := NewSynthdef(name, func(params Params) Ugen { 8 | bus, In := C(0), SinOsc{Freq: C(220)}.Rate(AR) 9 | src := LPF{In: In}.Rate(AR) 10 | return Out{bus, src}.Rate(AR) 11 | }) 12 | same, err := def.CompareToFile("testdata/LPFExample.scsyndef") 13 | if err != nil { 14 | t.Fatal(err) 15 | } 16 | if !same { 17 | t.Fatalf("synthdef different from sclang version") 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /maxlocalbufs.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // maxLocalBufs is used internally by LocalBuf, 4 | // sets the maximum number of local buffers in a synth. 5 | type maxLocalBufs struct { 6 | } 7 | 8 | // Rate creates a new ugen at a specific rate. 9 | // If rate is an unsupported value this method will cause a runtime panic. 10 | func (maxLocalBufs) Rate(rate int8) Input { 11 | CheckRate(rate) 12 | return NewInput("MaxLocalBufs", rate, 0, 1, C(1)) 13 | } 14 | -------------------------------------------------------------------------------- /median.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // Median returns the median of the last length input points. 4 | // This non-linear filter is good at reducing impulse noise from a signal. 5 | type Median struct { 6 | In Input 7 | Length Input 8 | } 9 | 10 | func (m *Median) defaults() { 11 | if m.Length == nil { 12 | m.Length = C(3) 13 | } 14 | } 15 | 16 | // Rate creates a new ugen at a specific rate. 17 | // If rate is an unsupported value this method will cause a runtime panic. 18 | // If the input signal is nil this method will panic. 19 | func (m Median) Rate(rate int8) Input { 20 | CheckRate(rate) 21 | if m.In == nil { 22 | panic("Median requires an input signal") 23 | } 24 | (&m).defaults() 25 | return NewInput("Median", rate, 0, 1, m.Length, m.In) 26 | } 27 | -------------------------------------------------------------------------------- /median_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestMedian(t *testing.T) { 8 | const defName = "MedianTest" 9 | 10 | // Out.ar(0, LeakDC.ar(Median.ar(31, WhiteNoise.ar(0.1) + SinOsc.ar(800,0,0.1)), 0.9)); 11 | compareAndWriteStructure(t, defName, NewSynthdef(defName, func(p Params) Ugen { 12 | sine := A(SinOsc{Freq: C(800)}).Mul(C(0.1)) 13 | return Out{ 14 | Bus: C(0), 15 | Channels: A(LeakDC{ 16 | In: A(Median{ 17 | Length: C(31), 18 | In: A(WhiteNoise{}).MulAdd(C(0.1), sine), 19 | }), 20 | Coeff: C(0.9), 21 | }), 22 | }.Rate(AR) 23 | })) 24 | } 25 | -------------------------------------------------------------------------------- /mix.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // Mix will mix an array of channels down to a single channel. 4 | func Mix(rate int8, inputs []Input) Input { 5 | CheckRate(rate) 6 | switch len(inputs) { 7 | case 0: 8 | panic("can not mix empty inputs slice") 9 | case 1: 10 | return inputs[0] 11 | case 2: 12 | return inputs[0].Add(inputs[1]) 13 | case 3: 14 | return Sum3(rate, inputs[0], inputs[1], inputs[2]) 15 | case 4: 16 | return Sum4(rate, inputs[0], inputs[1], inputs[2], inputs[3]) 17 | default: 18 | head := []Input{Sum4(rate, inputs[0], inputs[1], inputs[2], inputs[3])} 19 | return Mix(rate, append(head, inputs[4:]...)) 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /mix_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // func TestMix(t *testing.T) { 4 | // defName := "MixTest" 5 | // def := NewSynthdef(defName, func(params Params) Ugen { 6 | // bus := C(0) 7 | // sig := Mix(AR, []Input{ 8 | // PinkNoise{}.Rate(AR).Mul(C(0.1)), 9 | // FSinOsc{Freq: C(801), Phase: C(0.1)}.Rate(AR), 10 | // LFSaw{Freq: C(40), Iphase: C(0.1)}.Rate(AR), 11 | // Pulse{Freq: C(436)}.Rate(AR), 12 | // Dust{Density: C(4.0)}.Rate(AR), 13 | // }) 14 | // return Out{bus, sig}.Rate(AR) 15 | // }) 16 | // compareAndWrite(t, defName, def) 17 | // } 18 | -------------------------------------------------------------------------------- /moddif.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // moddif returns the smaller of the great circle distances between the two points. 4 | // This func panics if x is nil or if rate is not one of the supported rates (IR, KR, AR). 5 | func moddif(rate int8, x, y, mod Input, numOutputs int) Input { 6 | CheckRate(rate) 7 | 8 | if x == nil { 9 | panic("Moddif expects the first argument to not be nil") 10 | } 11 | if y == nil { 12 | y = C(0) 13 | } 14 | if mod == nil { 15 | mod = C(1) 16 | } 17 | return NewInput("ModDif", rate, 0, numOutputs, x, y, mod) 18 | } 19 | -------------------------------------------------------------------------------- /mousex.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // MouseX allpass delay with cubic interpolation 4 | type MouseX struct { 5 | // Min is the value of this ugen's output when the 6 | // mouse is at the left edge of the screen 7 | Min Input 8 | // Max is the value of this ugen's output when the 9 | // mouse is at the right edge of the screen 10 | Max Input 11 | // Warp is the mapping curve. 0 is linear, 1 is exponential 12 | Warp Input 13 | // Lag factor to dezipper cursor movements 14 | Lag Input 15 | } 16 | 17 | func (m *MouseX) defaults() { 18 | if m.Min == nil { 19 | m.Min = C(0) 20 | } 21 | if m.Max == nil { 22 | m.Max = C(1) 23 | } 24 | if m.Warp == nil { 25 | m.Warp = C(0) 26 | } 27 | if m.Lag == nil { 28 | m.Lag = C(0.2) 29 | } 30 | } 31 | 32 | // Rate creates a new ugen at a specific rate. 33 | // If rate is an unsupported value this method will cause 34 | // a runtime panic. 35 | func (m MouseX) Rate(rate int8) Input { 36 | CheckRate(rate) 37 | (&m).defaults() 38 | return NewInput("MouseX", rate, 0, 1, m.Min, m.Max, m.Warp, m.Lag) 39 | } 40 | -------------------------------------------------------------------------------- /mousey.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // Warp constants. 4 | var ( 5 | WarpExp = C(1) 6 | WarpLin = C(0) 7 | ) 8 | 9 | // MouseY allpass delay with cubic interpolation 10 | type MouseY struct { 11 | // Min is the value of this ugen's output when the 12 | // mouse is at the left edge of the screen 13 | Min Input 14 | // Max is the value of this ugen's output when the 15 | // mouse is at the right edge of the screen 16 | Max Input 17 | // Warp is the mapping curve. 0 is linear, 1 is exponential 18 | Warp Input 19 | // Lag factor to dezipper cursor movements 20 | Lag Input 21 | } 22 | 23 | func (m *MouseY) defaults() { 24 | if m.Min == nil { 25 | m.Min = C(0) 26 | } 27 | if m.Max == nil { 28 | m.Max = C(1) 29 | } 30 | if m.Warp == nil { 31 | m.Warp = C(0) 32 | } 33 | if m.Lag == nil { 34 | m.Lag = C(0.2) 35 | } 36 | } 37 | 38 | // Rate creates a new ugen at a specific rate. 39 | // If rate is an unsupported value this method will cause 40 | // a runtime panic. 41 | func (m MouseY) Rate(rate int8) Input { 42 | CheckRate(rate) 43 | (&m).defaults() 44 | return NewInput("MouseY", rate, 0, 1, m.Min, m.Max, m.Warp, m.Lag) 45 | } 46 | -------------------------------------------------------------------------------- /multi_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestMulti(t *testing.T) { 8 | def := NewSynthdef("SimpleMulti", func(p Params) Ugen { 9 | bus, freq := C(0), Multi(C(440), C(441)) 10 | sine := SinOsc{Freq: freq}.Rate(AR) 11 | return Out{bus, sine}.Rate(AR) 12 | }) 13 | same, err := def.CompareToFile("testdata/SimpleMulti.scsyndef") 14 | if err != nil { 15 | t.Fatal(err) 16 | } 17 | if !same { 18 | t.Fatalf("synthdef different from sclang version") 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /num_outout_buses.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // NumOutputBuses provides the number of output buses in a synthdef. 4 | type NumOutputBuses struct{} 5 | 6 | // Rate creates a new ugen at a specific rate. 7 | // If rate is not IR this method will cause a runtime panic. 8 | func (n NumOutputBuses) Rate(rate int8) Input { 9 | if rate != IR { 10 | panic("NumOutputBuses must be rate IR") 11 | } 12 | return NewInput("NumOutputBuses", rate, 0, 1) 13 | } 14 | -------------------------------------------------------------------------------- /offset_out.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // OffsetOut outputs a signal to a bus. 4 | // Tthe sample offset within the bus is kept exactly; i.e. if the synth is scheduled to be started part way 5 | // through a control cycle, OffsetOut will maintain the correct offset by buffering the output and 6 | // delaying it until the exact time that the synth was scheduled for. 7 | type OffsetOut struct { 8 | Bus Input 9 | Channels Input 10 | } 11 | 12 | // Rate creates a new ugen at a specific rate. 13 | // If rate is an unsupported value this method will cause 14 | // a runtime panic. 15 | func (out OffsetOut) Rate(rate int8) Input { 16 | CheckRate(rate) 17 | return NewInput("OffsetOut", rate, 0, 1, out.Bus, out.Channels) 18 | } 19 | -------------------------------------------------------------------------------- /onepole.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // OnePole is a one pole filter. Implements the formula: 4 | // out(i) = ((1 - abs(coef)) * in(i)) + (coef * out(i-1)) 5 | type OnePole struct { 6 | // In is the input signal. 7 | In Input 8 | 9 | // Coeff is the feedback coefficient. Should be between -1 and +1 10 | Coeff Input 11 | } 12 | 13 | func (o *OnePole) defaults() { 14 | if o.Coeff == nil { 15 | o.Coeff = C(0.5) 16 | } 17 | if o.In == nil { 18 | o.In = C(0) 19 | } 20 | } 21 | 22 | // Rate creates a new ugen at a specific rate. 23 | // If rate is an unsupported value this method will cause a runtime panic. 24 | func (o OnePole) Rate(rate int8) Input { 25 | CheckRate(rate) 26 | (&o).defaults() 27 | return NewInput("OnePole", rate, 0, 1, o.In, o.Coeff) 28 | } 29 | -------------------------------------------------------------------------------- /onepole_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestOnePole(t *testing.T) { 8 | const defName = "OnePoleTest" 9 | 10 | // Out.ar(0, OnePole.ar(WhiteNoise.ar(0.5), Line.kr(-0.99, 0.99, 10))); 11 | compareAndWriteStructure(t, defName, NewSynthdef(defName, func(p Params) Ugen { 12 | return Out{ 13 | Bus: C(0), 14 | Channels: A(OnePole{ 15 | In: A(WhiteNoise{}).Mul(C(0.5)), 16 | Coeff: K(Line{ 17 | Start: C(-0.99), 18 | End: C(0.99), 19 | Dur: C(10), 20 | }), 21 | }), 22 | }.Rate(AR) 23 | })) 24 | } 25 | -------------------------------------------------------------------------------- /onezero.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // OneZero is a one zero filter. Implements the formula: 4 | // out(i) = ((1 - abs(coef)) * in(i)) + (coef * in(i-1)) 5 | type OneZero struct { 6 | // In is the input signal. 7 | In Input 8 | 9 | // Coeff is the feed forward coefficient. 10 | // +0.5 makes a two point averaging filter (see also LPZ1 ). 11 | // -0.5 makes a differentiator (see also HPZ1 ). 12 | // +1 makes a single sample delay (see also Delay1 ). 13 | // -1 makes an inverted single sample delay. 14 | Coeff Input 15 | } 16 | 17 | func (o *OneZero) defaults() { 18 | if o.Coeff == nil { 19 | o.Coeff = C(0.5) 20 | } 21 | if o.In == nil { 22 | o.In = C(0) 23 | } 24 | } 25 | 26 | // Rate creates a new ugen at a specific rate. 27 | // If rate is an unsupported value this method will cause a runtime panic. 28 | func (o OneZero) Rate(rate int8) Input { 29 | CheckRate(rate) 30 | (&o).defaults() 31 | return NewInput("OneZero", rate, 0, 1, o.In, o.Coeff) 32 | } 33 | -------------------------------------------------------------------------------- /onezero_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestOneZero(t *testing.T) { 8 | const defName = "OneZeroTest" 9 | 10 | // Out.ar(0, OneZero.ar(WhiteNoise.ar(0.5), Line.kr(-0.5, 0.5, 10))); 11 | compareAndWriteStructure(t, defName, NewSynthdef(defName, func(p Params) Ugen { 12 | return Out{ 13 | Bus: C(0), 14 | Channels: A(OneZero{ 15 | In: A(WhiteNoise{}).Mul(C(0.5)), 16 | Coeff: K(Line{ 17 | Start: C(-0.5), 18 | End: C(0.5), 19 | Dur: C(10), 20 | }), 21 | }), 22 | }.Rate(AR) 23 | })) 24 | } 25 | -------------------------------------------------------------------------------- /osc_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestOsc(t *testing.T) { 8 | defName := "OscTest" 9 | 10 | // arg bufnum = 0; 11 | // Out.ar(out, Osc.ar(bufnum, XLine.kr(2000,200), 0, 0.5)); 12 | compareAndWriteStructure(t, defName, NewSynthdef(defName, func(p Params) Ugen { 13 | var ( 14 | bufnum = p.Add("bufnum", 0) 15 | ) 16 | return Out{ 17 | Bus: C(0), 18 | Channels: A(Osc{ 19 | BufNum: bufnum, 20 | Freq: K(XLine{ 21 | Start: C(2000), 22 | End: C(200), 23 | }), 24 | }).Mul(C(0.5)), 25 | }.Rate(AR) 26 | })) 27 | } 28 | -------------------------------------------------------------------------------- /oscn.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // OscN is a noninterpolating wavetable lookup oscillator with frequency 4 | // and phase modulation inputs. 5 | // It is usually better to use the interpolating oscillator Osc. 6 | type OscN struct { 7 | BufNum Input 8 | Freq Input 9 | Phase Input 10 | } 11 | 12 | func (o *OscN) defaults() { 13 | if o.Freq == nil { 14 | o.Freq = C(440) 15 | } 16 | if o.Phase == nil { 17 | o.Phase = C(0) 18 | } 19 | } 20 | 21 | // Rate creates a new ugen at a specific rate. 22 | // If rate is an unsupported value this method will cause a runtime panic. 23 | // If BufNum is nil this method will panic. 24 | func (o OscN) Rate(rate int8) Input { 25 | CheckRate(rate) 26 | if o.BufNum == nil { 27 | panic("OscN requires a buffer number") 28 | } 29 | (&o).defaults() 30 | return NewInput("OscN", rate, 0, 1, o.BufNum, o.Freq, o.Phase) 31 | } 32 | -------------------------------------------------------------------------------- /oscn_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestOscN(t *testing.T) { 8 | defName := "OscNTest" 9 | 10 | // arg bufnum = 0; 11 | // Out.ar(out, OscN.ar(bufnum, XLine.kr(2000,200), 0, 0.5)); 12 | compareAndWriteStructure(t, defName, NewSynthdef(defName, func(p Params) Ugen { 13 | var ( 14 | bufnum = p.Add("bufnum", 0) 15 | ) 16 | return Out{ 17 | Bus: C(0), 18 | Channels: A(OscN{ 19 | BufNum: bufnum, 20 | Freq: K(XLine{ 21 | Start: C(2000), 22 | End: C(200), 23 | }), 24 | }).Mul(C(0.5)), 25 | }.Rate(AR) 26 | })) 27 | } 28 | -------------------------------------------------------------------------------- /out.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // Out writes a signal to a bus. 4 | type Out struct { 5 | Bus Input 6 | Channels Input 7 | } 8 | 9 | // Rate creates a new ugen at a specific rate. 10 | // If rate is an unsupported value this method will cause 11 | // a runtime panic. 12 | func (out Out) Rate(rate int8) Ugen { 13 | CheckRate(rate) 14 | u := NewUgen("Out", rate, 0, 1, out.Bus, out.Channels) 15 | return *u 16 | } 17 | -------------------------------------------------------------------------------- /out_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestOut(t *testing.T) { 8 | var ( 9 | bus = C(0) 10 | sin = SinOsc{}.Rate(AR) 11 | out = Out{bus, sin}.Rate(AR) 12 | inputs = out.inputs 13 | numInputs = len(inputs) 14 | ) 15 | if numInputs != 2 { 16 | t.Fatalf("expected 2 inputs but got %d", numInputs) 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /output.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import ( 4 | "encoding/binary" 5 | "io" 6 | ) 7 | 8 | // Output is a ugen output. 9 | type Output int8 10 | 11 | // Write writes the output to an io.Writer. 12 | func (o Output) Write(w io.Writer) error { 13 | return binary.Write(w, byteOrder, int8(o)) 14 | } 15 | 16 | // readOutput 17 | func readOutput(r io.Reader) (Output, error) { 18 | var ( 19 | rate int8 20 | ) 21 | if err := binary.Read(r, byteOrder, &rate); err != nil { 22 | return Output(-1), err 23 | } 24 | return Output(rate), nil 25 | } 26 | -------------------------------------------------------------------------------- /pan2_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestPan2(t *testing.T) { 8 | defName := "Pan2Test" 9 | 10 | // Out.ar(0, Pan2.ar(PinkNoise.ar(0.4), FSinOsc.kr(2), 0.3)); 11 | def := NewSynthdef(defName, func(p Params) Ugen { 12 | return Out{ 13 | Bus: C(0), 14 | Channels: Pan2{ 15 | In: PinkNoise{}.Rate(AR).Mul(C(0.4)), 16 | Pos: FSinOsc{Freq: C(2)}.Rate(KR), 17 | Level: C(0.3), 18 | }.Rate(AR), 19 | }.Rate(AR) 20 | }) 21 | compareAndWriteStructure(t, defName, def) 22 | } 23 | -------------------------------------------------------------------------------- /pan4.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // Pan4 is a four channel equal power panner. 4 | // Outputs are in order LeftFront, RightFront, LeftBack, RightBack. 5 | type Pan4 struct { 6 | // In is the input signal. 7 | In Input 8 | 9 | // XPos is the X pan position from -1 to +1 (left to right). 10 | XPos Input 11 | 12 | // YPos is the Y pan position from -1 to +1 (back to front). 13 | YPos Input 14 | 15 | // Level is a control rate level input. 16 | Level Input 17 | } 18 | 19 | func (pan *Pan4) defaults() { 20 | if pan.XPos == nil { 21 | pan.XPos = C(0) 22 | } 23 | if pan.YPos == nil { 24 | pan.YPos = C(0) 25 | } 26 | if pan.Level == nil { 27 | pan.Level = C(1) 28 | } 29 | } 30 | 31 | // Rate creates a new ugen at a specific rate. 32 | // If rate is an unsupported value this method will cause a runtime panic. 33 | // If the input signal is nil this method will panic. 34 | func (pan Pan4) Rate(rate int8) Input { 35 | CheckRate(rate) 36 | if pan.In == nil { 37 | panic("Pan4 requires an input") 38 | } 39 | (&pan).defaults() 40 | in := NewInput("Pan4", rate, 0, 1, pan.In, pan.XPos, pan.YPos, pan.Level) 41 | return Multi(in, in, in, in) 42 | 43 | } 44 | -------------------------------------------------------------------------------- /pan4_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestPan4(t *testing.T) { 8 | defName := "Pan4Test" 9 | 10 | // Out.ar(0, Pan4.ar(PinkNoise.ar, FSinOsc.kr(2), FSinOsc.kr(1.2), 0.3)) 11 | compareAndWriteStructure(t, defName, NewSynthdef(defName, func(p Params) Ugen { 12 | return Out{ 13 | Bus: C(0), 14 | Channels: A(Pan4{ 15 | In: A(PinkNoise{}), 16 | XPos: K(FSinOsc{ 17 | Freq: C(2), 18 | }), 19 | YPos: K(FSinOsc{ 20 | Freq: C(1.2), 21 | }), 22 | Level: C(0.3), 23 | }), 24 | }.Rate(AR) 25 | })) 26 | } 27 | -------------------------------------------------------------------------------- /panaz_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestPanAz(t *testing.T) { 8 | defName := "PanAzTest" 9 | 10 | // Out.ar(0, PanAz.ar(2, DC.ar(1), Line.ar(0, 1/2, 0.1))); 11 | compareAndWriteStructure(t, defName, NewSynthdef(defName, func(p Params) Ugen { 12 | return Out{ 13 | Bus: C(0), 14 | Channels: A(PanAz{ 15 | NumChans: 2, 16 | In: DC{In: C(1)}.Rate(AR), 17 | Pos: A(Line{ 18 | Start: C(0), 19 | End: C(0.5), 20 | Dur: C(0.1), 21 | }), 22 | }), 23 | }.Rate(AR) 24 | })) 25 | } 26 | -------------------------------------------------------------------------------- /panb2.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // PanB2 encodes a mono signal to 2-dimensional ambisonic B-format. 4 | type PanB2 struct { 5 | // In is the input signal. 6 | In Input 7 | 8 | // Azimuth is the position around the circle from -1 to +1. -1 is behind, 9 | // -0.5 is left, 0 is forward, +0.5 is right, +1 is behind. 10 | Azimuth Input 11 | 12 | // Gain controls the amplitude of the output signal. 13 | Gain Input 14 | } 15 | 16 | func (pan *PanB2) defaults() { 17 | if pan.Azimuth == nil { 18 | pan.Azimuth = C(0) 19 | } 20 | if pan.Gain == nil { 21 | pan.Gain = C(1) 22 | } 23 | } 24 | 25 | // Rate creates a new ugen at a specific rate. 26 | // If rate is an unsupported value this method will cause a runtime panic. 27 | // If the input signal is nil this method will panic. 28 | func (pan PanB2) Rate(rate int8) Input { 29 | CheckRate(rate) 30 | if pan.In == nil { 31 | panic("PanB2 requires an input") 32 | } 33 | (&pan).defaults() 34 | return NewInput("PanB2", rate, 0, 3, pan.In, pan.Azimuth, pan.Gain) 35 | 36 | } 37 | -------------------------------------------------------------------------------- /panb2_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestPanB2(t *testing.T) { 8 | defName := "PanB2Test" 9 | 10 | // var w, x, y, p, a, b, c, d; 11 | // p = PinkNoise.ar; // source 12 | // // B-format encode 13 | // #w, x, y = PanB2.ar(p, MouseX.kr(-1,1), 0.1); 14 | // // B-format decode to quad 15 | // #a, b, c, d = DecodeB2.ar(4, w, x, y); 16 | // Out.ar(0, [a, b, d, c]); // reorder to my speaker arrangement: Lf Rf Lr Rr 17 | compareAndWriteStructure(t, defName, NewSynthdef(defName, func(p Params) Ugen { 18 | d := A(DecodeB2{ 19 | NumChans: 4, 20 | In: A(PanB2{ 21 | In: A(PinkNoise{}), 22 | Azimuth: A(MouseX{ 23 | Min: C(-1), 24 | Max: C(1), 25 | }), 26 | Gain: C(0.1), 27 | }), 28 | }) 29 | return Out{ 30 | Bus: C(0), 31 | Channels: d, 32 | }.Rate(AR) 33 | })) 34 | } 35 | -------------------------------------------------------------------------------- /paramName.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import ( 4 | "encoding/binary" 5 | "io" 6 | ) 7 | 8 | // ParamName represents a parameter name of a synthdef 9 | type ParamName struct { 10 | Name string `json:"name,omitempty"` 11 | Index int32 `json:"index"` 12 | } 13 | 14 | func (pn *ParamName) Write(w io.Writer) error { 15 | if err := newPstring(pn.Name).Write(w); err != nil { 16 | return err 17 | } 18 | return binary.Write(w, byteOrder, int32(pn.Index)) 19 | } 20 | 21 | // readParamName reads a ParamName from an io.Reader 22 | func readParamName(r io.Reader) (*ParamName, error) { 23 | name, err := readPstring(r) 24 | if err != nil { 25 | return nil, err 26 | } 27 | var idx int32 28 | if err := binary.Read(r, byteOrder, &idx); err != nil { 29 | return nil, err 30 | } 31 | pn := ParamName{name.String(), idx} 32 | return &pn, nil 33 | } 34 | -------------------------------------------------------------------------------- /param_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // import ( 4 | // "testing" 5 | // ) 6 | 7 | // func Test2Params(t *testing.T) { 8 | // synthName := "defWith2Params" 9 | // def := NewSynthdef(synthName, func(p Params) Ugen { 10 | // freq := p.Add("freq", 440) 11 | // gain := p.Add("gain", 0.5) 12 | // bus := C(0) 13 | // env := EnvGen{ 14 | // Env: EnvPerc{}, 15 | // Done: FreeEnclosing, 16 | // LevelScale: gain, 17 | // }.Rate(KR) 18 | // sig := SinOsc{Freq: freq}.Rate(AR).Mul(env) 19 | // return Out{bus, sig}.Rate(AR) 20 | // }) 21 | // compareAndWrite(t, synthName, def) 22 | // sclangVersion := `{ 23 | // arg freq=440, gain=0.5; 24 | // var env = EnvGen.kr(Env.perc, doneAction: 2, levelScale: gain); 25 | // var sine = SinOsc.ar(freq); 26 | // Out.ar(0, sine * env); 27 | // }` 28 | // same, err := def.Compare(sclangVersion) 29 | // if err != nil { 30 | // t.Fatal(err) 31 | // } 32 | // if !same { 33 | // f, err := os.Open(synthName + ".gosyndef") 34 | // if err != nil { 35 | // t.Fatal(err) 36 | // } 37 | // def.Write 38 | // t.Fatalf("synthdef different from sclang version") 39 | // } 40 | // } 41 | -------------------------------------------------------------------------------- /pinknoise.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // PinkNoise generates noise whose spectrum falls off 4 | // in power by 3 dB per octave. 5 | // This gives equal power over the span of each octave. 6 | // This version gives 8 octaves of pink noise. 7 | type PinkNoise struct { 8 | } 9 | 10 | // Rate creates a new ugen at a specific rate. 11 | // If rate is an unsupported value this method will cause 12 | // a runtime panic. 13 | func (pink PinkNoise) Rate(rate int8) Input { 14 | CheckRate(rate) 15 | return NewInput("PinkNoise", rate, 0, 1) 16 | } 17 | -------------------------------------------------------------------------------- /playbuf_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import "testing" 4 | 5 | func TestPlayBuf(t *testing.T) { 6 | def := NewSynthdef("PlayBufExample", func(p Params) Ugen { 7 | // sclang synthdef: 8 | // arg bufnum = 0; 9 | // Out.ar(0, PlayBuf.ar(1, bufnum, 1.0, 1.0, 0, 0, 2)); 10 | bufnum := p.Add("bufnum", 0) 11 | bus, channels := C(0), 1 12 | sig := PlayBuf{ 13 | NumChannels: channels, 14 | BufNum: bufnum, 15 | Done: FreeEnclosing, 16 | }.Rate(AR) 17 | return Out{bus, sig}.Rate(AR) 18 | }) 19 | compareAndWrite(t, "PlayBufExample", def) 20 | } 21 | -------------------------------------------------------------------------------- /pmosc_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestPMOsc(t *testing.T) { 8 | defName := "PMOscTest" 9 | def := NewSynthdef(defName, func(p Params) Ugen { 10 | // Out.ar(0, PMOsc.ar(Line.kr(600, 900, 5), 600, 3, 0, 0.1)); 11 | bus, gain := C(0), C(0.1) 12 | line := Line{Start: C(600), End: C(900), Dur: C(5)}.Rate(KR) 13 | sig := PMOsc{CarFreq: line, ModFreq: C(600), PMIndex: C(3)}.Rate(AR).Mul(gain) 14 | return Out{bus, sig}.Rate(AR) 15 | }) 16 | compareAndWrite(t, defName, def) 17 | } 18 | -------------------------------------------------------------------------------- /psingrain.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // PSinGrain is a very fast sine grain with a parabolic envelope. 4 | type PSinGrain struct { 5 | // Frequency in Hz. 6 | Freq Input 7 | 8 | // Grain duration in seconds. 9 | Dur Input 10 | 11 | // Grain amplitude. 12 | Amp Input 13 | } 14 | 15 | func (p *PSinGrain) defaults() { 16 | if p.Freq == nil { 17 | p.Freq = C(440) 18 | } 19 | if p.Dur == nil { 20 | p.Dur = C(0.2) 21 | } 22 | if p.Amp == nil { 23 | p.Amp = C(1) 24 | } 25 | } 26 | 27 | // Rate creates a new ugen at a specific rate. 28 | // If rate is a supported value this method will cause a runtime panic. 29 | func (p PSinGrain) Rate(rate int8) Input { 30 | CheckRate(rate) 31 | (&p).defaults() 32 | return NewInput("PSinGrain", rate, 0, 1, p.Freq, p.Dur, p.Amp) 33 | } 34 | -------------------------------------------------------------------------------- /psingrain_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestPSinGrain(t *testing.T) { 8 | const defName = "PSinGrainTest" 9 | 10 | // Out.ar(0, PSinGrain.ar(880, 0.1, 0.7(); 11 | compareAndWriteStructure(t, defName, NewSynthdef(defName, func(p Params) Ugen { 12 | return Out{ 13 | Bus: C(0), 14 | Channels: A(PSinGrain{ 15 | Freq: C(880), 16 | Dur: C(0.1), 17 | Amp: C(0.7), 18 | }), 19 | }.Rate(AR) 20 | })) 21 | } 22 | -------------------------------------------------------------------------------- /pulse.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // Pulse band-limited pulse wave generator with pulse width modulation. 4 | type Pulse struct { 5 | // Freq in Hz 6 | Freq Input 7 | // Width pulse width duty cycle from 0 to 1 8 | Width Input 9 | } 10 | 11 | func (pulse *Pulse) defaults() { 12 | if pulse.Freq == nil { 13 | pulse.Freq = C(440) 14 | } 15 | if pulse.Width == nil { 16 | pulse.Width = C(0.5) 17 | } 18 | } 19 | 20 | // Rate creates a new ugen at a specific rate. 21 | // If rate is an unsupported value this method will cause 22 | // a runtime panic. 23 | func (pulse Pulse) Rate(rate int8) Input { 24 | CheckRate(rate) 25 | (&pulse).defaults() 26 | return NewInput("Pulse", rate, 0, 1, pulse.Freq, pulse.Width) 27 | } 28 | -------------------------------------------------------------------------------- /pulse_count.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // PulseCount counts pulses. 4 | // Each trigger increments a counter which is output as a signal. 5 | type PulseCount struct { 6 | // Trig is the trigger signal. 7 | // A trigger happens when the signal changes from non-positive to positive. 8 | Trig Input 9 | 10 | // Reset resets the counter to zero when triggered. 11 | Reset Input 12 | } 13 | 14 | func (pc *PulseCount) defaults() { 15 | if pc.Trig == nil { 16 | pc.Trig = C(0) 17 | } 18 | if pc.Reset == nil { 19 | pc.Reset = C(0) 20 | } 21 | } 22 | 23 | // Rate creates a new ugen at a specific rate. 24 | // If rate is an unsupported value this method will cause a runtime panic. 25 | func (pc PulseCount) Rate(rate int8) Input { 26 | CheckRate(rate) 27 | (&pc).defaults() 28 | return NewInput("PulseCount", rate, 0, 1, pc.Trig, pc.Reset) 29 | } 30 | -------------------------------------------------------------------------------- /pulse_count_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestPulseCount(t *testing.T) { 8 | const defName = "PulseCountTest" 9 | 10 | // Out.ar(0, SinOsc.ar(PulseCount.ar(Impulse.ar(10), Impulse.ar(0.4)) * 200, 0, 0.05)); 11 | compareAndWriteStructure(t, defName, NewSynthdef(defName, func(p Params) Ugen { 12 | return Out{ 13 | Bus: C(0), 14 | Channels: A(SinOsc{ 15 | Freq: A(PulseCount{ 16 | Trig: Impulse{Freq: C(10)}.Rate(AR), 17 | Reset: Impulse{Freq: C(0.4)}.Rate(AR), 18 | }).Mul(C(200)), 19 | }).Mul(C(0.05)), 20 | }.Rate(AR) 21 | })) 22 | } 23 | -------------------------------------------------------------------------------- /pulse_divider.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // PulseDivider outputs one impulse each time it receives 4 | // a certain number of triggers at its input. 5 | type PulseDivider struct { 6 | // Trig can be any signal. 7 | // A trigger happens when the signal changes from non-positive to positive. 8 | Trig Input 9 | 10 | // Div is the number of triggers to count before outputting an impulse. 11 | Div Input 12 | 13 | // Start is the starting value for the trigger count. 14 | // This lets you start somewhere in the middle of a count. 15 | // If start is negative it adds that many counts to the first time the output is triggered. 16 | Start Input 17 | } 18 | 19 | func (pd *PulseDivider) defaults() { 20 | if pd.Trig == nil { 21 | pd.Trig = C(0) 22 | } 23 | if pd.Div == nil { 24 | pd.Div = C(2) 25 | } 26 | if pd.Start == nil { 27 | pd.Start = C(0) 28 | } 29 | } 30 | 31 | // Rate creates a new ugen at a specific rate. 32 | // If rate is an unsupported value this method will cause a runtime panic. 33 | func (pd PulseDivider) Rate(rate int8) Input { 34 | CheckRate(rate) 35 | (&pd).defaults() 36 | return NewInput("PulseDivider", rate, 0, 1, pd.Trig, pd.Div, pd.Start) 37 | } 38 | -------------------------------------------------------------------------------- /pulse_divider_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestPulseDivider(t *testing.T) { 8 | defName := "PulseDividerTest" 9 | 10 | compareAndWriteStructure(t, defName, NewSynthdef(defName, func(params Params) Ugen { 11 | var ( 12 | out = params.Add("out", 0) 13 | p = Impulse{Freq: C(8)}.Rate(AR) 14 | decay1 = Decay2{In: p, Attack: C(0.005), Decay: C(0.1)}.Rate(AR) 15 | decay2 = Decay2{In: PulseDivider{Trig: p, Div: C(4)}.Rate(AR), Attack: C(0.005), Decay: C(0.5)}.Rate(AR) 16 | b = SinOsc{Freq: C(600)}.Rate(AR).Mul(decay2) 17 | a = SinOsc{Freq: C(1200)}.Rate(AR).MulAdd(decay1, b) 18 | ) 19 | return Out{ 20 | Bus: out, 21 | Channels: a.Mul(C(0.4)), 22 | }.Rate(AR) 23 | })) 24 | } 25 | -------------------------------------------------------------------------------- /pulse_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestPulse(t *testing.T) { 8 | defName := "PulseTest" 9 | def := NewSynthdef(defName, func(p Params) Ugen { 10 | // Out.ar(0, Pulse.ar(XLine.kr(40,4000,6),0.1, 0.2)); 11 | bus, width, gain := C(0), C(0.1), C(0.2) 12 | line := XLine{Start: C(40), End: C(4000), Dur: C(6)}.Rate(KR) 13 | sig := Pulse{Freq: line, Width: width}.Rate(AR).Mul(gain) 14 | return Out{bus, sig}.Rate(AR) 15 | }) 16 | compareAndWrite(t, defName, def) 17 | } 18 | -------------------------------------------------------------------------------- /pv_brickwall.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // PVBrickWall clears bins above or below a cutoff point. 4 | type PVBrickWall struct { 5 | // FFT Buffer. 6 | Buffer Input 7 | 8 | // Can range between -1 and +1. 9 | // If wipe == 0 then there is no effect. 10 | // If wipe > 0 then it acts like a high pass filter, clearing bins from the bottom up. 11 | // If wipe < 0 then it acts like a low pass filter, clearing bins from the top down. 12 | Wipe Input 13 | } 14 | 15 | func (bw *PVBrickWall) defaults() { 16 | if bw.Wipe == nil { 17 | bw.Wipe = C(0) 18 | } 19 | } 20 | 21 | // Rate creates a new ugen at a specific rate. 22 | // If rate is an unsupported value this method will cause a runtime panic. 23 | // If Buffer is nil this method will panic. 24 | func (bw PVBrickWall) Rate(rate int8) Input { 25 | CheckRate(rate) 26 | if bw.Buffer == nil { 27 | panic("PVBrickWall requires a Buffer parameter") 28 | } 29 | (&bw).defaults() 30 | return NewInput("PV_BrickWall", rate, 0, 1, bw.Buffer, bw.Wipe) 31 | } 32 | -------------------------------------------------------------------------------- /rand.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // Rand generates a single random float value in uniform distribution from Lo to Hi. 4 | // It generates this when the SynthDef first starts playing, 5 | // and remains fixed for the duration of the synth's existence. 6 | type Rand struct { 7 | Lo, Hi Input 8 | } 9 | 10 | func (rand *Rand) defaults() { 11 | if rand.Lo == nil { 12 | rand.Lo = C(0) 13 | } 14 | if rand.Hi == nil { 15 | rand.Hi = C(1) 16 | } 17 | } 18 | 19 | // Rate creates a new ugen at a specific rate. 20 | // If rate is an unsupported value this method will cause a runtime panic. 21 | func (rand Rand) Rate(rate int8) Input { 22 | CheckRate(rate) 23 | (&rand).defaults() 24 | return NewInput("Rand", rate, 0, 1, rand.Lo, rand.Hi) 25 | } 26 | -------------------------------------------------------------------------------- /rate.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import "fmt" 4 | 5 | // Ugen rates. 6 | // - IR is initialization rate. 7 | // - KR is control rate. 8 | // - AR is audio rate. 9 | // See http://doc.sccode.org/Tutorials/Mark_Polishook_tutorial/08_Rates.html. 10 | const ( 11 | IR = 0 12 | KR = 1 13 | AR = 2 14 | ) 15 | 16 | // CheckRate causes a panic if rate is not IR, KR, or AR. 17 | func CheckRate(rate int8) { 18 | if rate != IR && rate != KR && rate != AR { 19 | panic(fmt.Errorf("Unsupported rate %d", rate)) 20 | } 21 | } 22 | 23 | // Rater is the interface of a Ugen that can compute its output at different rates. 24 | type Rater interface { 25 | Rate(int8) Input 26 | } 27 | 28 | // A returns a ugen input at audio rate. 29 | func A(r Rater) Input { 30 | return r.Rate(AR) 31 | } 32 | 33 | // I returns a ugen input at initialization rate. 34 | func I(r Rater) Input { 35 | return r.Rate(IR) 36 | } 37 | 38 | // K returns a ugen input at control rate. 39 | func K(r Rater) Input { 40 | return r.Rate(KR) 41 | } 42 | -------------------------------------------------------------------------------- /resonz_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestResonz(t *testing.T) { 8 | const defName = "ResonzTest" 9 | 10 | // Out.ar(0, Resonz.ar(WhiteNoise.ar(0.5), XLine.kr(1000,8000,10), 0.05)); 11 | compareAndWriteStructure(t, defName, NewSynthdef(defName, func(p Params) Ugen { 12 | return Out{ 13 | Bus: C(0), 14 | Channels: A(Resonz{ 15 | In: WhiteNoise{}.Rate(AR).Mul(C(0.5)), 16 | Freq: K(XLine{ 17 | Start: C(1000), 18 | End: C(8000), 19 | Dur: C(10), 20 | }), 21 | BWR: C(0.05), 22 | }), 23 | }.Rate(AR) 24 | })) 25 | } 26 | -------------------------------------------------------------------------------- /ringz_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestRingz(t *testing.T) { 8 | const defName = "RingzTest" 9 | 10 | // Out.ar(0, Ringz.ar(Impulse.ar(6, 0, 0.3), 2000, XLine.kr(4, 0.04, 8))) 11 | compareAndWriteStructure(t, defName, NewSynthdef(defName, func(p Params) Ugen { 12 | pulse := A(Impulse{ 13 | Freq: C(6), 14 | }) 15 | return Out{ 16 | Bus: C(0), 17 | Channels: A(Ringz{ 18 | In: pulse.Mul(C(0.3)), 19 | Freq: C(2000), 20 | DecayTime: K(XLine{ 21 | Start: C(4), 22 | End: C(0.04), 23 | Dur: C(8), 24 | }), 25 | }), 26 | }.Rate(AR) 27 | })) 28 | } 29 | -------------------------------------------------------------------------------- /rlpf.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // RLPF a resonant low pass filter 4 | type RLPF struct { 5 | // In is the input signal 6 | In Input 7 | // Freq cutoff in Hz 8 | Freq Input 9 | // RQ Reciprocal of Q 10 | RQ Input 11 | } 12 | 13 | func (rlpf *RLPF) defaults() { 14 | if rlpf.Freq == nil { 15 | rlpf.Freq = C(440) 16 | } 17 | if rlpf.RQ == nil { 18 | rlpf.RQ = C(1) 19 | } 20 | } 21 | 22 | // Rate creates a new ugen at a specific rate. 23 | // If rate is an unsupported value this method will cause 24 | // a runtime panic. 25 | func (rlpf RLPF) Rate(rate int8) Input { 26 | if rlpf.In == nil { 27 | panic("RLPF expects In to not be nil") 28 | } 29 | CheckRate(rate) 30 | (&rlpf).defaults() 31 | return NewInput("RLPF", rate, 0, 1, rlpf.In, rlpf.Freq, rlpf.RQ) 32 | } 33 | -------------------------------------------------------------------------------- /rlpf_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestRLPF(t *testing.T) { 8 | const defName = "RLPFTest" 9 | 10 | // Out.ar(0, RLPF.ar(Saw.ar(200, 0.1), FSinOsc.kr(XLine.kr(0.7, 300, 20), 0, 3600, 4000), 0.2)); 11 | compareAndWriteStructure(t, defName, NewSynthdef(defName, func(p Params) Ugen { 12 | saw := A(Saw{ 13 | Freq: C(200), 14 | }) 15 | sine := K(FSinOsc{ 16 | Freq: K(XLine{ 17 | Start: C(0.7), 18 | End: C(300), 19 | Dur: C(20), 20 | }), 21 | }) 22 | return Out{ 23 | Bus: C(0), 24 | Channels: A(RLPF{ 25 | In: saw.Mul(C(0.1)), 26 | Freq: sine.MulAdd(C(3600), C(4000)), 27 | RQ: C(0.2), 28 | }), 29 | }.Rate(AR) 30 | })) 31 | } 32 | -------------------------------------------------------------------------------- /runningsum.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // RunningSum is a running sum over a user specified number of samples, 4 | // useful for running RMS power windowing. 5 | type RunningSum struct { 6 | In Input 7 | NumSamp Input 8 | } 9 | 10 | func (r *RunningSum) defaults() { 11 | if r.NumSamp == nil { 12 | r.NumSamp = C(40) 13 | } 14 | } 15 | 16 | // Rate creates a new ugen at a specific rate. 17 | // If rate is an unsupported value this method will cause a runtime panic. 18 | // If the input signal is nil this method will panic. 19 | func (r RunningSum) Rate(rate int8) Input { 20 | CheckRate(rate) 21 | if r.In == nil { 22 | panic("RunningSum requires an input signal") 23 | } 24 | (&r).defaults() 25 | return NewInput("RunningSum", rate, 0, 1, r.In, r.NumSamp) 26 | } 27 | -------------------------------------------------------------------------------- /runningsum_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestRunningSum(t *testing.T) { 8 | const defName = "RunningSumTest" 9 | 10 | // var x = 100; 11 | // Out.ar(0, RunningSum.ar(LFSaw.ar, x) * (x.reciprocal)); 12 | compareAndWriteStructure(t, defName, NewSynthdef(defName, func(p Params) Ugen { 13 | x := C(100) 14 | sum := A(RunningSum{ 15 | In: A(LFSaw{}), 16 | NumSamp: x, 17 | }) 18 | return Out{ 19 | Bus: C(0), 20 | Channels: sum.Mul(x.Reciprocal()), 21 | }.Rate(AR) 22 | })) 23 | } 24 | -------------------------------------------------------------------------------- /sampledur.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // SampleDur returns the current sample duration of the server. 4 | // Equivalent to 1/SampleRate. 5 | type SampleDur struct{} 6 | 7 | // Rate creates a new ugen at a specific rate. 8 | // If rate is not IR this method will cause a runtime panic. 9 | func (s SampleDur) Rate(rate int8) Input { 10 | if rate != IR { 11 | panic("SampleDur only supports IR") 12 | } 13 | return NewInput("SampleDur", rate, 0, 1) 14 | } 15 | -------------------------------------------------------------------------------- /samplerate.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // SampleRate returns the current sample rate of the server. 4 | type SampleRate struct{} 5 | 6 | // Rate creates a new ugen at a specific rate. 7 | // If rate is not IR this method will cause a runtime panic. 8 | func (s SampleRate) Rate(rate int8) Input { 9 | if rate != IR { 10 | panic("SampleRate only supports IR") 11 | } 12 | return NewInput("SampleRate", rate, 0, 1) 13 | } 14 | -------------------------------------------------------------------------------- /saw.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // Saw is a band-limited sawtooth wave generator. 4 | type Saw struct { 5 | Freq Input 6 | } 7 | 8 | func (saw *Saw) defaults() { 9 | if saw.Freq == nil { 10 | saw.Freq = C(440) 11 | } 12 | } 13 | 14 | // Rate creates a new ugen at a specific rate. 15 | // If rate is an unsupported value this method will cause 16 | // a runtime panic. 17 | func (saw Saw) Rate(rate int8) Input { 18 | CheckRate(rate) 19 | (&saw).defaults() 20 | return NewInput("Saw", rate, 0, 1, saw.Freq) 21 | } 22 | -------------------------------------------------------------------------------- /select.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // Select selects an output from an array of inputs. 4 | type Select struct { 5 | Which Input 6 | Inputs []Input 7 | } 8 | 9 | // Rate creates a new ugen at a specific rate. 10 | // If rate is an unsupported value this method will cause 11 | // a runtime panic. 12 | func (sel Select) Rate(rate int8) Input { 13 | CheckRate(rate) 14 | inputs := append([]Input{sel.Which}, sel.Inputs...) 15 | return NewInput("Select", rate, 0, 1, inputs...) 16 | } 17 | -------------------------------------------------------------------------------- /server_darwin.go: -------------------------------------------------------------------------------- 1 | // +build darwin 2 | 3 | package sc 4 | 5 | // ServerPath is the path to scsynth on darwin systems. 6 | const ServerPath = "/Applications/SuperCollider.app/Contents/Resources/scsynth" 7 | -------------------------------------------------------------------------------- /server_linux.go: -------------------------------------------------------------------------------- 1 | // +build linux 2 | 3 | package sc 4 | 5 | // ServerPath is the path the scsynth executable on linux systems. 6 | const ServerPath = "/usr/bin/scsynth:/usr/local/bin/scsynth" 7 | -------------------------------------------------------------------------------- /shaper.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // Shaper performs waveshaping on the input signal by indexing into the table. 4 | type Shaper struct { 5 | // BufNum is the number of a buffer filled in wavetable format 6 | // containing the transfer function. 7 | BufNum Input 8 | 9 | // In is the input signal. 10 | In Input 11 | } 12 | 13 | func (s *Shaper) defaults() { 14 | if s.In == nil { 15 | s.In = C(0) 16 | } 17 | } 18 | 19 | // Rate creates a new ugen at a specific rate. 20 | // If rate is an unsupported value this method will cause a runtime panic. 21 | // If BufNum is nil this method will panic. 22 | func (s Shaper) Rate(rate int8) Input { 23 | CheckRate(rate) 24 | if s.BufNum == nil { 25 | panic("Shaper requires a buffer number") 26 | } 27 | (&s).defaults() 28 | return NewInput("Shaper", rate, 0, 1, s.BufNum, s.In) 29 | } 30 | -------------------------------------------------------------------------------- /shaper_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestShaper(t *testing.T) { 8 | const defName = "ShaperTest" 9 | 10 | // arg bufnum = 0; 11 | // Out.ar(0, Shaper.ar(bufnum, SinOsc.ar(440, 0.5, Line.kr(0,0.9,6))); 12 | compareAndWriteStructure(t, defName, NewSynthdef(defName, func(p Params) Ugen { 13 | var ( 14 | bufnum = p.Add("bufnum", 0) 15 | ) 16 | sine := A(SinOsc{ 17 | Freq: C(440), 18 | Phase: C(0.5), 19 | }) 20 | line := K(Line{ 21 | Start: C(0), 22 | End: C(0.9), 23 | Dur: C(6), 24 | }) 25 | return Out{ 26 | Bus: C(0), 27 | Channels: A(Shaper{ 28 | BufNum: bufnum, 29 | In: sine.Mul(line), 30 | }), 31 | }.Rate(AR) 32 | })) 33 | } 34 | -------------------------------------------------------------------------------- /silent.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // Silent outputs silence. 4 | type Silent struct { 5 | // Number of channels to output. Defaults to 1 if not set. 6 | NumChannels int 7 | } 8 | 9 | func (s *Silent) defaults() { 10 | if s.NumChannels == 0 { 11 | s.NumChannels = 1 12 | } 13 | } 14 | 15 | // Rate creates a new ugen at a specific rate. 16 | // If rate is an unsupported value this method will cause a runtime panic. 17 | func (s Silent) Rate(rate int8) Input { 18 | CheckRate(rate) 19 | (&s).defaults() 20 | return NewInput("DC", rate, 0, s.NumChannels, C(0)) 21 | } 22 | -------------------------------------------------------------------------------- /silent_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestSilent(t *testing.T) { 8 | const defName = "SilentTest" 9 | 10 | // Out.ar(0, Silent.ar(2)); 11 | compareAndWriteStructure(t, defName, NewSynthdef(defName, func(p Params) Ugen { 12 | return Out{ 13 | Bus: C(0), 14 | Channels: Silent{NumChannels: 2}.Rate(AR), 15 | }.Rate(AR) 16 | })) 17 | } 18 | -------------------------------------------------------------------------------- /sinosc_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import "testing" 4 | 5 | func TestSinOsc(t *testing.T) { 6 | name := "SineTone" 7 | def := NewSynthdef(name, func(params Params) Ugen { 8 | bus, freq := C(0), C(440) 9 | sine := SinOsc{Freq: freq}.Rate(AR) 10 | return Out{bus, sine}.Rate(AR) 11 | }) 12 | same, err := def.CompareToFile("testdata/SineTone.scsyndef") 13 | if err != nil { 14 | t.Fatal(err) 15 | } 16 | if !same { 17 | t.Fatalf("synthdef different from sclang version") 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /sinoscfb.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // SinOscFB is a sine oscillator that has phase modulation feedback: its output 4 | // plugs back into the phase input. 5 | // This allows a modulation between a sine wave and a sawtooth like wave. 6 | // Overmodulation causes chaotic oscillation. 7 | // It may be useful if you want to simulate feedback FM synths. 8 | type SinOscFB struct { 9 | Freq Input 10 | Feedback Input 11 | } 12 | 13 | func (s *SinOscFB) defaults() { 14 | if s.Freq == nil { 15 | s.Freq = C(440) 16 | } 17 | if s.Feedback == nil { 18 | s.Feedback = C(0) 19 | } 20 | } 21 | 22 | // Rate creates a new ugen at a specific rate. 23 | // If rate is an unsupported value this method will cause a runtime panic. 24 | func (s SinOscFB) Rate(rate int8) Input { 25 | CheckRate(rate) 26 | (&s).defaults() 27 | return NewInput("SinOscFB", rate, 0, 1, s.Freq, s.Feedback) 28 | } 29 | -------------------------------------------------------------------------------- /sinoscfb_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import ( 4 | "math" 5 | "testing" 6 | ) 7 | 8 | func TestSinOscFB(t *testing.T) { 9 | const defName = "SinOscFBTest" 10 | 11 | // Out.ar(0, SinOscFB.ar(100*SinOscFB.ar(MouseY.kr(1,1000,'exponential'))+200,MouseX.kr(0.5pi,pi))*0.1); 12 | compareAndWriteStructure(t, defName, NewSynthdef(defName, func(p Params) Ugen { 13 | modulator := A(SinOscFB{ 14 | Freq: K(MouseY{ 15 | Min: C(1), 16 | Max: C(1000), 17 | Warp: WarpExp, 18 | }), 19 | }) 20 | feedback := K(MouseX{ 21 | Min: C(0.5 * math.Pi), 22 | Max: C(math.Pi), 23 | }) 24 | return Out{ 25 | Bus: C(0), 26 | Channels: A(SinOscFB{ 27 | Freq: modulator.MulAdd(C(100), C(200)), 28 | Feedback: feedback, 29 | }).Mul(C(0.1)), 30 | }.Rate(AR) 31 | })) 32 | } 33 | -------------------------------------------------------------------------------- /slew.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // Slew limits the slope of an input signal. 4 | // The slope is expressed in units per second. 5 | // For smoothing out control signals, take a look at Lag and VarLag. 6 | type Slew struct { 7 | // In is the input signal 8 | In Input 9 | 10 | // Up is the maximum upward slope in units per second. 11 | Up Input 12 | 13 | // Dn is the maximum downward slope in units per second. 14 | Dn Input 15 | } 16 | 17 | func (s *Slew) defaults() { 18 | if s.In == nil { 19 | s.In = C(0) 20 | } 21 | if s.Up == nil { 22 | s.Up = C(1) 23 | } 24 | if s.Dn == nil { 25 | s.Dn = C(1) 26 | } 27 | } 28 | 29 | // Rate creates a new ugen at a specific rate. 30 | // If rate is an unsupported value this method will cause a runtime panic. 31 | func (s Slew) Rate(rate int8) Input { 32 | CheckRate(rate) 33 | (&s).defaults() 34 | return NewInput("Slew", rate, 0, 1, s.In, s.Up, s.Dn) 35 | } 36 | -------------------------------------------------------------------------------- /slew_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestSlew(t *testing.T) { 8 | const defName = "SlewTest" 9 | 10 | // Out.ar(0, Slew.ar(Saw.ar(800,mul:0.2), 400, 400)); 11 | compareAndWriteStructure(t, defName, NewSynthdef(defName, func(p Params) Ugen { 12 | saw := Saw{Freq: C(800)}.Rate(AR) 13 | return Out{ 14 | Bus: C(0), 15 | Channels: A(Slew{ 16 | In: saw.Mul(C(0.2)), 17 | Up: C(400), 18 | Dn: C(400), 19 | }), 20 | }.Rate(AR) 21 | })) 22 | } 23 | -------------------------------------------------------------------------------- /slope.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // Slope measures the rate of change per second of a signal. 4 | // The formula implemented is: 5 | // out[i] = (in[i] - in[i-1]) * sampling_rate 6 | type Slope struct { 7 | // Input signal. 8 | In Input 9 | } 10 | 11 | func (s *Slope) defaults() { 12 | if s.In == nil { 13 | s.In = C(0) 14 | } 15 | } 16 | 17 | // Rate creates a new ugen at a specific rate. 18 | // If rate is an unsupported value this method will cause a runtime panic. 19 | func (s Slope) Rate(rate int8) Input { 20 | CheckRate(rate) 21 | (&s).defaults() 22 | return NewInput("Slope", rate, 0, 1, s.In) 23 | } 24 | -------------------------------------------------------------------------------- /slope_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestSlope(t *testing.T) { 8 | const defName = "SlopeTest" 9 | 10 | // Out.ar(0, SinOsc.ar(Slope.ar(LFNoise2.ar(10)))); 11 | compareAndWriteStructure(t, defName, NewSynthdef(defName, func(p Params) Ugen { 12 | slope := A(Slope{ 13 | In: A(LFNoise{ 14 | Interpolation: NoiseQuadratic, 15 | Freq: C(10), 16 | }), 17 | }) 18 | return Out{ 19 | Bus: C(0), 20 | Channels: A(SinOsc{Freq: slope}), 21 | }.Rate(AR) 22 | })) 23 | } 24 | -------------------------------------------------------------------------------- /spring.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // Spring models the force of a resonating spring. 4 | type Spring struct { 5 | // Modulated input force. 6 | In Input 7 | 8 | // Spring constant (incl. mass) 9 | Spring Input 10 | 11 | // Damping. 12 | Damp Input 13 | } 14 | 15 | func (b *Spring) defaults() { 16 | if b.In == nil { 17 | b.In = C(0) 18 | } 19 | if b.Spring == nil { 20 | b.Spring = C(1) 21 | } 22 | if b.Damp == nil { 23 | b.Damp = C(0) 24 | } 25 | } 26 | 27 | // Rate creates a new ugen at a specific rate. 28 | // If rate is an unsupported value this method will cause a runtime panic. 29 | func (b Spring) Rate(rate int8) Input { 30 | CheckRate(rate) 31 | (&b).defaults() 32 | return NewInput("Spring", rate, 0, 1, b.In, b.Spring, b.Damp) 33 | } 34 | -------------------------------------------------------------------------------- /spring_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestSpring(t *testing.T) { 8 | const defName = "SpringTest" 9 | 10 | // var sf = LFNoise0.ar(MouseX.kr(1, 100, 1)); 11 | // var g = MouseY.kr(0.1, 10, 1); 12 | // var f = Spring.ar(sf, g, 0.01, 0.01); 13 | // f = f * 140 + 500; 14 | // SinOsc.ar(f, 0, 0.2) 15 | compareAndWriteStructure(t, defName, NewSynthdef(defName, func(p Params) Ugen { 16 | sf := A(LFNoise{ 17 | Interpolation: NoiseStep, 18 | Freq: K(MouseX{ 19 | Min: C(1), 20 | Max: C(100), 21 | Warp: WarpExp, 22 | }), 23 | }) 24 | g := K(MouseY{ 25 | Min: C(0.1), 26 | Max: C(10), 27 | Warp: WarpExp, 28 | }) 29 | f := A(Spring{ 30 | In: sf, 31 | Spring: g, 32 | Damp: C(0.01), 33 | }) 34 | f = f.MulAdd(C(140), C(500)) 35 | 36 | return Out{ 37 | Bus: C(0), 38 | Channels: SinOsc{Freq: f}.Rate(AR).Mul(C(0.2)), 39 | }.Rate(AR) 40 | })) 41 | } 42 | -------------------------------------------------------------------------------- /stack.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | type stack struct { 4 | l []interface{} 5 | } 6 | 7 | func (s *stack) Push(val interface{}) { 8 | s.l = append(s.l, val) 9 | } 10 | 11 | func (s *stack) Pop() interface{} { 12 | l := len(s.l) 13 | if l == 0 { 14 | return nil 15 | } 16 | el := s.l[l-1] 17 | s.l = s.l[0 : l-1] 18 | return el 19 | } 20 | 21 | func (s *stack) Size() int { 22 | return len(s.l) 23 | } 24 | 25 | func newStack() *stack { 26 | s := stack{make([]interface{}, 0)} 27 | return &s 28 | } 29 | -------------------------------------------------------------------------------- /stack_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestStackPushPop(t *testing.T) { 8 | s := newStack() 9 | if s == nil { 10 | t.Fatalf("NewStack returned nil") 11 | } 12 | s.Push(float32(3.14)) 13 | s.Push(float32(-1)) 14 | val := s.Pop() 15 | if fv, isFloat32 := val.(float32); !isFloat32 { 16 | t.Fatalf("Could not cast val to float32") 17 | if fv != float32(-1) { 18 | t.Fatalf("Expected val to be 3.14") 19 | } 20 | } 21 | val = s.Pop() 22 | if fv, isFloat32 := val.(float32); !isFloat32 { 23 | t.Fatalf("Could not cast val to float32") 24 | if fv != float32(3.14) { 25 | t.Fatalf("Expected val to be 3.14") 26 | } 27 | } 28 | val = s.Pop() 29 | if val != nil { 30 | t.Fatalf("popping an empty stack should return nil") 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /sums.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // Sum3 sums three signals. Should be used via Mix. 4 | func Sum3(rate int8, in1, in2, in3 Input) Input { 5 | CheckRate(rate) 6 | return NewInput("Sum3", rate, 0, 1, in1, in2, in3) 7 | } 8 | 9 | // Sum4 sums four signals. Should be used via Mix. 10 | func Sum4(rate int8, in1, in2, in3, in4 Input) Input { 11 | CheckRate(rate) 12 | return NewInput("Sum4", rate, 0, 1, in1, in2, in3, in4) 13 | } 14 | -------------------------------------------------------------------------------- /sums_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // func TestSums(t *testing.T) { 4 | // defName := "Sum3Test" 5 | // def := NewSynthdef(defName, func(params Params) Ugen { 6 | // bus := C(0) 7 | // sig := Sum3(AR, 8 | // PinkNoise{}.Rate(AR).Mul(C(0.1)), 9 | // FSinOsc{Freq: C(801), Phase: C(0.1)}.Rate(AR), 10 | // LFSaw{Freq: C(40), Iphase: C(0.1)}.Rate(AR), 11 | // ) 12 | // return Out{bus, sig}.Rate(AR) 13 | // }) 14 | // compareAndWrite(t, defName, def) 15 | // } 16 | -------------------------------------------------------------------------------- /sweep.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // Sweep starts a linear raise by rate/sec from zero when trig input crosses from 4 | // non-positive to positive. 5 | // When rate == 1, Sweep may be used to get a continually-updating measurement 6 | // of the time (in seconds) since the last trigger. 7 | type Sweep struct { 8 | // Trig triggers when trig input crosses from non-positive to positive. 9 | Trig Input 10 | 11 | // RaiseRate is the rate/sec raise rate. 12 | RaiseRate Input 13 | } 14 | 15 | func (sweep *Sweep) defaults() { 16 | if sweep.Trig == nil { 17 | sweep.Trig = C(0) 18 | } 19 | if sweep.RaiseRate == nil { 20 | sweep.RaiseRate = C(1) 21 | } 22 | } 23 | 24 | // Rate creates a new ugen at a specific rate. 25 | // If rate is an unsupported value this method will cause a runtime panic. 26 | func (sweep Sweep) Rate(rate int8) Input { 27 | CheckRate(rate) 28 | (&sweep).defaults() 29 | return NewInput("Sweep", rate, 0, 1, sweep.Trig, sweep.RaiseRate) 30 | } 31 | -------------------------------------------------------------------------------- /sweep_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestSweep(t *testing.T) { 8 | defName := "SweepTest" 9 | 10 | def := NewSynthdef(defName, func(p Params) Ugen { 11 | return Out{ 12 | Bus: C(0), 13 | Channels: LFPulse{}.Rate(AR).Mul(Sweep{}.Rate(AR)), 14 | }.Rate(AR) 15 | }) 16 | compareAndWrite(t, defName, def) 17 | } 18 | -------------------------------------------------------------------------------- /syncsaw.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // SyncSaw is a sawtooth wave that is hard synched to a fundamental pitch. 4 | // This produces an effect similar to moving formants or pulse width modulation. 5 | // The sawtooth oscillator has its phase reset when the sync oscillator completes a cycle. 6 | // This is not a band limited waveform, so it may alias. 7 | type SyncSaw struct { 8 | // SyncFreq is the frequency of the fundamental. 9 | SyncFreq Input 10 | 11 | // SawFreq is the frequency of the slave synched sawtooth wave. 12 | // It should always be greater than SyncFreq. 13 | SawFreq Input 14 | } 15 | 16 | func (s *SyncSaw) defaults() { 17 | if s.SyncFreq == nil { 18 | s.SyncFreq = C(440) 19 | } 20 | if s.SawFreq == nil { 21 | s.SawFreq = C(440) 22 | } 23 | } 24 | 25 | // Rate creates a new ugen at a specific rate. 26 | // If rate is an unsupported value this method will cause a runtime panic. 27 | func (s SyncSaw) Rate(rate int8) Input { 28 | CheckRate(rate) 29 | (&s).defaults() 30 | return NewInput("SyncSaw", rate, 0, 1, s.SyncFreq, s.SawFreq) 31 | } 32 | -------------------------------------------------------------------------------- /syncsaw_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import "testing" 4 | 5 | func TestSyncSaw(t *testing.T) { 6 | const defName = "SyncSawTest" 7 | 8 | // Out.ar(0, SyncSaw.ar(800, Line.kr(800, 1600, 0.01))); 9 | compareAndWriteStructure(t, defName, NewSynthdef(defName, func(p Params) Ugen { 10 | return Out{ 11 | Bus: C(0), 12 | Channels: A(SyncSaw{ 13 | SyncFreq: C(800), 14 | SawFreq: K(Line{ 15 | Start: C(800), 16 | End: C(1600), 17 | Dur: C(0.01), 18 | }), 19 | }), 20 | }.Rate(AR) 21 | })) 22 | } 23 | -------------------------------------------------------------------------------- /synthdef_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "testing" 7 | ) 8 | 9 | func TestReadSynthdef(t *testing.T) { 10 | // read a synthdef file created by sclang 11 | f, err := os.Open("testdata/SineTone.scsyndef") 12 | if err != nil { 13 | t.Fatal(err) 14 | } 15 | synthDef, err := ReadSynthdef(f) 16 | if err != nil { 17 | t.Fatal(err) 18 | } 19 | // check the name 20 | if synthDef.Name != "SineTone" { 21 | t.Fatal(fmt.Errorf("wrong synthdef name")) 22 | } 23 | } 24 | 25 | func ExampleNewSynthdef() { 26 | _ = NewSynthdef("SineTone", func(p Params) Ugen { 27 | var ( 28 | bus = C(0) 29 | sig = SinOsc{}.Rate(AR) 30 | ) 31 | return Out{Bus: bus, Channels: sig}.Rate(AR) 32 | }).WriteJSON(os.Stdout) 33 | // Output: 34 | // {"name":"SineTone","constants":[440,0],"ugens":[{"name":"SinOsc","rate":2,"specialIndex":0,"inputs":[{"ugenIndex":-1,"outputIndex":0},{"ugenIndex":-1,"outputIndex":1}],"outputs":[2]},{"name":"Out","rate":2,"specialIndex":0,"inputs":[{"ugenIndex":-1,"outputIndex":1},{"ugenIndex":0,"outputIndex":0}]}]} 35 | } 36 | -------------------------------------------------------------------------------- /tdelay.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // TDelay delays a trigger by a given time. 4 | // Any triggers which arrive in the time between an input trigger and its 5 | // delayed output, are ignored. 6 | type TDelay struct { 7 | // In is the input trigger signal. 8 | In Input 9 | 10 | // Dur is the delay time in seconds. 11 | Dur Input 12 | } 13 | 14 | func (t *TDelay) defaults() { 15 | if t.In == nil { 16 | t.In = C(0) 17 | } 18 | if t.Dur == nil { 19 | t.Dur = C(0.1) 20 | } 21 | } 22 | 23 | // Rate creates a new ugen at a specific rate. 24 | // If rate is an unsupported value this method will cause a runtime panic. 25 | func (t TDelay) Rate(rate int8) Input { 26 | CheckRate(rate) 27 | (&t).defaults() 28 | return NewInput("TDelay", rate, 0, 1, t.In, t.Dur) 29 | } 30 | -------------------------------------------------------------------------------- /tdelay_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestTDelay(t *testing.T) { 8 | const defName = "TDelayTest" 9 | 10 | // z = Impulse.ar(2); 11 | // Out.ar(0, [z * 0.1, ToggleFF.ar(TDelay.ar(z, 0.5)) * SinOsc.ar(mul: 0.1)]); 12 | compareAndWriteStructure(t, defName, NewSynthdef(defName, func(p Params) Ugen { 13 | var ( 14 | z = Impulse{Freq: C(2)}.Rate(AR) 15 | sine = SinOsc{}.Rate(AR).Mul(C(0.1)) 16 | ) 17 | toggle := A(ToggleFF{ 18 | Trig: A(TDelay{ 19 | In: z, 20 | Dur: C(0.5), 21 | }), 22 | }) 23 | return Out{ 24 | Bus: C(0), 25 | Channels: Multi( 26 | z.Mul(C(0.1)), 27 | toggle.Mul(sine), 28 | ), 29 | }.Rate(AR) 30 | })) 31 | } 32 | -------------------------------------------------------------------------------- /testdata/AllpassExample.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/AllpassExample.scsyndef -------------------------------------------------------------------------------- /testdata/AllpassnExample.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/AllpassnExample.scsyndef -------------------------------------------------------------------------------- /testdata/BAllPassExample.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/BAllPassExample.scsyndef -------------------------------------------------------------------------------- /testdata/BLowPassTest.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/BLowPassTest.scsyndef -------------------------------------------------------------------------------- /testdata/BPFExample.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/BPFExample.scsyndef -------------------------------------------------------------------------------- /testdata/BRFExample.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/BRFExample.scsyndef -------------------------------------------------------------------------------- /testdata/Balance2Test.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/Balance2Test.scsyndef -------------------------------------------------------------------------------- /testdata/BallTest.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/BallTest.scsyndef -------------------------------------------------------------------------------- /testdata/Beats.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/Beats.scsyndef -------------------------------------------------------------------------------- /testdata/BlipExample.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/BlipExample.scsyndef -------------------------------------------------------------------------------- /testdata/BrownNoiseTest.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/BrownNoiseTest.scsyndef -------------------------------------------------------------------------------- /testdata/COscTest.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/COscTest.scsyndef -------------------------------------------------------------------------------- /testdata/Cascade.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/Cascade.scsyndef -------------------------------------------------------------------------------- /testdata/CascadeExample.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/CascadeExample.scsyndef -------------------------------------------------------------------------------- /testdata/ClipNoiseTest.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/ClipNoiseTest.scsyndef -------------------------------------------------------------------------------- /testdata/CoinGateTest.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/CoinGateTest.scsyndef -------------------------------------------------------------------------------- /testdata/CombCTest.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/CombCTest.scsyndef -------------------------------------------------------------------------------- /testdata/CombLTest.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/CombLTest.scsyndef -------------------------------------------------------------------------------- /testdata/CombNTest.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/CombNTest.scsyndef -------------------------------------------------------------------------------- /testdata/CrackleTest.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/CrackleTest.scsyndef -------------------------------------------------------------------------------- /testdata/DCTest.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/DCTest.scsyndef -------------------------------------------------------------------------------- /testdata/Decay2Test.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/Decay2Test.scsyndef -------------------------------------------------------------------------------- /testdata/DelayCTest.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/DelayCTest.scsyndef -------------------------------------------------------------------------------- /testdata/DelayLTest.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/DelayLTest.scsyndef -------------------------------------------------------------------------------- /testdata/DelayNTest.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/DelayNTest.scsyndef -------------------------------------------------------------------------------- /testdata/DetectSilence.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/DetectSilence.scsyndef -------------------------------------------------------------------------------- /testdata/Dust2Test.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/Dust2Test.scsyndef -------------------------------------------------------------------------------- /testdata/DustTest.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/DustTest.scsyndef -------------------------------------------------------------------------------- /testdata/Envgen1.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/Envgen1.scsyndef -------------------------------------------------------------------------------- /testdata/EnvgenTest.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/EnvgenTest.scsyndef -------------------------------------------------------------------------------- /testdata/FFTTest.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/FFTTest.scsyndef -------------------------------------------------------------------------------- /testdata/FSinOscExample.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/FSinOscExample.scsyndef -------------------------------------------------------------------------------- /testdata/FittonBubbles.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/FittonBubbles.scsyndef -------------------------------------------------------------------------------- /testdata/FormantTest.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/FormantTest.scsyndef -------------------------------------------------------------------------------- /testdata/FormletTest.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/FormletTest.scsyndef -------------------------------------------------------------------------------- /testdata/FreeVerbExample.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/FreeVerbExample.scsyndef -------------------------------------------------------------------------------- /testdata/FreeVerbTest.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/FreeVerbTest.scsyndef -------------------------------------------------------------------------------- /testdata/GVerbExample.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/GVerbExample.scsyndef -------------------------------------------------------------------------------- /testdata/GateTest.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/GateTest.scsyndef -------------------------------------------------------------------------------- /testdata/Gendy1Test.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/Gendy1Test.scsyndef -------------------------------------------------------------------------------- /testdata/Gendy2Test.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/Gendy2Test.scsyndef -------------------------------------------------------------------------------- /testdata/Gendy3Test.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/Gendy3Test.scsyndef -------------------------------------------------------------------------------- /testdata/GrainBufTest.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/GrainBufTest.scsyndef -------------------------------------------------------------------------------- /testdata/GrainFMExample.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/GrainFMExample.scsyndef -------------------------------------------------------------------------------- /testdata/GrainFMTest.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/GrainFMTest.scsyndef -------------------------------------------------------------------------------- /testdata/GrainInTest.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/GrainInTest.scsyndef -------------------------------------------------------------------------------- /testdata/GrainSinTest.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/GrainSinTest.scsyndef -------------------------------------------------------------------------------- /testdata/HPFExample.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/HPFExample.scsyndef -------------------------------------------------------------------------------- /testdata/HasherTest.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/HasherTest.scsyndef -------------------------------------------------------------------------------- /testdata/ImpulseExample.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/ImpulseExample.scsyndef -------------------------------------------------------------------------------- /testdata/InTest.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/InTest.scsyndef -------------------------------------------------------------------------------- /testdata/IntegratorExample.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/IntegratorExample.scsyndef -------------------------------------------------------------------------------- /testdata/KlangTest.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/KlangTest.scsyndef -------------------------------------------------------------------------------- /testdata/KlankTest1.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/KlankTest1.scsyndef -------------------------------------------------------------------------------- /testdata/LFClipNoiseTest.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/LFClipNoiseTest.scsyndef -------------------------------------------------------------------------------- /testdata/LFCubTest.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/LFCubTest.scsyndef -------------------------------------------------------------------------------- /testdata/LFDClipNoiseTest.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/LFDClipNoiseTest.scsyndef -------------------------------------------------------------------------------- /testdata/LFGaussTest.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/LFGaussTest.scsyndef -------------------------------------------------------------------------------- /testdata/LFNoise1Example.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/LFNoise1Example.scsyndef -------------------------------------------------------------------------------- /testdata/LFParTest.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/LFParTest.scsyndef -------------------------------------------------------------------------------- /testdata/LFPulseTest.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/LFPulseTest.scsyndef -------------------------------------------------------------------------------- /testdata/LFSawExample.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/LFSawExample.scsyndef -------------------------------------------------------------------------------- /testdata/LFTriExample.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/LFTriExample.scsyndef -------------------------------------------------------------------------------- /testdata/LPFExample.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/LPFExample.scsyndef -------------------------------------------------------------------------------- /testdata/LagTest.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/LagTest.scsyndef -------------------------------------------------------------------------------- /testdata/LatchTest.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/LatchTest.scsyndef -------------------------------------------------------------------------------- /testdata/LeakDCTest.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/LeakDCTest.scsyndef -------------------------------------------------------------------------------- /testdata/LinPan2Test.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/LinPan2Test.scsyndef -------------------------------------------------------------------------------- /testdata/LinXFade2Test.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/LinXFade2Test.scsyndef -------------------------------------------------------------------------------- /testdata/LineTest.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/LineTest.scsyndef -------------------------------------------------------------------------------- /testdata/MedianTest.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/MedianTest.scsyndef -------------------------------------------------------------------------------- /testdata/MixTest.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/MixTest.scsyndef -------------------------------------------------------------------------------- /testdata/OnePoleTest.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/OnePoleTest.scsyndef -------------------------------------------------------------------------------- /testdata/OneZeroTest.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/OneZeroTest.scsyndef -------------------------------------------------------------------------------- /testdata/OscNTest.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/OscNTest.scsyndef -------------------------------------------------------------------------------- /testdata/OscTest.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/OscTest.scsyndef -------------------------------------------------------------------------------- /testdata/PMOscTest.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/PMOscTest.scsyndef -------------------------------------------------------------------------------- /testdata/PSinGrainTest.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/PSinGrainTest.scsyndef -------------------------------------------------------------------------------- /testdata/Pan2Test.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/Pan2Test.scsyndef -------------------------------------------------------------------------------- /testdata/Pan4Test.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/Pan4Test.scsyndef -------------------------------------------------------------------------------- /testdata/PanAzTest.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/PanAzTest.scsyndef -------------------------------------------------------------------------------- /testdata/PanB2Test.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/PanB2Test.scsyndef -------------------------------------------------------------------------------- /testdata/PlayBufExample.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/PlayBufExample.scsyndef -------------------------------------------------------------------------------- /testdata/PulseCountTest.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/PulseCountTest.scsyndef -------------------------------------------------------------------------------- /testdata/PulseDividerTest.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/PulseDividerTest.scsyndef -------------------------------------------------------------------------------- /testdata/PulseTest.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/PulseTest.scsyndef -------------------------------------------------------------------------------- /testdata/RLPFTest.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/RLPFTest.scsyndef -------------------------------------------------------------------------------- /testdata/ResonzTest.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/ResonzTest.scsyndef -------------------------------------------------------------------------------- /testdata/RingzTest.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/RingzTest.scsyndef -------------------------------------------------------------------------------- /testdata/RunningSumTest.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/RunningSumTest.scsyndef -------------------------------------------------------------------------------- /testdata/SameSame.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/SameSame.scsyndef -------------------------------------------------------------------------------- /testdata/SawTone1.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/SawTone1.scsyndef -------------------------------------------------------------------------------- /testdata/SelectTest.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/SelectTest.scsyndef -------------------------------------------------------------------------------- /testdata/ShaperTest.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/ShaperTest.scsyndef -------------------------------------------------------------------------------- /testdata/SilentTest.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/SilentTest.scsyndef -------------------------------------------------------------------------------- /testdata/SimpleMulti.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/SimpleMulti.scsyndef -------------------------------------------------------------------------------- /testdata/SinOscFBTest.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/SinOscFBTest.scsyndef -------------------------------------------------------------------------------- /testdata/SineTone.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/SineTone.scsyndef -------------------------------------------------------------------------------- /testdata/SineTone2.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/SineTone2.scsyndef -------------------------------------------------------------------------------- /testdata/SineTone3.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/SineTone3.scsyndef -------------------------------------------------------------------------------- /testdata/SineTone4.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/SineTone4.scsyndef -------------------------------------------------------------------------------- /testdata/SlewTest.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/SlewTest.scsyndef -------------------------------------------------------------------------------- /testdata/SlopeTest.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/SlopeTest.scsyndef -------------------------------------------------------------------------------- /testdata/SoundInTest0.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/SoundInTest0.scsyndef -------------------------------------------------------------------------------- /testdata/SoundInTest00.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/SoundInTest00.scsyndef -------------------------------------------------------------------------------- /testdata/SoundInTest01.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/SoundInTest01.scsyndef -------------------------------------------------------------------------------- /testdata/SoundInTest02.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/SoundInTest02.scsyndef -------------------------------------------------------------------------------- /testdata/SoundInTest12.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/SoundInTest12.scsyndef -------------------------------------------------------------------------------- /testdata/SoundInTest20.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/SoundInTest20.scsyndef -------------------------------------------------------------------------------- /testdata/SpringTest.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/SpringTest.scsyndef -------------------------------------------------------------------------------- /testdata/Sum3Test.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/Sum3Test.scsyndef -------------------------------------------------------------------------------- /testdata/SweepTest.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/SweepTest.scsyndef -------------------------------------------------------------------------------- /testdata/SyncSawTest.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/SyncSawTest.scsyndef -------------------------------------------------------------------------------- /testdata/TDelayTest.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/TDelayTest.scsyndef -------------------------------------------------------------------------------- /testdata/TGrainsExample.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/TGrainsExample.scsyndef -------------------------------------------------------------------------------- /testdata/THX.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/THX.scsyndef -------------------------------------------------------------------------------- /testdata/TestEnvADSR.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/TestEnvADSR.scsyndef -------------------------------------------------------------------------------- /testdata/Trig1Test.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/Trig1Test.scsyndef -------------------------------------------------------------------------------- /testdata/TrigTest.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/TrigTest.scsyndef -------------------------------------------------------------------------------- /testdata/UseParam.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/UseParam.scsyndef -------------------------------------------------------------------------------- /testdata/VOsc3Test.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/VOsc3Test.scsyndef -------------------------------------------------------------------------------- /testdata/VOscTest.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/VOscTest.scsyndef -------------------------------------------------------------------------------- /testdata/VarSawTest.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/VarSawTest.scsyndef -------------------------------------------------------------------------------- /testdata/VibratoTest.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/VibratoTest.scsyndef -------------------------------------------------------------------------------- /testdata/Warp1Example.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/Warp1Example.scsyndef -------------------------------------------------------------------------------- /testdata/XFade2Test.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/XFade2Test.scsyndef -------------------------------------------------------------------------------- /testdata/XLineTest.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/XLineTest.scsyndef -------------------------------------------------------------------------------- /testdata/absExample.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/absExample.scsyndef -------------------------------------------------------------------------------- /testdata/absdifExample.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/absdifExample.scsyndef -------------------------------------------------------------------------------- /testdata/acosExample.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/acosExample.scsyndef -------------------------------------------------------------------------------- /testdata/amclipExample.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/amclipExample.scsyndef -------------------------------------------------------------------------------- /testdata/ampdbExample.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/ampdbExample.scsyndef -------------------------------------------------------------------------------- /testdata/asinExample.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/asinExample.scsyndef -------------------------------------------------------------------------------- /testdata/atan2Example.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/atan2Example.scsyndef -------------------------------------------------------------------------------- /testdata/atanExample.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/atanExample.scsyndef -------------------------------------------------------------------------------- /testdata/bar.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/bar.scsyndef -------------------------------------------------------------------------------- /testdata/baz.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/baz.scsyndef -------------------------------------------------------------------------------- /testdata/bilinrandExample.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/bilinrandExample.scsyndef -------------------------------------------------------------------------------- /testdata/ceilExample.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/ceilExample.scsyndef -------------------------------------------------------------------------------- /testdata/clip2Example.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/clip2Example.scsyndef -------------------------------------------------------------------------------- /testdata/coinExample.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/coinExample.scsyndef -------------------------------------------------------------------------------- /testdata/cosExample.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/cosExample.scsyndef -------------------------------------------------------------------------------- /testdata/coshExample.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/coshExample.scsyndef -------------------------------------------------------------------------------- /testdata/cpsmidiExample.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/cpsmidiExample.scsyndef -------------------------------------------------------------------------------- /testdata/cpsoctExample.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/cpsoctExample.scsyndef -------------------------------------------------------------------------------- /testdata/cubedExample.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/cubedExample.scsyndef -------------------------------------------------------------------------------- /testdata/dbampExample.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/dbampExample.scsyndef -------------------------------------------------------------------------------- /testdata/defWith2Params.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/defWith2Params.scsyndef -------------------------------------------------------------------------------- /testdata/difsqrExample.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/difsqrExample.scsyndef -------------------------------------------------------------------------------- /testdata/distortExample.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/distortExample.scsyndef -------------------------------------------------------------------------------- /testdata/divExample.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/divExample.scsyndef -------------------------------------------------------------------------------- /testdata/excessExample.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/excessExample.scsyndef -------------------------------------------------------------------------------- /testdata/expExample.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/expExample.scsyndef -------------------------------------------------------------------------------- /testdata/exponExample.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/exponExample.scsyndef -------------------------------------------------------------------------------- /testdata/floorExample.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/floorExample.scsyndef -------------------------------------------------------------------------------- /testdata/fold2Example.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/fold2Example.scsyndef -------------------------------------------------------------------------------- /testdata/foo.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/foo.scsyndef -------------------------------------------------------------------------------- /testdata/fracExample.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/fracExample.scsyndef -------------------------------------------------------------------------------- /testdata/gcdExample.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/gcdExample.scsyndef -------------------------------------------------------------------------------- /testdata/gtExample.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/gtExample.scsyndef -------------------------------------------------------------------------------- /testdata/gteExample.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/gteExample.scsyndef -------------------------------------------------------------------------------- /testdata/hypotExample.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/hypotExample.scsyndef -------------------------------------------------------------------------------- /testdata/hypotapxExample.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/hypotapxExample.scsyndef -------------------------------------------------------------------------------- /testdata/lcmExample.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/lcmExample.scsyndef -------------------------------------------------------------------------------- /testdata/linrandExample.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/linrandExample.scsyndef -------------------------------------------------------------------------------- /testdata/log10Example.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/log10Example.scsyndef -------------------------------------------------------------------------------- /testdata/log2Example.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/log2Example.scsyndef -------------------------------------------------------------------------------- /testdata/logExample.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/logExample.scsyndef -------------------------------------------------------------------------------- /testdata/ltExample.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/ltExample.scsyndef -------------------------------------------------------------------------------- /testdata/lteExample.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/lteExample.scsyndef -------------------------------------------------------------------------------- /testdata/midiratioExample.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/midiratioExample.scsyndef -------------------------------------------------------------------------------- /testdata/minExample.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/minExample.scsyndef -------------------------------------------------------------------------------- /testdata/moddifExample.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/moddifExample.scsyndef -------------------------------------------------------------------------------- /testdata/moduloExample.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/moduloExample.scsyndef -------------------------------------------------------------------------------- /testdata/negExample.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/negExample.scsyndef -------------------------------------------------------------------------------- /testdata/octcpsExample.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/octcpsExample.scsyndef -------------------------------------------------------------------------------- /testdata/powExample.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/powExample.scsyndef -------------------------------------------------------------------------------- /testdata/rand2Example.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/rand2Example.scsyndef -------------------------------------------------------------------------------- /testdata/randExample.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/randExample.scsyndef -------------------------------------------------------------------------------- /testdata/ratiomidiExample.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/ratiomidiExample.scsyndef -------------------------------------------------------------------------------- /testdata/reciprocalExample.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/reciprocalExample.scsyndef -------------------------------------------------------------------------------- /testdata/ring1Example.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/ring1Example.scsyndef -------------------------------------------------------------------------------- /testdata/ring2Example.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/ring2Example.scsyndef -------------------------------------------------------------------------------- /testdata/ring3Example.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/ring3Example.scsyndef -------------------------------------------------------------------------------- /testdata/ring4Example.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/ring4Example.scsyndef -------------------------------------------------------------------------------- /testdata/roundExample.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/roundExample.scsyndef -------------------------------------------------------------------------------- /testdata/scalenegExample.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/scalenegExample.scsyndef -------------------------------------------------------------------------------- /testdata/signExample.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/signExample.scsyndef -------------------------------------------------------------------------------- /testdata/sinExample.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/sinExample.scsyndef -------------------------------------------------------------------------------- /testdata/sinhExample.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/sinhExample.scsyndef -------------------------------------------------------------------------------- /testdata/sqrdifExample.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/sqrdifExample.scsyndef -------------------------------------------------------------------------------- /testdata/sqrsumExample.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/sqrsumExample.scsyndef -------------------------------------------------------------------------------- /testdata/sqrtExample.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/sqrtExample.scsyndef -------------------------------------------------------------------------------- /testdata/squaredExample.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/squaredExample.scsyndef -------------------------------------------------------------------------------- /testdata/sub.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/sub.scsyndef -------------------------------------------------------------------------------- /testdata/sum3randExample.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/sum3randExample.scsyndef -------------------------------------------------------------------------------- /testdata/sumsqrExample.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/sumsqrExample.scsyndef -------------------------------------------------------------------------------- /testdata/tanExample.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/tanExample.scsyndef -------------------------------------------------------------------------------- /testdata/tanhExample.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/tanhExample.scsyndef -------------------------------------------------------------------------------- /testdata/threshExample.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/threshExample.scsyndef -------------------------------------------------------------------------------- /testdata/truncExample.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/truncExample.scsyndef -------------------------------------------------------------------------------- /testdata/wrap2Example.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scgolang/sc/2b87756659e2b72d97cec43b6896ed01c0365097/testdata/wrap2Example.scsyndef -------------------------------------------------------------------------------- /tgrains_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import "testing" 4 | 5 | func TestTGrains(t *testing.T) { 6 | name := "TGrainsExample" 7 | def := NewSynthdef(name, func(params Params) Ugen { 8 | bus, numChannels, trate := C(0), 2, Impulse{Freq: C(4)}.Rate(AR) 9 | tg := TGrains{NumChannels: numChannels, Trigger: trate}.Rate(AR) 10 | return Out{bus, tg}.Rate(AR) 11 | }) 12 | same, err := def.CompareToFile("testdata/TGrainsExample.scsyndef") 13 | if err != nil { 14 | t.Fatal(err) 15 | } 16 | if !same { 17 | t.Fatalf("synthdef different from sclang version") 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /toggleff.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // ToggleFF toggles between 0 and 1 upon receiving a trigger. 4 | type ToggleFF struct { 5 | Trig Input 6 | } 7 | 8 | func (t *ToggleFF) defaults() { 9 | if t.Trig == nil { 10 | t.Trig = C(0) 11 | } 12 | } 13 | 14 | // Rate creates a new ugen at a specific rate. 15 | // If rate is an unsupported value this method will cause a runtime panic. 16 | func (t ToggleFF) Rate(rate int8) Input { 17 | CheckRate(rate) 18 | (&t).defaults() 19 | return NewInput("ToggleFF", rate, 0, 1, t.Trig) 20 | } 21 | -------------------------------------------------------------------------------- /trand.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // TRand generates a random float value in uniform distribution from 4 | // Lo to Hi each time Trig changes from nonpositive to positive values. 5 | type TRand struct { 6 | Lo Input 7 | Hi Input 8 | Trig Input 9 | } 10 | 11 | func (t *TRand) defaults() { 12 | if t.Lo == nil { 13 | t.Lo = C(0) 14 | } 15 | if t.Hi == nil { 16 | t.Hi = C(1) 17 | } 18 | if t.Trig == nil { 19 | t.Trig = C(0) 20 | } 21 | } 22 | 23 | // Rate creates a new ugen at a specific rate. 24 | // If rate is an unsupported value this method will cause a runtime panic. 25 | func (t TRand) Rate(rate int8) Input { 26 | CheckRate(rate) 27 | (&t).defaults() 28 | return NewInput("TRand", rate, 0, 1, t.Lo, t.Hi, t.Trig) 29 | } 30 | -------------------------------------------------------------------------------- /trig.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // Trig outputs the level of the triggering input for the specified duration 4 | // when a nonpositive to positive transition occurs at the input. 5 | // Otherwise it outputs zero. 6 | type Trig struct { 7 | // In is the input trigger signal. 8 | // A trigger happens when the signal changes from non-positive to positive. 9 | In Input 10 | 11 | // Dur is the duration of the trigger output. 12 | Dur Input 13 | } 14 | 15 | func (t *Trig) defaults() { 16 | if t.In == nil { 17 | t.In = C(0) 18 | } 19 | if t.Dur == nil { 20 | t.Dur = C(0.1) 21 | } 22 | } 23 | 24 | // Rate creates a new ugen at a specific rate. 25 | // If rate is an unsupported value this method will cause a runtime panic. 26 | func (t Trig) Rate(rate int8) Input { 27 | CheckRate(rate) 28 | (&t).defaults() 29 | return NewInput("Trig", rate, 0, 1, t.In, t.Dur) 30 | } 31 | -------------------------------------------------------------------------------- /trig1.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // Trig1 outputs 1 for the specified duration when a nonpositive to positive transition occurs 4 | // at the trigger input. 5 | // Otherwise it outputs zero. 6 | type Trig1 struct { 7 | // In is the input trigger signal. 8 | // A trigger happens when the signal changes from non-positive to positive. 9 | In Input 10 | 11 | // Dur is the duration of the trigger output. 12 | Dur Input 13 | } 14 | 15 | func (t *Trig1) defaults() { 16 | if t.In == nil { 17 | t.In = C(0) 18 | } 19 | if t.Dur == nil { 20 | t.Dur = C(0.1) 21 | } 22 | } 23 | 24 | // Rate creates a new ugen at a specific rate. 25 | // If rate is an unsupported value this method will cause a runtime panic. 26 | func (t Trig1) Rate(rate int8) Input { 27 | CheckRate(rate) 28 | (&t).defaults() 29 | return NewInput("Trig1", rate, 0, 1, t.In, t.Dur) 30 | } 31 | -------------------------------------------------------------------------------- /trig1_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestTrig1(t *testing.T) { 8 | const defname = "Trig1Test" 9 | 10 | // Trig1.ar(Dust.ar(1), 0.2) * FSinOsc.ar(800, 0.5) 11 | compareAndWriteStructure(t, defname, NewSynthdef(defname, func(p Params) Ugen { 12 | dust := A(Dust{ 13 | Density: C(1), 14 | }) 15 | trig := A(Trig1{ 16 | In: dust, 17 | Dur: C(0.2), 18 | }) 19 | sine := A(FSinOsc{ 20 | Freq: C(800), 21 | Phase: C(0.5), 22 | }) 23 | return Out{ 24 | Bus: C(0), 25 | Channels: trig.Mul(sine), 26 | }.Rate(AR) 27 | })) 28 | } 29 | -------------------------------------------------------------------------------- /trig_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestTrig(t *testing.T) { 8 | const defname = "TrigTest" 9 | 10 | // Trig.ar(Dust.ar(1), 0.2) * FSinOsc.ar(800, 0.5) 11 | compareAndWriteStructure(t, defname, NewSynthdef(defname, func(p Params) Ugen { 12 | dust := A(Dust{ 13 | Density: C(1), 14 | }) 15 | trig := A(Trig{ 16 | In: dust, 17 | Dur: C(0.2), 18 | }) 19 | sine := A(FSinOsc{ 20 | Freq: C(800), 21 | Phase: C(0.5), 22 | }) 23 | return Out{ 24 | Bus: C(0), 25 | Channels: trig.Mul(sine), 26 | }.Rate(AR) 27 | })) 28 | } 29 | -------------------------------------------------------------------------------- /ugenFunc.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // UgenFunc is a func that is used to define a ugen graph. 4 | type UgenFunc func(p Params) Ugen 5 | 6 | // Play corresponds to http://doc.sccode.org/Classes/Function.html#-play. 7 | // It wraps the provided UgenFunc in a synthdef, 8 | // sends this synthdef to a server instance with DefaultClient, 9 | // then creates a new synth from the synthdef. 10 | func Play(c *Client, f UgenFunc) error { 11 | // To implement this we need a DefaultServer and 12 | // a way to generate the names of the temp synthdefs. 13 | // If the ugen node returned by f is not Out, 14 | // wrap the node in an Out ugen with bus 0. 15 | return nil 16 | } 17 | -------------------------------------------------------------------------------- /ugenNode_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestAddConstantInput(t *testing.T) { 8 | n := NewUgen("foo", 2, 0, 1, C(3.14)) 9 | if inputs := n.inputs; len(inputs) != 1 { 10 | t.Fatalf("len(inputs) was %d", len(inputs)) 11 | } 12 | } 13 | 14 | func TestIsOutput(t *testing.T) { 15 | n := NewUgen("foo", 2, 0, 1) 16 | n = asOutput(n) 17 | outputs := n.Outputs 18 | if numOutputs := len(outputs); numOutputs != 1 { 19 | t.Fatalf("number of outputs was %d", numOutputs) 20 | } 21 | } 22 | 23 | func TestAddUgenInput(t *testing.T) { 24 | s := SinOsc{}.Rate(AR) 25 | if s == nil { 26 | t.Fatalf("SinOsc.Rate returned nil") 27 | } 28 | Out{C(0), s}.Rate(AR) 29 | if sn, isNode := s.(*Ugen); isNode { 30 | outputs := sn.Outputs 31 | if numOutputs := len(outputs); numOutputs != 1 { 32 | t.Fatalf("number of SinOsc outputs was %d", numOutputs) 33 | } 34 | } else { 35 | t.Fatalf("SinOsc with no multi inputs should return *Node") 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /variant.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import ( 4 | "encoding/binary" 5 | "io" 6 | ) 7 | 8 | // Variant provides a way to create synthdef presets. 9 | type Variant struct { 10 | Name string `json:"name,omitempty"` 11 | InitialParamValues []float32 `json:"initialParamValues"` 12 | } 13 | 14 | // Write writes a variant to an io.Writer. 15 | func (variant *Variant) Write(w io.Writer) error { 16 | if err := newPstring(variant.Name).Write(w); err != nil { 17 | return err 18 | } 19 | for _, v := range variant.InitialParamValues { 20 | if err := binary.Write(w, byteOrder, v); err != nil { 21 | return err 22 | } 23 | } 24 | return nil 25 | } 26 | 27 | // readVariant read a Variant from an io.Reader 28 | func readVariant(r io.Reader, numParams int32) (*Variant, error) { 29 | name, err := readPstring(r) 30 | if err != nil { 31 | return nil, err 32 | } 33 | paramValues := make([]float32, numParams) 34 | for i := 0; int32(i) < numParams; i++ { 35 | if err := binary.Read(r, byteOrder, ¶mValues[i]); err != nil { 36 | return nil, err 37 | } 38 | } 39 | v := Variant{name.String(), paramValues} 40 | return &v, nil 41 | } 42 | -------------------------------------------------------------------------------- /varsaw.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // VarSaw is a sawtooth-triangle oscillator with variable duty. 4 | type VarSaw struct { 5 | // Freq is the oscillator's frequency in Hz. 6 | Freq Input 7 | 8 | // IPhase is the oscillator's initial phase in cycles (0..1). 9 | IPhase Input 10 | 11 | // Width is the duty cycle from 0 to 1. 12 | Width Input 13 | } 14 | 15 | func (vs *VarSaw) defaults() { 16 | if vs.Freq == nil { 17 | vs.Freq = C(440) 18 | } 19 | if vs.IPhase == nil { 20 | vs.IPhase = C(0) 21 | } 22 | if vs.Width == nil { 23 | vs.Width = C(0.5) 24 | } 25 | } 26 | 27 | // Rate creates a new ugen at a specific rate. 28 | // If rate is an unsupported value this method will cause a runtime panic. 29 | func (vs VarSaw) Rate(rate int8) Input { 30 | CheckRate(rate) 31 | (&vs).defaults() 32 | return NewInput("VarSaw", rate, 0, 1, vs.Freq, vs.IPhase, vs.Width) 33 | } 34 | -------------------------------------------------------------------------------- /varsaw_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestVarSaw(t *testing.T) { 8 | const defname = "VarSawTest" 9 | 10 | // Out.ar(0, VarSaw.ar(LFPulse.kr(3, 0, 0.3, 200, 200), 0, 0.2, 0.1)); 11 | compareAndWriteStructure(t, defname, NewSynthdef(defname, func(p Params) Ugen { 12 | pulse := K(LFPulse{ 13 | Freq: C(3), 14 | IPhase: C(0), 15 | Width: C(0.3), 16 | }) 17 | saw := A(VarSaw{ 18 | Freq: pulse.MulAdd(C(200), C(200)), 19 | IPhase: C(0), 20 | Width: C(0.2), 21 | }) 22 | return Out{ 23 | Bus: C(0), 24 | Channels: saw.Mul(C(0.1)), 25 | }.Rate(AR) 26 | })) 27 | } 28 | -------------------------------------------------------------------------------- /vibrato_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestVibrato(t *testing.T) { 8 | const defName = "VibratoTest" 9 | 10 | // var freq = DC.ar(400.0); 11 | // var rate = MouseX.kr(2.0, 100.0); 12 | // var ratevar = MouseY.kr(0.0, 1.0); 13 | // Out.ar(0, SinOsc.ar(Vibrato.ar(freq, rate, 0.1, 1.0, 1.0, ratevar, 0.1))); 14 | compareAndWriteStructure(t, defName, NewSynthdef(defName, func(p Params) Ugen { 15 | var ( 16 | freq = DC{In: C(400)}.Rate(AR) 17 | rate = MouseX{Min: C(2), Max: C(100)}.Rate(KR) 18 | ratevar = MouseY{Min: C(0), Max: C(1)}.Rate(KR) 19 | ) 20 | return Out{ 21 | Bus: C(0), 22 | Channels: A(SinOsc{ 23 | Freq: A(Vibrato{ 24 | Freq: freq, 25 | Speed: rate, 26 | Depth: C(0.1), 27 | Delay: C(1), 28 | Onset: C(1), 29 | RateVariation: ratevar, 30 | DepthVariation: C(0.1), 31 | }), 32 | }), 33 | }.Rate(AR) 34 | })) 35 | } 36 | -------------------------------------------------------------------------------- /vosc3_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestVOsc3(t *testing.T) { 8 | defName := "VOsc3Test" 9 | 10 | // arg bufnum = 0; 11 | // var line1 = XLine.kr(2000, 200, 0.5); 12 | // var line2 = XLine.kr(2000, 200, 1.5); 13 | // var line3 = XLine.kr(2000, 200, 4.5); 14 | // Out.ar(0, VOsc3.ar(bufnum, line1, line2, line3)); 15 | compareAndWriteStructure(t, defName, NewSynthdef(defName, func(p Params) Ugen { 16 | var ( 17 | bufnum = p.Add("bufnum", 0) 18 | ) 19 | line1 := K(XLine{ 20 | Start: C(2000), 21 | End: C(200), 22 | Dur: C(0.5), 23 | }) 24 | line2 := K(XLine{ 25 | Start: C(2000), 26 | End: C(200), 27 | Dur: C(1.5), 28 | }) 29 | line3 := K(XLine{ 30 | Start: C(2000), 31 | End: C(200), 32 | Dur: C(4.5), 33 | }) 34 | return Out{ 35 | Bus: C(0), 36 | Channels: A(VOsc3{ 37 | BufNum: bufnum, 38 | Freq1: line1, 39 | Freq2: line2, 40 | Freq3: line3, 41 | }), 42 | }.Rate(AR) 43 | })) 44 | } 45 | -------------------------------------------------------------------------------- /vosc_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestVOsc(t *testing.T) { 8 | defName := "VOscTest" 9 | 10 | // arg bufnum = 0; 11 | // Out.ar(out, VOsc.ar(bufnum, XLine.kr(2000,200), 0, 0.5)); 12 | compareAndWriteStructure(t, defName, NewSynthdef(defName, func(p Params) Ugen { 13 | var ( 14 | bufnum = p.Add("bufnum", 0) 15 | ) 16 | return Out{ 17 | Bus: C(0), 18 | Channels: A(VOsc{ 19 | BufNum: bufnum, 20 | Freq: K(XLine{ 21 | Start: C(2000), 22 | End: C(200), 23 | }), 24 | }).Mul(C(0.5)), 25 | }.Rate(AR) 26 | })) 27 | } 28 | -------------------------------------------------------------------------------- /warp1_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import "testing" 4 | 5 | func TestWarp1(t *testing.T) { 6 | name := "Warp1Example" 7 | def := NewSynthdef(name, func(params Params) Ugen { 8 | bus, numChannels := C(0), 2 9 | src := Warp1{NumChannels: numChannels}.Rate(AR) 10 | return Out{bus, src}.Rate(AR) 11 | }) 12 | same, err := def.CompareToFile("testdata/Warp1Example.scsyndef") 13 | if err != nil { 14 | t.Fatal(err) 15 | } 16 | if !same { 17 | t.Fatalf("synthdef different from sclang version") 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /whitenoise.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // WhiteNoise generates noise whose spectrum has equal power at all frequencies. 4 | type WhiteNoise struct { 5 | } 6 | 7 | // Rate creates a new ugen at a specific rate. 8 | // If rate is an unsupported value this method will cause 9 | // a runtime panic. 10 | func (white WhiteNoise) Rate(rate int8) Input { 11 | CheckRate(rate) 12 | return NewInput("WhiteNoise", rate, 0, 1) 13 | } 14 | -------------------------------------------------------------------------------- /xfade2.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // XFade2 is a two channel equal power crossfader. 4 | type XFade2 struct { 5 | A Input 6 | B Input 7 | Pan Input 8 | Level Input 9 | } 10 | 11 | func (x *XFade2) defaults() { 12 | if x.A == nil { 13 | x.A = C(0) 14 | } 15 | if x.B == nil { 16 | x.B = C(0) 17 | } 18 | if x.Pan == nil { 19 | x.Pan = C(0) 20 | } 21 | if x.Level == nil { 22 | x.Level = C(1) 23 | } 24 | } 25 | 26 | // Rate creates a new ugen at a specific rate. 27 | // If rate is an unsupported value this method will cause a runtime panic. 28 | func (x XFade2) Rate(rate int8) Input { 29 | CheckRate(rate) 30 | (&x).defaults() 31 | return NewInput("XFade2", rate, 0, 1, x.A, x.B, x.Pan, x.Level) 32 | } 33 | -------------------------------------------------------------------------------- /xfade2_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestXFade2(t *testing.T) { 8 | defName := "XFade2Test" 9 | 10 | // Out.ar(0, XFade2.ar( Saw.ar, SinOsc.ar , LFTri.kr(0.1) )); 11 | compareAndWriteStructure(t, defName, NewSynthdef(defName, func(p Params) Ugen { 12 | return Out{ 13 | Bus: C(0), 14 | Channels: A(XFade2{ 15 | A: Saw{}.Rate(AR), 16 | B: SinOsc{}.Rate(AR), 17 | Pan: K(LFTri{ 18 | Freq: C(0.1), 19 | }), 20 | }), 21 | }.Rate(AR) 22 | })) 23 | } 24 | -------------------------------------------------------------------------------- /xline.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | // XLine generates an exponential curve from the start value to 4 | // the end value. Both the start and end values must be non-zero 5 | // and have the same sign. 6 | type XLine struct { 7 | Start Input 8 | End Input 9 | Dur Input 10 | Done int 11 | } 12 | 13 | func (xline *XLine) defaults() { 14 | if xline.Start == nil { 15 | xline.Start = C(1) 16 | } 17 | if xline.End == nil { 18 | xline.End = C(2) 19 | } 20 | if xline.Dur == nil { 21 | xline.Dur = C(1) 22 | } 23 | } 24 | 25 | // Rate creates a new ugen at a specific rate. 26 | // If rate is an unsupported value this method will cause 27 | // a runtime panic. 28 | func (xline XLine) Rate(rate int8) Input { 29 | CheckRate(rate) 30 | (&xline).defaults() 31 | return NewInput("XLine", rate, 0, 1, xline.Start, xline.End, xline.Dur, C(float32(xline.Done))) 32 | } 33 | -------------------------------------------------------------------------------- /xline_test.go: -------------------------------------------------------------------------------- 1 | package sc 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestXLine(t *testing.T) { 8 | defName := "XLineTest" 9 | 10 | // Out.ar(0, SinOsc.ar(Line.kr(200, 17000, 10), 0, 0.1)); 11 | def := NewSynthdef(defName, func(p Params) Ugen { 12 | line := XLine{ 13 | Start: C(200), 14 | End: C(17000), 15 | Dur: C(10), 16 | }.Rate(KR) 17 | 18 | return Out{ 19 | Bus: C(0), 20 | Channels: SinOsc{Freq: line}.Rate(AR).Mul(C(0.1)), 21 | }.Rate(AR) 22 | }) 23 | compareAndWriteStructure(t, defName, def) 24 | } 25 | --------------------------------------------------------------------------------