// Fetch data from JSON file and initialize fetch('BhagvatGlory.json') .then(response => response.json()) .then(jsonData => initializeApp(jsonData)) .catch(error => console.error('Error loading JSON:', error)); const skandaList = document.getElementById("skanda-list"); const chapterTitle = document.getElementById("chapter-title"); const slokeContainer = document.getElementById("sloke-container"); function initializeApp(data) { // Populate Skanda and Chapter List const skandaItem = document.createElement("li"); skandaItem.textContent = data.skandaTitle; const chapterList = document.createElement("ul"); data.chapters.forEach((chapter, chapterIndex) => { const chapterItem = document.createElement("li"); chapterItem.textContent = chapter.chapterTitle; chapterItem.onclick = () => displayChapter(chapter); chapterList.appendChild(chapterItem); }); skandaItem.appendChild(chapterList); skandaList.appendChild(skandaItem); } // Display Slokes function displayChapter(chapter) { chapterTitle.textContent = chapter.chapterTitle; slokeContainer.innerHTML = ""; const slokes = chapter.slokes .replace(/श्लोक\s*\d+:/g, "") // Remove "श्लोक-X" .trim() .split("\n"); // Split by newline slokes.forEach((sloke, index) => { const slokeItem = document.createElement("div"); slokeItem.className = "sloke-item"; const slokeText = document.createElement("p"); slokeText.textContent = sloke.trim(); const speakButton = document.createElement("button"); speakButton.textContent = "Speak"; speakButton.onclick = () => speakSloke(sloke.trim()); const downloadButton = document.createElement("button"); downloadButton.textContent = "Download"; downloadButton.onclick = () => downloadAudio(sloke.trim(), `sloke-${index + 1}.wav`); slokeItem.appendChild(slokeText); slokeItem.appendChild(speakButton); slokeItem.appendChild(downloadButton); slokeContainer.appendChild(slokeItem); }); } // Speak Sloke with Advanced Features function speakSloke(text) { // Normalize and preprocess the text const normalizedText = text .normalize("NFC") .replace(/ऽ/g, " "); // Replace avagraha with a space for better pronunciation // Split the text into meaningful phrases const phrases = normalizedText.split(/[।॥]/).filter(phrase => phrase.trim().length > 0); let phraseIndex = 0; function speakNextPhrase() { if (phraseIndex >= phrases.length) return; const currentPhrase = phrases[phraseIndex].trim(); const utterance = new SpeechSynthesisUtterance(currentPhrase); // Set voice and TTS parameters for a bold, heavy tone utterance.lang = "sa-IN"; utterance.pitch = 0.8; // Lower pitch for a deeper, heavier voice utterance.rate = 0.8; // Slower rate for gravitas and clarity utterance.volume = 1.0; // Full volume for boldness // Select the male Sanskrit voice const voices = speechSynthesis.getVoices(); utterance.voice = voices.find(voice => voice.lang === "sa-IN" && voice.name.includes("Male")); // Handle completion of the current phrase utterance.onend = () => { phraseIndex++; setTimeout(speakNextPhrase, 500); // Slightly longer pause for dramatic effect }; // Handle errors gracefully utterance.onerror = (error) => { console.error(`Error speaking phrase: ${currentPhrase}`, error); phraseIndex++; setTimeout(speakNextPhrase, 500); }; console.log(`Speaking phrase with bold voice: ${currentPhrase}`); // Debugging speechSynthesis.speak(utterance); } speakNextPhrase(); // Start speaking the sloke } // Speak Sloke // function speakSloke(text) { // alert(text) // const utterance = new SpeechSynthesisUtterance(text); // utterance.lang = "sa-IN"; // utterance.rate = 0.8; // utterance.pitch = 1.0; // const voices = speechSynthesis.getVoices(); // utterance.voice = voices.find(voice => voice.lang === "sa-IN" && voice.name.includes("Male")); // speechSynthesis.speak(utterance); // } // Download Audio function downloadAudio(text, filename) { const utterance = new SpeechSynthesisUtterance(text); utterance.lang = "sa-IN"; const audioChunks = []; const streamDestination = new MediaStreamAudioDestinationNode(new AudioContext()); const mediaRecorder = new MediaRecorder(streamDestination.stream); utterance.onstart = () => mediaRecorder.start(); utterance.onend = () => { mediaRecorder.stop(); const audioBlob = new Blob(audioChunks, { type: "audio/wav" }); const audioUrl = URL.createObjectURL(audioBlob); const link = document.createElement("a"); link.href = audioUrl; link.download = filename; link.click(); }; mediaRecorder.ondataavailable = event => audioChunks.push(event.data); speechSynthesis.speak(utterance); }