ChiptuneSynth에 대한 전체 참조 — Web Audio API용 4트랙 칩튠 신디사이저
// 1. Include the library
<script src="chiptune-synth.js"></script>
// 2. Create and initialize
const synth = new ChiptuneSynth();
await synth.init();
// 3. Play a note
synth.playNoteByName('C', 4, 0, 0.5);
// 4. Or play a sound effect
synth.playPreset('coin');
// 5. Load an instrument
synth.loadInstrument('violin', 0);
synth.playNoteByName('A', 4, 0, 1.0); init()`를 호출하십시오.4개의 트랙(Lead, Bass, Drums, FX), 기본 엔벨로프 및 비어 있는 비브라토 설정을 가진 새로운 신디사이저 인스턴스를 생성합니다.
const synth = new ChiptuneSynth(); Web Audio API 컨텍스트를 초기화하고, 마스터 게인, 분석기, 트랙별 게인 노드 및 노이즈 버퍼를 생성합니다. 재생 전에 반드시 한 번 호출해야 합니다.
await synth.init(); 모든 노트를 중지하고 AudioContext를 닫습니다. 신디사이저 사용이 완료되면 호출하십시오.
지정된 트랙에서 주어진 주파수(Hz)의 노트를 재생합니다.
| 매개 변수 | 유형 | 기본값 | 설명 |
|---|---|---|---|
| 주파수 | 숫자 | — | 주파수(Hz 단위, 예: A4의 경우 440) |
| 트랙 인덱스 | 번호 | 0 | 트랙 인덱스: 0=리드, 1=베이스, 2=드럼, 3=FX |
| duration | 숫자 | 10 | 초 단위의 지속 시간. 10 이상의 값은 지속 음을 생성합니다 |
| 시작 시간 | 숫자 | 지금 | 시작 시간(스케줄링용) |
const noteId = synth.playNote(440, 0, 0.5); // A4, Lead, 0.5s stopNote()를 사용하여 수동으로 제어하는 지속 음의 경우, duration = 10 이상을 사용하십시오. 이것이 키보드와 MIDI의 작동 방식입니다.음표의 음악적 이름으로 음표를 재생합니다.
| 매개 변수 | 유형 | 기본값 | 설명 |
|---|---|---|---|
| note | 문자열 | — | 음표 이름: C, C#, D, D#, E, F, F#, G, G#, A, A#, B (Db, Eb, Gb, Ab, Bb 포함) |
| 옥타브 | 번호 | 4 | 옥타브 (1-7) |
| 트랙 인덱스 | 번호 | 0 | 대상 트랙 |
| 재생 시간 | 번호 | 10 | 초 단위 지속 시간 |
synth.playNoteByName('C', 4, 0, 0.5); // Middle C on Lead
synth.playNoteByName('Eb', 3, 1, 1.0); // Eb3 on Bass 지정된 음표와 그 릴리스 엔벨로프를 중지합니다. playNote() 또는 playNoteByName()에서 반환된 noteId를 사용하십시오.
모든 트랙의 활성 노트를 즉시 중지합니다.
한 번의 호출로 내장된 SFX 프리셋을 불러와 재생합니다. 게임 사운드 효과에 적합합니다.
synth.playPreset('coin');
synth.playPreset('explosion');
synth.playPreset('jump'); | 이름 | 설명 | 사용 사례 |
|---|---|---|
| 레이저 | 하강하는 잽 빔 | 사격, 빔 |
| 동전 | 오르는 밝은 딩 | 아이템 수집 |
| 점프 | 빠른 상승 스윕 | 점프, 튀어오르기 |
| 폭발 | 소음 폭발 감쇠 | 파괴, 죽음 |
| 파워업 | 상승하는 스윕 팡파르 | 파워업, 업그레이드 |
| 타격 | 날카로운 충격음 | 피해, 충돌 |
| 삐 | 짧은 UI 클릭 | 메뉴 선택, UI |
| 저음 | 깊은 삼각형 쿵 | 베이스 드롭, 충격음 |
| 사격 | 빠른 전기 충격 사격 | 연사 무기 |
| 1UP | 상승하는 팡파르 | 추가 생명, 보너스 |
프리셋의 구성(파형, 엔벨로프, 이펙트)을 재생하지 않고 트랙에 불러옵니다. 수동으로 노트를 트리거하기 전에 트랙을 설정할 때 유용합니다.
지정된 트랙에 전체 악기 프리셋을 불러와 파형, 엔벨로프, 비브라토 및 모듈레이션을 설정합니다.
synth.loadInstrument('violin', 0);
synth.playNoteByName('A', 4, 0, 2.0); | 이름 | 유형 | 설명 |
|---|---|---|
| 피아노 | 트라이앵글 | 밝은 타악기 음색에 댐핑이 빠름 |
| 바이올린 | 톱니파 | 비브라토가 가미된 따뜻한 활 연주 음색 |
| 첼로 | 톱니파 | 저음역의 깊은 활 닿는 현 |
| 플루트 | 사인파 | 비브라토가 가미된 부드럽고 숨결이 느껴지는 음색 |
| 오르간 | 스퀘어 | 지속적인 파이프 오르간 음색 |
| 금관 | 톱니파형 | 강렬한 호른/트럼펫 사운드 |
| 하모니카 | 사각파 | 트레몰로가 가미된 리디 PWM 톤 |
| 신스 리드 | 스퀘어 | 클래식 칩튠 리드 |
| 신스 패드 | 톱니파 | 필터가 적용된 와이드 유니슨 패드 |
| 신스 베이스 | 톱니파형 | 강렬한 신스 베이스 |
| 마림바 | 사인파 | 타악기 같은 말렛 음색 |
| 일렉트릭 기타 | 스퀘어 | 오버드라이브 기타 에뮬레이션 |
트랙의 하나 이상의 속성을 업데이트합니다. 변경 사항은 현재 재생 중인 음표에 실시간으로 적용됩니다.
synth.updateTrack(0, {
type: 'sawtooth',
volume: 0.4,
unisonVoices: 4,
unisonDetune: 20
}); | 속성 | 유형 | 기본값 | 설명 |
|---|---|---|---|
| 유형 | 문자열 | 'square' | 파형: 'square', 'triangle', 'sawtooth', 'sine', 'noise' |
| 볼륨 | 숫자 | 0.3 | 트랙 볼륨 (0-1) |
| 듀티 사이클 | 숫자 | 0.5 | 사각파의 펄스 폭 (0-1) |
| 디튠 | 숫자 | 0 | 센트 단위의 미세 튜닝 (1200 = 1 옥타브) |
| 옥타브 오프셋 | 숫자 | 0 | 옥타브 이동 (±) |
| 반음 오프셋 | 숫자 | 0 | 반음 이동 (±) |
| 피치 엔벨로프 | 숫자 | 0 | 반음 단위의 피치 엔벨로프 깊이 |
| 글라이드 | 숫자 | 0 | 포르타멘토 시간 (초) |
트랙 오브젝트의 속성을 직접 설정할 수도 있습니다:
synth.tracks[0].type = 'sawtooth';
synth.tracks[0].volume = 0.4;
synth.updateLiveNotes(0); // Apply to active notes 트랙의 진폭 엔벨로프를 설정합니다. 음표의 페이드 인, 서스테인, 페이드 아웃 방식을 제어합니다.
synth.updateEnvelope(0, {
attack: 0.1, // Fade-in time (seconds)
decay: 0.2, // Decay to sustain level
sustain: 0.6, // Held level (0-1)
release: 0.5 // Fade-out after note stops
}); | 속성 | 유형 | 범위 | 설명 |
|---|---|---|---|
| attack | 횟수 | 0~5초 | 최대 음량에 도달하는 시간 |
| 감쇠 | 숫자 | 0-5초 | 피크에서 서스테인 레벨로 떨어지는 시간 |
| 지속 | 숫자 | 0-1 | 노트가 유지되는 동안의 볼륨 레벨 (0 = 디케이 후 꺼짐) |
| 릴리스 | 숫자 | 0-10초 | 노트가 멈춘 후 페이드 아웃 시간 |
| 트랙 | 어택 | 디케이 | 서스테인 | 릴리즈 |
|---|---|---|---|---|
| 0 - 리드 | 0.01 | 0.10 | 0.7 | 0.20 |
| 1 - 베이스 | 0.01 | 0.20 | 0.8 | 0.15 |
| 2 - 드럼 | 0.001 | 0.10 | 0.0 | 0.05 |
| 3 - 효과음 | 0.005 | 0.30 | 0.0 | 0.20 |
트랙의 피치 변조(비브라토)를 설정합니다.
synth.updateVibrato(0, {
rate: 5, // Speed in Hz
depth: 12 // Amount in cents
}); | 속성 | 유형 | 기본값 | 설명 |
|---|---|---|---|
| 속도 | 숫자 | 0 | LFO 속도(Hz) (0 = 꺼짐) |
| 깊이 | 숫자 | 0 | 센트 단위의 피치 편차 (0 = 꺼짐) |
각 트랙에는 사운드의 주파수 성분을 조절할 수 있는 필터가 선택적으로 제공됩니다.
synth.tracks[0].filterEnabled = true;
synth.tracks[0].filterType = 'lowpass';
synth.tracks[0].filterCutoff = 2000;
synth.tracks[0].filterQ = 5;
synth.updateLiveNotes(0); | 속성 | 유형 | 기본값 | 설명 |
|---|---|---|---|
| filterEnabled | 부울 | false | 필터 활성화/비활성화 |
| filterType | 문자열 | '저역통과' | '저역통과', '고역통과', '대역통과', '노치' |
| filterCutoff | 숫자 | 20000 | 컷오프 주파수 (Hz) |
| 필터 Q | 숫자 | 0.1 | 공진 / Q 계수 |
| 필터 키 트랙 | 숫자 | 0 | 키 트래킹 0-100 (컷오프가 피치를 따름) |
| 필터 엔벨로프 양 | 숫자 | 0 | 필터 엔벨로프 깊이 (반음) |
| filterEnvAttack | 숫자 | 0.01 | 필터 엔벨로프 어택 (초) |
| filterEnvRelease | 숫자 | 0.2 | 필터 엔벨로프 릴리스 (초) |
여러 개의 디튠된 오실레이터를 중첩하여 두껍고 넓은 사운드를 만듭니다. 패드와 리드 사운드에 필수적입니다.
synth.tracks[0].unisonVoices = 8;
synth.tracks[0].unisonDetune = 25; // cents between voices
synth.tracks[0].unisonSpread = 80; // stereo spread % | 속성 | 유형 | 기본값 | 설명 |
|---|---|---|---|
| unisonVoices | 숫자 | 1 | 오실레이터 수 (1-16) |
| unisonDetune | 숫자 | 0 | 센트 단위의 디튠 스프레드 |
| unisonSpread | 숫자 | 0 | 스테레오 패닝 범위 (0-100%) |
synth.tracks[0].tremoloRate = 6; // Hz
synth.tracks[0].tremoloDepth = 50; // 0-100 synth.tracks[0].filterEnabled = true;
synth.tracks[0].filterCutoff = 1000;
synth.tracks[0].lfoFilterRate = 3; // Hz
synth.tracks[0].lfoFilterDepth = 2000; // Hz range | 속성 | 유형 | 설명 |
|---|---|---|
| tremoloRate | 숫자 | 트레몰로 속도(Hz) (0 = 꺼짐) |
| tremoloDepth | 숫자 | 트레몰로 양 (0-100) |
| lfoFilterRate | 숫자 | Hz 단위의 필터 LFO 속도 (0 = 꺼짐) |
| lfoFilterDepth | 숫자 | Hz 단위의 필터 LFO 범위 |
연결된 컨트롤러의 MIDI 입력을 활성화합니다. 감지된 MIDI 입력 장치 이름의 배열을 반환합니다.
const inputs = await synth.enableMIDI({
track: 0,
channel: 0, // 0 = all channels
onConnect: (name) => console.log('Connected:', name),
onDisconnect: (name) => console.log('Disconnected:', name),
onNoteOn: (note, vel, ch) => { /* MIDI note 0-127 */ },
onNoteOff: (note, ch) => { /* ... */ },
onCC: (cc, value, ch) => { /* CC 0-127 */ }
}); | 속성 | 유형 | 기본값 | 설명 |
|---|---|---|---|
| 트랙 | 번호 | 0 | MIDI 노트를 위한 대상 트랙 |
| 채널 | 번호 | 0 | MIDI 채널 필터 (1-16, 0 = 전체) |
| onConnect | onConnect | — | MIDI 장치가 연결될 때 호출됨 |
| onDisconnect | 함수 | — | MIDI 장치가 연결 해제될 때 호출됨 |
| onNoteOn | 함수 | — | note on 호출 시 (note, velocity, channel) |
| onNoteOff | 함수 | — | 노트 오프 시 호출됨 (note, channel) |
| onCC | 함수 | — | 컨트롤 변경 시 호출됨 (cc, value, channel) |
| CC | 이름 | 효과 |
|---|---|---|
| 1 | 모드 휠 | 비브라토 강도를 조절합니다 |
| 7 | 볼륨 | 트랙 볼륨 조절 |
| 64 | 서스테인 페달 | 지속되는 음을 유지합니다 |
| 120 | 모든 소리 끄기 | 모든 음을 멈춤 |
| 123 | 모든 음소거 | 모든 음표 중지 |
MIDI 입력을 비활성화하고 유지 중인 모든 MIDI 음을 중지합니다.
MIDI 입력을 수신할 트랙을 변경합니다.
MIDI 채널 필터를 설정합니다(0 = 모든 채널).
현재 MIDI가 활성화되어 있는지 여부를 반환합니다.
오실로스코프 스타일의 시각화를 그리기 위한 시간 영역 파형 데이터를 반환합니다. 값의 범위는 0~255입니다(128 = 중심).
function draw() {
const data = synth.getWaveformData();
// Draw on canvas...
ctx.beginPath();
data.forEach((v, i) => {
const x = (i / data.length) * width;
const y = (v / 255) * height;
i === 0 ? ctx.moveTo(x, y) : ctx.lineTo(x, y);
});
ctx.stroke();
requestAnimationFrame(draw);
} 스펙트럼 시각화를 위한 주파수 영역(FFT) 데이터를 반환합니다. 값의 범위는 0~255입니다.
마스터 출력 볼륨을 설정합니다(0~1).
현재 마스터 볼륨을 반환합니다.
모든 트랙, 엔벨로프 및 비브라토를 기본값으로 재설정합니다.
음표 이름과 옥타브를 Hz 단위의 주파수로 변환합니다.
ChiptuneSynth.noteToFrequency('A', 4); // → 440
ChiptuneSynth.noteToFrequency('C', 4); // → 261.63 MIDI 노트 번호(0-127)를 Hz 단위의 주파수로 변환합니다.
주파수를 가장 가까운 MIDI 음표 번호로 변환합니다.
사용 가능한 모든 SFX 프리셋 이름의 배열을 반환합니다.
ChiptuneSynth.getPresetNames();
// → ['laser','coin','jump','explosion','powerup','hit','blip','bass','shoot','1up'] 사용 가능한 모든 악기 프리셋 이름의 배열을 반환합니다.
악기 이름을 키로 하는 객체를 반환하며, 각 값에는 전체 정의(트랙 설정, 엔벨로프, 비브라토, 필터 등)가 포함됩니다.
const instruments = ChiptuneSynth.getInstruments();
// { piano: { name, label, icon, type, volume, ... }, violin: { ... }, ... }
// Access a specific instrument definition
const piano = instruments.piano;
console.log(piano.type); // 'triangle'
console.log(piano.label); // 'Piano' 트랙 설정, 엔벨로프, 비브라토, 필터를 조합하여 나만의 악기를 만들 수 있습니다. 다음은 사운드를 처음부터 만드는 방법입니다.
트랙을 수동으로 구성한 후, 해당 트랙에서 음을 연주합니다:
// Create a retro pluck bass
synth.updateTrack(1, {
type: 'sawtooth',
volume: 0.5,
octaveOffset: -1
});
synth.updateEnvelope(1, {
attack: 0.005,
decay: 0.3,
sustain: 0.0,
release: 0.1
});
synth.playNoteByName('E', 2, 1, 0.4); 프리셋 패턴을 재현해 보세요 — 트랙을 구성하고, 음을 연주하면 나머지는 엔벨로프가 처리합니다:
// Custom "warp" SFX on FX track (3)
function playWarp() {
synth.updateTrack(3, {
type: 'square',
volume: 0.3,
dutyCycle: 0.25,
pitchEnv: -24 // pitch drops 2 octaves
});
synth.updateEnvelope(3, {
attack: 0.01,
decay: 0.4,
sustain: 0.0,
release: 0.1
});
synth.playNote(880, 3, 0.5);
}
// Now call playWarp() anytime! 다양한 기능을 결합하여 표현력 풍부한 악기를 만드세요:
// Dreamy synth pad with filter sweep
function setupDreamPad(track) {
synth.updateTrack(track, {
type: 'square',
volume: 0.25,
dutyCycle: 0.3,
unisonVoices: 6,
unisonDetune: 18,
unisonSpread: 70
});
synth.updateEnvelope(track, {
attack: 0.8,
decay: 0.5,
sustain: 0.6,
release: 2.0
});
synth.updateVibrato(track, {
rate: 4,
depth: 8
});
// Add filter with LFO modulation
synth.tracks[track].filterEnabled = true;
synth.tracks[track].filterType = 'lowpass';
synth.tracks[track].filterCutoff = 1200;
synth.tracks[track].filterQ = 3;
synth.tracks[track].lfoFilterRate = 0.3;
synth.tracks[track].lfoFilterDepth = 800;
}
setupDreamPad(0);
synth.playNoteByName('C', 4, 0, 3.0); 복잡한 사운드를 위해 여러 트랙을 레이어링하세요:
// Layered "epic hit" — noise + bass + lead
function playEpicHit() {
// Layer 1: noise crash
synth.updateTrack(2, { type: 'noise', volume: 0.4 });
synth.updateEnvelope(2, { attack:0.001, decay:0.3, sustain:0, release:0.1 });
synth.playNote(200, 2, 0.4);
// Layer 2: sub bass thump
synth.updateTrack(1, { type: 'sine', volume: 0.6, pitchEnv: 12 });
synth.updateEnvelope(1, { attack:0.001, decay:0.25, sustain:0, release:0.1 });
synth.playNote(60, 1, 0.3);
// Layer 3: bright accent
synth.updateTrack(0, { type: 'square', volume: 0.2 });
synth.updateEnvelope(0, { attack:0.001, decay:0.1, sustain:0, release:0.2 });
synth.playNote(440, 0, 0.15);
} 사용자 정의 악기를 구성 객체로 정리하세요:
// Define instrument configs
const myInstruments = {
retroLead: {
track: { type: 'square', dutyCycle: 0.25, volume: 0.3 },
env: { attack: 0.02, decay: 0.15, sustain: 0.5, release: 0.3 },
vib: { rate: 5.5, depth: 10 }
},
fatBass: {
track: { type: 'sawtooth', volume: 0.5, unisonVoices: 3, unisonDetune: 10 },
env: { attack: 0.01, decay: 0.2, sustain: 0.7, release: 0.1 },
vib: { rate: 0, depth: 0 }
}
};
// Apply an instrument to a track
function applyInstrument(name, trackIndex) {
const inst = myInstruments[name];
synth.updateTrack(trackIndex, inst.track);
synth.updateEnvelope(trackIndex, inst.env);
synth.updateVibrato(trackIndex, inst.vib);
}
applyInstrument('retroLead', 0);
synth.playNoteByName('C', 5, 0, 0.5); | 트랙 | 인덱스 | 파형 | 볼륨 |
|---|---|---|---|
| 리드 | 0 | 제곱 | 0.30 |
| 베이스 | 1 | 삼각형 | 0.40 |
| 드럼 | 2 | 노이즈 | 0.50 |
| FX | 3 | 톱니파형 | 0.25 |
노트별 'gainNode'는 ADSR 엔벨로프(정규화 0→1→서스테인)만 처리합니다. 트랙 볼륨은 별도의 '_trackGains[]' 노드로 제어됩니다. 이 아키텍처는 연주 중인 노트의 ADSR 일정을 방해하지 않고도 실시간으로 파라미터를 변경할 수 있게 해줍니다.