Spaces:
Running
Running
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>Singing Vocoder with Rhythm</title> | |
</head> | |
<body> | |
<h1>Singing Vocoder with Rhythm</h1> | |
<input type="text" id="textInput" placeholder="Enter text to synthesize"> | |
<button id="synthesizeButton">Synthesize</button> | |
<script> | |
const audioContext = new AudioContext(); | |
let source, vocoder, rhythmInterval; | |
const textInput = document.getElementById('textInput'); | |
const synthesizeButton = document.getElementById('synthesizeButton'); | |
synthesizeButton.addEventListener('click', () => { | |
const text = textInput.value; | |
if (text) { | |
synthesizeText(text); | |
} | |
}); | |
function synthesizeText(text) { | |
const utterance = new SpeechSynthesisUtterance(text); | |
const voices = window.speechSynthesis.getVoices(); | |
utterance.voice = voices.find(voice => voice.name === 'Google US English') || voices[0]; | |
window.speechSynthesis.speak(utterance); | |
utterance.addEventListener('start', () => { | |
console.log('Speech synthesis started'); | |
}); | |
utterance.addEventListener('end', () => { | |
console.log('Speech synthesis ended'); | |
const audioBlob = new Blob([utterance.audioBuffer], { type: 'audio/wav' }); | |
const audioUrl = URL.createObjectURL(audioBlob); | |
setupVocoder(audioUrl); | |
startRhythmGenerator(); | |
}); | |
} | |
function setupVocoder(audioUrl) { | |
const carrier = audioContext.createOscillator(); | |
carrier.type = 'sawtooth'; | |
carrier.frequency.value = 200; | |
const modulator = audioContext.createBufferSource(); | |
modulator.connect(audioContext.destination); | |
vocoder = audioContext.createGain(); | |
const modulatorGain = audioContext.createGain(); | |
modulatorGain.gain.value = 500; | |
modulator.connect(modulatorGain); | |
modulatorGain.connect(vocoder.gain); | |
carrier.connect(vocoder); | |
vocoder.connect(audioContext.destination); | |
audioContext.decodeAudioData(fetch(audioUrl).then(response => response.arrayBuffer())) | |
.then(buffer => { | |
modulator.buffer = buffer; | |
modulator.loop = true; | |
source = modulator; | |
source.start(0); | |
}); | |
} | |
function startRhythmGenerator() { | |
const tempoRange = [60, 120]; // Диапазон темпа в ударах в минуту | |
const tempo = Math.floor(Math.random() * (tempoRange[1] - tempoRange[0] + 1)) + tempoRange[0]; | |
const beatDuration = 60 / tempo; // Длительность удара в секундах | |
rhythmInterval = setInterval(() => { | |
vocoder.gain.value = vocoder.gain.value === 0 ? 1 : 0; // Переключение усиления вокодера между 0 и 1 | |
}, beatDuration * 1000 / 2); // Интервал в миллисекундах, соответствующий половине длительности удара | |
} | |
</script> | |
</body> | |
</html> |