Learning
레슨 5 / 8·20분

시퀀싱과 패턴

고급 시퀀싱 기법

Tone.js의 시퀀싱 기능을 활용하면 복잡한 리듬 패턴과 멜로디를 프로그래밍할 수 있습니다. Part를 사용하면 각 음에 개별 시간과 길이를 지정할 수 있고, 여러 Part를 조합하여 완전한 악곡 구성이 가능합니다.

javascript
import * as Tone from 'tone';

// Part — 각 음에 개별 시간/길이/속도 지정
const synth = new Tone.Synth().toDestination();

const melody = new Tone.Part(
  (time, event) => {
    synth.triggerAttackRelease(
      event.note,
      event.duration,
      time,
      event.velocity
    );
  },
  [
    { time: '0:0:0', note: 'C4', duration: '8n', velocity: 0.9 },
    { time: '0:0:2', note: 'E4', duration: '8n', velocity: 0.7 },
    { time: '0:1:0', note: 'G4', duration: '4n', velocity: 0.8 },
    { time: '0:2:0', note: 'B4', duration: '8n', velocity: 0.6 },
    { time: '0:2:2', note: 'C5', duration: '2n', velocity: 1.0 },
  ]
);

melody.loop = true;
melody.loopEnd = '1m'; // 1마디마다 반복
melody.start(0);

Tone.Transport.bpm.value = 120;
Tone.Transport.start();

다중 트랙 구성

javascript
// 멜로디 트랙
const melodySynth = new Tone.Synth({
  oscillator: { type: 'triangle' },
}).toDestination();

const melodyPart = new Tone.Sequence(
  (time, note) => {
    if (note !== null) {
      melodySynth.triggerAttackRelease(note, '8n', time);
    }
  },
  ['C4', 'E4', 'G4', null, 'E4', 'C4', null, 'G3'],
  '8n'
);

// 베이스 트랙
const bassSynth = new Tone.MonoSynth({
  oscillator: { type: 'sawtooth' },
  filter: { Q: 2, frequency: 800, type: 'lowpass' },
  envelope: { attack: 0.01, decay: 0.3, sustain: 0.4, release: 0.8 },
}).toDestination();

const bassPart = new Tone.Sequence(
  (time, note) => {
    bassSynth.triggerAttackRelease(note, '4n', time);
  },
  ['C2', 'C2', 'G2', 'E2'],
  '4n'
);

// 드럼 트랙
const kick = new Tone.MembraneSynth().toDestination();
const snare = new Tone.NoiseSynth({
  noise: { type: 'white' },
  envelope: { attack: 0.005, decay: 0.15, sustain: 0 },
}).toDestination();

const drumPart = new Tone.Loop((time) => {
  kick.triggerAttackRelease('C1', '8n', time);
  snare.triggerAttackRelease('16n', time + Tone.Time('8n').toSeconds());
}, '4n');
javascript
// 모든 트랙 동시 시작/정지
function startAll() {
  melodyPart.start(0);
  bassPart.start(0);
  drumPart.start(0);
  Tone.Transport.start();
}

function stopAll() {
  melodyPart.stop();
  bassPart.stop();
  drumPart.stop();
  Tone.Transport.stop();
}

// BPM 변경
function setBPM(bpm) {
  Tone.Transport.bpm.rampTo(bpm, 1); // 1초에 걸쳐 변경
}

// 스윙 추가 (셔플 느낌)
Tone.Transport.swing = 0.3;    // 0~1, 스윙 정도
Tone.Transport.swingSubdivision = '8n'; // 스윙 적용 단위

// 시간 표기법
// '0:0:0' = 마디:박:16분음표
// '4n' = 4분음표, '8n' = 8분음표
// '1m' = 1마디, '2t' = 2분음표 셋잇단
  • Part — 각 이벤트에 개별 시간/값을 지정하는 유연한 시퀀서
  • Sequence — 배열을 균등 간격으로 순차 재생
  • Loop — 일정 간격마다 콜백 반복
  • null — Sequence에서 해당 타이밍을 쉼표(rest)로 처리
  • swing — 셔플/스윙 느낌 추가 (재즈, 펑크 등)
  • 시간 표기: "마디:박:16분음표" 또는 "4n"(음표 단위)
💡

Part에서 time은 "마디:박:16분음표" 형식입니다. "0:0:0"은 시작점, "0:1:0"은 두 번째 박, "1:0:0"은 두 번째 마디입니다. 4/4 박자에서 한 마디는 4박입니다.