top of page
Buscar

GENERADOR DE MELODIAS GIRALISMO

<!DOCTYPE html>

<html>

<head>

<style>

body {

font-family: Arial, sans-serif;

background: #f0f0f0;

margin: 0;

padding: 20px;

}


.container {

max-width: 800px;

margin: 0 auto;

background: white;

padding: 20px;

border-radius: 10px;

box-shadow: 0 2px 10px rgba(0,0,0,0.1);

}


.controls {

margin-bottom: 20px;

display: flex;

gap: 10px;

flex-wrap: wrap;

}


.button {

background: #4CAF50;

color: white;

border: none;

padding: 10px 20px;

border-radius: 5px;

cursor: pointer;

transition: background 0.3s;

}


.button:hover {

background: #45a049;

}


.button.stop {

background: #f44336;

}


.button.stop:hover {

background: #da190b;

}


.piano {

display: flex;

justify-content: center;

position: relative;

height: 200px;

margin: 20px 0;

}


.key {

position: relative;

width: 40px;

height: 180px;

border: 1px solid #000;

background: white;

border-radius: 0 0 5px 5px;

cursor: pointer;

transition: background 0.1s;

}


.key.black {

position: absolute;

width: 24px;

height: 100px;

background: #000;

z-index: 1;

}


.key.active {

background: #e3f2fd;

}


.key.black.active {

background: #444;

}


.settings {

margin: 20px 0;

padding: 15px;

background: #f5f5f5;

border-radius: 5px;

}


.settings label {

display: block;

margin-bottom: 10px;

}


.settings input[type="range"] {

width: 200px;

}


.visualization {

height: 100px;

background: #f5f5f5;

margin: 20px 0;

border-radius: 5px;

overflow: hidden;

position: relative;

}


.note-particle {

position: absolute;

width: 10px;

height: 10px;

background: #4CAF50;

border-radius: 50%;

opacity: 0.8;

transition: transform 1s, opacity 1s;

}

</style>

</head>

<body>

<div class="container">

<h1>Generador de Melodías de Piano</h1>

<div class="controls">

<button class="button" id="playButton">Generar Melodía</button>

<button class="button stop" id="stopButton">Detener</button>

<button class="button" id="tempoUpButton">Tempo +</button>

<button class="button" id="tempoDownButton">Tempo -</button>

</div>


<div class="settings">

<label>

Velocidad:

<input type="range" id="tempoSlider" min="60" max="180" value="100">

<span id="tempoValue">100 BPM</span>

</label>

<label>

Notas por secuencia:

<input type="range" id="notesSlider" min="2" max="7" value="3">

<span id="notesValue">3 notas</span>

</label>

</div>


<div class="visualization" id="visualization"></div>


<div class="piano" id="piano"></div>

</div>


<script>

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

let isPlaying = false;

let currentTempo = 100;

let noteCount = 3;

let melodyInterval;

const notes = [

{ note: 'C4', freq: 261.63 },

{ note: 'D4', freq: 293.66 },

{ note: 'E4', freq: 329.63 },

{ note: 'F4', freq: 349.23 },

{ note: 'G4', freq: 392.00 },

{ note: 'A4', freq: 440.00 },

{ note: 'B4', freq: 493.88 },

{ note: 'C5', freq: 523.25 }

];


// Crear piano visual

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

notes.forEach((note, index) => {

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

key.className = 'key';

key.dataset.note = note.note;

key.dataset.freq = note.freq;

piano.appendChild(key);

});


function playNote(frequency, duration = 0.5) {

const oscillator = audioContext.createOscillator();

const gainNode = audioContext.createGain();

oscillator.type = 'sine';

oscillator.frequency.setValueAtTime(frequency, audioContext.currentTime);

gainNode.gain.setValueAtTime(0.5, audioContext.currentTime);

gainNode.gain.exponentialRampToValueAtTime(0.001, audioContext.currentTime + duration);

oscillator.connect(gainNode);

gainNode.connect(audioContext.destination);

oscillator.start(audioContext.currentTime);

oscillator.stop(audioContext.currentTime + duration);


createNoteVisualization(frequency);

}


function createNoteVisualization(frequency) {

const viz = document.getElementById('visualization');

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

particle.className = 'note-particle';

const x = Math.random() * (viz.offsetWidth - 10);

const y = viz.offsetHeight - 10;

particle.style.left = `${x}px`;

particle.style.bottom = '0';

viz.appendChild(particle);

requestAnimationFrame(() => {

particle.style.transform = `translateY(-${y}px)`;

particle.style.opacity = '0';

});

setTimeout(() => particle.remove(), 1000);

}


function generateMelody() {

const selectedNotes = [];

for (let i = 0; i < noteCount; i++) {

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

selectedNotes.push(randomNote);

}

return selectedNotes;

}


function highlightKey(note) {

const keys = document.querySelectorAll('.key');

keys.forEach(key => key.classList.remove('active'));

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

if (activeKey) activeKey.classList.add('active');

}


function playMelody() {

const melody = generateMelody();

let noteIndex = 0;

melodyInterval = setInterval(() => {

if (noteIndex >= melody.length) {

noteIndex = 0;

}

const note = melody[noteIndex];

playNote(note.freq, 0.8);

highlightKey(note.note);

noteIndex++;

}, (60 / currentTempo) * 1000);

}


// Event Listeners

document.getElementById('playButton').addEventListener('click', () => {

if (!isPlaying) {

isPlaying = true;

playMelody();

}

});


document.getElementById('stopButton').addEventListener('click', () => {

isPlaying = false;

clearInterval(melodyInterval);

document.querySelectorAll('.key').forEach(key => key.classList.remove('active'));

});


document.getElementById('tempoSlider').addEventListener('input', (e) => {

currentTempo = parseInt(e.target.value);

document.getElementById('tempoValue').textContent = `${currentTempo} BPM`;

if (isPlaying) {

clearInterval(melodyInterval);

playMelody();

}

});


document.getElementById('notesSlider').addEventListener('input', (e) => {

noteCount = parseInt(e.target.value);

document.getElementById('notesValue').textContent = `${noteCount} notas`;

});


document.getElementById('tempoUpButton').addEventListener('click', () => {

const slider = document.getElementById('tempoSlider');

slider.value = Math.min(parseInt(slider.value) + 10, slider.max);

slider.dispatchEvent(new Event('input'));

});


document.getElementById('tempoDownButton').addEventListener('click', () => {

const slider = document.getElementById('tempoSlider');

slider.value = Math.max(parseInt(slider.value) - 10, slider.min);

slider.dispatchEvent(new Event('input'));

});

</script>

</body>

</html>


ree

 
 
 

Comentarios


bottom of page