Tipo de Onda:
Senoidal
Cuadrada
Triangular
Diente de Sierra
Volumen:
50%
/* INICIO del contenido de script.js */
// 1. Obtener referencias a los elementos HTML (actualizadas para el nuevo input de texto)
const frequencyTextInput = document.getElementById(‘frequency-input’); // Nuevo input de texto
const frequencySlider = document.getElementById(‘frequency-slider’); // Slider, renombrado por claridad
const frequencyDisplay = document.getElementById(‘frequency-display’);
const waveTypeSelect = document.getElementById(‘wave-type’);
const volumeSlider = document.getElementById(‘volume’);
const volumeDisplay = document.getElementById(‘volume-display’);
const startButton = document.getElementById(‘start-button’);
const stopButton = document.getElementById(‘stop-button’);
// 2. Inicializar el AudioContext y nodos de audio
let audioContext;
let oscillator;
let gainNode;
let isPlaying = false;
// Función auxiliar para formatear la frecuencia
// Muestra hasta 3 decimales si no es un número entero, y elimina los ceros finales
function formatFrequency(freq) {
if (typeof freq !== ‘number’ || isNaN(freq)) {
return »;
}
// Formatea a 3 decimales y luego usa parseFloat().toString() para limpiar ceros finales
let fixed = freq.toFixed(3);
return parseFloat(fixed).toString();
}
// Función para inicializar el AudioContext y configurar los nodos
function initAudio() {
if (!audioContext) {
audioContext = new (window.AudioContext || window.webkitAudioContext)();
}
gainNode = audioContext.createGain();
gainNode.connect(audioContext.destination);
gainNode.gain.setValueAtTime(parseFloat(volumeSlider.value), audioContext.currentTime);
oscillator = audioContext.createOscillator();
oscillator.type = waveTypeSelect.value;
// Usamos la frecuencia del input de texto como la fuente de verdad para la precisión
let currentFreq = parseFloat(frequencyTextInput.value.replace(‘,’, ‘.’));
// Asegurarse de que la frecuencia esté dentro del rango permitido (1-20000 Hz)
currentFreq = Math.max(1, Math.min(20000, currentFreq));
oscillator.frequency.setValueAtTime(currentFreq, audioContext.currentTime);
oscillator.connect(gainNode);
}
// Función para iniciar la generación de tono
function startTone() {
if (!isPlaying) {
initAudio();
oscillator.start();
isPlaying = true;
startButton.disabled = true;
stopButton.disabled = false;
}
}
// Función para detener la generación de tono
function stopTone() {
if (isPlaying) {
if (oscillator) {
oscillator.stop();
oscillator.disconnect();
oscillator = null;
}
isPlaying = false;
startButton.disabled = false;
stopButton.disabled = true;
}
}
// 3. Añadir Event Listeners a los controles de UI
startButton.addEventListener(‘click’, startTone);
stopButton.addEventListener(‘click’, stopTone);
// Event Listener para el Input de Texto de Frecuencia (precisión)
frequencyTextInput.addEventListener(‘input’, () => {
let value = frequencyTextInput.value.replace(‘,’, ‘.’); // Permite coma como decimal
let freq = parseFloat(value);
if (isNaN(freq)) {
// Podrías mostrar un mensaje de error o simplemente no actualizar
frequencyDisplay.textContent = ‘Frec. Inválida’;
return;
}
// Clampar la frecuencia dentro del rango (1 a 20000 Hz)
freq = Math.max(1, Math.min(20000, freq));
// Actualizar el slider (se ajustará al valor más cercano si su ‘step’ es 1)
frequencySlider.value = freq;
// Actualizar el display con la frecuencia formateada
frequencyDisplay.textContent = `${formatFrequency(freq)} Hz`;
// Si está sonando, actualizar la frecuencia del oscilador
if (oscillator) {
oscillator.frequency.setValueAtTime(freq, audioContext.currentTime);
}
});
// Event Listener para el Slider de Frecuencia (ajuste rápido)
frequencySlider.addEventListener(‘input’, () => {
const freq = parseFloat(frequencySlider.value);
// Actualizar el input de texto con el valor del slider (formateado)
frequencyTextInput.value = formatFrequency(freq);
// Actualizar el display
frequencyDisplay.textContent = `${formatFrequency(freq)} Hz`;
// Si está sonando, actualizar la frecuencia del oscilador
if (oscillator) {
oscillator.frequency.setValueAtTime(freq, audioContext.currentTime);
}
});
// Actualizar tipo de onda si está sonando
waveTypeSelect.addEventListener(‘change’, () => {
if (oscillator) {
oscillator.type = waveTypeSelect.value;
}
});
// Actualizar volumen y display
volumeSlider.addEventListener(‘input’, () => {
const vol = parseFloat(volumeSlider.value);
volumeDisplay.textContent = `${Math.round(vol * 100)}%`;
if (gainNode) {
gainNode.gain.setValueAtTime(vol, audioContext.currentTime);
}
});
// Inicializar displays con valores por defecto al cargar la página
document.addEventListener(‘DOMContentLoaded’, () => {
const initialFreq = parseFloat(frequencySlider.value);
frequencyTextInput.value = formatFrequency(initialFreq); // Sincroniza el input de texto al inicio
frequencyDisplay.textContent = `${formatFrequency(initialFreq)} Hz`;
volumeDisplay.textContent = `${Math.round(parseFloat(volumeSlider.value) * 100)}%`;
});
/* FIN del contenido de script.js */