top of page
Buscar

Sinfonía Orquestal Interactiva

<!DOCTYPE html>

<html lang="es">

<head>

<meta charset="UTF-8">

<meta name="viewport" content="width=device-width, initial-scale=1.0">

<title>Sinfonía Orquestal Interactiva</title>

<style>

body {

margin: 0;

padding: 0;

background: linear-gradient(135deg, #1a1a2e, #16213e, #0f3460);

font-family: 'Georgia', serif;

color: #fff;

overflow: hidden;

height: 100vh;

}


.orchestra-container {

position: relative;

width: 100%;

height: 100vh;

display: flex;

align-items: center;

justify-content: center;

}


.stage {

position: relative;

width: 90%;

height: 70%;

background: radial-gradient(ellipse at center, rgba(255,215,0,0.1), transparent);

border-radius: 50% 50% 0 0;

display: flex;

align-items: center;

justify-content: space-around;

padding: 40px;

box-shadow: 0 -20px 40px rgba(255,215,0,0.3);

}


.instrument {

display: flex;

flex-direction: column;

align-items: center;

cursor: pointer;

transition: all 0.3s ease;

padding: 20px;

border-radius: 15px;

background: rgba(255,255,255,0.05);

backdrop-filter: blur(10px);

border: 1px solid rgba(255,255,255,0.1);

position: relative;

}


.instrument:hover {

transform: translateY(-10px) scale(1.05);

box-shadow: 0 20px 40px rgba(255,215,0,0.4);

background: rgba(255,255,255,0.1);

}


.instrument.playing {

animation: pulse 0.8s ease-in-out infinite alternate;

box-shadow: 0 0 30px rgba(255,215,0,0.8);

}


@keyframes pulse {

from {

transform: scale(1);

box-shadow: 0 0 20px rgba(255,215,0,0.6);

}

to {

transform: scale(1.15);

box-shadow: 0 0 40px rgba(255,215,0,1);

}

}


.instrument-icon {

font-size: 4rem;

margin-bottom: 15px;

filter: drop-shadow(0 0 10px rgba(255,215,0,0.5));

transition: all 0.3s ease;

}


.instrument.playing .instrument-icon {

animation: bounce 0.8s ease-in-out infinite;

}


@keyframes bounce {

0%, 100% { transform: translateY(0); }

50% { transform: translateY(-15px); }

}


.instrument-name {

font-size: 1.2rem;

font-weight: bold;

text-shadow: 0 0 10px rgba(255,215,0,0.7);

}


.status {

position: absolute;

bottom: -10px;

left: 50%;

transform: translateX(-50%);

font-size: 0.8rem;

opacity: 0;

transition: opacity 0.3s ease;

}


.instrument.playing .status {

opacity: 1;

}


.controls {

position: absolute;

bottom: 30px;

left: 50%;

transform: translateX(-50%);

display: flex;

gap: 20px;

z-index: 100;

}


.control-btn {

padding: 15px 30px;

background: linear-gradient(45deg, #ff6b6b, #ee5a24);

border: none;

border-radius: 25px;

color: white;

font-size: 1rem;

font-weight: bold;

cursor: pointer;

transition: all 0.3s ease;

box-shadow: 0 5px 15px rgba(0,0,0,0.3);

}


.control-btn:hover {

transform: translateY(-3px);

box-shadow: 0 8px 25px rgba(238,90,36,0.4);

}


.control-btn.active {

background: linear-gradient(45deg, #10ac84, #01a3a4);

}


.volume-control {

position: absolute;

top: 30px;

right: 30px;

display: flex;

align-items: center;

gap: 10px;

background: rgba(255,255,255,0.1);

padding: 15px;

border-radius: 15px;

backdrop-filter: blur(10px);

}


.volume-slider {

width: 100px;

height: 5px;

background: rgba(255,255,255,0.3);

border-radius: 5px;

outline: none;

cursor: pointer;

appearance: none;

}


.volume-slider::-webkit-slider-thumb {

appearance: none;

width: 15px;

height: 15px;

background: #ffd700;

border-radius: 50%;

cursor: pointer;

}


.title {

position: absolute;

top: 30px;

left: 50%;

transform: translateX(-50%);

font-size: 2.5rem;

font-weight: bold;

text-align: center;

background: linear-gradient(45deg, #ffd700, #ffed4e);

-webkit-background-clip: text;

-webkit-text-fill-color: transparent;

background-clip: text;

text-shadow: 0 0 20px rgba(255,215,0,0.5);

}


.note-visualizer {

position: absolute;

top: 0;

left: 0;

width: 100%;

height: 100%;

pointer-events: none;

z-index: 1;

}


.note {

position: absolute;

width: 12px;

height: 12px;

background: radial-gradient(circle, #ffd700, #ffed4e);

border-radius: 50%;

opacity: 0;

animation: float 2.5s ease-out forwards;

box-shadow: 0 0 10px rgba(255,215,0,0.8);

}


@keyframes float {

0% {

opacity: 1;

transform: translateY(0) scale(0.3);

}

30% {

opacity: 1;

transform: translateY(-50px) scale(1);

}

100% {

opacity: 0;

transform: translateY(-150px) scale(0.3);

}

}


.audio-status {

position: absolute;

top: 100px;

left: 30px;

background: rgba(0,0,0,0.5);

padding: 10px;

border-radius: 10px;

font-size: 0.9rem;

}

</style>

</head>

<body>

<div class="orchestra-container">

<h1 class="title">🎼 Sinfonía Orquestal 🎼</h1>

<div class="audio-status" id="audioStatus">

🔇 Audio listo - Haz clic para activar

</div>

<div class="volume-control">

<span>🔊</span>

<input type="range" class="volume-slider" min="0" max="1" step="0.1" value="0.4" id="volumeControl">

<span id="volumeDisplay">40%</span>

</div>


<div class="stage">

<div class="instrument" data-instrument="violin">

<div class="instrument-icon">🎻</div>

<div class="instrument-name">Violín</div>

<div class="status">♪ Tocando...</div>

</div>

<div class="instrument" data-instrument="piano">

<div class="instrument-icon">🎹</div>

<div class="instrument-name">Piano</div>

<div class="status">♫ Sonando...</div>

</div>

<div class="instrument" data-instrument="guitar">

<div class="instrument-icon">🎸</div>

<div class="instrument-name">Guitarra</div>

<div class="status">♬ Vibrando...</div>

</div>

</div>


<div class="controls">

<button class="control-btn" id="playBtn">▶️ Reproducir Sinfonía</button>

<button class="control-btn" id="stopBtn">⏹️ Detener</button>

<button class="control-btn" id="soloBtn">🎵 Modo Solo</button>

<button class="control-btn" id="testBtn">🔧 Probar Audio</button>

</div>


<div class="note-visualizer" id="noteVisualizer"></div>

</div>


<script>

// Variables globales

let audioContext = null;

let isPlaying = false;

let currentVolume = 0.4;

let symphonyTimeouts = [];

let soloMode = false;

let audioInitialized = false;


// Frecuencias de notas musicales optimizadas

const notes = {

// Octava 3 (graves)

C3: 130.81, D3: 146.83, E3: 164.81, F3: 174.61,

G3: 196.00, A3: 220.00, B3: 246.94,

// Octava 4 (medias)

C4: 261.63, D4: 293.66, E4: 329.63, F4: 349.23,

G4: 392.00, A4: 440.00, B4: 493.88,

// Octava 5 (agudas)

C5: 523.25, D5: 587.33, E5: 659.25, F5: 698.46,

G5: 783.99, A5: 880.00, B5: 987.77

};


// Configuración mejorada de instrumentos

const instrumentConfig = {

violin: {

ascending: ['G4', 'A4', 'B4', 'C5', 'D5', 'E5', 'F5', 'G5'],

descending: ['G5', 'F5', 'E5', 'D5', 'C5', 'B4', 'A4', 'G4'],

waveType: 'sawtooth',

baseVolume: 0.25,

attack: 0.1,

decay: 0.3,

sustain: 0.6,

release: 0.8

},

piano: {

ascending: ['C4', 'D4', 'E4', 'F4', 'G4', 'A4', 'B4', 'C5'],

descending: ['C5', 'B4', 'A4', 'G4', 'F4', 'E4', 'D4', 'C4'],

waveType: 'triangle',

baseVolume: 0.3,

attack: 0.05,

decay: 0.4,

sustain: 0.4,

release: 1.2

},

guitar: {

ascending: ['E3', 'F3', 'G3', 'A3', 'B3', 'C4', 'D4', 'E4'],

descending: ['E4', 'D4', 'C4', 'B3', 'A3', 'G3', 'F3', 'E3'],

waveType: 'square',

baseVolume: 0.2,

attack: 0.02,

decay: 0.2,

sustain: 0.5,

release: 0.6

}

};


// Inicializar contexto de audio mejorado

function initAudioContext() {

try {

audioContext = new (window.AudioContext || window.webkitAudioContext)();

if (audioContext.state === 'suspended') {

audioContext.resume();

}

audioInitialized = true;

updateAudioStatus('🔊 Audio activado y listo');

return true;

} catch (error) {

console.error('Error inicializando audio:', error);

updateAudioStatus('❌ Error de audio');

return false;

}

}


// Actualizar estado del audio

function updateAudioStatus(message) {

const status = document.getElementById('audioStatus');

if (status) {

status.textContent = message;

}

}


// Crear sonido realista de instrumento

function createInstrumentSound(frequency, config, duration = 1000) {

if (!audioContext || !audioInitialized) {

console.log('Audio no inicializado');

return null;

}


try {

const currentTime = audioContext.currentTime;

// Oscilador principal

const oscillator = audioContext.createOscillator();

const gainNode = audioContext.createGain();

const filterNode = audioContext.createBiquadFilter();

// Configurar oscilador

oscillator.type = config.waveType;

oscillator.frequency.setValueAtTime(frequency, currentTime);

// Configurar filtro para suavizar el sonido

filterNode.type = 'lowpass';

filterNode.frequency.setValueAtTime(frequency * 4, currentTime);

filterNode.Q.setValueAtTime(1, currentTime);

// Configurar envolvente ADSR realista

const totalVolume = currentVolume * config.baseVolume;

gainNode.gain.setValueAtTime(0, currentTime);

gainNode.gain.linearRampToValueAtTime(totalVolume, currentTime + config.attack);

gainNode.gain.linearRampToValueAtTime(totalVolume * config.sustain, currentTime + config.attack + config.decay);

gainNode.gain.setValueAtTime(totalVolume * config.sustain, currentTime + duration/1000 - config.release);

gainNode.gain.linearRampToValueAtTime(0, currentTime + duration/1000);

// Conectar nodos

oscillator.connect(filterNode);

filterNode.connect(gainNode);

gainNode.connect(audioContext.destination);

// Reproducir

oscillator.start(currentTime);

oscillator.stop(currentTime + duration/1000);

return { oscillator, gainNode, filterNode };

} catch (error) {

console.error('Error creando sonido:', error);

return null;

}

}


// Agregar armónicos para enriquecer el sonido

function addHarmonics(baseFreq, config, duration, harmonicVolume = 0.1) {

if (!audioContext) return;

// Agregar segunda y tercera armónica

const harmonics = [2, 3, 4];

harmonics.forEach((harmonic, index) => {

setTimeout(() => {

if (audioContext) {

const harmonicFreq = baseFreq * harmonic;

const harmonicConfig = {...config, baseVolume: config.baseVolume * harmonicVolume / harmonic};

createInstrumentSound(harmonicFreq, harmonicConfig, duration * 0.7);

}

}, index * 50);

});

}


// Reproducir nota de instrumento específico

function playInstrumentNote(instrument, noteName, duration = 1000) {

if (!audioInitialized) {

updateAudioStatus('⚠️ Haz clic en "Probar Audio" primero');

return;

}


const frequency = notes[noteName];

const config = instrumentConfig[instrument];

if (frequency && config) {

// Sonido principal

const sound = createInstrumentSound(frequency, config, duration);

if (sound) {

// Agregar armónicos según el instrumento

if (instrument === 'violin') {

addHarmonics(frequency, config, duration, 0.15);

} else if (instrument === 'guitar') {

addHarmonics(frequency, config, duration, 0.12);

}

// Activar animación visual

const instrumentEl = document.querySelector(`[data-instrument="${instrument}"]`);

instrumentEl.classList.add('playing');

setTimeout(() => {

instrumentEl.classList.remove('playing');

}, duration * 0.8);

// Crear visualización

createNoteVisualization(instrument, noteName);

}

}

}


// Reproducir melodía completa de un instrumento

function playMelody(instrument, pattern, startDelay = 0) {

const config = instrumentConfig[instrument];

const noteSequence = config[pattern];

updateAudioStatus(`🎵 Tocando ${instrument} - patrón ${pattern}`);

noteSequence.forEach((noteName, index) => {

const timeout = setTimeout(() => {

if (isPlaying) {

playInstrumentNote(instrument, noteName, 1200);

}

}, startDelay + (index * 1000));

symphonyTimeouts.push(timeout);

});

}


// Crear visualización mejorada de notas

function createNoteVisualization(instrument, noteName) {

const visualizer = document.getElementById('noteVisualizer');

const note = document.createElement('div');

note.className = 'note';

// Posiciones específicas por instrumento

const positions = {

violin: { left: '25%', color: '#ff6b9d' },

piano: { left: '50%', color: '#4ecdc4' },

guitar: { left: '75%', color: '#ffe66d' }

};

const pos = positions[instrument];

note.style.left = pos.left;

note.style.bottom = '20%';

note.style.background = `radial-gradient(circle, ${pos.color}, transparent)`;

note.style.boxShadow = `0 0 15px ${pos.color}`;

// Agregar texto de nota

note.textContent = noteName;

note.style.fontSize = '10px';

note.style.textAlign = 'center';

note.style.lineHeight = '12px';

note.style.color = '#fff';

note.style.fontWeight = 'bold';

visualizer.appendChild(note);

setTimeout(() => {

if (note.parentNode) {

note.parentNode.removeChild(note);

}

}, 2500);

}


// Reproducir sinfonía completa con mejores tiempos

function playSymphony() {

if (!isPlaying || !audioInitialized) return;

updateAudioStatus('🎼 Reproduciendo sinfonía completa...');

// Secuencia musical mejorada

const symphonySequence = [

// Introducción - Violin solo

{ instrument: 'violin', pattern: 'ascending', delay: 0 },

{ instrument: 'violin', pattern: 'descending', delay: 9000 },

// Desarrollo - Piano se une

{ instrument: 'piano', pattern: 'ascending', delay: 18000 },

{ instrument: 'violin', pattern: 'ascending', delay: 19000 },

// Clímax - Guitarra entra

{ instrument: 'guitar', pattern: 'ascending', delay: 36000 },

{ instrument: 'piano', pattern: 'descending', delay: 36500 },

{ instrument: 'violin', pattern: 'ascending', delay: 37000 },

// Final - Armonía descendente

{ instrument: 'violin', pattern: 'descending', delay: 54000 },

{ instrument: 'piano', pattern: 'descending', delay: 55000 },

{ instrument: 'guitar', pattern: 'descending', delay: 56000 }

];


symphonySequence.forEach(({ instrument, pattern, delay }) => {

const timeout = setTimeout(() => {

if (isPlaying) {

playMelody(instrument, pattern);

}

}, delay);

symphonyTimeouts.push(timeout);

});


// Programar siguiente ciclo

const cycleTimeout = setTimeout(() => {

if (isPlaying) {

playSymphony();

}

}, 72000);

symphonyTimeouts.push(cycleTimeout);

}


// Detener todos los sonidos

function stopAllSounds() {

isPlaying = false;

// Limpiar timeouts

symphonyTimeouts.forEach(timeout => clearTimeout(timeout));

symphonyTimeouts = [];

// Remover animaciones

document.querySelectorAll('.instrument').forEach(inst => {

inst.classList.remove('playing');

});

updateAudioStatus('⏹️ Música detenida');

}


// Probar audio individual

function testAudio() {

if (!initAudioContext()) {

updateAudioStatus('❌ No se pudo inicializar el audio');

return;

}

updateAudioStatus('🔧 Probando instrumentos...');

// Probar cada instrumento

setTimeout(() => playInstrumentNote('violin', 'A4', 800), 200);

setTimeout(() => playInstrumentNote('piano', 'C4', 800), 1200);

setTimeout(() => playInstrumentNote('guitar', 'G3', 800), 2200);

setTimeout(() => {

updateAudioStatus('✅ Prueba completada - Audio funcionando');

}, 3500);

}


// Event listeners

document.addEventListener('DOMContentLoaded', function() {

const playBtn = document.getElementById('playBtn');

const stopBtn = document.getElementById('stopBtn');

const soloBtn = document.getElementById('soloBtn');

const testBtn = document.getElementById('testBtn');

const volumeControl = document.getElementById('volumeControl');

const volumeDisplay = document.getElementById('volumeDisplay');

const instruments = document.querySelectorAll('.instrument');


// Botón de reproducción

playBtn.addEventListener('click', function() {

if (!initAudioContext()) {

updateAudioStatus('❌ Error: Haz clic en "Probar Audio" primero');

return;

}

isPlaying = true;

playBtn.classList.add('active');

stopBtn.classList.remove('active');

if (!soloMode) {

playSymphony();

} else {

updateAudioStatus('🎵 Modo solo activo - Haz clic en los instrumentos');

}

});


// Botón de parar

stopBtn.addEventListener('click', function() {

stopAllSounds();

playBtn.classList.remove('active');

stopBtn.classList.add('active');

});


// Modo solo

soloBtn.addEventListener('click', function() {

soloMode = !soloMode;

soloBtn.classList.toggle('active');

soloBtn.textContent = soloMode ? '🎼 Modo Orquesta' : '🎵 Modo Solo';

if (soloMode) {

stopAllSounds();

updateAudioStatus('🎵 Modo solo - Haz clic en instrumentos para tocar');

}

});


// Botón de prueba

testBtn.addEventListener('click', function() {

testAudio();

});


// Control de volumen

volumeControl.addEventListener('input', function() {

currentVolume = parseFloat(this.value);

volumeDisplay.textContent = Math.round(currentVolume * 100) + '%';

});


// Instrumentos individuales (modo solo)

instruments.forEach(instrument => {

instrument.addEventListener('click', function() {

if (!audioInitialized) {

updateAudioStatus('⚠️ Primero haz clic en "Probar Audio"');

return;

}

if (soloMode || !isPlaying) {

const instrumentType = this.dataset.instrument;

const config = instrumentConfig[instrumentType];

// Alternar entre patrones

const pattern = Math.random() > 0.5 ? 'ascending' : 'descending';

updateAudioStatus(`🎵 Tocando ${instrumentType} - ${pattern}`);

// Tocar secuencia completa

config[pattern].forEach((noteName, index) => {

setTimeout(() => {

playInstrumentNote(instrumentType, noteName, 800);

}, index * 600);

});

}

});


// Efecto hover con sonido suave

instrument.addEventListener('mouseenter', function() {

if (audioInitialized && !isPlaying) {

const instrumentType = this.dataset.instrument;

const config = instrumentConfig[instrumentType];

const randomNote = config.ascending[Math.floor(Math.random() * config.ascending.length)];

playInstrumentNote(instrumentType, randomNote, 400);

}

});

});


// Auto-inicializar audio en primera interacción

document.addEventListener('click', function autoInit() {

if (!audioInitialized) {

initAudioContext();

}

}, { once: true });


// Inicialización automática del volumen

volumeDisplay.textContent = Math.round(currentVolume * 100) + '%';

});


// Efectos visuales mejorados

function createBackgroundTwinkle() {

const container = document.querySelector('.orchestra-container');

const twinkle = document.createElement('div');

twinkle.style.cssText = `

position: absolute;

width: 3px;

height: 3px;

background: radial-gradient(circle, #ffd700, transparent);

border-radius: 50%;

pointer-events: none;

opacity: 0;

left: ${Math.random() * 100}%;

top: ${Math.random() * 100}%;

animation: twinkleEffect 3s ease-in-out;

`;

container.appendChild(twinkle);

setTimeout(() => {

if (twinkle.parentNode) {

twinkle.parentNode.removeChild(twinkle);

}

}, 3000);

}


// Agregar estilos de animación para efectos

const additionalStyles = document.createElement('style');

additionalStyles.textContent = `

@keyframes twinkleEffect {

0%, 100% { opacity: 0; transform: scale(0); }

50% { opacity: 1; transform: scale(1); }

}

`;

document.head.appendChild(additionalStyles);


// Crear efectos de fondo

setInterval(createBackgroundTwinkle, 1500);


// Debug: Mostrar información de audio

window.debugAudio = function() {

console.log('Estado del audio:', {

audioContext: !!audioContext,

audioInitialized: audioInitialized,

isPlaying: isPlaying,

currentVolume: currentVolume,

contextState: audioContext ? audioContext.state : 'No creado'

});

};

</script>

</body>

</html>

ree

 
 
 

Comentarios


bottom of page