SuperCollider에서 변조 위치를 일시 정지하고 다음 트리거에서 역방향으로 다시 시작하는 방법
변조 위치를 일시 정지한 뒤 역방향으로 다시 시작하려면, 위상 생성기를 증가량이 0인 상태로 계속 실행하고 다음 트리거에서 증가량을 음수로 바꾸세요. 움직임이 멈춘 위치에서 이어지도록 위상 재설정 입력은 해당 트리거와 연결하지 마세요.
이 튜토리얼에서는 SuperCollider로 이 동작을 구현합니다. 상승하는 피치 스윕이 첫 번째 트리거에서 멈추고 두 번째 트리거에서 경로를 되짚습니다. 연속된 이벤트로 제어하는 반복 가능한 변조 제스처를 원하는 사운드 디자이너를 위한 내용입니다. 같은 위상 신호를 나중에 다른 파라미터에 사용할 수도 있습니다.
일시 정지 중 무엇을 유지해야 하나요?
변조를 서로 연결된 두 가지 작업으로 생각하세요. 위치가 한 주기를 따라 움직이고, 매핑이 그 위치를 유용한 파라미터 값으로 변환합니다. 여기서는 위치가 0에서 1을 향해 움직이고, 매핑이 이를 오실레이터 주파수로 변환합니다.
SuperCollider의 Phasor가 위치를 제공합니다. rate 인수는 샘플당 증가량을 지정하고, 트리거 입력은 대신 위치를 resetPos으로 이동시킵니다. 이들은 별도의 제어 입력이므로, 방향을 바꾸는 데 사용하는 트리거로 위치까지 재설정하면 안 됩니다. Phasor 문서
이 구현은 내부 레벨을 유지하면서 여기에 속도를 더합니다. 이 동작에 따라 속도가 0이면 레벨이 유지되고, 음수 속도이면 레벨이 감소합니다. 아래 패치는 이를 직접 적용해 일시 정지 중에도 생성기의 상태를 보존합니다. SuperCollider 3.14.0 TriggerUGens.cpp 구현
연속된 각 트리거는 어떤 동작을 해야 하나요?
사운드에 연결하기 전에 이벤트 순서를 정하세요. 이 패치에서는 움직임이 즉시 정방향으로 시작됩니다. 이후 각 트리거가 상태를 하나씩 진행시킵니다.
| 수신한 트리거 수 | 상태 | 방향 배수 |
|---|---|---|
| 0 | 정방향 이동 | +1 |
| 1 | 현재 위치 유지 | 0 |
| 2 | 역방향 재개 | −1 |
| 3 | 현재 위치 유지 | 0 |
| 4 | 정방향 재개 | +1 |
이 네 상태 순환에서는 두 가지 유지 상태가 구분됩니다. 하나는 역방향 이동으로 이어지고, 다른 하나는 정방향 이동으로 이어집니다. 따라서 방향 버튼을 따로 추가하지 않아도 제스처를 반복해서 예측 가능하게 만들 수 있습니다.
PulseCount는 입력이 0 이하에서 양수로 바뀔 때 카운트를 증가시킵니다. 카운트를 4로 나머지 연산하면 0–3 인덱스가 반복됩니다. 그러면 Select가 [1, 0, -1, 0]에서 해당하는 배수를 선택합니다. 이는 PulseCount와 Select의 문서화된 역할입니다.
완전한 패치는 어떻게 만드나요?
오디오 출력이 작동하는 로컬 SuperCollider 설치 환경을 사용하세요. 이 예제는 3.14.0 문서를 기준으로 합니다. 내장 유닛 제너레이터를 사용하고 자체적으로 사운드를 생성하므로 샘플 파일이나 확장 기능은 필요하지 않습니다. 전체 블록을 한 번 평가하고 준비 완료 메시지가 나올 때까지 기다리세요.
waitForBoot는 필요한 경우 서버를 시작합니다. 신스를 만들기 전에 정의를 전송하고, s.sync이 대기 중인 서버 작업이 끝날 때까지 기다립니다. Server 문서와 SynthDef 문서를 참고하세요.
(
s = Server.default;
s.waitForBoot({
SynthDef(\pauseReverseMod, {
|out = 0, t_step = 0, cycleSeconds = 8, amp = 0.08|
var state, direction, increment, phase, frequency, sound;
state = PulseCount.kr(t_step) % 4;
direction = Select.kr(state, [1, 0, -1, 0]);
// A full 0..1 traversal takes cycleSeconds seconds.
increment = direction * SampleDur.ir
/ cycleSeconds.max(0.01);
// State-changing triggers never reset this phase.
phase = Phasor.ar(
trig: 0,
rate: increment,
start: 0,
end: 1,
resetPos: 0
);
frequency = LinExp.ar(phase, 0, 1, 220, 880);
sound = SinOsc.ar(frequency, 0, amp);
Out.ar(out, sound ! 2);
Poll.kr(Impulse.kr(2), state, "state");
Poll.kr(Impulse.kr(2), A2K.kr(phase), "phase");
}).add;
s.sync;
~pauseReverseSynth = Synth(\pauseReverseMod);
"Ready: evaluate ~pauseReverseSynth.set(\\t_step, 1);".postln;
});
)
증가량은 방향에 샘플 지속 시간을 곱한 뒤 주기 지속 시간으로 나눈 값입니다. SampleDur는 서버 샘플 레이트의 역수를 반환하므로, 8초 설정은 특정 샘플 레이트를 전제로 하지 않습니다. SampleDur 문서
피치 매핑 범위는 220–880 Hz입니다. LinExp는 선형 입력 범위를 지수 출력 범위로 변환합니다. 목적지의 양 끝값은 0이 아니어야 하며 부호가 같아야 합니다. 여기서는 두 끝값 모두 이 조건을 충족합니다. LinExp 문서
검색 과정에서 확인한 문서와 SuperCollider 예제를 대조해 살펴봤습니다. 조사 환경에서는 SuperCollider 런타임을 사용할 수 없어 이 패치를 실행하거나 직접 들어보지는 못했습니다. 별도의 결정론적 산술 검사를 통해 방향 순서와 증가량이 0일 때의 유지 동작을 확인했습니다.
일시 정지 후 역방향으로 재개하려면 어떻게 하나요?
준비 완료 메시지가 나온 뒤 약 2초 동안 피치가 올라가도록 두세요. 그런 다음 다음 상호작용 명령을 한 번 평가하세요.
~pauseReverseSynth.set(\t_step, 1);
상태가 1로 바뀌고 출력되는 위상 값이 일정하게 유지되어야 합니다. 잠시 기다린 뒤 같은 명령을 다시 평가하세요. 상태는 2로 바뀌고, 멈춰 있던 위치에서 위상이 감소해야 합니다. 세 번째로 평가하면 하강 스윕이 멈추고, 네 번째로 평가하면 다시 정방향으로 시작합니다.
t_ 접두어를 사용하면 t_step은 트리거 제어 입력이 됩니다. 값을 설정하면 컨트롤 레이트 임펄스가 발생하므로, 간격을 두고 명령을 평가할 때마다 별도로 0을 보내지 않아도 같은 명령을 반복해서 사용할 수 있습니다. SynthDef 트리거 제어 문서
예시 계산으로, 8초 주기는 초당 범위의 0.125만큼 진행됩니다. 따라서 2초 뒤에 일시 정지하면 약 0.25에서 멈춥니다. 일시 정지 시간과 관계없이 역방향으로 1초 움직이면 약 0.125에 도달합니다. 이는 계산으로 얻은 예상값이며 실제 정지 위치는 명령을 수동으로 입력하는 시점에 따라 달라집니다.
마지막으로 정리 명령을 평가하세요.
~pauseReverseSynth.free;
위치가 실제로 유지됐는지 어떻게 확인하나요?
출력되는 위상 값을 주요 진단 수단으로 사용하세요. 정방향으로 움직일 때는 값이 증가하고, 어느 쪽이든 유지 상태에서는 일정해야 하며, 역방향으로 움직일 때는 주기 경계에 도달할 때까지 감소해야 합니다.
패치는 초당 두 번 출력하므로 화면에는 모든 샘플이 아니라 동작을 샘플링한 값이 표시됩니다. 일시 정지 중 연속된 여러 값을 살펴본 다음 재개 후 처음으로 감소하는 값들과 비교하세요. Poll은 유닛 제너레이터 값 디버깅용입니다. 일반적인 사용을 위해 정의를 수정할 때는 두 개의 폴링 라인을 제거하세요. Poll 문서
이 검사는 소리만 듣는 것보다 더 많은 정보를 줍니다. 사운드가 일정하면 출력값이 더 이상 변하지 않는다는 뜻이고, 위상 값이 안정적으로 유지되면 기반 위치도 멈췄다는 점을 확인할 수 있습니다. 검사 중에는 매핑을 고정해 두면 결과를 더 쉽게 해석할 수 있습니다.
패치가 왜 다시 시작되거나, 튀거나, 트리거를 놓칠 수 있나요?
재개할 때 처음부터 다시 시작합니다. 이벤트가 Phasor의 트리거 입력에도 전달되는지 확인하세요. 해당 입력은 위치를 명시적으로 재설정합니다. 이 패치에서는 그 입력을 0으로 유지하고 이벤트는 상태 카운터에만 전달합니다. Phasor 문서
끝점에 도달한 뒤 값이 튑니다. 이 예제는 의도적으로 순환하도록 설계되어 있습니다. 구현은 위상이 음의 방향으로 이동할 때도 설정된 범위 안에서 위상을 순환시킵니다. 역방향 이동이 0을 지나면 위상은 상한 경계 근처로 돌아가며, 이 램프 매핑에서는 피치가 튑니다. 우선 경계에서 떨어진 위치에서 일시 정지와 방향 전환을 테스트하세요. Phasor 구현
명령을 빠르게 여러 번 입력해도 여러 상태가 만들어지지 않습니다. 카운터가 증가하려면 서로 구분되는 상승 전이가 필요합니다. 트리거 제어는 컨트롤 레이트로 작동하므로, 한 컨트롤 블록 안에 도착한 여러 명령이 별개의 이벤트로 처리된다고 가정하지 마세요. 먼저 간격을 두고 명령을 입력하세요. 시점을 촘촘히 맞춘 시퀀스가 필요하다면 서로 구분되는 펄스를 생성하도록 이벤트 소스를 설계하세요. PulseCount 문서, SynthDef 문서
위상이 유지되는 동안 사운드가 바뀝니다. 목적지 매핑이나 다른 사운드 파라미터도 바꾸고 있지 않은지 확인하세요. 이 테스트에서는 피치 끝값을 고정하고 출력되는 위상 값으로 변조 전달 동작만 분리해 확인하세요.
완성된 제스처는 정방향 이동, 유지, 역방향 이동, 유지, 다시 정방향 이동의 순서입니다. 이 순서가 제대로 동작하면 상태 카운터와 위상 생성기를 재사용 가능한 변조 소스로 유지하고, 만들고 있는 사운드에 맞게 목적지 매핑을 바꾸세요.
출처
- Phasor — SuperCollider 3.14.0 도움말
- TriggerUGens.cpp — SuperCollider, Version-3.14.0
- PulseCount — SuperCollider 3.14.0 도움말
- Select — SuperCollider 3.14.0 도움말
- Server — SuperCollider 3.14.0 도움말
- SynthDef — SuperCollider 3.14.0 도움말
- SampleDur — SuperCollider 3.14.0 도움말
- LinExp — SuperCollider 3.14.0 도움말
- Poll — SuperCollider 3.14.0 도움말
