technobeat-machine / index.html
Robertogdl's picture
Crea una caja de ritmos para musica techno funcional
e84c097 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>TechnoBeat Machine - Drum Machine for Techno Music</title>
<link rel="icon" type="image/x-icon" href="/static/favicon.ico">
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script>
<script src="https://unpkg.com/feather-icons"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/tone/14.7.77/Tone.js"></script>
<style>
@import url('https://fonts.googleapis.com/css2?family=Orbitron:wght@400;500;700;900&family=Inter:wght@300;400;500;600;700&display=swap');
body {
font-family: 'Inter', sans-serif;
background: linear-gradient(135deg, #0f0f23 0%, #1a1a2e 50%, #16213e 100%);
color: #e2e8f0;
overflow-x: hidden;
}
.orb-font {
font-family: 'Orbitron', monospace;
}
.glow {
box-shadow: 0 0 10px rgba(66, 153, 225, 0.5), 0 0 20px rgba(66, 153, 225, 0.3);
}
.pulse {
animation: pulse 0.5s ease-in-out;
}
@keyframes pulse {
0% { transform: scale(1); }
50% { transform: scale(1.05); }
100% { transform: scale(1); }
}
.knob {
background: conic-gradient(from 0deg, #4299e1 0%, #4299e1 var(--rotation, 0%), #2d3748 var(--rotation, 0%), #2d3748 100%);
border-radius: 50%;
width: 60px;
height: 60px;
position: relative;
cursor: pointer;
}
.knob::after {
content: '';
position: absolute;
top: 5px;
left: 50%;
transform: translateX(-50%);
width: 4px;
height: 20px;
background: #e2e8f0;
border-radius: 2px;
}
.sequencer-cell {
transition: all 0.1s ease;
border-radius: 4px;
}
.sequencer-cell.active {
background-color: #4299e1;
transform: scale(1.05);
box-shadow: 0 0 10px rgba(66, 153, 225, 0.7);
}
.sequencer-cell.playing {
background-color: #ed64a6;
transform: scale(1.1);
box-shadow: 0 0 15px rgba(237, 100, 166, 0.8);
}
.beat-visualizer {
height: 4px;
background: linear-gradient(90deg, #4299e1, #ed64a6, #48bb78, #f6ad55);
border-radius: 2px;
width: 100%;
transform-origin: left;
transition: transform 0.1s ease;
}
/* Custom scrollbar */
::-webkit-scrollbar {
width: 8px;
}
::-webkit-scrollbar-track {
background: #1a202c;
border-radius: 4px;
}
::-webkit-scrollbar-thumb {
background: #4299e1;
border-radius: 4px;
}
/* Responsive adjustments */
@media (max-width: 768px) {
.drum-pad {
width: 70px;
height: 70px;
}
.knob {
width: 50px;
height: 50px;
}
}
</style>
</head>
<body class="min-h-screen flex flex-col">
<!-- Header -->
<header class="py-6 px-4 sm:px-6 lg:px-8 bg-black bg-opacity-30 backdrop-blur-lg border-b border-gray-800">
<div class="max-w-7xl mx-auto flex flex-col sm:flex-row justify-between items-center">
<div class="flex items-center mb-4 sm:mb-0">
<div class="w-10 h-10 rounded-full bg-gradient-to-r from-blue-500 to-purple-600 flex items-center justify-center mr-3">
<i data-feather="music" class="text-white"></i>
</div>
<h1 class="text-2xl sm:text-3xl font-bold orb-font">TechnoBeat <span class="text-blue-400">Machine</span></h1>
</div>
<div class="flex items-center space-x-4">
<div class="flex items-center bg-gray-900 rounded-full px-4 py-2">
<i data-feather="clock" class="text-blue-400 mr-2"></i>
<span class="orb-font" id="bpm-display">120 BPM</span>
</div>
<button id="play-pause" class="bg-blue-600 hover:bg-blue-700 text-white rounded-full w-12 h-12 flex items-center justify-center transition-all duration-200 glow">
<i data-feather="play" id="play-icon"></i>
</button>
</div>
</div>
</header>
<!-- Main Content -->
<main class="flex-grow py-8 px-4 sm:px-6 lg:px-8">
<div class="max-w-7xl mx-auto">
<!-- Beat Visualizer -->
<div class="mb-8">
<div class="beat-visualizer" id="beat-visualizer"></div>
</div>
<!-- Drum Pads -->
<div class="grid grid-cols-2 sm:grid-cols-4 gap-4 mb-8">
<div class="drum-pad bg-gray-800 rounded-xl p-4 flex flex-col items-center justify-center cursor-pointer transition-all duration-200 hover:bg-gray-700 glow" data-sound="kick">
<div class="w-16 h-16 rounded-full bg-gradient-to-br from-gray-700 to-gray-900 flex items-center justify-center mb-2">
<i data-feather="square" class="text-blue-400"></i>
</div>
<span class="orb-font text-sm">KICK</span>
</div>
<div class="drum-pad bg-gray-800 rounded-xl p-4 flex flex-col items-center justify-center cursor-pointer transition-all duration-200 hover:bg-gray-700 glow" data-sound="snare">
<div class="w-16 h-16 rounded-full bg-gradient-to-br from-gray-700 to-gray-900 flex items-center justify-center mb-2">
<i data-feather="circle" class="text-pink-500"></i>
</div>
<span class="orb-font text-sm">SNARE</span>
</div>
<div class="drum-pad bg-gray-800 rounded-xl p-4 flex flex-col items-center justify-center cursor-pointer transition-all duration-200 hover:bg-gray-700 glow" data-sound="hihat">
<div class="w-16 h-16 rounded-full bg-gradient-to-br from-gray-700 to-gray-900 flex items-center justify-center mb-2">
<i data-feather="star" class="text-green-400"></i>
</div>
<span class="orb-font text-sm">HIHAT</span>
</div>
<div class="drum-pad bg-gray-800 rounded-xl p-4 flex flex-col items-center justify-center cursor-pointer transition-all duration-200 hover:bg-gray-700 glow" data-sound="clap">
<div class="w-16 h-16 rounded-full bg-gradient-to-br from-gray-700 to-gray-900 flex items-center justify-center mb-2">
<i data-feather="zap" class="text-yellow-400"></i>
</div>
<span class="orb-font text-sm">CLAP</span>
</div>
</div>
<!-- Sequencer -->
<div class="bg-gray-900 bg-opacity-50 rounded-xl p-6 mb-8 border border-gray-800">
<h2 class="text-xl font-bold mb-4 orb-font">SEQUENCER</h2>
<div class="overflow-x-auto">
<div class="min-w-max">
<!-- Step labels -->
<div class="flex mb-2">
<div class="w-24"></div>
<div class="flex">
<?php for ($i = 1; $i <= 16; $i++): ?>
<div class="w-10 text-center orb-font text-sm opacity-70"><?php echo $i; ?></div>
<?php endfor; ?>
</div>
</div>
<!-- Sequencer rows -->
<div class="sequencer-grid">
<?php
$sounds = ['kick', 'snare', 'hihat', 'clap'];
foreach ($sounds as $sound):
?>
<div class="flex items-center mb-3">
<div class="w-24 orb-font text-sm uppercase"><?php echo $sound; ?></div>
<div class="flex">
<?php for ($i = 1; $i <= 16; $i++): ?>
<div class="sequencer-cell w-8 h-8 mx-1 bg-gray-800 cursor-pointer transition-all duration-200" data-sound="<?php echo $sound; ?>" data-step="<?php echo $i; ?>"></div>
<?php endfor; ?>
</div>
</div>
<?php endforeach; ?>
</div>
</div>
</div>
</div>
<!-- Controls -->
<div class="grid grid-cols-1 md:grid-cols-3 gap-6">
<!-- BPM Control -->
<div class="bg-gray-900 bg-opacity-50 rounded-xl p-6 border border-gray-800">
<h3 class="text-lg font-bold mb-4 orb-font">TEMPO</h3>
<div class="flex flex-col items-center">
<div class="knob mb-4" id="bpm-knob" style="--rotation: 180deg"></div>
<div class="flex items-center">
<button class="bg-gray-800 rounded-full w-8 h-8 flex items-center justify-center mr-2" id="bpm-down">
<i data-feather="minus" class="text-white"></i>
</button>
<span class="orb-font text-2xl" id="bpm-value">120</span>
<button class="bg-gray-800 rounded-full w-8 h-8 flex items-center justify-center ml-2" id="bpm-up">
<i data-feather="plus" class="text-white"></i>
</button>
</div>
</div>
</div>
<!-- Effects -->
<div class="bg-gray-900 bg-opacity-50 rounded-xl p-6 border border-gray-800">
<h3 class="text-lg font-bold mb-4 orb-font">EFFECTS</h3>
<div class="grid grid-cols-2 gap-4">
<div class="flex flex-col items-center">
<span class="text-sm mb-2">FILTER</span>
<div class="knob" style="--rotation: 120deg"></div>
</div>
<div class="flex flex-col items-center">
<span class="text-sm mb-2">DELAY</span>
<div class="knob" style="--rotation: 60deg"></div>
</div>
<div class="flex flex-col items-center">
<span class="text-sm mb-2">REVERB</span>
<div class="knob" style="--rotation: 240deg"></div>
</div>
<div class="flex flex-col items-center">
<span class="text-sm mb-2">DISTORTION</span>
<div class="knob" style="--rotation: 300deg"></div>
</div>
</div>
</div>
<!-- Pattern Control -->
<div class="bg-gray-900 bg-opacity-50 rounded-xl p-6 border border-gray-800">
<h3 class="text-lg font-bold mb-4 orb-font">PATTERNS</h3>
<div class="grid grid-cols-4 gap-2">
<?php for ($i = 1; $i <= 8; $i++): ?>
<button class="bg-gray-800 rounded-lg py-2 orb-font transition-all duration-200 hover:bg-gray-700 <?php echo $i === 1 ? 'bg-blue-600' : ''; ?>">P<?php echo $i; ?></button>
<?php endfor; ?>
</div>
<div class="mt-4 flex space-x-2">
<button class="flex-1 bg-gray-800 rounded-lg py-2 orb-font text-sm transition-all duration-200 hover:bg-gray-700">SAVE</button>
<button class="flex-1 bg-gray-800 rounded-lg py-2 orb-font text-sm transition-all duration-200 hover:bg-gray-700">CLEAR</button>
</div>
</div>
</div>
</div>
</main>
<!-- Footer -->
<footer class="py-6 px-4 sm:px-6 lg:px-8 bg-black bg-opacity-30 backdrop-blur-lg border-t border-gray-800">
<div class="max-w-7xl mx-auto flex flex-col sm:flex-row justify-between items-center">
<div class="text-sm text-gray-400 mb-4 sm:mb-0">
&copy; 2023 TechnoBeat Machine. Create your own techno beats.
</div>
<div class="flex space-x-4">
<a href="#" class="text-gray-400 hover:text-blue-400 transition-colors duration-200">
<i data-feather="github"></i>
</a>
<a href="#" class="text-gray-400 hover:text-blue-400 transition-colors duration-200">
<i data-feather="twitter"></i>
</a>
<a href="#" class="text-gray-400 hover:text-blue-400 transition-colors duration-200">
<i data-feather="mail"></i>
</a>
</div>
</div>
</footer>
<script>
// Initialize Feather Icons
feather.replace();
// Drum Machine Logic
document.addEventListener('DOMContentLoaded', function() {
let isPlaying = false;
let bpm = 120;
let currentStep = 0;
let sequencerInterval;
// Initialize Tone.js
const kick = new Tone.MembraneSynth().toDestination();
const snare = new Tone.NoiseSynth({
noise: { type: "white" },
envelope: { attack: 0.005, decay: 0.1, sustain: 0 }
}).toDestination();
const hihat = new Tone.MetalSynth({
frequency: 200,
envelope: { attack: 0.001, decay: 0.1, sustain: 0 },
harmonicity: 5.1,
modulationIndex: 32,
resonance: 4000,
octaves: 1.5
}).toDestination();
const clap = new Tone.NoiseSynth({
noise: { type: "white" },
envelope: { attack: 0.005, decay: 0.1, sustain: 0 }
}).toDestination();
// Play/Pause button
const playPauseBtn = document.getElementById('play-pause');
const playIcon = document.getElementById('play-icon');
playPauseBtn.addEventListener('click', function() {
if (!isPlaying) {
startSequencer();
playIcon.setAttribute('data-feather', 'square');
feather.replace();
playPauseBtn.classList.add('bg-red-500', 'hover:bg-red-600');
playPauseBtn.classList.remove('bg-blue-600', 'hover:bg-blue-700');
} else {
stopSequencer();
playIcon.setAttribute('data-feather', 'play');
feather.replace();
playPauseBtn.classList.remove('bg-red-500', 'hover:bg-red-600');
playPauseBtn.classList.add('bg-blue-600', 'hover:bg-blue-700');
}
isPlaying = !isPlaying;
});
// Drum pad clicks
document.querySelectorAll('.drum-pad').forEach(pad => {
pad.addEventListener('click', function() {
const sound = this.getAttribute('data-sound');
playSound(sound);
this.classList.add('pulse');
setTimeout(() => {
this.classList.remove('pulse');
}, 200);
});
});
// Sequencer cell clicks
document.querySelectorAll('.sequencer-cell').forEach(cell => {
cell.addEventListener('click', function() {
this.classList.toggle('active');
});
});
// BPM controls
const bpmValue = document.getElementById('bpm-value');
const bpmDisplay = document.getElementById('bpm-display');
const bpmUp = document.getElementById('bpm-up');
const bpmDown = document.getElementById('bpm-down');
const bpmKnob = document.getElementById('bpm-knob');
bpmUp.addEventListener('click', function() {
if (bpm < 200) {
bpm += 5;
updateBPM();
}
});
bpmDown.addEventListener('click', function() {
if (bpm > 60) {
bpm -= 5;
updateBPM();
}
});
function updateBPM() {
bpmValue.textContent = bpm;
bpmDisplay.textContent = `${bpm} BPM`;
const rotation = ((bpm - 60) / 140) * 360;
bpmKnob.style.setProperty('--rotation', `${rotation}deg`);
if (isPlaying) {
stopSequencer();
startSequencer();
}
}
// Sequencer functions
function startSequencer() {
const stepDuration = 60 / bpm / 4; // 16th notes
currentStep = 0;
sequencerInterval = setInterval(() => {
// Reset previous step
document.querySelectorAll('.sequencer-cell.playing').forEach(cell => {
cell.classList.remove('playing');
});
// Highlight current step
document.querySelectorAll(`.sequencer-cell[data-step="${currentStep + 1}"]`).forEach(cell => {
cell.classList.add('playing');
// Play sound if active
if (cell.classList.contains('active')) {
const sound = cell.getAttribute('data-sound');
playSound(sound);
}
});
// Animate beat visualizer
const visualizer = document.getElementById('beat-visualizer');
visualizer.style.transform = `scaleX(${(currentStep + 1) / 16})`;
currentStep = (currentStep + 1) % 16;
}, stepDuration * 1000);
}
function stopSequencer() {
clearInterval(sequencerInterval);
document.querySelectorAll('.sequencer-cell.playing').forEach(cell => {
cell.classList.remove('playing');
});
document.getElementById('beat-visualizer').style.transform = 'scaleX(0)';
}
function playSound(sound) {
const now = Tone.now();
switch(sound) {
case 'kick':
kick.triggerAttackRelease("C1", "8n", now);
break;
case 'snare':
snare.triggerAttackRelease("8n", now);
break;
case 'hihat':
hihat.triggerAttackRelease("8n", now);
break;
case 'clap':
clap.triggerAttackRelease("8n", now);
break;
}
}
// Initialize BPM display
updateBPM();
});
</script>
</body>
</html>