File size: 3,407 Bytes
a5338b8
41d7d0b
a5338b8
88eba2f
 
e0a8546
a5338b8
 
e0a8546
4a341f8
e0a8546
88eba2f
 
e0a8546
 
 
4a341f8
e0a8546
88eba2f
e0a8546
4a341f8
 
 
88eba2f
4a341f8
88eba2f
4a341f8
 
 
 
88eba2f
4a341f8
88eba2f
4a341f8
 
 
88eba2f
4a341f8
 
 
 
e0a8546
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
88eba2f
e0a8546
88eba2f
e0a8546
 
 
 
 
 
 
 
41d7d0b
fcd6164
a626371
fcd6164
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
<!DOCTYPE html>
<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>