RD5 GOLD WEB EDITOR
📄
📄 2-RB4-3CC.HTML
📄 222.JPG
📄 3CC-BASIC1.HTML
📄 Microsoft Paint.exe
📄 R2C-3.HTML
📄 R2C-4.HTML
📄 RB4-3C.HTML
📄 RB4-3CC.HTML
📄 RB4-RETRO.HTML
📄 RB4-RETRO.html
📄 RD5-3CC.html
📄 RL-4.html
📄 TARS.html
📄 TES10.mp3
📄 TES11.mp3
📄 TRISHA-OK.html
📄 TRISHA-WIN.HTML
📄 Tiny-demo.html
📄 Tinybj7-blindado.html
📄 Tinybj7-publica.html
📄 aplicaciones-rd5.html
📄 app1.html
📄 app2.html
📄 app3.html
📄 appb1.html
📄 appb2.html
📄 appb3.html
📄 appb4.html
📄 appb5.html
📄 appb6.html
📄 c-julio.JPG
📄 caratula.gif
📄 caratula02.gif
📄 caratula2.gif
📄 chokurei2.jpg
📄 columna-julio.html
📄 columna-stella.html
📄 columna-stellab.html
📄 demos.html
📄 df3.html
📄 dni.gif
📄 donaciones.gif
📄 ecualizador.html
📄 ed-podcast.JPG
📄 ed-radio.JPG
📄 editorv.html
📄 editorv1.html
📄 editorv2.html
📄 fondo5d.jpg
📄 fresi-clip.html
📄 gold.php
📄 gold62.php
📄 gold93.php
📄 googlefd161ffccea5f6ab.html
📄 gw.php
📄 index-anterior.html
📄 index.html
📄 index2.html
📄 logo.png
📄 logo.webp
📄 magazine.html
📄 manager3.php
📄 mic2.jpg
📄 mini1.html
📄 minib2a.html
📄 mn.php
📄 muestra.JPG
📄 p.html
📄 pm.html
📄 pm2.html
📄 pod-rd5.html
📄 podcast-stops.gif
📄 podcast2.mp3
📄 pp.html
📄 promo-tinybj7.html
📄 radio.html
📄 radio_gold.html
📄 rd5-fresia-4 canvashtml
📄 rd5-fresia-ok.html
📄 rd5-fresia.html
📄 rd5-plus-anterior.html
📄 rd5-plus.html
📄 rd5-plus2.html
📄 rd5-radioplayer.html
📄 rd5-tv.html
📄 rd5.html
📄 sst.html
📄 st.html
📄 starclip.html
📄 stella-2.JPG
📄 stella.JPG
📄 stt.html
📄 t-rd5.html.html
📄 t-rd6.html
📄 t-rd7.html
📄 t-tiny.html
📄 tes0.jpg
📄 tes1.jpg
📄 tes2.jpg
📄 tes4.jpg
📄 tes4.mp3
📄 tes5.jpg
📄 tes7.jpg
📄 tes8.jpg
📄 tienda.html
📄 tiendaaps.html
📄 tiendapps.html
📄 tiny-bj6.html
📄 tiny-bj7-full.html
📄 tiny-bj7.html
📄 tiny3-bj2.html
📄 tinybj7-blindado.html
📄 tinydemo.html
📄 titulo.jpg
📄 tnw2.html
📄 trisha-basic.html
📄 trisha-cafe.html
📄 trisha-mini.html
📄 tv-pantalla.php
📄 tv.html
📄 xdni.html
CÓDIGO (OSCURO GOLD)
VISTA PREVIA
💾 GUARDAR
Tema: Monokai
Tema: Dracula
Tema: Material
Tema: Blackboard
Tema: Abyss
Monospace
Courier
12px
14px
16px
18px
20px
22px
24px
26px
28px
30px
32px
↷ Rehacer
↶ Deshacer
🔍 BUSCAR
+ REPRO RADIO
SIG.
X
<!DOCTYPE html> <html lang="es"> <head> <meta charset="UTF-8"> <title>Trisha TINY-BJ2 - 8 Band EQ ARMOURED</title> <style> :root { --accent: orange; --bg-panel: #1a110f; --bg-body: #231815; --border: #3a2c28; --text-muted: #888; --text-main: #ccc; } body { background: var(--bg-body); color:white; font-family:Arial, sans-serif; margin:15px; overflow-x: hidden; transition: background 0.3s; } #contador { font-size: 20px; margin-top:10px; color:white; font-family: monospace; border-top: 1px solid var(--border); padding-top: 10px; } .linea { display:flex; align-items:flex-start; gap:15px; flex-wrap:wrap; } .cont-sliders { display: flex; gap: 8px; align-items: flex-end; background: var(--bg-panel); padding: 10px; border-radius: 8px; border: 1px solid var(--border); box-shadow: inset 0 0 10px #000; } .control-vertical { display: flex; flex-direction: column; align-items: center; gap: 5px; width: 42px; } .slider-v { -webkit-appearance: slider-vertical; width: 8px; height: 60px; background: var(--border); outline: none; cursor: pointer; } .val-pct { font-size: 9px; color: var(--accent); font-family: monospace; min-height: 11px; } label { font-size: 8px; text-transform: uppercase; color: var(--text-muted); font-weight: bold; } canvas.vu { background:black; border:4px solid #888; border-radius:50%; box-shadow: 0 0 5px #000; } #lista { margin-top:10px; max-height:259px; overflow-y:auto; list-style:none; padding-left:0; user-select: none; border: 1px solid var(--border); background: var(--bg-panel); border-radius: 4px; } #lista li { padding:8px 12px; border-bottom: 1px solid #333; font-size: 13px; color: var(--text-main); cursor: grab; transition: background 0.2s; } #lista li:active { cursor: grabbing; } #lista li.dragging { opacity: 0.5; background: #444; } #lista li.active { background:#42322f; color: var(--accent); font-weight: bold; border-left: 4px solid var(--accent); } #prog { -webkit-appearance:none; appearance:none; width:100%; height:8px; background: var(--border); border-radius:5px; margin: 15px 0; cursor: pointer; } #prog::-webkit-slider-thumb { -webkit-appearance:none; width:14px; height:14px; background: var(--accent); border-radius:50%; border:2px solid black; } #btnLimpiar { padding: 5px; background: #e3a465; color: black; border: none; border-radius: 4px; cursor: pointer; font-weight: bold; writing-mode: vertical-lr; text-transform: uppercase; height: 105px; font-size: 11px; } .librero { display: flex; gap: 4px; } .btnTema { width: 25px; height: 105px; border: none; border-radius: 2px; cursor: pointer; font-weight: bold; writing-mode: vertical-lr; font-size: 9px; text-transform: uppercase; color: white; transition: 0.2s; display: flex; align-items: center; justify-content: center; } .btnTema:hover { transform: translateY(-3px); filter: brightness(1.2); } .t-azul { background: #2980b9; } .t-verde { background: #27ae60; } .t-rojo { background: #c0392b; } .t-custom { background: #444; position: relative; overflow: hidden; } #colorCustom { position: absolute; width: 150%; height: 150%; cursor: pointer; border: none; padding: 0; } </style> </head> <body> <div class="linea"> <div style="display:flex; flex-direction:column; gap:10px;"> <input type="file" id="archivos" multiple accept="audio/*"> <div style="display:flex; gap:10px;"> <canvas id="btnPlay" class="vu" width="70" height="70" style="cursor:pointer;"></canvas> <canvas id="vuL" class="vu" width="70" height="70"></canvas> <canvas id="vuR" class="vu" width="70" height="70"></canvas> <canvas id="vuECG" class="vu" width="70" height="70"></canvas> <canvas id="vuSpectrum" class="vu" width="70" height="70"></canvas> </div> </div> <div class="cont-sliders"> <div class="control-vertical"><label>VOL</label><input type="range" id="vol" class="slider-v" min="0" max="1" step="0.01" value="0.7"><span id="v-vol" class="val-pct">70%</span></div> <div class="control-vertical"><label>32Hz</label><input type="range" id="eq1" class="slider-v" min="-15" max="15" step="1" value="0"><span id="v-eq1" class="val-pct">0</span></div> <div class="control-vertical"><label>64Hz</label><input type="range" id="eq2" class="slider-v" min="-15" max="15" step="1" value="0"><span id="v-eq2" class="val-pct">0</span></div> <div class="control-vertical"><label>125Hz</label><input type="range" id="eq3" class="slider-v" min="-15" max="15" step="1" value="0"><span id="v-eq3" class="val-pct">0</span></div> <div class="control-vertical"><label>500Hz</label><input type="range" id="eq4" class="slider-v" min="-15" max="15" step="1" value="0"><span id="v-eq4" class="val-pct">0</span></div> <div class="control-vertical"><label>1kHz</label><input type="range" id="eq5" class="slider-v" min="-15" max="15" step="1" value="0"><span id="v-eq5" class="val-pct">0</span></div> <div class="control-vertical"><label>4kHz</label><input type="range" id="eq6" class="slider-v" min="-15" max="15" step="1" value="0"><span id="v-eq6" class="val-pct">0</span></div> <div class="control-vertical"><label>8kHz</label><input type="range" id="eq7" class="slider-v" min="-15" max="15" step="1" value="0"><span id="v-eq7" class="val-pct">0</span></div> <div class="control-vertical"><label>16kHz</label><input type="range" id="eq8" class="slider-v" min="-15" max="15" step="1" value="0"><span id="v-eq8" class="val-pct">0</span></div> <button id="btnLimpiar">Limpiar Lista</button> <div class="librero"> <button class="btnTema t-azul" onclick="cambiarTema('#3498db', '#1a1c2c', '#0d1117')"></button> <button class="btnTema t-verde" onclick="cambiarTema('#2ecc71', '#0f1a11', '#0d140f')"></button> <button class="btnTema t-rojo" onclick="cambiarTema('#e74c3c', '#1a0f0f', '#140d0d')"></button> <div class="btnTema t-custom"> <span style="pointer-events:none; z-index:1;">Custom</span> <input type="color" id="colorCustom" value="#ff8800"> </div> </div> </div> </div> <input type="range" id="prog" min="0" max="100" step="0.1" value="0"> <div id="contador">00:00 / 00:00 • <span id="currentTrack" style="font-weight:bold; color:var(--accent);">esperando motor...</span></div> <ul id="lista"></ul> <script> let audioCtx = new (window.AudioContext || window.webkitAudioContext)(); const player = document.createElement('audio'); const archivos = document.getElementById('archivos'), lista = document.getElementById('lista'), prog = document.getElementById('prog'), contador = document.getElementById('contador'), btnLimpiar = document.getElementById('btnLimpiar'); let playlist = [], index = 0, sourceNode, gainNode, filters = [], splitter, anaL, anaR; // --- TEMA Y COLORES --- function cambiarTema(color, bgPanel, bgBody) { document.documentElement.style.setProperty('--accent', color); if(bgPanel) document.documentElement.style.setProperty('--bg-panel', bgPanel); if(bgBody) document.documentElement.style.setProperty('--bg-body', bgBody); dibujarBtn(); } document.getElementById('colorCustom').oninput = (e) => cambiarTema(e.target.value); // --- NAVEGACIÓN Y TECLADO --- window.addEventListener('keydown', (e) => { if (playlist.length === 0) return; if (e.code === "Space") { e.preventDefault(); togglePlay(); } if (e.code === "ArrowDown") { e.preventDefault(); moverSeleccion(1); } if (e.code === "ArrowUp") { e.preventDefault(); moverSeleccion(-1); } if (e.code === "Enter") { cargar(); player.play(); } }); function moverSeleccion(dir) { index = (index + dir + playlist.length) % playlist.length; actualizarLista(); const activo = lista.querySelector('.active'); if (activo) activo.scrollIntoView({ block: "nearest", behavior: "smooth" }); } function togglePlay() { if (!player.src && playlist.length > 0) cargar(); if (player.src) player.paused ? player.play() : player.pause(); } // --- DRAG & DROP --- lista.addEventListener('dragstart', e => { if(e.target.tagName==='LI') e.target.classList.add('dragging'); }); lista.addEventListener('dragend', e => { if(e.target.tagName==='LI') { e.target.classList.remove('dragging'); reordenarPlaylist(); } }); lista.addEventListener('dragover', e => { e.preventDefault(); const dragging = document.querySelector('.dragging'); if (!dragging) return; const afterElement = getDragAfterElement(lista, e.clientY); if (afterElement == null) lista.appendChild(dragging); else lista.insertBefore(dragging, afterElement); }); function getDragAfterElement(container, y) { const elements = [...container.querySelectorAll('li:not(.dragging)')]; return elements.reduce((closest, child) => { const box = child.getBoundingClientRect(); const offset = y - box.top - box.height / 2; if (offset < 0 && offset > closest.offset) return { offset: offset, element: child }; else return closest; }, { offset: Number.NEGATIVE_INFINITY }).element; } function reordenarPlaylist() { const items = [...lista.querySelectorAll('li')]; const cancionActual = playlist[index]; const nuevaPlaylist = items.map(li => playlist[parseInt(li.getAttribute('data-id'))]); playlist = nuevaPlaylist; index = playlist.indexOf(cancionActual); renderLista(); // Refresca IDs } // --- AUDIO CORE --- player.onplay = () => { if(audioCtx.state === "suspended") audioCtx.resume(); initAudio(); dibujarBtn(); }; player.onpause = () => dibujarBtn(); function initAudio(){ if(sourceNode) return; sourceNode = audioCtx.createMediaElementSource(player); gainNode = audioCtx.createGain(); gainNode.gain.value = document.getElementById('vol').value; const freqs = [32, 64, 125, 500, 1000, 4000, 8000, 16000]; let lastNode = sourceNode; freqs.forEach((freq, i) => { const f = audioCtx.createBiquadFilter(); f.type = (i===0)?"lowshelf":(i===7)?"highshelf":"peaking"; f.frequency.value = freq; f.Q.value = 1.4; f.gain.value = document.getElementById('eq'+(i+1)).value; filters.push(f); lastNode.connect(f); lastNode = f; }); lastNode.connect(gainNode); gainNode.connect(audioCtx.destination); splitter = audioCtx.createChannelSplitter(2); anaL = audioCtx.createAnalyser(); anaR = audioCtx.createAnalyser(); anaL.fftSize = 256; anaR.fftSize = 256; gainNode.connect(splitter); splitter.connect(anaL,0); splitter.connect(anaR,1); } archivos.onchange = e => { const nuevos = [...e.target.files].filter(f=>f.type.startsWith("audio/")); if(!nuevos.length) return; playlist = playlist.concat(nuevos); renderLista(); if(!player.src) { index = 0; cargar(); } }; function renderLista(){ lista.innerHTML = ""; playlist.forEach((f,i)=>{ const li = document.createElement("li"); li.textContent = f.name; li.draggable = true; li.setAttribute('data-id', i); li.onclick = () => { index = i; cargar(); player.play(); }; lista.appendChild(li); }); actualizarLista(); } function actualizarLista(){ [...lista.children].forEach((li, i) => li.classList.toggle("active", i === index)); } function cargar(){ if(!playlist[index]) return; if(player.src) URL.revokeObjectURL(player.src); player.src = URL.createObjectURL(playlist[index]); player.load(); actualizarLista(); } // Sliders vol.oninput = e => { if(gainNode) gainNode.gain.value = e.target.value; document.getElementById('v-vol').textContent = Math.round(e.target.value*100)+'%'; }; [1,2,3,4,5,6,7,8].forEach(n => { document.getElementById('eq'+n).oninput = e => { if(filters[n-1]) filters[n-1].gain.value = e.target.value; document.getElementById('v-eq'+n).textContent = e.target.value; }; }); player.onended = () => { index = (index + 1) % playlist.length; cargar(); player.play(); }; player.ontimeupdate = () => { if(player.duration){ prog.max = player.duration; prog.value = player.currentTime; let m1=Math.floor(player.currentTime/60), s1=Math.floor(player.currentTime%60).toString().padStart(2,0); let m2=Math.floor(player.duration/60), s2=Math.floor(player.duration%60).toString().padStart(2,0); contador.innerHTML = `${m1}:${s1} / ${m2}:${s2} • <span style="color:var(--accent);">${playlist[index].name}</span>`; } }; prog.oninput = () => player.currentTime = prog.value; btnLimpiar.onclick = () => { playlist=[]; index=0; player.pause(); player.src=""; lista.innerHTML=""; }; // --- VISUALIZADORES --- const ctxL = document.getElementById("vuL").getContext("2d"), ctxR = document.getElementById("vuR").getContext("2d"), ctxECG = document.getElementById("vuECG").getContext("2d"), ctxSpec = document.getElementById("vuSpectrum").getContext("2d"), btnC = document.getElementById("btnPlay"), ctxBtn = btnC.getContext("2d"); let aL = -Math.PI, aR = -Math.PI; function aguja(ctx, ang){ ctx.clearRect(0,0,70,70); ctx.beginPath(); ctx.arc(35,35,28,-Math.PI,0,false); ctx.strokeStyle="#1a110f"; ctx.lineWidth=30; ctx.stroke(); ctx.save(); ctx.translate(35,35); ctx.rotate(ang); ctx.beginPath(); ctx.moveTo(0,0); ctx.lineTo(32,0); ctx.strokeStyle = getComputedStyle(document.documentElement).getPropertyValue('--accent'); ctx.lineWidth=4; ctx.stroke(); ctx.restore(); } function dibujarBtn(){ const acc = getComputedStyle(document.documentElement).getPropertyValue('--accent'); ctxBtn.clearRect(0,0,70,70); ctxBtn.beginPath(); ctxBtn.arc(35,35,30,0,Math.PI*2); ctxBtn.fillStyle = !player.paused?acc:"#42322f"; ctxBtn.fill(); ctxBtn.fillStyle="black"; if(player.paused){ ctxBtn.beginPath(); ctxBtn.moveTo(28,22); ctxBtn.lineTo(28,48); ctxBtn.lineTo(48,35); ctxBtn.fill(); } else { ctxBtn.fillRect(28,22,6,26); ctxBtn.fillRect(40,22,6,26); } } function animar(){ if(anaL){ let dE = new Uint8Array(anaL.fftSize); anaL.getByteTimeDomainData(dE); ctxECG.clearRect(0,0,70,70); ctxECG.beginPath(); ctxECG.moveTo(0,35); for(let i=0;i<dE.length;i++) ctxECG.lineTo(i/dE.length*70, 35+(dE[i]-128)/128*30); ctxECG.strokeStyle = getComputedStyle(document.documentElement).getPropertyValue('--accent'); ctxECG.stroke(); let dS = new Uint8Array(anaR.frequencyBinCount); anaR.getByteFrequencyData(dS); ctxSpec.clearRect(0,0,70,70); for(let i=0;i<dS.length;i++) { ctxSpec.fillStyle=`hsl(${i/dS.length*360},100%,50%)`; ctxSpec.fillRect(i*(70/dS.length),70-dS[i]/255*70,70/dS.length,dS[i]/255*70); } let L=new Uint8Array(anaL.frequencyBinCount), R=new Uint8Array(anaR.frequencyBinCount); anaL.getByteFrequencyData(L); anaR.getByteFrequencyData(R); aL += ((-1.57 + L.reduce((a,b)=>a+b,0)/L.length/255*3.14) - aL)*0.1; aR += ((-1.57 + R.reduce((a,b)=>a+b,0)/R.length/255*3.14) - aR)*0.1; aguja(ctxL,aL); aguja(ctxR,aR); } requestAnimationFrame(animar); } btnC.onclick = togglePlay; dibujarBtn(); animar(); </script> <div id="armoured-final-row" style="width:100%; margin-top:5px; background:#1a110f; border:1px solid #3a2c28; border-radius:4px; padding:8px; display:flex; align-items:center; gap:10px; box-shadow:inset 0 0 5px #000; box-sizing:border-box;"> <button id="z-mic" style="background:#c0392b; color:white; border:none; padding:6px 10px; border-radius:3px; font-weight:bold; cursor:pointer; font-size:9px;">🔴 MIC</button> <input type="range" id="z-l" min="-15" max="15" value="0" style="width:80px; height:4px; cursor:pointer; accent-color:orange;">low <input type="range" id="z-m" min="-15" max="15" value="0" style="width:80px; height:4px; cursor:pointer; accent-color:orange;">mid <input type="range" id="z-h" min="-15" max="15" value="0" style="width:80px; height:4px; cursor:pointer; accent-color:orange;">hi <div style="width:50px; height:10px; background:#000; border:1px solid #333; border-radius:2px; overflow:hidden;"> <div id="z-vu" style="height:100%; width:0%; background:linear-gradient(90deg, #27ae60, #f1c40f, #e74c3c); transition:width 0.05s;"></div> </div> <button id="z-pv" style="background:#333; color:#aaa; border:none; padding:6px 8px; border-radius:3px; font-size:9px; cursor:pointer;">OÍR</button> <div style="width:1px; height:20px; background:#333;"></div> <button id="z-cp" style="background:#e67e22; color:white; border:none; padding:6px 10px; border-radius:3px; font-weight:bold; cursor:pointer; font-size:9px;">🟠 COMPILAR</button> <button id="z-pp" style="background:#333; color:#aaa; border:none; padding:6px 8px; border-radius:3px; font-size:9px; cursor:pointer;">PREVIEW</button> <div style="width:100px; height:10px; background:#000; border:1px solid #333; border-radius:2px; overflow:hidden;"> <div id="z-vu-p" style="height:100%; width:0%; background:linear-gradient(90deg, #3498db, #9b59b6, #e74c3c); transition:width 0.05s;"></div> </div> <button id="z-dl" style="background:#27ae60; color:white; border:none; padding:6px 12px; border-radius:3px; font-weight:bold; cursor:pointer; font-size:9px; flex-grow:1;">💾 DESCARGAR MP3</button><h1 style="color:var(--accent); font-size: 12px; margin-top:20px; font-weight: bold; text-shadow: 2px 2px 5px black;">Trisha TINY podcaster-BJ7</h1><font color="#3a2c28">............. <audio id="z-am" style="display:none"></audio> <audio id="z-ac" style="display:none"></audio> <script> (function() { let s, r, ch = [], ctx, an, fl = [], micNode, pAn; const bM = document.getElementById('z-mic'), aM = document.getElementById('z-am'), vM = document.getElementById('z-vu'), vP = document.getElementById('z-vu-p'), aC = document.getElementById('z-ac'), btnOir = document.getElementById('z-pv'), btnPreview = document.getElementById('z-pp'); // --- Mic bM.onclick = async () => { if (!s) { try { s = await navigator.mediaDevices.getUserMedia({ audio: true }); ctx = (typeof audioCtx !== 'undefined') ? audioCtx : new AudioContext(); let src = ctx.createMediaStreamSource(s), n = src; an = ctx.createAnalyser(); [250, 1200, 5000].forEach((f,i)=>{ let flt = ctx.createBiquadFilter(); flt.type = i==1?'peaking':i==0?'lowshelf':'highshelf'; flt.frequency.value = f; fl[i] = flt; n.connect(flt); n = flt; }); micNode = n; const d = ctx.createMediaStreamDestination(); n.connect(an); n.connect(d); r = new MediaRecorder(d.stream); ch = []; r.ondataavailable = e => ch.push(e.data); r.onstop = () => aM.src = URL.createObjectURL(new Blob(ch, {type:'audio/mp3'})); r.start(); bM.textContent = "⏹ STOP"; // Vúmetro Mic const lp = () => { if(!s) { vM.style.width="0%"; return; } const dt = new Uint8Array(an.frequencyBinCount); an.getByteFrequencyData(dt); vM.style.width = (dt.reduce((a,b)=>a+b)/dt.length)*2.5 + "%"; requestAnimationFrame(lp); }; lp(); } catch(e){ console.error(e); } } else { r.stop(); s.getTracks().forEach(t=>t.stop()); s=null; bM.textContent="🔴 MIC"; vM.style.width="0%"; } }; // --- Compilar let rC, chC = []; document.getElementById('z-cp').onclick = function() { if(!rC || rC.state === "inactive") { if(typeof gainNode === 'undefined') return; const d = gainNode.context.createMediaStreamDestination(); gainNode.connect(d); if(s && micNode) micNode.connect(d); rC = new MediaRecorder(d.stream); chC=[]; rC.ondataavailable = e => chC.push(e.data); rC.onstop = () => aC.src = URL.createObjectURL(new Blob(chC, {type:'audio/mp3'})); rC.start(); this.textContent="⏹ STOP"; } else { rC.stop(); this.textContent="🟠 COMPILAR"; if(micNode) try{micNode.disconnect();}catch(e){} } }; // --- OÍR Mic Playback con Vúmetro btnOir.onclick = () => { if(!aM.src) return; if(aM.paused) aM.play(); else aM.pause(); btnOir.textContent = aM.paused ? "OÍR" : "⏹ STOP"; const updateVU = () => { if(aM.paused){ vM.style.width="0%"; return; } if(!ctx) ctx = (typeof audioCtx !== 'undefined') ? audioCtx : new AudioContext(); if(!an) { an = ctx.createAnalyser(); const src = ctx.createMediaElementSource(aM); src.connect(an); an.connect(ctx.destination); } const data = new Uint8Array(an.frequencyBinCount); an.getByteFrequencyData(data); vM.style.width = (data.reduce((a,b)=>a+b)/data.length)*2.5 + "%"; requestAnimationFrame(updateVU); }; updateVU(); }; // --- Preview Compilado con Vúmetro btnPreview.onclick = () => { if(!aC.src) return; if(aC.paused) aC.play(); else aC.pause(); btnPreview.textContent = aC.paused ? "PREVIEW" : "⏹ STOP"; if(!pAn) { const pCtx = (typeof audioCtx !== 'undefined') ? audioCtx : new AudioContext(); pAn = pCtx.createAnalyser(); const pSrc = pCtx.createMediaElementSource(aC); pSrc.connect(pAn); pAn.connect(pCtx.destination); } const loopVU = () => { if(aC.paused){ vP.style.width="0%"; return; } const data = new Uint8Array(pAn.frequencyBinCount); pAn.getByteFrequencyData(data); vP.style.width = (data.reduce((a,b)=>a+b)/data.length)*2.5 + "%"; requestAnimationFrame(loopVU); }; loopVU(); }; // --- Descargar document.getElementById('z-dl').onclick = () => { if(!aC.src) return; const a = document.createElement('a'); a.href=aC.src; a.download='mix_final.mp3'; a.click(); }; // --- EQ Mic ['z-l','z-m','z-h'].forEach((id,i)=> document.getElementById(id).oninput = e => fl[i] && (fl[i].gain.value = e.target.value)); })(); </script> </div> <style> /* Estilos del Panel Emergente */ #evo-panel { display: none; position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 90%; max-width: 500px; background: var(--bg-panel); border: 2px solid var(--accent); border-radius: 12px; z-index: 20000; padding: 15px; box-shadow: 0 0 30px #000; backdrop-filter: blur(8px); font-family: monospace; } .evo-header { display: flex; justify-content: space-between; color: var(--accent); border-bottom: 1px solid var(--border); padding-bottom: 8px; margin-bottom: 10px; font-weight: bold; } #evo-canvas { width: 100%; height: 180px; background: #000; border-radius: 4px; border: 1px solid var(--border); } .evo-close { cursor: pointer; color: var(--text-muted); font-size: 20px; } .evo-close:hover { color: #fff; } /* Animación Neón para el botón */ @keyframes pulse-accent { 0% { box-shadow: 0 0 0px var(--accent); } 50% { box-shadow: 0 0 10px var(--accent); } 100% { box-shadow: 0 0 0px var(--accent); } } .btn-evo { background: transparent; color: var(--accent); border: 1px solid var(--accent); padding: 6px 12px; border-radius: 3px; font-weight: bold; cursor: pointer; font-size: 9px; text-transform: uppercase; animation: pulse-accent 2s infinite; } </style> <script> // Insertar el botón dinámicamente en la última fila para no romper el HTML document.addEventListener("DOMContentLoaded", function() { const row = document.getElementById('armoured-final-row'); const btn = document.createElement('button'); btn.className = 'btn-evo'; btn.innerHTML = '✨ EVO MONITOR'; btn.onclick = toggleEvoPanel; row.insertBefore(btn, document.getElementById('z-dl')); }); let evoCanvas, evoCtx, evoAnalyser; function toggleEvoPanel() { const panel = document.getElementById('evo-panel'); if (panel.style.display === 'block') { panel.style.display = 'none'; } else { panel.style.display = 'block'; setupEvoLogic(); } } function setupEvoLogic() { if (evoAnalyser) return; // Ya configurado // Usamos el audioCtx que ya existe en tu código if (typeof audioCtx === 'undefined') return; evoAnalyser = audioCtx.createAnalyser(); evoAnalyser.fftSize = 128; // Barras más anchas tipo "Grok" // Conectamos el gainNode existente al nuevo analizador if (typeof gainNode !== 'undefined') { gainNode.connect(evoAnalyser); } evoCanvas = document.getElementById('evo-canvas'); evoCtx = evoCanvas.getContext('2d'); function renderEvo() { requestAnimationFrame(renderEvo); const bufferLength = evoAnalyser.frequencyBinCount; const dataArray = new Uint8Array(bufferLength); evoAnalyser.getByteFrequencyData(dataArray); evoCtx.fillStyle = '#000'; evoCtx.fillRect(0, 0, evoCanvas.width, evoCanvas.height); const barWidth = (evoCanvas.width / bufferLength) * 2; let x = 0; const accentColor = getComputedStyle(document.documentElement).getPropertyValue('--accent').trim(); for (let i = 0; i < bufferLength; i++) { const barHeight = (dataArray[i] / 255) * evoCanvas.height; // Efecto de degradado dinámico let gradient = evoCtx.createLinearGradient(0, evoCanvas.height, 0, 0); gradient.addColorStop(0, accentColor); gradient.addColorStop(1, '#ffffff'); evoCtx.fillStyle = gradient; evoCtx.fillRect(x, evoCanvas.height - barHeight, barWidth - 2, barHeight); // "Glow" o brillo en la punta de la barra evoCtx.fillStyle = '#fff'; evoCtx.fillRect(x, evoCanvas.height - barHeight, barWidth - 2, 2); x += barWidth; } } renderEvo(); } </script> <div id="evo-panel"> <div class="evo-header"> <span>TINY-BJ7 ENGINE MONITOR</span> <span class="evo-close" onclick="toggleEvoPanel()">×</span> </div> <canvas id="evo-canvas"></canvas> <div style="margin-top:10px; font-size:9px; color:var(--text-muted); text-align:center;"> MAPPING AUDIO FLOW... <span style="color:var(--accent)">ONLINE</span> </div> </div> </body> </html>