Spaces:
Running
Running
Update index.html
Browse files- index.html +47 -16
index.html
CHANGED
@@ -3,21 +3,21 @@
|
|
3 |
<head>
|
4 |
<meta charset="UTF-8">
|
5 |
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
6 |
-
<title>
|
7 |
-
<script src="https://cdnjs.cloudflare.com/ajax/libs/howler/2.2.3/howler.min.js"></script>
|
8 |
</head>
|
9 |
<body>
|
10 |
-
<h1>
|
11 |
<input type="text" id="textInput" placeholder="Enter text to synthesize">
|
12 |
-
<button id="
|
13 |
-
<div id="audioContainer"></div>
|
14 |
|
15 |
<script>
|
|
|
|
|
|
|
16 |
const textInput = document.getElementById('textInput');
|
17 |
-
const
|
18 |
-
const audioContainer = document.getElementById('audioContainer');
|
19 |
|
20 |
-
|
21 |
const text = textInput.value;
|
22 |
if (text) {
|
23 |
synthesizeText(text);
|
@@ -39,16 +39,47 @@
|
|
39 |
console.log('Speech synthesis ended');
|
40 |
const audioBlob = new Blob([utterance.audioBuffer], { type: 'audio/wav' });
|
41 |
const audioUrl = URL.createObjectURL(audioBlob);
|
42 |
-
|
43 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
44 |
});
|
45 |
-
|
46 |
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
|
|
|
|
|
|
52 |
}
|
53 |
</script>
|
54 |
</body>
|
|
|
3 |
<head>
|
4 |
<meta charset="UTF-8">
|
5 |
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
6 |
+
<title>Singing Vocoder with Rhythm</title>
|
|
|
7 |
</head>
|
8 |
<body>
|
9 |
+
<h1>Singing Vocoder with Rhythm</h1>
|
10 |
<input type="text" id="textInput" placeholder="Enter text to synthesize">
|
11 |
+
<button id="synthesizeButton">Synthesize</button>
|
|
|
12 |
|
13 |
<script>
|
14 |
+
const audioContext = new AudioContext();
|
15 |
+
let source, vocoder, rhythmInterval;
|
16 |
+
|
17 |
const textInput = document.getElementById('textInput');
|
18 |
+
const synthesizeButton = document.getElementById('synthesizeButton');
|
|
|
19 |
|
20 |
+
synthesizeButton.addEventListener('click', () => {
|
21 |
const text = textInput.value;
|
22 |
if (text) {
|
23 |
synthesizeText(text);
|
|
|
39 |
console.log('Speech synthesis ended');
|
40 |
const audioBlob = new Blob([utterance.audioBuffer], { type: 'audio/wav' });
|
41 |
const audioUrl = URL.createObjectURL(audioBlob);
|
42 |
+
setupVocoder(audioUrl);
|
43 |
+
startRhythmGenerator();
|
44 |
+
});
|
45 |
+
}
|
46 |
+
|
47 |
+
function setupVocoder(audioUrl) {
|
48 |
+
const carrier = audioContext.createOscillator();
|
49 |
+
carrier.type = 'sawtooth';
|
50 |
+
carrier.frequency.value = 200;
|
51 |
+
|
52 |
+
const modulator = audioContext.createBufferSource();
|
53 |
+
modulator.connect(audioContext.destination);
|
54 |
+
|
55 |
+
vocoder = audioContext.createGain();
|
56 |
+
|
57 |
+
const modulatorGain = audioContext.createGain();
|
58 |
+
modulatorGain.gain.value = 500;
|
59 |
+
|
60 |
+
modulator.connect(modulatorGain);
|
61 |
+
modulatorGain.connect(vocoder.gain);
|
62 |
+
|
63 |
+
carrier.connect(vocoder);
|
64 |
+
vocoder.connect(audioContext.destination);
|
65 |
+
|
66 |
+
audioContext.decodeAudioData(fetch(audioUrl).then(response => response.arrayBuffer()))
|
67 |
+
.then(buffer => {
|
68 |
+
modulator.buffer = buffer;
|
69 |
+
modulator.loop = true;
|
70 |
+
source = modulator;
|
71 |
+
source.start(0);
|
72 |
});
|
73 |
+
}
|
74 |
|
75 |
+
function startRhythmGenerator() {
|
76 |
+
const tempoRange = [60, 120]; // Диапазон темпа в ударах в минуту
|
77 |
+
const tempo = Math.floor(Math.random() * (tempoRange[1] - tempoRange[0] + 1)) + tempoRange[0];
|
78 |
+
const beatDuration = 60 / tempo; // Длительность удара в секундах
|
79 |
+
|
80 |
+
rhythmInterval = setInterval(() => {
|
81 |
+
vocoder.gain.value = vocoder.gain.value === 0 ? 1 : 0; // Переключение усиления вокодера между 0 и 1
|
82 |
+
}, beatDuration * 1000 / 2); // Интервал в миллисекундах, соответствующий половине длительности удара
|
83 |
}
|
84 |
</script>
|
85 |
</body>
|