DynGen – 在 SuperCollider 服务器上运行动态脚本
DynGen – Run dynamic scripts on a SuperCollider server

原始链接: https://scsynth.org/t/dyngen-dynamic-ugen/12518

## DynGen:使用SuperCollider进行实时DSP DynGen是一个新的SuperCollider UGen,它允许用户使用EEL2语言编写和执行数字信号处理(DSP)代码,并进行即时编译。可以将其视为SuperCollider中类似于Max/MSP的`gen~`对象。 它的工作方式是定义一个包含DSP指令的脚本(`DynGenDef`),然后使用`DynGen.ar()`实例化它。简单的例子包括幅度控制,但DynGen擅长于复杂的任务,例如过采样(通过交叉相位调制振荡器演示)和创建可调制延迟线。 一个关键特性是**现场编码**:更新`DynGenDef`的脚本会自动替换正在运行的UGen,从而允许实时动态地改变DSP行为。 目前处于测试阶段,DynGen的接口可能会发生变化。开发者正在寻求社区反馈,特别是关于Windows兼容性和潜在的设计改进。它建立在Spacechild1关于实时同步的贡献之上。

Hacker News 新闻 | 过去 | 评论 | 提问 | 展示 | 招聘 | 提交 登录 DynGen – 在 SuperCollider 服务器上运行动态脚本 (scsynth.org) 4 点赞 来自 mstep 1 小时前 | 隐藏 | 过去 | 收藏 | 讨论 考虑申请 YC 2026 冬季班!申请截止日期为 11 月 10 日 指南 | 常见问题 | 列表 | API | 安全 | 法律 | 申请 YC | 联系方式 搜索:
相关文章

原文

DynGen is a meta-UGen which allows to write DSP code on the fly using EEL2 as JIT-compiled language. This is essentially the SC equivalent of the gen~ object from Max MSP.

An example on how to use it for halfing the amplitude of a given signal.

// start the server
s.boot;

// registers a dyngen script on the server with identifier \simple
~simple = DynGenDef(\simple, "out0 = in0 * 0.5;").add;

// spawn a synth which evaluates our script
(
Ndef(\x, {DynGen.ar(
	1, // numOutputs
	~simple, // script to use - can also be DynGenDef(\simple) or \simple
	SinOsc.ar(200.0)), // ... the inputs to the script
}).scope;
)

This example isn’t too interesting, but we can also use DynGen for oversampling and single sample feedback really easily - e.g. here is the code and a sound snippet for two cross-phase-modulated SinOscs, 128 times oversampled

(
~complex = DynGenDef(\complex, "
twopi = 2*$pi;

phaseA += 0;
phaseB += 0;

freqA = in0;
freqB = in1;
modIndexA = in2;
modIndexB = in3;

oversample = 128;

osSrate = srate * oversample;
incA = freqA / osSrate;
incB = freqB / osSrate;

sumA = 0;
sumB = 0;

// calculate subsaples
loop(oversample,
    phaseA += incA;
    phaseB += incB;
    // wrap phases between [0, 1)
    phaseA -= floor(phaseA);
    phaseB -= floor(phaseB);

    // apply cross-phase modulation
    phaseA = phaseA + modIndexA * sin(twopi * phaseB);
    phaseB = phaseB + modIndexB * sin(twopi * phaseA);

    // accumulate (for downsampling)
    sumA += sin(twopi * phaseA);
    sumB += sin(twopi * phaseB);
);

// scale down b/c of os
out0 = sumA / oversample;
out1 = sumB / oversample;
").add;
)

(
Ndef(\y, {
	var sig = DynGen.ar(2, ~complex, 
		\freqA.ar(200.0),
		\freqB.ar(pi*100),
		\modA.ar(0.02, spec: [-0.1, 0.1]) * 0.05 * Env.perc(releaseTime: \releaseTime.kr(0.2)).ar(gate: Impulse.ar(\offsetKick.kr(4.0))),
		\modB.ar(0.0, spec: [-0.1, 0.1]) * 0.05,
	);
	sig * 0.1;
}).play.gui;
)

It is also easy to write modulatable delay lines

(
~delayLine = DynGenDef(\delayLine, "
buf[in1] = in0;
out0 = buf[in2];
").add;
)

(
Ndef(\z, {
	var bufSize = SinOsc.ar(4.2).range(1000, 2000);
	var writePos = LFSaw.ar(2.0, 0.02).range(1, bufSize);
	var readPos = LFSaw.ar(pi, 0.0).range(1, bufSize);
	var sig = DynGen.ar(1, ~delayLine,
		SinOsc.ar(100.0),
		writePos.floor,
		readPos.floor,
	);
	sig.dup * 0.1;
}).play;
)

When the script of a DynGenDef is updated, it will automatically replace the running UGen, such that livecoding of DSP is now possible.

The UGen is still considered beta, so the interface is not stable and is open to change.
I still have some open design questions, maybe the community can help me out here.
I haven’t tried if it works on Windows, so would be great to get some feedback for it.

Looking forward to hear some new sounds and see some interesting pseudo UGens popping up :slight_smile:

Massive thanks to @Spacechild1 for helping me how to handle NRT/RT synchronization in a good way and giving the initial idea for this during the symposium.

联系我们 contact @ memedata.com