«audio transitions» by 56228375

on 19 Aug'17 11:06 in transitiontutorialeffects

Code used in the blog article about audio transitions https://technogems.blogspot.be/2017/08/audio-transitions-in-supercollider.html The program proposes a few ways to gradually switch between 2 sounds that go further than simple crossfading. Can you think of other ways?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
(
s.waitForBoot({
	var synthGroup = Group.new;
	var transitionGroup = Group.after(synthGroup);

	if ((~b1.notNil), { ~b1.free; ~b2.free; });
	~b1 = Bus.audio(s, 2);
	~b2 = Bus.audio(s, 2);

	SynthDef(\sound1, {
		| out=0 |
		var sig = SinOsc.ar(LFNoise0.ar(4, 400, 450), 0, 0.2);
		Out.ar(out, sig!2);
	}).add;

	SynthDef(\sound2, {
		| out = 0 |
		var sig = VarSaw.ar(freq:LFPulse.kr(3, 0, 0.3, 200, 200), iphase:0, width:LFTri.kr(1.0).range(0,1), mul:0.1);
		Out.ar(out, sig!2);
	}).add;

	SynthDef(\transitionCut, { // direct cut, no smooth transition
		| inBusA, inBusB, outBus=0, pos= -1 |
		var sig1 = In.ar(inBusA, 2);
		var sig2 = In.ar(inBusB, 2);
		//var testPos = pos;
		var testPos = EnvGen.kr(Env.new(levels:[-1,-1,1,1,-1,-1], times:[5,5,5,5,5]), doneAction:2);
		Out.ar(outBus, Select.ar(testPos.linlin(-1,1,0,1), [sig1, sig2]));
	}).add;

	SynthDef(\transitionCrossFadeEqualGain, {  // cross fade linearly
		|  inBusA, inBusB, outBus=0, pos= -1 |
		var sig1 = In.ar(inBusA, 2);
		var sig2 = In.ar(inBusB, 2);
		//var testPos = pos;
		var testPos = EnvGen.kr(Env.new(levels:[-1,-1,1,1,-1,-1], times:[5,5,5,5,5]).plot, doneAction:2);
		Out.ar(outBus, (testPos.linlin(-1,1,0,1)*sig1) + (testPos.linlin(-1,1,1,0)*sig2));
	}).add;

	SynthDef(\transitionCrossFadeEqualPower, { // cross fade according to square root law
		| inBusA, inBusB, outBus=0, pos= -1 |
		var sig1 = In.ar(inBusA, 2);
		var sig2 = In.ar(inBusB, 2);
		//var testPos = pos;
		var testPos = EnvGen.kr(Env.new(levels:[-1,-1,1,1,-1,-1], times:[5,5,5,5,5]), doneAction:2);
		Out.ar(outBus, ((((1+testPos).sqrt)/2)*sig1) + ((((1-testPos).sqrt)/2)*sig2) );
	}).add;

	SynthDef(\transitionSpectralCurtainHPF, { // wipe using sweeping hpf filter
		| inBusA, inBusB, outBus=0, pos= -1 |
		var sig1 = In.ar(inBusA, 2);
		var sig2 = In.ar(inBusB, 2);
		//var testPos = pos;
		var testPos = EnvGen.kr(Env.new(levels:[-1,-1,1,1,-1,-1], times:[5,5,5,5,5]), doneAction:2);
		Out.ar(outBus, (HPF.ar(sig1, testPos.linexp(-1,1,2,20000)) + HPF.ar(sig2, testPos.linexp(-1,1,20000,2))));
	}).add;

	SynthDef(\transitionSpectralCurtainLPF, { // wipe using sweeping lpf filter
		| inBusA, inBusB, outBus=0, pos= -1 |
		var sig1 = In.ar(inBusA, 2);
		var sig2 = In.ar(inBusB, 2);
		//var testPos = pos;
		var testPos = EnvGen.kr(Env.new(levels:[-1,-1,1,1,-1,-1], times:[5,5,5,5,5]), doneAction:2);
		Out.ar(outBus, (LPF.ar(sig1, testPos.linexp(-1,1,20000,2)) + LPF.ar(sig2, testPos.linexp(-1,1,2,20000))));
	}).add;

	SynthDef(\transitionReverbWash, { // blur out
		| inBusA, inBusB, outBus=0, pos= -1 |
		var sig1 = In.ar(inBusA, 2);
		var sig2 = In.ar(inBusB, 2);
		//var testPos = pos;
		var testPos = EnvGen.kr(Env.new(levels:[-1,-1,1,1,-1,-1], times:[5,5,5,5,5]), doneAction:2);
		Out.ar(outBus,
			(testPos.linlin(-1,1,1,0)*FreeVerb.ar(in:sig1, mix:testPos.linlin(-1,1,0,1), room:15, damp:0.01)) +
			(testPos.linlin(-1,1,0,1)*FreeVerb.ar(in:sig2, mix:testPos.linlin(-1,1,1,0), room:15, damp:0.01)));
	}).add;

	SynthDef(\transitionPulseTrain, { // "pixelate"
		| inBusA, inBusB, outBus=0, pos= -1 |
		var sig1 = In.ar(inBusA, 2);
		var sig2 = In.ar(inBusB, 2);
		//var testPos = pos;
		var testPos = EnvGen.kr(Env.new(levels:[-1,-1,1,1,-1,-1], times:[5,5,5,5,5]), doneAction:2);
		var pulsefreq = 15;
		// do some waveshaping with an Env: generate 0,1,2 but stay 10x longer in 1 than in 0 and 2.
		// the generated value will be used in a Select UGen
		var mapper = Env.new([0,0,1,1,2,2],[0.1,0.01,1,0.01,0.1].normalizeSum);
		var mappedTestPos = IEnvGen.ar(mapper, testPos.linlin(-1,1,0,1));
		Out.ar(outBus,
			Select.ar(mappedTestPos,
				[testPos.linlin(-1,1,1,0)*sig1,
				 LeakDC.ar(((testPos.linlin(-1,1,1,0)*(LFPulse.kr(pulsefreq, 0, testPos.linlin(-1,1,1,0))*sig1)) +
			    			(testPos.linlin(-1,1,0,1)*(LFPulse.kr(pulsefreq, 1, testPos.linlin(-1,1,0,1))*sig2)))),
				 testPos.linlin(-1,1,0,1)*sig2]));
	}).add;

	SynthDef(\transitionPanLR, { // shift LR
		| inBusA, inBusB, outBus=0, pos= -1 |
		var sig1 = In.ar(inBusA, 2);
		var sig2 = In.ar(inBusB, 2);
		//var testPos = pos;
		var testPos = EnvGen.kr(Env.new(levels:[-1,-1,1,1,-1,-1], times:[5,5,5,5,5]), doneAction:2);
		Out.ar(outBus,
			Balance2.ar(sig1[0], sig1[1], testPos.linlin(-1,1,-1,0), testPos.linlin(-1,1,0,1)) +
			Balance2.ar(sig2[0], sig2[1], testPos.linlin(-1,1,0,1),  testPos.linlin(-1,1,1,0))
		);
	}).add;

	s.sync;

	fork {
		var s1 = Synth(\sound1, [\out, ~b1], synthGroup);
		var s2 = Synth(\sound2, [\out, ~b2], synthGroup);

		[//\transitionCut, // boring
		 \transitionCrossFadeEqualGain,
		 \transitionCrossFadeEqualPower,
		 \transitionSpectralCurtainHPF,
		 \transitionSpectralCurtainLPF,
		 \transitionReverbWash,
		 \transitionPulseTrain,
		 \transitionPanLR

		].do({
			| item , idx |
			("Now switching to transition "++item).postln;
			Synth(item, [\inBusA, ~b1, \inBusB, ~b2], transitionGroup);
			25.wait;
		});
	}

});
)
raw 5018 chars (focus & ctrl+a+c to copy)
reception
comments