sc3 중급반 01 (VC, LFO, AM, RM, FM, & PM synthesis + S&H) 

아래는 작년에 teum님이 올리신 synth 방법에 대한 설명입니다.
거기에다가 제가 Sample&Hold를 추가했습니다.

2010.3.1
세미나 6주차
Voltage Control, LFO, AM, RM, FM, and PM synthesis + S&H
(ixi 6강, 코틀 12강+16강)

1. ========= Voltage Control ==========

초기 신디사이저 모듈들은 VCO(voltage controlled oscillator), VCA(voltage controlled amplitude), VCF(voltage controlled frequency)등의 이름을 갖고있다. 이 이름들은 pitch를 컨트롤하기 위한 오실레이터, amplitude를 컨트롤하기 위한 amplifier, upper harmonic structure등을 컨트롤하기 위한 필터를 voltage로 컨트롤하는 것을 뜻한다. 이 콘셉은 모든 신디사이저의 핵심과 SC패치에 적용된다. 여기서 ‘컨트롤’한다는 것은 간단히 말해 패러미터를 변화시킨다는 뜻이다. 음악을 들을때 스테레오 볼륨을 크게하는 것은 amplitude 패러미터를 수동으로 컨트롤하는 것과 같다. 기타 줄을 손으로 누르면 줄의 길이를 수동으로 컨트롤하는 것이므로 이는 주파수를 컨트롤하는 것과 같다. 일렉트로닉 음악의 선구자들은 전기를 이용해 소리의 패러미터들을 컨트롤하여 세밀함, 정확성,속도, 유연성등을 성취하고자 했다. 그들은 인간과 악기들이 갖고있는 한계가 전기적으로 발생되고 컨트롤되는 소리로 극복될 수 있다고 생각했다. 그들은 옳았고, 오늘날 가상적으로 기계로 발생해내는 소리(음악)에는 한계가 없다. 사실 그 음악들은 쉽게 우리의 지각능력의 범위를 초월할 수 있다.

Voltage 컨트롤은 어떤 유젠의 패러미터나 argument를 조절하기 위해 다른 유젠을 사용하는 것을 뜻한다. LFNoise0 유젠은 주어진 rate로 값을 발생시키고 이 값들은 SinOsc의 주파수로 사용된다. 우리가 MouseX를 사용하여 주파수를 컨트롤하면 그것은 ‘수동 컨트롤(manual control)’이며, LFNoise0을 사용하는 것은 voltage 컨트롤 혹은 ‘기계적인 컨트롤(mechanical control)’이 된다. SC의 거의 모든 오브젝트는 ‘volataged 컨트롤’이다. 어떤 모듈은 하나의 속성만을 컨트롤하게 하지만, 거의 대부분의 모듈은 3가지-주파수, 필터, amp-를 조절할 수 있게 되어 있다.

2. ========= LFO ==========

오디오 범위 아래의 주파수 소리(20Hz이하)는 들을 수 없지만, 그것이 다른 오실레이터에 가하는 영향을 들을 수 있다. 많은 신디사이저들이 이러한 현상을 설명하는데 LFO 혹은 Low Frequency Control이라는 용어를 사용한다. 컨트롤을 위한 주파수는 20헤르츠가 넘지 않아야 하며(이것을 넘으면 AM/FM현상이 발생한다), add는 mul보다 커야한다. (mul이 더 크면 음수값이 나오기 때문이다.)

2-1. Vibrato
voltage 컨트롤의 간단한 예가 vibrato이다. vibrato는 amp(목소리의 경우)나 pitch(현악기의 경우)에 미묘하게 오가는 변동이다. 현악기 연주자들은 vibrato 중간에 손가락을 앞쪽이나 뒷쪽으로 굴린다. (pitch가 특정 구간을 이동한다) SC에서 이것을 구현하려면, SinOsc의 주파수 arg자리에 고정값(static value)대신 시간의 변화에 따라 변화하는 함수나 유젠을 넣어주면 된다. vibrato의 모양은 실제로 사인파와 아주 유사하다. 두 값 사이를 주기적으로 오간다. 하나의 SinOsc의 결과물을 다른 SinOsc의 주파수 arg로 사용할 수 있을까? 이것은 가능하며, 단 그 결과값이 적절하게 조절(scaled, offset)되어야 한다.

  • SinOsc as Vibrato

SinOsc(freq: 5, mul: 5, add: 440)
//중심값이 0이고 -1~1 사이를 오가는 것을 중심값이 440이고 1초에 5번 434~445 사이를 오가는 것으로 스케일함: (n*5)+440


(
{
var vibrato;
vibrato = SinOsc.kr(5,0, 5, 440);
SinOsc.ar(vibrato, 0.5);
}.play
)

// mouseX is the power of the vibrato (움직이는 주파수 범위)
// mouseY is the frequency of the vibrato (주기)
(
{
var vibrato;
vibrato = SinOsc.ar(MouseY.kr(200, 5), 0, MouseX.kr(5, 200)); 
SinOsc.ar(440 + vibrato, 0, 1);
}.freqscope;
)

2-2. Tremolo – variations in amplitude


(
// mouseX is the frequency of the tremolo
{
var tremolo;
tremolo = SinOsc.kr(MouseX.kr(2,20));
SinOsc.ar(333, 0, tremolo);
}.freqscope;
)

2-3. Theremin
테라민은 최초의 일렉트로닉 악기중의 하나이다. pitch와 amp의 변화가 퍼포머의 손 동작과 링크되어 발생하기 때문에(하나는 pitch, 다른 하나는 volume과 연관있는 두개의 메탈 안테나) 정확히 말하자면 voltage 컨트롤되는 모듈은 아니다. 이 악기 소리의 특성은 크게 2가지인데, pitch간의 glissando(분절된 pitch라기 보다는 연결된 pitch)와 단단하고 넓은 vibrato이다. 
(
{
var vibrato,freq;
vibrato = SinOsc.kr(7,0,0.02);
freq = MouseY.kr(4000, 200, 1, 0.8);
SinOsc.ar(freq+(freq*vibrato), 0, MouseX.kr(0, 0.9)
	)!2
}.freqscope;
)


2-4. LFO 컨트롤들

// LFSaw
{ SinOsc.ar(LFSaw.kr(4, 0, 200, 400), 0, 0.7) }.scope

// LFTri
{ SinOsc.ar(LFTri.kr(4, 0, 200, 400), 0, 0.7) }.scope
{ Saw.ar(LFTri.kr(4, 0, 200, 400), 0.7) }.play

// LFPar
{ SinOsc.ar(LFPar.kr(0.2, 0, 400,800),0, 0.7) }.play

// LFCub
{ SinOsc.ar(LFCub.kr(0.2, 0, 400,800),0, 0.7) }.play

// LFPulse
{ SinOsc.ar(LFPulse.kr(3, 1, 0.3, 200, 200),0, 0.7) }.play
{ SinOsc.ar(LFPulse.kr(3, 1, 0.3, 2000, 200),0, 0.7) }.play
{ SinOsc.ar(LFPulse.kr(freq:15, mul:200, add:1000),0.5) }.play //전화소리
{ SinOsc.ar(LFNoise0.kr(freq:[28, 27], mul:1000, add:2000),0.5) }.play //computer
{ SinOsc.ar(LFNoise1.kr(freq:[28, 27], mul:400, add:2000),0.5) }.play // birds

// LFOs can also perform at audio rate(??)
{ LFPulse.ar(LFPulse.kr(3, 1, 0.3, 200, 200),0, 0.7) }.play
{ LFSaw.ar(LFSaw.kr(4, 0, 200, 400), 0, 0.7) }.play
{ LFTri.ar(LFTri.kr(4, 0, 200, 400), 0, 0.7) }.play
{ LFTri.ar(LFSaw.kr(4, 0, 200, 800), 0, 0.7) }.play
3. =========  Amplitude modulation  ==========

voltage 컨트롤을 사용해 vibrato를 만들 때 컨트롤 주파수가 20Hz를 넘게 되면 예상하지 못한 결과가 발생한다. 컨트롤되고 있는 주파수 위아래로 새로운 주파수들이 생기는데 이것을 sidebands(측파대)라고 한다. LFO 범위 이상의 컨트롤 소스로 인해 들리는 소리는 라디오의 주파수를 찾을 때 나는 소리와 비슷하다. 이것은 주파수변조(FM), 진폭변조(AM)의 영역으로 들어갈 때 나는 소리이다. 또한 놀랍게도 새소리와도 유사한데, 어떤 새들은 (위와 같은 원리로) 상호작용하는 두 개의 주파수를 만들어낼 수 있다.  


AM/FM이 LFO와 구분되는 것은 upper, lower sidebands이다. 두개의 변조되는 주파수의 결과물로서 이러한 추가적인 주파수들이 발생한다. 

진폭변조(AM)에는 두 개의 측파대(sidebands)가 있다. 반송주파수(carrier frequency-변조되는 오디오 주파수)와 modulator frequency(오디오 주파수를 컨트롤하는 주파수)의 합(sum)과 차(difference)이다. 반송주파수 500에 modulator freq가 112면 sidebands는 612와 318이다. 

{SinOsc.ar(500, mul: SinOsc.ar(50, mul: 0.5))}.scope(1)

바깥에 있는 SinOsc가 carrier이고, 안에 있는 SinOsc가 modulator이다. sidebands는 550과 450이다. 
고정값 50을 MouseX로 대체해보면서, 소리의 변화를 들어보자.

{SinOsc.ar(500, mul: SinOsc.ar(MouseX.kr(1, 500), mul: 0.5))}.freqscope(1) // 500으로 갈 수록 그라프가 변하는 것을 확인할 것. 

// In AM synthesis the modulator is unipolar (from 0 to 1) - so we add 1 to the wave
// and divide by 2 (i.e. multiply by 0.5)

(
{
var modulator, carrier;
modulator = SinOsc.ar(MouseX.kr(2, 20000, 1), 0, mul:0.5, add:1); //2000으로 갈 수록 그라프가 변하는 것을 확인할 것.
carrier = SinOsc.ar(MouseY.kr(300,2000), 0, modulator);
carrier!2 
}.scope
// interesting example of foldover happening in AM
)

//파형이 배음들로 되어 있는 경우(즉, 사인파 여러개로 만들어진 톱니파) 각각의 배음마다 sidebands가 생긴다. 

(
{
var modulator, carrier;
modulator = SinOsc.ar(MouseX.kr(2, 2000, 1), mul:0.5, add:1);
carrier = Saw.ar(533, modulator);
carrier!2 // the output
}.freqscope

)
4. =========  FM synthesis  ==========

AM과 FM은 유사한 효과를 발생시키지만 FM으로는 더 많은 sidebands를 발생시킬 수 있다. 그 수는 변조지수(modulation index)에 따라 결정된다. 변조지수란 변조주파수가 carrier로부터 얼마나 멀리 떨어져있는가를 나타낸다. 

// the same as above - with explanations:
(
{
SinOsc.ar(400 // the carrier and the carrier frequency
	+ SinOsc.ar(MouseX.kr(2,2000,1), // the modulator and the modulator frequency
		0, 						// the phase of the modulator
		MouseY.kr(1,1000) 			// the modulation depth (index)
		), 
0,		// the carrier phase 
0.5)		// the carrier amplitude
}.play

)

{SinOsc.ar(400+SinOsc.ar(124, mul:MouseX.kr(1, 500)), mul: 0.5)}.scope(1)
// carrier:400, modulator: 124, index: MouseX.kr(1, 500)

// Frequency Modulation
(
var carrier, carFreq, carAmp, 	
modulator, modFreq, modAmp; 

carFreq = 2000; 
carAmp = 0.2;		
modFreq = 327; 
modAmp = 0.2; 

{
	modAmp = MouseX.kr(0, 1); 		// choose normalized range for modulation
	modFreq = MouseY.kr(1000, 10, 'exponential');
	modulator = SinOsc.ar( modFreq, 0, modAmp);			
	carrier = SinOsc.ar( carFreq + (modulator * carFreq), 0, carAmp);
	
	[ carrier, carrier, modulator ] // on OSX, you can .scope it and see 3 separate channels

}.play
)
5. =========  Phase Modulation  ==========
: FM과 거의 유사하다. 

PM synthesis

{PMOsc.ar(400, 124, 1, mul: 0.5)}.scope(1)
//PMOsc.ar(carfreq, modfreq, index, modphase, mul, add)

{PMOsc.ar(400, 124, MouseX.kr(1, 500), mul: 0.5)}.scope(1)

//carrier와 control freq사이의 비율이 sidebands를 결정하며, 이는 소리의 속성에 영향을 끼친다. index는 sidebands의 숫자를 결정하여, 파형의 밝기등을 변화시킨다.  

// carrier freq를 바꾸면 악기의 소리는 같고 pitch가 달라짐: carrier=fundamental pitch
{PMOsc.ar(LFNoise0.kr(5, 300, 700), 134, 4, mul:0.4)}.scope(1)
// modulator freq를 바꾸면 pitch는 같고 악기소리가 달라짐: modulator: character of the wave
{PMOsc.ar(700, LFNoise0.kr(5, 300, 700), 4, mul:0.4)}.scope(1)
// index를 바꾸면 필터된 악기 소리가 남: number of partials or filter
{PMOsc.ar(700, 567, LFNoise0.kr(5, 6, 12), mul:0.4)}.scope(1)
// 3개를 다 바꾸면:
(
{PMOsc.ar(LFNoise0.kr([9, 9], 300, 700),
                LFNoise0.kr([9, 9], 500, 700),
                LFNoise0.kr([9, 9], 6, 12),
                mul: 0.5
                )}.scope(1)
)
         
   
- PM과 가산합성의 효율성(CPU점유) 비교      
{PMOsc.ar(1000, 1367, 12, mul: EnvGen.kr(Env.perc(0, 0.5), Impulse.kr(1)))}.scope(1)

(
{
Mix.ar(
     SinOsc.ar(abs((-20..20)*1367+1000),
      mul: EnvGen.kr(Env.perc(0, 0.5), Impulse.kr(1)))
)}.play
)

// Carrier and modulator ratio

(
{
var freq, ratio; 
freq=LFNoise0.kr(4, 20, 60).round(1).midicps;
ratio= 2.01;
PMOsc.ar(freq, //carrier
                freq*ratio, //modulator
                MouseY.kr(0.1, 10), //index
                mul: [0.4, 0.4]
)}.play
)

//Envelop applied to amplitude and modulation index

(
{
var freq, trig, ratio, env, rate=5;
trig=Impulse.kr(5);
ratio=2;
env=EnvGen.kr(Env.perc(0, 1/rate), gate: trig);
freq=TRand.kr([36, 60], [72, 86], trig).midicps;
PMOsc.ar(freq,
         freq*ratio,
         3+env*4,
         mul: env)
}.play
)

// let's fork it and create a perc env!
(
{
	
	40.do({
		{ 	var freq, ratio, modulator, carrier;
			// create an array of 12 midinotes, choose one, change it to cps and post it:
			freq = Array.fill(12, {arg i; 60 + i}).choose.midicps.postln; 
			ratio = MouseX.kr(0.5,2); 
			
			modulator = SinOsc.ar(freq * ratio, 0, MouseY.kr(0.1,10));
			carrier = SinOsc.ar(freq + (modulator * freq), 0, 0.5);
			
			carrier	* EnvGen.ar(Env.perc, doneAction:2)
		}.play;
		1.wait;
	});
}.fork
)

// Phase Modulation
(
var carrier, carFreq, carAmp, 		// variables for a carrier
modulator, modFreq, modAmp; 		// and a modulator oscillator.

carFreq = 200; 			// initial parameters for both.
carAmp = 0.2;				// (needed if you decide to turn mouse control off.)
modFreq = 327; 
modAmp = 0.2; 

{ 
	modAmp = MouseX.kr(0, 7); 
	modFreq = MouseY.kr(1000, 10, 'exponential');
	modulator = SinOsc.ar(		// modulator is a Sine oscillator
		modFreq, 					
		0, 
		modAmp);			

	carrier = SinOsc.ar(
		carFreq, 
		modulator, 			// modulate the phase input of the SinOsc.
		carAmp);
	[ carrier, carrier, modulator * 0.2 ] 
}.play
)

6. ========= 응용예제  ==========

6-1. Sequencer 
: Sequencer는 일정한 속도로(혹은 트리거 될 때) 일련의 값을 거쳐 이동한다. Select와 Stepper유젠을 함께 사용한다. 

(
var pitchArray;
pitchArray = [60, 62, 64, 65, 67, 69, 71, 72].midicps;
{SinOsc.ar(
    Select.kr(
       Stepper.kr(Impulse.kr(8), max: pitchArray.size-1, step:1),// step: -1, 3 등 바꿔보기
       pitchArray),
    mul: 0.5) !2
}.play 
)

(
var pitchArray;
pitchArray = Array.rand(24, 100, 2000); //Array.rand(number of items in array, low ends of random range, high ends of random range)
{SinOsc.ar(
    Select.kr(
       Stepper.kr(Impulse.kr(8), max: pitchArray.size-1),
       pitchArray),
    mul: 0.5) !2
}.play 
)

//Array.rand(24, 100, 2000);

(
var pitchArray;
pitchArray = Array.rand(10, 60, 84);
pitchArray.postln.scramble.postln.reverse.postln;
(pitchArray+12).postln
)

6-2. Sequencer Variation

(
var pitchArray;
pitchArray = [60, 62, 64, 65, 67, 69, 71, 72];
pitchArray = [
              (pitchArray+rrand(1, 12)).midicps,//transpose(조옮김)
               pitchArray.reverse.midicps,
               pitchArray.scramble.midicps,
               Array.rand(12, 36, 72).midicps,
               Array.rand(12, 100, 1200)
             ].choose;
{SinOsc.ar(
     Select.kr(
       Stepper.kr(Impulse.kr(7), pitchArray.size-1),
       pitchArray),
     mul: 0.5)
}.play
)


6-3. Sample and Hold - Latch

(
{SinOsc.ar(
  Latch.kr(
    LFSaw.kr(MouseX.kr(0.1, 20), 0, 500, 600),
    Impulse.kr(10)),
  mul: 0.3
)}.scope(1)
)   

// Latch.ar(in, trig)

(
{SinOsc.ar(
  Latch.kr(
    LFSaw.kr(Line.kr(0.1, 20, 60), 0, 500, 600),
    Impulse.kr(10)),
  mul: 0.3
)}.scope(1)
)   
6-4. FM을 이용한 SynthDef만들기

// And finally we make a synthDef with FM synthesis, something that we
// can play from a say MIDI keyboard or tune with knobs and sliders:

( 
SynthDef(\fmsynth, {arg outbus = 0, freq=440, carPartial=1, modPartial=1, index=3, mul=0.2, ts=1;
	var mod, car, env;
	// modulator frequency
	mod = SinOsc.ar(freq * modPartial, 0, freq * index );
	// carrier frequency
	car = SinOsc.ar((freq * carPartial) + mod, 0, mul );
	// envelope
	env = EnvGen.ar( Env.perc(0.01, 1), doneAction: 2, timeScale: ts);
	Out.ar( outbus, car * env)
}).send(s);
)


Synth(\fmsynth, [ \outbus, 0, \freq, 600.0, \carPartial, 1.5, \ts, 1]);
Synth(\fmsynth, [ \outbus, 0, \freq, 600.0, \carPartial, 2.5, \ts, 2]);
Synth(\fmsynth, [ \outbus, 0, \freq, 600.0, \carPartial, 3.5, \ts, 2]);
Synth(\fmsynth, [ \outbus, 0, \freq, 600.0, \carPartial, 4.0, \ts, 2]);
Synth(\fmsynth, [ \outbus, 0, \freq, 300.0, \carPartial, 1.5, \ts, 2]);
Synth(\fmsynth, [ \outbus, 0, \freq, 600.0, \carPartial, 0.5, \ts, 2]);

Synth(\fmsynth, [ \outbus, 0, \freq, 600.0, \carPartial, 1.5, \modPartial, 1, \ts, 2]);
Synth(\fmsynth, [ \outbus, 0, \freq, 300.0, \carPartial, 1.5, \modPartial, 1, \ts, 2]);
Synth(\fmsynth, [ \outbus, 0, \freq, 400.0, \carPartial, 1.5, \modPartial, 1, \ts, 2]);
Synth(\fmsynth, [ \outbus, 0, \freq, 800.0, \carPartial, 1.5, \modPartial, 1, \ts, 2]);

Synth(\fmsynth, [ \outbus, 0, \freq, 600.0, \carPartial, 1.5, \modPartial, 1, \ts, 2]);
Synth(\fmsynth, [ \outbus, 0, \freq, 600.0, \carPartial, 1.5, \modPartial, 1.1, \ts, 2]);
Synth(\fmsynth, [ \outbus, 0, \freq, 600.0, \carPartial, 1.5, \modPartial, 1.15, \ts, 2]);
Synth(\fmsynth, [ \outbus, 0, \freq, 600.0, \carPartial, 1.5, \modPartial, 1.2, \ts, 2]);



Sample and Hold (SH)

샘플앤드홀드(SH)는 구형 모듈러 신디사이저에서 사용했던 클래시컬한 신스콘트롤 소스이다.
신스가 모듈형에서 통합형으로가면서 s&h가 살아남지 못했는데 Cottle은 S&H가 존속가치가 있다고 생각한다. SC에서는 Latch.kr로 S&H를 구현한다.

어떤 파형을 일정간격으로 샘플하고 그 결과 값을 컨트롤로 사용한다.
입력 : 어떤파형
출력 : 컨트롤로 사용됨

SC에서는 Latch.kr로 SampleAndHold를 구현한다.


a={SinOsc.ar(20)} // 이것이 입력파형이라고 보자
a.plot(2)
{Latch.kr(a, Impulse.kr(210))}.plot(2) ////Latch.ar(in, trig)        in : Input signal, trig: trigger



특정 샘플시점의 값을 다음 샘플시점까지 지속한다.

신스에서 이것이 왜 유용할까?
주기적 파형을 샘플하므로 샘플한 결과물은 점점 변화하는 패턴이다.  
영화에서 바퀴가 반대로 돌아가는 것으로 보이는 효과와 비슷하다. 
a={SinOsc.ar(20)} 
a.plot(2)
{Latch.kr(a, Impulse.kr(21))}.plot(2) 

s and h는 노이즈 보다는 주기적이고 단순진행보다는 다양하다.
(변화와 반복간의 조화)  


아래의 예제를 해보삼...
마우스를 좌우로 하면 샘플되는 톱니파의 프리퀀시가 바뀐다...

16.12. Latch  
 
(
{ 
SinOsc.ar( 
 Latch.kr( 
  LFSaw.kr(MouseX.kr(0.1, 20), 0, 500, 600),  
  Impulse.kr(10)), 
 mul: 0.3 //Volume of Blip 
) 
}.scope(1) 
) 

위의 예제를 연구하려면 아래의 플롯을 보세요. 
({Latch.kr( 
  LFSaw.kr(2.715),  
  Impulse.kr(10)) }.plot(1);)
 {LFSaw.kr(2.715)}.plot(1); 
=========================================== 
( 
{ 
SinOsc.ar( 
 Latch.kr( 
  LFSaw.kr(200, 0, 50, 600),  
  Impulse.kr(40)), 
 mul: 0.3 //Volume of Blip 
) 
}.scope(1) 
 )   
                                             
  
16.13. Latch  
 
(
{ // controlling modulator and carrier freq  
f = Latch.kr( 
  LFSaw.kr(MouseX.kr(1.1, 30), 0, 1000, 1100),  
  Impulse.kr(10)); 
PMOsc.ar(f, f*2, 12, mul: 0.3) 
}.scope(1) 
) 
 
(
{ // controlling index 
i = Latch.kr( 
  LFSaw.kr(MouseX.kr(1.1, 30), 0, 5, 5),  
  Impulse.kr(10)); 
PMOsc.ar(300, 356, i, mul: 0.3) 
}.scope(1) 
) 
 
(
{ // controlling ratio 
r = Latch.kr( 
  LFSaw.kr(MouseX.kr(1.1, 30), 0, 2.0, 3.0),  
  Impulse.kr(10)); 
PMOsc.ar(300, 300*r, 12, mul: 0.3) 
}.scope(1) 
) 
 
(
{ // and of course, scaled to control all three 
c = Latch.kr( 
  LFSaw.kr(MouseX.kr(1.1, 30), 0, 0.5, 0.5),  
  Impulse.kr(10)); 
f = c*1000+200; 
o = PMOsc.ar(f, f*(c*3+4), c*5+6, mul: 0.3); 
[o, CombL.ar(o, 2, 2)] 
}.scope(1) 
) 
 
샘플되는 파형의 주파수와 샘플하는 횟수의 비율이 패턴을 결정하는데
이 비율을 특정숫자로(1.61803399 ) 고정시키고 샘플횟수를 바꿔보자.
즉 마우스로 조정되는 샘플하는 횟수가 바뀌면 샘플되는 파형의 주파수도 같이 바뀌게 해본것...
 
 
16.14. Latch sample and speed ratio (Blip, Latch, LFSaw, Impulse, mul) 
  
(
{  
var rate, speed, ratio; 
rate = MouseX.kr(1, 24);  
ratio = 1.61803399; 
c = Latch.kr( 
  LFSaw.kr(rate*ratio, 0, 0.5, 0.5),  
  Impulse.kr(rate)); 
f = c*1000+200; 
o = PMOsc.ar(f, f*(c*3+4), c*5+6, mul: 0.3); 
[o, CombL.ar(o, 2, 2)] 
}.scope(1) 
) 
 
(
{  
var rate, speed, ratio; 
rate = MouseX.kr(1, 24);  
ratio = SinOsc.ar(2/7, mul: 0.2, add: 1.75); 
c = Latch.kr( 
  LFSaw.kr(rate*ratio, 0, 0.5, 0.5),  
  Impulse.kr(rate)); 
f = c*1000+200; 
o = PMOsc.ar(f, f*(c*3+4), c*5+6, mul: 0.3); 
[o, CombL.ar(o, 2, 2)] 
}.scope(1) 
) 
 
또다른 재밌는 방법은 샘플되는 파형을 좀 복잡한것을 사용하는 것이다.
복잡하더라도 그것이 주기적이라면 그것으로부터 나온 파형또한 주기적이 된다.

아래는 세개의 파형을 섞었지만 아직 주기적이다.

 
16.15. Complex Wave as Sample Source (Mix, SinOsc, Blip, Latch, Mix, Impulse) 
 
{Mix.ar(SinOsc.ar([100, 200, 300, 550], mul: 0.1))}.scope(1) 

 
(
//Used in a sample and hold 
{ 
f = Latch.kr( 
  Mix.ar(SinOsc.ar([100, 200, 300, 550], mul: 100, add: 110)),  
  Impulse.kr(7)); 
e = EnvGen.kr(Env.perc(0, 0.2), Impulse.kr(7)); 
PMOsc.ar(f, f*1.25, e*5, mul: e*0.3) 
}.play 
) 
 
Practice S and H FM 
재밌게하려면 복잡한 정도와 주기적인 정도의 적정지점을 찾는 것이다.
이것은 작곡의 가장 중요한 부분 즉 predictability와 surprise의 적정한 정도 말이다.

 
16.16. Practice, Sample and Hold, FM 
 
(
{var freq, latchrate, index, ratio, env, rate; 
rate = 9; 
latchrate = rate*1.61803399; 
// latchrate = rate*LFNoise1.kr(1/7, mul: 0.03, add: 1.6); 
// latchrate = rate*LFNoise0.kr(1/3, mul: 0.03, add: 1.6); 
 
index = Latch.kr( 
 LFSaw.kr(latchrate, mul: 4, add: 8), 
 Impulse.kr(rate) 
 ); 
freq = Latch.kr( 
 LFSaw.kr(latchrate, mul: 36, add: 60), 
 Impulse.kr(rate) 
 ).round(1).midicps; 
// freq = 200; //uncomment this line to hear just the index 
 
ratio = 2.01;  
// ratio = LFNoise1.kr(1, mul: 2.3, add: 3.0); 
// ratio = LFNoise0.kr(1, mul: 2.3, add: 3.0); 
// ratio = LFNoise1.kr(1/5, mul: 2.0, add: 5.0); 
 
env = EnvGen.kr(Env.perc(0, 2/rate), gate: Impulse.kr(rate)); 
 
PMOsc.ar([freq, freq * 1.5], 
  [freq*ratio, freq*1.5*ratio],  
  index,  
  mul: env*0.5 
)}.play 
) 
 
// Variation 
 
(
{var freq, latchrate, index, ratio, env, rate; 
rate = 9; 
latchrate = rate*LFNoise0.kr(1/10, mul: 0.03, add: 1.6); 
index = Latch.kr( 
 LFSaw.kr(latchrate, mul: 5, add: 6), 
 Impulse.kr(rate) 
 ); 
freq = Latch.kr( 
 LFSaw.kr(latchrate,  
  mul: max(0, LFNoise1.kr(1/5, 24, 10)),  
  add: LFNoise0.kr(1/7, 12, 60)), 
 Impulse.kr(rate) 
 ).round(1).midicps; 
ratio = LFNoise1.kr(1/10, mul: 2.0, add: 5.0); 
 
env = EnvGen.kr(Env.perc(0, LFNoise0.kr(rate, 1, 1.5)/rate), Impulse.kr(rate), 
LFNoise1.kr([5, 5], 2, 1).max(0).min(0.8)); 
PMOsc.ar( 
 [freq, freq * 1.5], 
 freq*ratio, 
 index, 
 mul: env //overall volume 
)}.play 
) 
 
 
Advertisements