New Year Gift : Ping Garden Software Instrument


Happy Chinese New Year! :izakaya_lantern: We wish you a great fruitful 2021. Here is a gift from us, it’s called Ping Garden, a software instrument utilizing Mac multitouch pad as playing interface. It uses filter pinging and FM for sound synthesis.

When I was working on Wing Pinger in last year’s CNY, factories were closed during the holiday, so I learned a bit of SuperCollider to kill time. That’s how Ping Garden was born.

Ping Garden makes rain falling sounds with gestural control density. Here is a small video of me playing it. Hope you enjoy.

  1. Install SuperCollider And git :
    https://supercollider.github.io/download
    https://git-scm.com

  2. Open Terminal. Input these line by line :

    xcode-select --install
    git clone https://github.com/batuhan/tongsengmod.git
    cd tongsengmod
    make
    sudo make install
    

From now on, all opeations are in SuperCollider. Open this file in SC.
https://www.mengqimusic.com/s/MengQi-PingGarden.scd

  1. Put cursor in the line “Quarks.Install(“MultiTouchPad”);”, press Command + Enter;

  2. Put cursor in the line “s.reboot();”, press Command + Enter;

  3. Put cursor in the section below line 27, press Command + Enter;

  4. Put cursor in the section below line 85, press Command + Enter. Now the software interface should appear and you can start playing on the Touchpad.

Enjoy!

3 Likes

Btw… Mengqi is one of the few analog module designers and builders in mainland China. He’s highly innovative. Very glad to see this release :grin: – 新年快乐孟奇 :tada::confetti_ball::tada:

hjh

very cool and sweet sounding!

btw. has anyone on newer macOS’es been successful with tongsenmod - I moved to 10.15 lately, and, of course, no way to get it to run…

I am on Catalina too, I compiled it myself as shown in the instructions and had no issue running this project. I am not sure what problem you encountered or whether you have tried to compile it yourself since upgrading your OS, but I can post my compiled binary somewhere on github if that would be useful.

I’m on 10.14.6: I followed all the instructions. No issues here.

That would indeed be super helpful, @virtualdog, if you would upload your compile, as I don’t have a compiling toolchain set up.

I added “\pitch, 1 - xys[1]” to “MultiTouchPad.setAction” This way pitch is dynamic for each living blob. Maybe it was meant to be this way? Anyway it’s fun both ways. Thanks for the new years gift :slight_smile: This made me discover MTP.

Simply stopping with command-period doesn’t stop Tongsengmod. One needs to run “MultiTouchPad.stop” before restarting the whole thing.

// It's recommended to disable all Trackpad gestures before playing.

// 1. 安装 git:
// 1. Install git:
// https://git-scm.com

// 2. 打开 Terminal,逐行输入:
// 2. Open Terminal and run:
//
// xcode-select --install
// git clone https://github.com/batuhan/tongsengmod.git
// cd tongsengmod
// make
// sudo make install

// 3. 运行这一句(把光标放到这句内按 Command + 回车):
// 3. Install a Quark :
Quarks.install("MultiTouchPad");

// 4. 运行这一句:
// 4. Run this:
s.reboot();

// 5. 运行这一段。下面还有一段:
// 5. Run this, there's another part below:
(
var scale, buff, revBus, modBus, rev;
revBus = Bus.audio(s, 1);
modBus = Bus.audio(s, 1);
scale = Scale.minorPentatonic(\just).degrees;
buff = Buffer.alloc(s, scale.size, 1, {|a| a.setnMsg(0, scale)});

SynthDef(\reverb,
	{
		arg inBus, revLvl, time = 0.5, damping = 0.5;
		var rev;
		rev = GVerb.ar (
			In.ar(modBus) * revLvl,
			300,
			time,
			damping,
			0.85, // inputbw
			5, // spread
			0.5,
			-5,
			0.9,
			301,
			1
		);
		Out.ar(0, rev.tanh);
}).add;

SynthDef(\osc,
	{
		arg pitch, lPingSpd, rPingSpd, modIndex, vol, q, noteMin, noteMax;
		var note, freq, modSig, lSnd, rSnd, cs, monoSig;
		cs = ControlSpec(noteMin, noteMax, \lin, 1, noteMin);
		note = cs.map(pitch);
		freq = DegreeToKey.ar(buff.bufnum, note, 12, 1, 0).midicps;
		modSig = InFeedback.ar(modBus, 1) * modIndex * freq;

		lSnd = RLPF.ar(
			Dust.ar(lPingSpd),
			freq + modSig,
			q,
			1
		);
		rSnd = RLPF.ar(
			Dust.ar(rPingSpd),
			freq + modSig,
			q,
			1
		);
		monoSig = Mix.new([lSnd, rSnd]);
		Out.ar(modBus, monoSig.tanh);
		Out.ar(revBus, monoSig.tanh);
		Out.ar(0, [lSnd, rSnd].tanh);
	}
).add;
)

// 6. 运行这一段:
// 6. Run this:
(
var window, oscDict = Dictionary.new, noteRange = [25, 40];
var slider0, slider1;
var maxRange = [15, 45];
var rev, revLvl;
window = Window.new("孟奇 Meng Qi - Ping Garden", Rect(650, 100, 500, 360)).front;

if (MultiTouchPad.guiOn, {"Touch Pad GUI On".postln}, {MultiTouchPad.gui});

window.onClose = {
	MultiTouchPad.stop;
	oscDict.collect { arg item; item.free };
	oscDict.keys.do { arg key; oscDict.removeAt(key) };
	rev.free;
};

window.view.decorator = FlowLayout(window.view.bounds, 20@20, 20@10);

slider0 = RangeSlider(window, 40@280)
.lo_(0.18)
.hi_(0.85)
.action_({
	|slider|
	noteRange[0] = slider.lo.linlin(0.0, 1.0, maxRange[0], maxRange[1]).asInteger;
	noteRange[1] = slider.hi.linlin(0.0, 1.0, maxRange[0], maxRange[1]).asInteger;
	[slider.lo, noteRange[0], slider.hi, noteRange[1]].postln;
}
);

slider1 = Array.fill(3, { Slider(window.view, 40@280)});
slider1.size.do { |i|
	slider1.at(i)
	.value_(0.1)
	.action_({
		var revMix = slider1.at(0).value,
		damping = slider1.at(1).value * 0.9 + 0.1,
		time = slider1.at(2).value;
		rev.set(\revLvl, revMix * 0.5,
			\time, time * 10,
			\damping, damping
		);
	}
	)
};

StaticText(window, 220@280)
.align_(\left)
.string_(
	"Ping Garden

触控板操作

X - 左右声道触发密度,中央静音;
Y - 起始点决定音高
Z - 延音时长 和 调频深度

touch your trackpad

X - ping density left / right;
Y - starting point = pitch
Z - decay & FM index

孟奇 Meng Qi / 2020.02
Instagram : @mengqimusic
微信公众号:合成少数派");

window.view.decorator.nextLine;

4.do {
	|i|
	StaticText(window, 40@35)
	.align_(\left)
	.string_(["🎹","🏔","🏞","✨"].at(i))};

rev = Synth(\reverb, [\revLvl, 0.05]);

MultiTouchPad.resetActions.start;

MultiTouchPad.touchAction =
{
	|curID, xys|
	oscDict.put(curID, Synth.head(s, \osc,
		[
			\pitch, 1 - xys[1],
			\vol, 1,
			\noteMin, noteRange[0],
			\noteMax, noteRange[1]
		]
	);
	);
};

MultiTouchPad.untouchAction =
{
	|curID|
	oscDict.at(curID).free;
	oscDict.removeAt(curID);
};

MultiTouchPad.setAction =
{
	|curID, xys|
	oscDict.at(curID).set(
		\lPingSpd, xys[0].bilin(0.5, 0.0,1.0,0.0,5.0,0.0),
		\rPingSpd, xys[0].bilin(0.5, 0.0,1.0,0.0,0.0,5.0),
		\pitch, 1 - xys[1],
		\modIndex, xys[2].linexp(0.0, 2.08, 0.01, 2.0),
		\q, (2.08 - xys[2]).linexp(0.0, 2.08, 0.001, 0.25)
	);

};
)

@weego here you go: https://github.com/brianlheim/tongsengmod/releases/tag/brianlheim-0.5

merci bien @ virtualdog ! !

1 Like

Yes, this tongsengmod compile of yours now works now on 10.15 !

still took a bit to get it to run, but now it’s fine:

  • get across the “unidentified developer” barrier
  • chmod 755

Note that apart from the MultiTouch Class, the Quark contains a pimped up version by Alberto de Campo that makes this thing more comfprtable to use: add and display shortcuts for minimize/maximize, start/stop the tongseng app.
And for the JITLib adepts, there is a comfortable NPVoicer Class in

Quark.install("JITLibExtensions") 

that handles this polyphony stuff very elegantly in the Ndef writing style.
Promise that I will post a nice example here in my copious free time !-)

H