<button onclick="startMusic()">๐ต ์์
์์</button>
<script>
const audioCtx = new (window.AudioContext || window.webkitAudioContext)();
let isPlaying = false;
function playNote(freq, startTime, duration = 0.2, type = 'sine', volume = 0.3) {
const osc = audioCtx.createOscillator();
const gain = audioCtx.createGain();
osc.type = type;
osc.frequency.value = freq;
gain.gain.setValueAtTime(volume, startTime);
gain.gain.exponentialRampToValueAtTime(0.001, startTime + duration);
osc.connect(gain);
gain.connect(audioCtx.destination);
osc.start(startTime);
osc.stop(startTime + duration);
}
function scheduleRhythm(startTime, tempo, measures = 8) {
const beatTime = 60 / tempo;
const totalBeats = measures * 4;
for (let i = 0; i < totalBeats; i++) {
const t = startTime + i * beatTime;
if (i % 4 === 0) playNote(100, t, 0.1, 'square', 0.4); // Kick
if (i % 4 === 2) playNote(180, t, 0.1, 'triangle', 0.2); // Snare
const bassNotes = [130.81, 196.00, 220.00, 174.61]; // C-G-A-F
const bassFreq = bassNotes[Math.floor(i / 8) % 4];
if (i % 2 === 0) playNote(bassFreq, t, 0.2, 'sawtooth', 0.3);
}
return totalBeats * beatTime;
}
function scheduleMelodyPhase(startTime, tempo) {
const beat = 60 / tempo;
// Phase 1: ๊ธฐ - ๋จ์ํ๊ณ ์์ ์ ์ธ ๋ฉ๋ก๋ (C E G ๋ฐ๋ณต)
[[523.25, 0], [659.25, 1], [783.99, 2], [659.25, 3]].forEach(([f, i]) =>
playNote(f, startTime + i * beat, 0.3, 'triangle', 0.2)
);
// Phase 2: ์น - ์ ์ฌ๋ผ๊ฐ๊ณ ์๋ ๋นจ๋ผ์ง
[[659.25, 4], [698.46, 4.5], [783.99, 5], [880.00, 5.5], [987.77, 6], [880.00, 6.5]].forEach(([f, i]) =>
playNote(f, startTime + i * beat, 0.2, 'triangle', 0.25)
);
// Phase 3: ์ - ๊ฐ๋ ฌํ๊ฒ! 16๋ถ์ํ ๋๋
[880.00, 987.77, 1046.50, 1174.66].forEach((f, idx) =>
playNote(f, startTime + (7 + idx * 0.25) * beat, 0.15, 'triangle', 0.25)
);
// Phase 4: ๊ฒฐ - ์ฒ์ ๋ฉ๋ก๋์ ๋ณํ, ๋ฎ์์ง๋ฉฐ ์์ ๊ฐ
[[783.99, 8], [659.25, 9], [587.33, 10], [523.25, 11]].forEach(([f, i]) =>
playNote(f, startTime + i * beat, 0.25, 'triangle', 0.2)
);
}
function startMusic() {
if (isPlaying) return;
isPlaying = true;
const tempo1 = 120;
const tempo2 = 160;
const now = audioCtx.currentTime;
const dur1 = scheduleRhythm(now, tempo1, 8);
scheduleMelodyPhase(now, tempo1); // ๐ต ๊ธฐ์น์ ๊ฒฐ ๋ฉ๋ก๋
function loopFastPart(start) {
const dur2 = scheduleRhythm(start, tempo2, 8);
scheduleMelodyPhase(start, tempo2);
setTimeout(() => loopFastPart(start + dur2), dur2 * 1000);
}
setTimeout(() => loopFastPart(now + dur1), dur1 * 1000);
}
</script>