728x90

🎼 비트박스 리듬

표기법

기호의미

X 연주
-
K Kick
S Snare
H HiHat
C Clap
B Bass
L Laser FX

16 Step 기준:

1---2---3---4---

1. 기본 힙합

Step : 1 2 3 4 5 6 7 8 9 A B C D E F G

Kick : K - - - K - - - K - - - K - - -
Snare: - - - - S - - - - - - - S - - -
HiHat: H - H - H - H - H - H - H - H -

2. 붐뱁 (Boom Bap)

Kick : K - - K - - - - K - - - K - - -
Snare: - - - - S - - - - - - - S - - -
HiHat: H H - H H - H H H - H H - H H -
Bass : B - - - - - B - - - - - B - - -

3. 트랩

Kick : K - - - - - K - - - K - - - - -
Snare: - - - - S - - - - - - - S - - -
HiHat: H H H H H H H H H H H H H H H H
Bass : B - - - B - - - - - - B - - - -

4. 하우스

Kick : K - - - K - - - K - - - K - - -
Snare: - - - - S - - - - - - - S - - -
HiHat: - - H - - - H - - - H - - - H -
Clap : - - - - C - - - - - - - C - - -

5. EDM 드롭

Kick : K - - - K - - - K - - - K - - -
Snare: - - - - S - - - - - - - S - - -
HiHat: H H H H H H H H H H H H H H H H
Laser: - - L - - - L - - - L - - - L -
Bass : B B B B B B B B B B B B B B B B

6. 드럼앤베이스

Kick : K - - - - - K - - - - - K - - -
Snare: - - - - S - - - - - - - S - - -
HiHat: H H H H H H H H H H H H H H H H
Bass : B - B - B - B - B - B - B - B -

7. 레게

Kick : K - - - - - - - K - - - - - - -
Snare: - - - - S - - - - - - - S - - -
HiHat: - - H - - - H - - - H - - - H -
Bass : B - - - B - - - B - - - B - - -

8. 펑크(Funk)

Kick : K - K - - - K - K - - - K - - -
Snare: - - - - S - - - - - - - S - - -
HiHat: H - H H - H H - H - H H - H H -
Clap : - - - - - - - C - - - - - - - C

9. 테크노

Kick : K - - - K - - - K - - - K - - -
Snare: - - - - - - - - S - - - - - - -
HiHat: H - H - H - H - H - H - H - H -
Laser: - - - - - - - L - - - - - - - L

10. 게임 보스전 스타일

Kick : K - K - K - K - K - K - K - K -
Snare: - - - - S - - S - - - S - - - -
HiHat: H H H H H H H H H H H H H H H H
Laser: - - L - - - - - L - - - - - L -
Bass : B B B B B B B B B B B B B B B B

🧠 AI 자동 작곡용 추천 구조

Intro

Kick : K-------K-------
HiHat: H-H-H-H-H-H-H-H-

Build Up

Kick : K---K---K---K---
Snare: ----S-------S---

Drop

Kick : K-K-K-K-K-K-K-K-
Snare: ----S---S---S---
Bass : BBBBBBBBBBBBBBBB

Ending

Kick : K-------K-------
HiHat: H---H---H---H---

🎵 BPM 추천

장르BPM

HipHop 80~100
Trap 130~150
House 120~128
EDM 128~140
DnB 160~180
LoFi 70~90
Funk 90~110

🎹 추천 추가 기능

추가 구현 가능:

  • MIDI 저장
  • WAV Export
  • MP3 녹음
  • AI 멜로디 생성
  • 코드 진행 자동 생성
  • 피아노 추가
  • 808 베이스
  • 스윙 리듬
  • 실시간 키보드 연주
  • 드래그 페인팅
  • 64 Step Sequencer
  • 패턴 저장/불러오기
  • 머신러닝 스타일 생성
  • Transformer 기반 AI 작곡
  • Web MIDI 연결
  • 실제 드럼 샘플 적용
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>AI 자동 작곡 비트박스</title>

<style>
*{
    margin:0;
    padding:0;
    box-sizing:border-box;
}

body{
    background:#0f0f0f;
    color:white;
    font-family:Arial;
    padding:20px;
}

h1{
    text-align:center;
    margin-bottom:20px;
    font-size:40px;
}

.controls{
    display:flex;
    gap:10px;
    justify-content:center;
    flex-wrap:wrap;
    margin-bottom:20px;
}

button{
    padding:12px 20px;
    background:#222;
    border:none;
    border-radius:10px;
    color:white;
    cursor:pointer;
    font-size:16px;
}

button:hover{
    background:#444;
}

.grid{
    display:grid;
    grid-template-columns:120px repeat(16,1fr);
    gap:5px;
    max-width:1400px;
    margin:auto;
}

.label{
    background:#1c1c1c;
    border-radius:8px;
    display:flex;
    justify-content:center;
    align-items:center;
    font-weight:bold;
    min-height:45px;
}

.cell{
    aspect-ratio:1;
    background:#181818;
    border:2px solid #333;
    border-radius:8px;
    cursor:pointer;
    transition:0.1s;
}

.cell.active{
    background:#00d2ff;
    box-shadow:0 0 10px #00d2ff;
}

.cell.playing{
    border-color:white;
    transform:scale(1.1);
}

.info{
    text-align:center;
    margin-top:20px;
    color:#aaa;
    line-height:1.8;
}

select,input{
    padding:10px;
    border-radius:8px;
    border:none;
}
</style>
</head>
<body>

<h1>🤖 AI 자동 작곡 비트박스</h1>

<div class="controls">

    <button id="playBtn">▶ 재생</button>
    <button id="stopBtn">■ 정지</button>
    <button id="aiBtn">🎲 AI 자동 작곡</button>
    <button id="clearBtn">🧹 전체 삭제</button>

    <select id="style">
        <option value="hiphop">HipHop</option>
        <option value="trap">Trap</option>
        <option value="house">House</option>
        <option value="edm">EDM</option>
        <option value="dnb">DnB</option>
    </select>

    <span>BPM</span>
    <input type="range" id="bpm" min="60" max="200" value="110">
    <span id="bpmText">110</span>

</div>

<div class="grid" id="grid"></div>

<div class="info">
AI 버튼을 누르면 자동으로 비트를 생성합니다.<br>
Kick / Snare / HiHat / Clap / Bass / Laser 지원
</div>

<script>

const instruments = [
    "Kick",
    "Snare",
    "HiHat",
    "Clap",
    "Bass",
    "Laser"
];

const STEPS = 16;

const grid = document.getElementById("grid");

const pattern = [];

instruments.forEach((inst,row)=>{

    pattern[row] = [];

    const label = document.createElement("div");
    label.className = "label";
    label.innerText = inst;

    grid.appendChild(label);

    for(let i=0;i<STEPS;i++){

        pattern[row][i] = false;

        const cell = document.createElement("div");
        cell.className = "cell";

        cell.dataset.row = row;
        cell.dataset.step = i;

        cell.onclick = ()=>{

            pattern[row][i] = !pattern[row][i];

            cell.classList.toggle("active");
        };

        grid.appendChild(cell);
    }
});

function updateGrid(){

    document.querySelectorAll(".cell").forEach(cell=>{

        const row = Number(cell.dataset.row);
        const step = Number(cell.dataset.step);

        cell.classList.toggle("active", pattern[row][step]);
    });
}

function clearPattern(){

    for(let r=0;r<instruments.length;r++){

        for(let s=0;s<STEPS;s++){

            pattern[r][s] = false;
        }
    }

    updateGrid();
}

function randomChance(percent){

    return Math.random() < percent;
}

function aiCompose(){

    clearPattern();

    const style = document.getElementById("style").value;

    const map = {};

    instruments.forEach((v,i)=>map[v]=i);

    // 공통 하이햇
    for(let i=0;i<16;i+=2){

        pattern[map.HiHat][i] = true;
    }

    if(style==="hiphop"){

        [0,4,8,12].forEach(i=>{
            pattern[map.Kick][i] = true;
        });

        [4,12].forEach(i=>{
            pattern[map.Snare][i] = true;
        });

        pattern[map.Bass][0] = true;
        pattern[map.Bass][8] = true;
    }

    if(style==="trap"){

        [0,6,10].forEach(i=>{
            pattern[map.Kick][i] = true;
        });

        [4,12].forEach(i=>{
            pattern[map.Snare][i] = true;
        });

        for(let i=0;i<16;i++){

            if(randomChance(0.9))
                pattern[map.HiHat][i] = true;
        }

        pattern[map.Bass][0] = true;
        pattern[map.Bass][4] = true;
        pattern[map.Bass][11] = true;
    }

    if(style==="house"){

        [0,4,8,12].forEach(i=>{
            pattern[map.Kick][i] = true;
        });

        [4,12].forEach(i=>{
            pattern[map.Clap][i] = true;
        });

        [2,6,10,14].forEach(i=>{
            pattern[map.HiHat][i] = true;
        });
    }

    if(style==="edm"){

        [0,4,8,12].forEach(i=>{
            pattern[map.Kick][i] = true;
        });

        [4,12].forEach(i=>{
            pattern[map.Snare][i] = true;
        });

        for(let i=0;i<16;i++){

            pattern[map.HiHat][i] = true;
        }

        [2,6,10,14].forEach(i=>{
            pattern[map.Laser][i] = true;
        });

        for(let i=0;i<16;i+=2){

            pattern[map.Bass][i] = true;
        }
    }

    if(style==="dnb"){

        [0,6,12].forEach(i=>{
            pattern[map.Kick][i] = true;
        });

        [4,12].forEach(i=>{
            pattern[map.Snare][i] = true;
        });

        for(let i=0;i<16;i++){

            pattern[map.HiHat][i] = true;
        }

        for(let i=0;i<16;i+=2){

            pattern[map.Bass][i] = true;
        }
    }

    // AI 랜덤 변형
    for(let r=0;r<instruments.length;r++){

        for(let s=0;s<16;s++){

            if(randomChance(0.05)){

                pattern[r][s] = !pattern[r][s];
            }
        }
    }

    updateGrid();
}

const AudioContext = window.AudioContext || window.webkitAudioContext;
const audioCtx = new AudioContext();

function noiseBuffer(){

    const buffer = audioCtx.createBuffer(1,44100,44100);

    const data = buffer.getChannelData(0);

    for(let i=0;i<44100;i++){

        data[i] = Math.random()*2-1;
    }

    return buffer;
}

function playSound(type){

    const now = audioCtx.currentTime;

    if(type==="Kick"){

        const osc = audioCtx.createOscillator();
        const gain = audioCtx.createGain();

        osc.type="sine";

        osc.frequency.setValueAtTime(150,now);
        osc.frequency.exponentialRampToValueAtTime(0.001,now+0.5);

        gain.gain.setValueAtTime(1,now);
        gain.gain.exponentialRampToValueAtTime(0.001,now+0.5);

        osc.connect(gain);
        gain.connect(audioCtx.destination);

        osc.start();
        osc.stop(now+0.5);
    }

    if(type==="Snare"){

        const noise = audioCtx.createBufferSource();
        noise.buffer = noiseBuffer();

        const gain = audioCtx.createGain();

        gain.gain.setValueAtTime(1,now);
        gain.gain.exponentialRampToValueAtTime(0.01,now+0.2);

        noise.connect(gain);
        gain.connect(audioCtx.destination);

        noise.start();
        noise.stop(now+0.2);
    }

    if(type==="HiHat"){

        const osc = audioCtx.createOscillator();
        const gain = audioCtx.createGain();

        osc.type="square";
        osc.frequency.value = 1200;

        gain.gain.setValueAtTime(0.3,now);
        gain.gain.exponentialRampToValueAtTime(0.01,now+0.05);

        osc.connect(gain);
        gain.connect(audioCtx.destination);

        osc.start();
        osc.stop(now+0.05);
    }

    if(type==="Clap"){

        for(let i=0;i<3;i++){

            const noise = audioCtx.createBufferSource();

            noise.buffer = noiseBuffer();

            const gain = audioCtx.createGain();

            const t = now + i*0.03;

            gain.gain.setValueAtTime(0.7,t);
            gain.gain.exponentialRampToValueAtTime(0.01,t+0.08);

            noise.connect(gain);
            gain.connect(audioCtx.destination);

            noise.start(t);
            noise.stop(t+0.08);
        }
    }

    if(type==="Bass"){

        const osc = audioCtx.createOscillator();
        const gain = audioCtx.createGain();

        osc.type="sawtooth";
        osc.frequency.value = 60;

        gain.gain.setValueAtTime(0.4,now);
        gain.gain.exponentialRampToValueAtTime(0.01,now+0.4);

        osc.connect(gain);
        gain.connect(audioCtx.destination);

        osc.start();
        osc.stop(now+0.4);
    }

    if(type==="Laser"){

        const osc = audioCtx.createOscillator();
        const gain = audioCtx.createGain();

        osc.type="sawtooth";

        osc.frequency.setValueAtTime(1500,now);
        osc.frequency.exponentialRampToValueAtTime(100,now+0.3);

        gain.gain.setValueAtTime(0.5,now);
        gain.gain.exponentialRampToValueAtTime(0.01,now+0.3);

        osc.connect(gain);
        gain.connect(audioCtx.destination);

        osc.start();
        osc.stop(now+0.3);
    }
}

let currentStep = 0;
let timer = null;

function highlight(step){

    document.querySelectorAll(".cell").forEach(c=>{
        c.classList.remove("playing");
    });

    document.querySelectorAll(`.cell[data-step='${step}']`)
        .forEach(c=>c.classList.add("playing"));
}

function start(){

    if(timer) return;

    const bpm = Number(document.getElementById("bpm").value);

    const interval = (60000 / bpm) / 4;

    timer = setInterval(()=>{

        highlight(currentStep);

        instruments.forEach((inst,row)=>{

            if(pattern[row][currentStep]){

                playSound(inst);
            }
        });

        currentStep++;

        if(currentStep>=16){

            currentStep = 0;
        }

    },interval);
}

function stop(){

    clearInterval(timer);

    timer = null;

    currentStep = 0;

    document.querySelectorAll(".cell").forEach(c=>{
        c.classList.remove("playing");
    });
}

document.getElementById("playBtn").onclick = async ()=>{

    await audioCtx.resume();

    stop();
    start();
};

document.getElementById("stopBtn").onclick = stop;

document.getElementById("aiBtn").onclick = ()=>{

    aiCompose();
};

document.getElementById("clearBtn").onclick = clearPattern;

document.getElementById("bpm").oninput = e=>{

    document.getElementById("bpmText").innerText = e.target.value;

    if(timer){

        stop();
        start();
    }
};

</script>

</body>
</html>
728x90

+ Recent posts