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
'Software > JavaScript' 카테고리의 다른 글
| Javascript 시작하기 - 비트박스 (0) | 2026.05.13 |
|---|---|
| Javascript 시작하기 - 그림판 (0) | 2026.05.10 |
| Javascript 시작하기 - 40음계 피아노 (0) | 2026.05.09 |
| Javascript 시작하기 - ThreeJS로 육각형 그려서 크기 바꾸기#1 (0) | 2026.02.08 |
| Javascript 시작하기 - ThreeJS로 선그리기 #1 (0) | 2026.02.08 |
