ThatAIguyA world of ideas

THE CONSCIOUSNESS ATLAS
Read. Experiment. Follow the evidence.

ConsciousnessLearn · Explore · Joseph Anady

Janady13/Jennys-Drumste / freestyle-mode.html

Source identity, revision, and recovered contents.

GitHub sourceSource text recovered

Source identity

FieldRecorded value
Source typeGitHub source
Original recordJanady13/Jennys-Drumste / freestyle-mode.html
DateNot specified in source
RepositoryJanady13/Jennys-Drumste
Revision1f946b9e18e552f80f4b2ffd7f59c01d0126aa53
Branchclaude/jenny-drumsets-research-MofSb
Path or archive memberfreestyle-mode.html
Original SHA-256dac5cdb7da7b72be13664ed1614b0f764741e8c92774aef192d2bc1aaf8dc1f5
Git blob SHA361bf3bfa48f3a6676e4e8b81dc6ca12b792335c
Reading-copy SHA-256dac5cdb7da7b72be13664ed1614b0f764741e8c92774aef192d2bc1aaf8dc1f5

Original source ↗

Recovered source transcript

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>DrumMaster Pro - Freestyle Jam Mode</title> <script src="seferim-core.js"></script> <script src="audio-engine.js"></script> <script src="game-systems.js"></script> <link href="https://fonts.googleapis.com/css2?family=Press+Start+2P&family=Orbitron:wght@400;700;900&display=swap" rel="stylesheet"> <style> * { margin: 0; padding: 0; box-sizing: border-box; } :root { --kick: #ff6b35; --snare: #f7c948; --hihat: #4ecdc4; --crash: #ff006e; --tom1: #8338ec; --tom2: #3a86ff; --tom3: #06d6a0; --ride: #06ffa5; --neon-pink: #ff00ff; --neon-cyan: #00ffff; } body { font-family: 'Orbitron', sans-serif; background: linear-gradient(135deg, #0a0015 0%, #1a0030 50%, #0a0a20 100%); color: white; min-height: 100vh; overflow: hidden; } .container { display: grid; grid-template-rows: auto 1fr auto; height: 100vh; padding: 20px; gap: 20px; } /* Header */ .header { display: flex; justify-content: space-between; align-items: center; padding: 15px 25px; background: rgba(0,0,0,0.5); border: 1px solid rgba(255,0,255,0.3); border-radius: 15px; } .logo { font-family: 'Press Start 2P', cursive; font-size: 1.2em; background: linear-gradient(90deg, var(--neon-pink), var(--neon-cyan)); -webkit-background-clip: text; -webkit-text-fill-color: transparent; } .controls { display: flex; gap: 15px; align-items: center; } .btn { padding: 10px 20px; border: none; border-radius: 8px; font-family: 'Orbitron', sans-serif; font-weight: 600; cursor: pointer; transition: all 0.2s; } .btn-metro { background: linear-gradient(135deg, #8338ec, #6b2cb3); color: white; } .btn-metro.active { background: linear-gradient(135deg, var(--neon-cyan), #00aacc); box-shadow: 0 0 20px rgba(0,255,255,0.5); } .btn-record { background: linear-gradient(135deg, #ff006e, #cc0058); color: white; } .btn-record.recording { animation: pulse-red 0.5s infinite; } @keyframes pulse-red { 0%, 100% { box-shadow: 0 0 10px #ff006e; } 50% { box-shadow: 0 0 30px #ff006e; } } .bpm-control { display: flex; align-items: center; gap: 10px; padding: 8px 15px; background: rgba(0,0,0,0.5); border-radius: 8px; } .bpm-value { font-size: 1.5em; font-weight: 900; color: var(--neon-cyan); min-width: 60px; text-align: center; } .bpm-btn { width: 30px; height: 30px; border: none; border-radius: 50%; background: rgba(255,255,255,0.1); color: white; font-size: 1.2em; cursor: pointer; } .bpm-btn:hover { background: rgba(0,255,255,0.2); } /* Main Drum Kit Area */ .kit-container { display: flex; justify-content: center; align-items: center; position: relative; } .drum-kit { display: grid; grid-template-columns: repeat(4, 1fr); grid-template-rows: repeat(2, 1fr); gap: 20px; max-width: 900px; } .drum-pad { width: 150px; height: 150px; border-radius: 50%; display: flex; flex-direction: column; align-items: center; justify-content: center; cursor: pointer; transition: all 0.1s; position: relative; user-select: none; } .drum-pad::before { content: ''; position: absolute; inset: -5px; border-radius: 50%; background: inherit; opacity: 0.3; filter: blur(15px); z-index: -1; } .drum-pad[data-drum="kick"] { background: radial-gradient(circle at 30% 30%, var(--kick), #aa4520); border: 4px solid var(--kick); grid-column: 2; grid-row: 2; width: 180px; height: 180px; } .drum-pad[data-drum="snare"] { background: radial-gradient(circle at 30% 30%, var(--snare), #aa8830); border: 4px solid var(--snare); grid-column: 3; grid-row: 2; } .drum-pad[data-drum="hihat"] { background: radial-gradient(circle at 30% 30%, var(--hihat), #2a9a90); border: 4px solid var(--hihat); grid-column: 1; grid-row: 1; } .drum-pad[data-drum="crash"] { background: radial-gradient(circle at 30% 30%, var(--crash), #aa0050); border: 4px solid var(--crash); grid-column: 1; grid-row: 2; width: 130px; height: 130px; } .drum-pad[data-drum="tom1"] { background: radial-gradient(circle at 30% 30%, var(--tom1), #5a20aa); border: 4px solid var(--tom1); grid-column: 2; grid-row: 1; } .drum-pad[data-drum="tom2"] { background: radial-gradient(circle at 30% 30%, var(--tom2), #2060cc); border: 4px solid var(--tom2); grid-column: 3; grid-row: 1; } .drum-pad[data-drum="tom3"] { background: radial-gradient(circle at 30% 30%, var(--tom3), #04a87a); border: 4px solid var(--tom3); grid-column: 4; grid-row: 2; } .drum-pad[data-drum="ride"] { background: radial-gradient(circle at 30% 30%, var(--ride), #04cc80); border: 4px solid var(--ride); grid-column: 4; grid-row: 1; width: 130px; height: 130px; } .drum-pad.hit { transform: scale(0.92); filter: brightness(1.5); } .drum-pad .name { font-family: 'Press Start 2P', cursive; font-size: 0.7em; margin-bottom: 5px; text-shadow: 0 2px 4px rgba(0,0,0,0.5); } .drum-pad .key { font-size: 1.5em; opacity: 0.8; } .drum-pad .key-hint { position: absolute; bottom: 10px; font-size: 0.6em; opacity: 0.5; font-family: 'Press Start 2P', cursive; } /* Metronome indicator */ .metro-indicator { position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 200px; height: 200px; border-radius: 50%; border: 4px solid rgba(255,255,255,0.1); pointer-events: none; opacity: 0; transition: opacity 0.1s; } .metro-indicator.active { opacity: 1; } .metro-indicator.beat { animation: metroPulse 0.2s ease-out; } .metro-indicator.accent { border-color: var(--neon-cyan); box-shadow: 0 0 40px var(--neon-cyan); } @keyframes metroPulse { 0% { transform: translate(-50%, -50%) scale(0.8); opacity: 1; } 100% { transform: translate(-50%, -50%) scale(1.5); opacity: 0; } } /* Beat counter */ .beat-counter { position: fixed; top: 120px; left: 50%; transform: translateX(-50%); display: flex; gap: 15px; opacity: 0; transition: opacity 0.3s; } .beat-counter.active { opacity: 1; } .beat-dot { width: 20px; height: 20px; border-radius: 50%; background: rgba(255,255,255,0.2); border: 2px solid rgba(255,255,255,0.3); transition: all 0.1s; } .beat-dot.current { background: var(--neon-cyan); box-shadow: 0 0 15px var(--neon-cyan); transform: scale(1.3); } .beat-dot.accent { border-color: var(--neon-pink); } /* Recording visualization */ .recording-viz { position: fixed; bottom: 100px; left: 50%; transform: translateX(-50%); width: 80%; max-width: 800px; height: 100px; background: rgba(0,0,0,0.5); border: 1px solid rgba(255,0,110,0.3); border-radius: 10px; overflow: hidden; display: none; } .recording-viz.active { display: block; } .recording-timeline { height: 100%; display: flex; align-items: center; padding: 10px; gap: 2px; } .recording-hit { height: 60%; width: 8px; border-radius: 4px; opacity: 0.8; } /* Footer Stats */ .footer { display: flex; justify-content: center; gap: 30px; padding: 15px; background: rgba(0,0,0,0.5); border: 1px solid rgba(0,255,255,0.2); border-radius: 15px; } .stat { text-align: center; } .stat-value { font-size: 1.8em; font-weight: 900; color: var(--neon-cyan); } .stat-label { font-size: 0.7em; opacity: 0.6; text-transform: uppercase; } /* Effects canvas */ #effectsCanvas { position: fixed; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; z-index: 100; } /* Volume slider */ .volume-control { display: flex; align-items: center; gap: 10px; } .volume-slider { width: 100px; -webkit-appearance: none; height: 6px; background: rgba(255,255,255,0.2); border-radius: 3px; } .volume-slider::-webkit-slider-thumb { -webkit-appearance: none; width: 16px; height: 16px; background: var(--neon-cyan); border-radius: 50%; cursor: pointer; } /* Kit selector */ .kit-selector { display: flex; gap: 10px; } .kit-option { padding: 8px 15px; background: rgba(255,255,255,0.05); border: 1px solid rgba(255,255,255,0.2); border-radius: 8px; cursor: pointer; transition: all 0.2s; } .kit-option:hover { background: rgba(255,255,255,0.1); } .kit-option.active { background: linear-gradient(135deg, rgba(0,255,255,0.2), rgba(255,0,255,0.2)); border-color: var(--neon-cyan); } </style> </head> <body> <canvas id="effectsCanvas"></canvas> <div class="container"> <!-- Header --> <div class="header"> <div class="logo">FREESTYLE JAM</div> <div class="controls"> <div class="volume-control"> <span>🔊</span> <input type="range" class="volume-slider" id="volumeSlider" min="0" max="100" value="80"> </div> <div class="kit-selector"> <div class="kit-option active" data-kit="rock">Rock</div> <div class="kit-option" data-kit="jazz">Jazz</div> <div class="kit-option" data-kit="electronic">Electronic</div> </div> <div class="bpm-control"> <button class="bpm-btn" onclick="changeBPM(-5)">-</button> <div class="bpm-value" id="bpmDisplay">120</div> <button class="bpm-btn" onclick="changeBPM(5)">+</button> <span style="font-size: 0.8em; opacity: 0.6;">BPM</span> </div> <button class="btn btn-metro" id="metroBtn" onclick="toggleMetronome()"> METRONOME </button> <button class="btn btn-record" id="recordBtn" onclick="toggleRecording()"> ⏺ RECORD </button> </div> </div> <!-- Beat Counter --> <div class="beat-counter" id="beatCounter"> <div class="beat-dot accent" data-beat="0"></div> <div class="beat-dot" data-beat="1"></div> <div class="beat-dot" data-beat="2"></div> <div class="beat-dot" data-beat="3"></div> </div> <!-- Metronome Indicator --> <div class="metro-indicator" id="metroIndicator"></div> <!-- Drum Kit --> <div class="kit-container"> <div class="drum-kit"> <div class="drum-pad" data-drum="hihat" data-note="46"> <span class="name">HI-HAT</span> <span class="key">🎩</span> <span class="key-hint">H</span> </div> <div class="drum-pad" data-drum="tom1" data-note="48"> <span class="name">TOM 1</span> <span class="key">🥁</span> <span class="key-hint">T</span> </div> <div class="drum-pad" data-drum="tom2" data-note="45"> <span class="name">TOM 2</span> <span class="key">🥁</span> <span class="key-hint">Y</span> </div> <div class="drum-pad" data-drum="ride" data-note="51"> <span class="name">RIDE</span> <span class="key">🔔</span> <span class="key-hint">R</span> </div> <div class="drum-pad" data-drum="crash" data-note="49"> <span class="name">CRASH</span> <span class="key">💥</span> <span class="key-hint">C</span> </div> <div class="drum-pad" data-drum="kick" data-note="36"> <span class="name">KICK</span> <span class="key">👢</span> <span class="key-hint">SPACE</span> </div> <div class="drum-pad" data-drum="snare" data-note="38"> <span class="name">SNARE</span> <span class="key">🎵</span> <span class="key-hint">S</span> </div> <div class="drum-pad" data-drum="tom3" data-note="43"> <span class="name">FLOOR</span> <span class="key">🥁</span> <span class="key-hint">F</span> </div> </div> </div> <!-- Recording Visualization --> <div class="recording-viz" id="recordingViz"> <div class="recording-timeline" id="recordingTimeline"></div> </div> <!-- Footer Stats --> <div class="footer"> <div class="stat"> <div class="stat-value" id="totalHits">0</div> <div class="stat-label">Total Hits</div> </div> <div class="stat"> <div class="stat-value" id="currentCombo">0</div> <div class="stat-label">Combo</div> </div> <div class="stat"> <div class="stat-value" id="maxCombo">0</div> <div class="stat-label">Best Combo</div> </div> <div class="stat"> <div class="stat-value" id="sessionTime">0:00</div> <div class="stat-label">Session Time</div> </div> </div> </div> <script> // ═══════════════════════════════════════════════════════════════════════════ // FREESTYLE MODE // ═══════════════════════════════════════════════════════════════════════════ const DRUM_COLORS = { kick: '#ff6b35', snare: '#f7c948', hihat: '#4ecdc4', crash: '#ff006e', tom1: '#8338ec', tom2: '#3a86ff', tom3: '#06d6a0', ride: '#06ffa5' }; const KEY_MAP = { ' ': 'kick', 's': 'snare', 'h': 'hihat', 'c': 'crash', 't': 'tom1', 'y': 'tom2', 'f': 'tom3', 'r': 'ride' }; const MIDI_MAP = { 36: 'kick', 38: 'snare', 46: 'hihat', 49: 'crash', 48: 'tom1', 45: 'tom2', 43: 'tom3', 51: 'ride' }; // State let state = { bpm: 120, metronomeOn: false, recording: false, recordedHits: [], recordStartTime: 0, totalHits: 0, currentCombo: 0, maxCombo: 0, lastHitTime: 0, sessionStartTime: Date.now() }; // Audio & Effects let effectsCanvas, effectsCtx; let activeEffects = []; let metronome = null; // ═══════════════════════════════════════════════════════════════════════════ // INITIALIZATION // ═══════════════════════════════════════════════════════════════════════════ function init() { effectsCanvas = document.getElementById('effectsCanvas'); effectsCtx = effectsCanvas.getContext('2d'); resizeCanvas(); window.addEventListener('resize', resizeCanvas); setupKeyboard(); setupDrumPads(); setupMIDI(); setupVolumeControl(); setupKitSelector(); // Wait for audio engine const waitForAudio = setInterval(() => { if (window.drumAudio && window.drumAudio.isInitialized) { clearInterval(waitForAudio); metronome = new Metronome(window.drumAudio); metronome.onBeat = onMetronomeBeat; console.log('[Freestyle] Audio ready'); } }, 100); // Start render loop requestAnimationFrame(render); // Session timer setInterval(updateSessionTime, 1000); } function resizeCanvas() { effectsCanvas.width = window.innerWidth; effectsCanvas.height = window.innerHeight; } // ═══════════════════════════════════════════════════════════════════════════ // INPUT HANDLERS // ═══════════════════════════════════════════════════════════════════════════ function setupKeyboard() { document.addEventListener('keydown', (e) => { const drum = KEY_MAP[e.key.toLowerCase()]; if (drum) { e.preventDefault(); playDrum(drum); } }); } function setupDrumPads() { document.querySelectorAll('.drum-pad').forEach(pad => { pad.addEventListener('mousedown', () => playDrum(pad.dataset.drum)); pad.addEventListener('touchstart', (e) => { e.preventDefault(); playDrum(pad.dataset.drum); }); }); } async function setupMIDI() { try { const access = await navigator.requestMIDIAccess(); for (const input of access.inputs.values()) { input.onmidimessage = (msg) => { const [status, note, velocity] = msg.data; if (status >= 144 && status <= 159 && velocity > 0) { const drum = MIDI_MAP[note]; if (drum) playDrum(drum, velocity / 127); } }; } console.log('[Freestyle] MIDI connected'); } catch (e) { console.log('[Freestyle] MIDI not available'); } } function setupVolumeControl() { const slider = document.getElementById('volumeSlider'); slider.addEventListener('input', () => { if (window.drumAudio) { window.drumAudio.setVolume(slider.value / 100); } }); } function setupKitSelector() { document.querySelectorAll('.kit-option').forEach(opt => { opt.addEventListener('click', () => { document.querySelectorAll('.kit-option').forEach(o => o.classList.remove('active')); opt.classList.add('active'); if (window.drumAudio) { window.drumAudio.setKit(opt.dataset.kit); } }); }); } // ═══════════════════════════════════════════════════════════════════════════ // DRUM PLAYING // ═══════════════════════════════════════════════════════════════════════════ function playDrum(drumName, velocity = 1) { // Initialize audio on first interaction if (window.drumAudio && !window.drumAudio.isInitialized) { window.drumAudio.init(); } // Play sound if (window.drumAudio) { window.drumAudio.play(drumName, velocity); } // Visual feedback const pad = document.querySelector(`.drum-pad[data-drum="${drumName}"]`); if (pad) { pad.classList.add('hit'); setTimeout(() => pad.classList.remove('hit'), 100); } // Create explosion effect createExplosion(drumName); // Update stats state.totalHits++; document.getElementById('totalHits').textContent = state.totalHits; // Combo tracking (within 2 seconds) const now = Date.now(); if (now - state.lastHitTime < 2000) { state.currentCombo++; } else { state.currentCombo = 1; } state.lastHitTime = now; if (state.currentCombo > state.maxCombo) { state.maxCombo = state.currentCombo; document.getElementById('maxCombo').textContent = state.maxCombo; } document.getElementById('currentCombo').textContent = state.currentCombo; // Recording if (state.recording) { const time = now - state.recordStartTime; state.recordedHits.push({ drum: drumName, time, velocity }); addRecordingHit(drumName); } // SEFERIM learning if (window.SEFERIM) { window.SEFERIM.processDrumHit(drumName, velocity * 127, now, now, 'freestyle'); } // Profile stats if (window.playerProfile) { window.playerProfile.data.totalNotesHit++; const statMap = { kick: 'kicksHit', snare: 'snaresHit', hihat: 'hihatsHit', tom1: 'tomsHit', tom2: 'tomsHit', tom3: 'tomsHit', crash: 'cymbalsHit', ride: 'cymbalsHit' }; if (statMap[drumName]) { window.playerProfile.data.stats[statMap[drumName]]++; } window.playerProfile.save(); } } // ═══════════════════════════════════════════════════════════════════════════ // METRONOME // ═══════════════════════════════════════════════════════════════════════════ function toggleMetronome() { state.metronomeOn = !state.metronomeOn; const btn = document.getElementById('metroBtn'); const counter = document.getElementById('beatCounter'); if (state.metronomeOn) { btn.classList.add('active'); counter.classList.add('active'); if (metronome) { metronome.setBPM(state.bpm); metronome.start(); } } else { btn.classList.remove('active'); counter.classList.remove('active'); if (metronome) { metronome.stop(); } } } function onMetronomeBeat(beat, isAccent) { // Update beat dots document.querySelectorAll('.beat-dot').forEach((dot, i) => { dot.classList.toggle('current', i === beat); }); // Pulse indicator const indicator = document.getElementById('metroIndicator'); indicator.classList.remove('beat', 'accent'); indicator.classList.add('active'); void indicator.offsetWidth; // Trigger reflow indicator.classList.add('beat'); if (isAccent) indicator.classList.add('accent'); } function changeBPM(delta) { state.bpm = Math.max(40, Math.min(300, state.bpm + delta)); document.getElementById('bpmDisplay').textContent = state.bpm; if (metronome && state.metronomeOn) { metronome.setBPM(state.bpm); } } // ═══════════════════════════════════════════════════════════════════════════ // RECORDING // ═══════════════════════════════════════════════════════════════════════════ function toggleRecording() { state.recording = !state.recording; const btn = document.getElementById('recordBtn'); const viz = document.getElementById('recordingViz'); if (state.recording) { btn.classList.add('recording'); btn.innerHTML = '⏹ STOP'; viz.classList.add('active'); document.getElementById('recordingTimeline').innerHTML = ''; state.recordedHits = []; state.recordStartTime = Date.now(); } else { btn.classList.remove('recording'); btn.innerHTML = '⏺ RECORD'; if (state.recordedHits.length > 0) { console.log('[Freestyle] Recording:', state.recordedHits); // Could export or save the recording here } } } function addRecordingHit(drum) { const timeline = document.getElementById('recordingTimeline'); const hit = document.createElement('div'); hit.className = 'recording-hit'; hit.style.background = DRUM_COLORS[drum]; timeline.appendChild(hit); // Scroll to end timeline.scrollLeft = timeline.scrollWidth; } // ═══════════════════════════════════════════════════════════════════════════ // VISUAL EFFECTS // ═══════════════════════════════════════════════════════════════════════════ function createExplosion(drum) { const pad = document.querySelector(`.drum-pad[data-drum="${drum}"]`); if (!pad) return; const rect = pad.getBoundingClientRect(); const x = rect.left + rect.width / 2; const y = rect.top + rect.height / 2; const color = DRUM_COLORS[drum]; // Ring effect activeEffects.push({ type: 'ring', x, y, radius: rect.width / 2, maxRadius: rect.width * 1.5, color, alpha: 1 }); // Particles for (let i = 0; i < 12; i++) { const angle = (Math.PI * 2 / 12) * i; const speed = 4 + Math.random() * 6; activeEffects.push({ type: 'particle', x, y, vx: Math.cos(angle) * speed, vy: Math.sin(angle) * speed, radius: 4 + Math.random() * 4, color, alpha: 1, decay: 0.02 + Math.random() * 0.02 }); } } function render() { effectsCtx.clearRect(0, 0, effectsCanvas.width, effectsCanvas.height); for (let i = activeEffects.length - 1; i >= 0; i--) { const e = activeEffects[i]; if (e.type === 'ring') { e.radius += 5; e.alpha -= 0.05; effectsCtx.beginPath(); effectsCtx.arc(e.x, e.y, e.radius, 0, Math.PI * 2); effectsCtx.strokeStyle = e.color + Math.floor(e.alpha * 255).toString(16).padStart(2, '0'); effectsCtx.lineWidth = 4; effectsCtx.stroke(); } else if (e.type === 'particle') { e.x += e.vx; e.y += e.vy; e.vy += 0.15; e.alpha -= e.decay; effectsCtx.beginPath(); effectsCtx.arc(e.x, e.y, e.radius, 0, Math.PI * 2); effectsCtx.fillStyle = e.color + Math.floor(Math.max(0, e.alpha) * 255).toString(16).padStart(2, '0'); effectsCtx.fill(); } if (e.alpha <= 0) { activeEffects.splice(i, 1); } } requestAnimationFrame(render); } // ═══════════════════════════════════════════════════════════════════════════ // SESSION TIME // ═══════════════════════════════════════════════════════════════════════════ function updateSessionTime() { const elapsed = Math.floor((Date.now() - state.sessionStartTime) / 1000); const mins = Math.floor(elapsed / 60); const secs = elapsed % 60; document.getElementById('sessionTime').textContent = `${mins}:${secs.toString().padStart(2, '0')}`; // Update profile play time if (window.playerProfile) { window.playerProfile.data.totalPlayTime++; if (elapsed % 60 === 0) { window.playerProfile.save(); } } } // ═══════════════════════════════════════════════════════════════════════════ // INIT // ═══════════════════════════════════════════════════════════════════════════ document.addEventListener('DOMContentLoaded', init); </script> </body> </html>

Search equations, builds, manuscript text, and recovered sources.