Updates from 2월, 2012 댓글 스레드 토글 전환 | 키보드 단축키

  • mortp February 29, 2012 9:45 pm 퍼머링크 | 응답
    태그: , , makingclass, , , writingclass   

    SC에서 클래스 만들기 

    <SC의 클래스만들기 규칙>

    Platform.systemExtensionDir;   // Extensions available to all users on the machine, .rtf가 아니라, .sc로 저장해서 여기에 넣으면 됩니다.

    home/library/applicationsupport/supercollider/extensions 에 저장 후 cmd + k

    0. 한글 주석 사용 불가

    1. Getter vs Setter

    <는 클래스 외부에서 변수의 값을 불러올 수 있게. (Getter)

    >는 클래스 외부에서 변수의 값을 변경할 수 있게. (Setter)

    <> 두개 동시에 가능

    2. classvar vs var

    classvar 는 클래스 차원에서 접근이 가능하고, (Cc.classvar이름)

    var는 인스턴스 차원에서만 접근이 가능하다. (a = Cc.new; a.var이름)

    3. ‘메소드’ =  ‘함수’라고 생각해도 무방.

    둘 모두 그 이름을 불렀을 때 수행될 일들을 적어놓는 곳.

    클래스에 대해 적용될 함수는 정의되는 이름앞에 *을 붙이고, 인스턴스에 대해 적용될 함수는 *를 붙이지 않는다.

    4. ^(꺾쇠)표시는 다른 언어에서의 ‘return’과 같은 의미.

    뒤따라 나오는 구문의 결과값을, 함수를 부른(실행하라고 명령한) 곳으로 돌려준다.

    5. 인스턴스 메소드와 클래스 메소드를 구분짓는 것은, SC(혹은 그것의 모태인 smalltalk)만의 특징인 듯.

    SC의 클래스 구조에는 별도의 생성자(Constructor)개념이 없고, 기본적으로 상속받게 되는 최상위의 Object 클래스의 메소드를 빌려 필요한 메모리 공간 등을 할당받는 구조로 보임. Object 클래스의 내용을 이용하는 일종의 생성자 개념.

    Object.new;

    //새로운 인스턴스를 할당한다. 어떤 클래스든 실제로 인스턴스를 만들어 내기 위해서는 이것이 꼭 필요하다.

    새로 정의되는 어떠한 클래스라도 그것을 실제 사용할 수 있는 인스턴스로 만들기 위해서는 위와같은 명령이 반드시 필요. 관습적으로 쓰여지는 아래와 같은 .new라는 메소드의 내용은 최소한 위와 같은 동작을 수행하기 위해서이다.

    *new{

    //new라는 이름으로 생성의 역할을 정의하는 것은 다른 클래스들과의 통일성으로보면 당연하지만 다른 이름이어도 상관 없을 듯.

    ^ super.new; //Object.new 를 하는것과 마찬가지.

    }

    여기에 클래스만의 특별한 초기화 조건을 덫붙이기 위해서는,
    Object.new와 동시에 수행될 인스턴스 함수를 정의하여 실행한다.

    *new{

    ^ super.new.init(500, 0.5, 0.7); //Object.new + 그로인해 만들어진 인스턴스.init(아규먼트에 각각 500, 0.5, 0.7)

    }

    init{arg f = 200, a = 1.0, p = 1.0; //init는 그저 initialize 역할임을 표기하기 위한 이름. 다른 이름이어도 상관 없음.

    var freq, amp, pan;

    freq = f;

    amp = a;

    pan = p;

    }

    6. 실습코드

    
    Mtr{
    
    // classvar
    
    var <>routine, <>bpm, <>amp, <>tick, <>synth, <>synthNode, <>intv;
    
    *new{| argbpm, argamp, argtick = 4, argsynth = \default |
    
    ^super.new.play(argbpm, argamp, argtick, argsynth);
    
    }
    
    
    
    play{| argbpm, argamp, argtick, argsynth |
    
    bpm = argbpm;
    
    amp = argamp;
    
    tick = argtick;
    
    synth = argsynth;
    
    routine = fork{
    
    inf.do{| i |
    
    if(i % tick == 0,
    
    {
    
    intv = 60000 / bpm; //millisecond
    
    synthNode = Synth.new(synth, [\freq, 700, \amp, amp]);
    
    },
    
    {synthNode = Synth.new(synth, [\amp, amp]);});
    
    ((intv/1000)/2).wait;
    
    synthNode.free;
    
    ((intv/1000)/2).wait;
    
    }
    
    };
    
    }
    
    
    
    stop{
    
    routine.stop;
    
    synthNode.free;
    
    }
    
    }
    
    Advertisements
     
    • mortp 2월 29, 2012 9:59 오후 퍼머링크 | 응답

      엔터를 쳐도 줄간격이 안늘어나요 이런;;;

    • joynimm 3월 1, 2012 1:01 오전 퍼머링크 | 응답

      this 가 뭐라그랬져? ^ 는 리턴…
      요즘 느끼는 바는 sc 같은 oop에서는 class 작성을 배워두면 많이 유용할 듯합니다.

      • mortp 3월 1, 2012 2:18 오후 퍼머링크 | 응답

        this는,
        클래스메소드를 정의할 때 쓰면 클래스를,
        인스턴스메소드를 정의할 때 쓰면 인스턴스를 참조한다고 하네요.
        음.. super와 대비되는 개념으로 생각하면 될 것 같아요.

  • mortp February 22, 2012 8:45 pm 퍼머링크 | 응답
    태그: Document, , , ,   

    내일의 시간 절약을 위해 공부 할 코드를 미리… 

    내일의 시간 절약을 위해,

    공부(?)할 코드를 미리 올려둘게요.

    우선은 startup.rtf 파일로 저장해 주세요.

    
    s = Server.internal;
    
    Server.default = s;
    
    s.boot;
    
    
    CocoaDocument.defaultFont_(Font("Arial Unicode MS",16)); //set default font
    
    
    s.doWhenBooted
    
    {
    
    var ranNum = 0;
    
    var postWindow = Document.listener;
    
    
    //set post window
    
    postWindow.font_(Font("Arial Unicode MS",16)); //set post window default font
    
    Document.postColor_(Color.white);
    
    postWindow.background_(Color.new255(10, 20, 100, 180));
    
    postWindow.bounds_(Rect.new(0, 270, 290, 768 - 270 ));
    
    
    //set own colorize theme
    
    Document.themes.put
    
    (\myTheme,
    
    (
    
    classColor: Color.new255(53, 74, 237),
    
    textColor: Color.new255(25, 175, 120),
    
    stringColor: Color.new255(96, 129, 158),
    
    commentColor: Color.new255(206, 27, 28),
    
    symbolColor: Color.new255(57, 154, 20),
    
    numberColor: Color.new255(157, 80, 65)
    
    )
    
    );
    
    
    //and then calling setTheme with the name:
    
    Document.setTheme('myTheme');
    
    
    //document setting(문서가 새로 만들어지거나, open 할 때의 설정)
    
    Document.initAction_({
    
    Document.current.background_(Color.new255(10, 20, 20, 230));
    
    Document.current.stringColor_(Document.themes.myTheme.textColor);
    
    Document.current.selectedBackground_(Color.new255(220, 180, 150, 60)); //selected block color
    
    Document.current.syntaxColorize;
    
    Document.current.endFrontAction_({ //문서가 뒤로 갈 때의 액션을 정해 둠
    
    Document.current.background_(Color.new255(80, 20, 30, 150));
    
    });
    
    Document.current.toFrontAction_({ //문서가 앞으로 나올 때의 액션을 정해 둠
    
    Document.current.background_(Color.new255(10, 20, 20, 230));
    
    });
    
    });
    
    
    " ".postln;
    
    " ".postln;
    
    " ".postln;
    
    " ".postln;
    
    " ".postln;
    
    " ".postln;
    
    
    //run s.meter
    
    //SCLevelIndicator.meter_Xpos = 290; //set X pos, 쓰시려면 좀 더 수정이 필요해서 일단 주석처 합니다
    
    //SCLevelIndicator.meter_Ypos = 0; //set Y pos, 쓰시려면 좀 더 수정이 필요해서 일단 주석처 합니다
    
    s.meter;
    
    
    //run FreqScope
    
    //SCFreqScopeWindow.scopeXpos = 650; //set Freq Scope's X pos, 쓰시려면 좀 더 수정이 필요해서 일단 주석처 합니다
    
    //SCFreqScopeWindow.scopeYpos = 3; //set Freq Scope's Y pos, 쓰시려면 좀 더 수정이 필요해서 일단 주석처 합니다
    
    FreqScope.new(300, 200);
    
    
    //run T-D Scope
    
    //SCStethoscope.stethXpos = 1023; //set T - D Scope's X pos, 쓰시려면 좀 더 수정이 필요해서 일단 주석처 합니다
    
    //SCStethoscope.stethYpos = 8; //set T - D Scope's Y pos, 쓰시려면 좀 더 수정이 필요해서 일단 주석처 합니다
    
    SCStethoscope.new(s, 2);
    
    
    " ".postln;
    
    " ".postln;
    
    
    
    //print welcome message
    
    ranNum = 3.rand;
    
    switch(ranNum,
    
    0, {"HOW ARE YOU, GANG IL ?".postln;},
    
    1, {"IS EVERYTHING ARIGHT ?".postln;},
    
    2, {"HOW'S THE THINGS GOING ?".postln;}
    
    );
    
    
    
    " ".postln;
    
    " ".postln;
    
    " ".postln;
    
    " ".postln;
    
    };
    
    
    
    //---------------- auto colorizing -------------------
    
    Document.globalKeyDownAction_({| doc, char, mod, unicode, keycode |
    
    if((doc.name.find("htm").isNil) and: (doc.name.find("html").isNil) and: (doc.isListener == false),
    
    {
    
    if((unicode==13) or: (unicode==32) or: (unicode==46), // Enter, Space bar, Period
    
    {
    
    doc.syntaxColorize;
    
    })
    
    });
    
    });
    
    

    아래는 간단히 용어에 대한 정리 입니다.

     

    <용어 정리>

     

    -Document

    : 슈퍼콜라이더에서 ‘문서’. 우리가 지금 보고있는 편집창.

    이것 역시 클래스로 이루어져 있고, 창을 연다는 것은 이 클래스의 인스턴스를 생성하는 셈.

    따라서 정의된 속성(Properties)을 변경하거나, 함수(Method, Function)를 이용하여 어떤 일을 시킬 수 있다.

    Document 를 선택하고 cmd + y를 눌러보자.

     

    -listener

    :Document의 메소드 중 하나. post창을 의미한다.

    클래스에 직접 적용하는 class method, 인스턴스에 적용해야 하는 instance method 는 모두 클래스의 헬프파일에 설명되고 있다.

     

    -bounds

    :GUI를 이용하는, 혹은 GUI와 관련된 클래스들은 보통 bounds라는 속성을 가지는데,

    이것은 GUI 창의 좌측 하단 모서리의 x축 상의 위치,  y축 상의 위치(화면의 아랫쪽이 좌표 0), 창의 넓이, 창의 높이 정보를 말한다.

    실제로는 대부분,

    Rect(xPos, yPos, width, height);

    이런 식으로, Rect 클래스의 인스턴스를 타입으로 요구한다.

     

    -theme

    :Document의

    classColor: Color.new255(53, 74, 237),

    textColor: Color.new255(25, 175, 120),

    stringColor: Color.new255(96, 129, 158),

    commentColor: Color.new255(206, 27, 28),

    symbolColor: Color.new255(57, 154, 20),

    numberColor: Color.new255(157, 80, 65)

     

    에 대한 속성을 짝지워 담고 있는 저장공간으로,

    슈퍼콜라이더에서 사용되는 여섯 종류의 글자들이 syntaxColorize 됐을 경우 바뀔 색을 미리 지정한다.

    Event 라는 클래스의 인스턴스이다.

     

    -initAction

    :새로운 Document를 만들거나 기존의 Document를 열었을 때에, 자동으로 실행될 행동들을 예약해 두겠다는 메소드.

     
  • mortp February 22, 2012 10:57 am 퍼머링크 | 응답  

    이번주 딱히 주제가 정해지지 않았다면, 

    슈콜 구이(Gui)환경 사용자화와 startup 파일에 대해 공부해 볼게요.

     

     

    예를들어 슈콜을 켜면 이런 식으로 짠 하고 셋팅이 되는.

    *startup 파일은 예전 도스의 “autoexec.bat” 파일과 비슷하고, 맥의 ‘start at login’과 비슷한건데요,

    슈콜을 켜자마자 할 일들을 적어주면 되는 곳입니다.

     
  • mortp December 31, 2011 5:46 pm 퍼머링크 | 응답  

    기억적 자폭을 위한 게임의 티저 

    라 치고, 봐주시면 감사하죠.

     

    슈콜과 프로세싱, 위리모트를 이용했습니다.

    슈콜 부분 허세적이니까 허세반 갑니다-

     
  • joynimm August 17, 2011 12:42 pm 퍼머링크 | 응답  

    일본사람이 쓰고있는 sc3 tutorial 

    뒷부분은 미완성인것 같은데 oop 와 sc3를 번갈아가면서 하는 강좌가 인상적이네요… 저도 다보지는 못했어요…

    http://ge.tt/9zedys6?c

     
    • morogado 8월 17, 2011 1:27 오후 퍼머링크 | 응답

      색깔이 확실한 문서 같아서 유용할것 같아요.

    • hoonida 8월 17, 2011 11:15 오후 퍼머링크 | 응답

      oop란 오브젝트지향이란 즉 객체지향 프로그래밍? 이건뭐라는거죠? sc3파일이라 차별이란 ? 뭐죠?

    • joynimm 8월 18, 2011 1:12 오후 퍼머링크 | 응답

      sc3는 smalltalk라는 객체지향프로그램에 많은 영향을 받았다고 들었어요.

      oop 강좌 부분은 sc3로 객체지향적인 내용이 구현된 사례를 보고
      sc3 강좌 부분은 실제적 용례를 설명하는 것 같습니다.

  • joynimm August 11, 2011 6:17 pm 퍼머링크 | 응답
    태그: , , synthesis   

    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 
    ) 
     
     
    
     
c
새 글 작성
j
다음 글/다음 댓글
k
이전 글/이전 댓글
r
응답
e
편집
o
댓글 표시/숨기기
t
상위로 가기
l
로그인하기
h
도움말 표시/숨기기
shift + esc
취소