diff --git a/create_audiobook_nem.py b/create_audiobook_nem.py index 2743d78..26e2505 100644 --- a/create_audiobook_nem.py +++ b/create_audiobook_nem.py @@ -4,12 +4,17 @@ audiobook_nem.py Generate the Book of the Nem audiobook — one unique voice per book/section. Usage: - python audiobook_nem.py + python create_audiobook_nem.py # all enabled books + python create_audiobook_nem.py --list # list available book labels + python create_audiobook_nem.py Introduction + python create_audiobook_nem.py "Book of Hagoth" + python create_audiobook_nem.py Introduction "Book of Hagoth" -To skip a section, comment out its entry in BOOKS below. +To permanently skip a section, comment out its entry in BOOKS below. Output .wav files are written to OUTPUT_DIR (created automatically). """ +import argparse import re import time import numpy as np @@ -41,30 +46,30 @@ LANG_CODE = "a" # 'a' = American English # am_santa – American male [downloaded] (not used) # ── Book definitions ─────────────────────────────────────────────────────────── -# Format: (label, start_marker, voice, output_wav) -# start_marker – exact text of the FIRST line of the section header in the source -# (leading/trailing whitespace is ignored when matching) +# Format: (label, (start_line1, start_line2), voice, output_wav) +# start_line1 – exact text of the FIRST line of the section header +# start_line2 – prefix of the SECOND line (used together for unambiguous matching) # voice – Kokoro voice name # output_wav – filename saved inside OUTPUT_DIR # # Comment out any line to skip that section entirely. BOOKS = [ - # label start_marker voice output_wav - ("Introduction", "Introduction", "af_heart", "00_introduction.wav"), - ("Book of Hagoth", "THE BOOK OF HAGOTH", "am_fenrir", "01_hagoth.wav"), - # ("Shi-Tugo I", "THE FIRST BOOK OF SHI-TUGO", "am_eric", "02_shi_tugo_1.wav"), - # ("Sanempet", "THE BOOK OF SANEMPET", "am_liam", "03_sanempet.wav"), - # ("Oug", "THE BOOK OF OUG", "am_michael", "04_oug.wav"), - # ("Temple Writings of Oug", "THE BOOK OF", "am_michael", "05_temple_writings_oug.wav"), - # ("Sacred Temple Writings", "THE SACRED", "am_michael", "06_sacred_temple_writings.wav"), - # ("Samuel the Lamanite I", "THE FIRST BOOK", "am_echo", "07_samuel_lamanite_1.wav"), - # ("Samuel the Lamanite II", "THE SECOND BOOK", "am_echo", "08_samuel_lamanite_2.wav"), - # ("Manti", "THE BOOK OF MANTI", "am_onyx", "09_manti.wav"), - # ("Pa Nat I", "THE FIRST BOOK OF PA NAT", "af_nicole", "10_pa_nat_1.wav"), - # ("Moroni I", "THE FIRST BOOK OF MORONI", "am_adam", "11_moroni_1.wav"), - # ("Moroni II", "THE SECOND BOOK OF MORONI", "am_adam", "12_moroni_2.wav"), - # ("Moroni III", "THE THIRD BOOK OF MORONI", "am_adam", "13_moroni_3.wav"), - # ("Shioni", "THE BOOK OF SHIONI", "am_puck", "14_shioni.wav"), + # label (start_line1, start_line2) voice output_wav + ("Introduction", ("Introduction", "The Book of the Nem"), "af_heart", "00_introduction.wav"), + ("Book of Hagoth", ("THE BOOK OF HAGOTH", "THE SON OF HAGMENI,"), "am_fenrir", "01_hagoth.wav"), + ("Shi-Tugo I", ("THE FIRST BOOK OF SHI-TUGO", "FORMER WARRIOR, AMMONITE"), "am_eric", "02_shi_tugo_1.wav"), + ("Sanempet", ("THE BOOK OF SANEMPET", "THE SON OF HAGMENI,"), "am_liam", "03_sanempet.wav"), + ("Oug", ("THE BOOK OF OUG", "THE SON OF SANEMPET"), "am_michael", "04_oug.wav"), + ("Temple Writings of Oug", ("THE BOOK OF", "THE TEMPLE WRITINGS"), "am_michael", "05_temple_writings_oug.wav"), + ("Sacred Temple Writings", ("THE SACRED", "TEMPLE WRITINGS"), "am_michael", "06_sacred_temple_writings.wav"), + ("Samuel the Lamanite I", ("THE FIRST BOOK", "OF SAMUEL THE LAMANITE"), "am_echo", "07_samuel_lamanite_1.wav"), + ("Samuel the Lamanite II", ("THE SECOND BOOK", "OF SAMUEL THE LAMANITE"), "am_echo", "08_samuel_lamanite_2.wav"), + ("Manti", ("THE BOOK OF MANTI", "THE SON OF OUG"), "am_onyx", "09_manti.wav"), + ("Pa Nat I", ("THE FIRST BOOK OF PA NAT", "THE DAUGHTER OF SHIMLEI"), "af_nicole", "10_pa_nat_1.wav"), + ("Moroni I", ("THE FIRST BOOK OF MORONI", "THE SON OF MORMON,"), "am_adam", "11_moroni_1.wav"), + ("Moroni II", ("THE SECOND BOOK OF MORONI", "THE SON OF MORMON,"), "am_adam", "12_moroni_2.wav"), + ("Moroni III", ("THE THIRD BOOK OF MORONI", "THE SON OF MORMON,"), "am_adam", "13_moroni_3.wav"), + ("Shioni", ("THE BOOK OF SHIONI", "THE SON OF MORONI"), "am_puck", "14_shioni.wav"), ] # ── Helpers ──────────────────────────────────────────────────────────────────── @@ -72,23 +77,24 @@ BOOKS = [ def load_and_split(source: Path, books: list) -> dict[str, str]: """ Read the source file and split it into sections keyed by label. - Each section starts at its start_marker line and ends just before the - next section's start_marker. + Each section starts at its (start_line1, start_line2) marker pair and + ends just before the next section's marker. """ raw_lines = source.read_text(encoding="utf-8").splitlines() - # Build a mapping: marker_text → index in BOOKS - markers = [(label, marker.strip()) for label, marker, _, _ in books] + # Build a mapping: (label, line1, line2) for each book + markers = [(label, m[0].strip(), m[1].strip()) for label, m, _, _ in books] - # Find the line index of each marker's first occurrence + # Find the line index of each marker's first occurrence (two-line match) marker_positions: list[tuple[int, int]] = [] # (line_idx, books_idx) - for book_idx, (label, marker) in enumerate(markers): - for line_idx, line in enumerate(raw_lines): - if line.strip() == marker: + for book_idx, (label, m1, m2) in enumerate(markers): + for line_idx, line in enumerate(raw_lines[:-1]): + if (line.strip() == m1 and + raw_lines[line_idx + 1].strip().startswith(m2)): marker_positions.append((line_idx, book_idx)) break else: - print(f" ⚠ Marker not found for '{label}': '{marker}' — skipping") + print(f" ⚠ Marker not found for '{label}': '{m1}' / '{m2}' — skipping") marker_positions.sort(key=lambda x: x[0]) @@ -154,6 +160,38 @@ def generate_audio(pipeline: KPipeline, text: str, voice: str, # ── Main ─────────────────────────────────────────────────────────────────────── def main() -> None: + # ── CLI ──────────────────────────────────────────────────────────── + parser = argparse.ArgumentParser(description="Generate Nem audiobook sections.") + parser.add_argument( + "books", nargs="*", + help="Labels of sections to generate (default: all enabled books). " + "Use --list to see available labels." + ) + parser.add_argument( + "--list", action="store_true", + help="Print all enabled book labels and exit." + ) + args = parser.parse_args() + + enabled_labels = [label for label, _, _, _ in BOOKS] + + if args.list: + print("Enabled books:") + for label in enabled_labels: + print(f" {label}") + return + + # Filter to requested subset, preserving BOOKS order + if args.books: + unknown = [b for b in args.books if b not in enabled_labels] + if unknown: + print(f"Unknown book label(s): {', '.join(unknown)}") + print(f"Run with --list to see available labels.") + return + run_books = [b for b in BOOKS if b[0] in args.books] + else: + run_books = list(BOOKS) + device = "cuda" if torch.cuda.is_available() else "cpu" print(f"Device: {device}") if device == "cuda": @@ -164,8 +202,10 @@ def main() -> None: print(f"\nSource: '{SOURCE_FILE}'" + (" ✓ (TTS fixed)" if SOURCE_FILE == _FIXED_FILE else " ⚠ (original — run 'Apply Fixes to Text' in the GUI to use phonetic fixes)")) + # Always split using ALL books for correct section boundaries, + # but only generate for run_books. sections = load_and_split(SOURCE_FILE, BOOKS) - print(f" Found {len(sections)} sections.\n") + print(f" Found {len(sections)} sections ({len(run_books)} selected).\n") print("Initialising Kokoro pipeline …") pipeline = KPipeline(lang_code=LANG_CODE) @@ -173,14 +213,26 @@ def main() -> None: # Pre-compute char counts for all sections so we can estimate ETAs section_chars: dict[str, int] = { label: len(clean_text(sections[label])) - for label, _, _, _ in BOOKS + for label, _, _, _ in run_books if label in sections } + # Print char count summary before starting + print(f"\n{'─' * 52}") + print(f" {'Section':<30} {'Chars':>8}") + print(f"{'─' * 52}") + for label, _, _, wav_name in run_books: + if label in section_chars: + print(f" {label:<30} {section_chars[label]:>8,}") + print(f"{'─' * 52}") + total_chars = sum(section_chars.values()) + print(f" {'TOTAL':<30} {total_chars:>8,}") + print() + chars_per_sec: float | None = None # derived from the first book that finishes timing_rows: list[tuple[str, int, float]] = [] # (label, chars, elapsed) - for label, marker, voice, wav_name in BOOKS: + for label, _marker, voice, wav_name in run_books: if label not in sections: continue diff --git a/gui_proper_noun_player.py b/gui_proper_noun_player.py index 0fd4965..12d8ff3 100644 --- a/gui_proper_noun_player.py +++ b/gui_proper_noun_player.py @@ -84,8 +84,11 @@ MAUVE = "#cba6f7" def play_async(path: Path) -> None: sd.stop() def _play(): - data, sr = sf.read(str(path), dtype="float32") - sd.play(data, sr) + try: + data, sr = sf.read(str(path), dtype="float32") + sd.play(data, sr) + except Exception as exc: + print(f"[audio] playback error: {exc}") threading.Thread(target=_play, daemon=True).start() @@ -119,11 +122,14 @@ def synth_and_play(text: str, on_ready=None) -> None: *on_ready(path)* is called on the same thread once the file is written. """ def _run(): - path = _synth_to_cache(text) - if path: - if on_ready: - on_ready(path) - play_async(path) + try: + path = _synth_to_cache(text) + if path: + if on_ready: + on_ready(path) + play_async(path) + except Exception as exc: + print(f"[synth] error synthesising '{text}': {exc}") threading.Thread(target=_run, daemon=True).start() @@ -216,6 +222,8 @@ class ProperNounAuditor(tk.Tk): self._build_ui() self._refresh_all() + self._alive = True + self.protocol("WM_DELETE_WINDOW", self._on_close) # Window-level hotkeys (work even when a listbox has keyboard focus) self.bind("", lambda e: self._replay()) @@ -224,6 +232,19 @@ class ProperNounAuditor(tk.Tk): if self.focus_get() is not self._fix_entry else None) self.bind("", lambda e: self._reset_fix_entry()) + def _on_close(self) -> None: + self._alive = False + sd.stop() + self.destroy() + + def _safe_after(self, ms: int, func) -> None: + """Schedule func on the Tk thread; silently no-ops if window is gone.""" + if self._alive: + try: + self.after(ms, func) + except RuntimeError: + pass + # ── UI construction ──────────────────────────────────────────────────────── def _build_ui(self) -> None: @@ -457,7 +478,7 @@ class ProperNounAuditor(tk.Tk): self.fix_var.set(replacement) self.now_playing_var.set(f"… {replacement}") def _on_ready(_path): - self.after(0, lambda: self.now_playing_var.set(replacement)) + self._safe_after(0, lambda: self.now_playing_var.set(replacement)) synth_and_play(replacement, on_ready=_on_ready) else: # Correct list — show word in fix entry, play it @@ -515,7 +536,7 @@ class ProperNounAuditor(tk.Tk): target.unlink() self.now_playing_var.set(f"… regen {fix_text}") def _on_ready(_p): - self.after(0, lambda: self.now_playing_var.set(fix_text)) + self._safe_after(0, lambda: self.now_playing_var.set(fix_text)) synth_and_play(fix_text, on_ready=_on_ready) else: # Re-gen the manifest audio for the review word @@ -528,18 +549,21 @@ class ProperNounAuditor(tk.Tk): self.now_playing_var.set(f"… regen {word}") def _regen(): - import warnings, numpy as np - pipeline = _get_pipeline() - chunks = [] - with warnings.catch_warnings(): - warnings.filterwarnings("ignore", category=UserWarning) - for _, _, audio in pipeline(word, voice=VOICE): - if audio is not None: - chunks.append(audio) - if chunks: - sf.write(str(wav_path), np.concatenate(chunks), SAMPLE_RATE) - self.after(0, lambda: self.now_playing_var.set(word)) - play_async(wav_path) + try: + import warnings, numpy as np + pipeline = _get_pipeline() + chunks = [] + with warnings.catch_warnings(): + warnings.filterwarnings("ignore", category=UserWarning) + for _, _, audio in pipeline(word, voice=VOICE): + if audio is not None: + chunks.append(audio) + if chunks: + sf.write(str(wav_path), np.concatenate(chunks), SAMPLE_RATE) + self._safe_after(0, lambda: self.now_playing_var.set(word)) + play_async(wav_path) + except Exception as exc: + print(f"[regen] error for '{word}': {exc}") threading.Thread(target=_regen, daemon=True).start() @@ -669,17 +693,21 @@ class ProperNounAuditor(tk.Tk): self._pregen_status_var.set(f"0 / {new_count} new ({already} cached)") def _run(): - done = 0 - for rep in replacements: - cache_path = REPLACEMENTS_DIR / f"{_slug(rep)}.wav" - if not cache_path.exists(): - _synth_to_cache(rep) - done += 1 - self.after(0, lambda d=done, t=new_count: - self._pregen_status_var.set(f"{d} / {t} synthesised…")) - self.after(0, lambda: self._pregen_status_var.set( - f"Done — {total} clips ready")) - self.after(0, lambda: self._pregen_btn.config(state="normal")) + try: + done = 0 + for rep in replacements: + cache_path = REPLACEMENTS_DIR / f"{_slug(rep)}.wav" + if not cache_path.exists(): + _synth_to_cache(rep) + done += 1 + self._safe_after(0, lambda d=done, t=new_count: + self._pregen_status_var.set(f"{d} / {t} synthesised…")) + self._safe_after(0, lambda: self._pregen_status_var.set( + f"Done — {total} clips ready")) + except Exception as exc: + print(f"[pregen] error: {exc}") + finally: + self._safe_after(0, lambda: self._pregen_btn.config(state="normal")) threading.Thread(target=_run, daemon=True).start() diff --git a/output_proper_nouns/correct_words.json b/output_proper_nouns/correct_words.json index 991e8f0..4a6f93f 100644 --- a/output_proper_nouns/correct_words.json +++ b/output_proper_nouns/correct_words.json @@ -1,15 +1,13 @@ [ + "Ninety-Two", + "Gilgal", "Nat", "Monoriah", "Akim", "Amoron", - "Migdan Idi", "Migdan", "Midgan-Idi", - "Midgan Idi", "Midgan", - "Mic", - "Mi", "Mentina", "Hemeacum", "Micah", @@ -21,7 +19,6 @@ "Kishkumen", "Kee", "Kayith", - "Kay", "Pah", "Kamiakim", "Corian-Co-Hah", @@ -29,9 +26,6 @@ "Chunish", "Chu", "Cheem", - "Co", - "Thanksgiving", - "Way", "Zoreth", "Zoramites", "Zoramite", @@ -42,374 +36,120 @@ "Zen", "Zeezret", "Zedekiah", - "King", "Zarahemla", - "Yourselves", - "Yourself", - "Yours", - "Kingdom", - "Day", - "Young", "Yohks", - "Yesterday", - "Yay", - "Writings", - "Write", - "Worthy", - "Worlds", - "World", "Worketh", - "Word", - "Women", - "Woman", "Woe", - "Wives", - "Winter", "Winebag", "Winding", - "Wind", "Willow", - "Wife", - "Whom", "Whereupon", "Wherefore", - "Whatsoever", - "Western", - "West", - "Weeks", - "Wee", - "Ways", "Waylit", "Wayat", - "Waters", - "Water", - "Washing", "Wards", - "War", "Wallohitwah", - "Walk", "Wah", - "Voice", - "Virtue", "Vineyards", "Vineyard", "Verily", "Veil", - "Heaven", - "Valley", "Urim", "Unquenchable", - "Fire", - "Universe", - "Universal", - "United", "Two-Fold", - "Two", - "Thousand", - "Months", - "Hundred", - "Days", - "Twins", - "Twenty", - "Five", - "Years", - "Twelve", "Tugo", - "Truth", - "True", - "Tree", - "Traveling", - "Councils", "Peli", "Tornit", "Torieth", "Tor", - "Toniah Lotnah", "Toniah", - "Tomorrow", - "Token", - "Today", "Tithe", "Timothy", - "Son", "Brethren", - "Thunder", "Thummim", - "Three", - "Quarters", - "Thousands", - "Miles", "Knewest", "Perilous", - "Year", - "Present", - "Land", "Northward", - "Holy", - "Spirit", - "Place", - "Ghost", - "Great", - "Council", "Everlasting", "Covenant", - "Thirteen", - "Third", - "Last", - "Men", - "Spirits", "Firstborn", - "River", - "Sea", - "Mountains", "Anointing", "Wasatch", - "Front", - "Warm", - "Mob", - "Law", - "Restoration", - "Order", - "Sons", - "Daughters", "Elohim", "Heavenly", - "People", - "Life", - "Knowledge", - "Good", - "Evil", - "Thirty", - "Eighth", - "Book", - "Lodge", - "Terrible", "Terrestrial", - "Temple", - "Lord", "Eve", "Bountiful", - "Hill", "Tamahu-Ah", - "Sweat", - "Sure", - "Sign", - "Nail", - "Summer", - "Spring", "Levi", - "Father", - "Snake", - "Sixty", - "Ninth", - "Sixth", "Shortest", - "Seventy", - "Fifth", - "Seventh", - "Sacred", - "Direction", - "Sees", "Habitation", - "Seeks", - "Second", "Endowment", - "Season", - "Coast", "Salten", - "Record", - "Pipe", "Herbs", "Hearth", "Garments", - "Directions", - "Animals", "Sabbath", "Robe", "Priesthood", "Akish", - "Right", - "Prayer", "Remnant", - "House", "Israel", "Jacob", "Purification", "Ammonites", "Melchizedek", - "Power", - "Mother", - "God", - "Sacrifice", "Adam", - "Ceremony", - "Gulf", "Hagoth", "Corianton", "Ammon", "Patriarchal", - "Grip", - "Path", - "Creator", - "Past", - "Ten", - "Orders", - "North", - "Country", "Ninety", - "Night", - "Next", - "Newborn", - "Children", - "New", "Nemenha", "Nem", - "Volume", - "Another", - "Testament", - "Jesus", - "Christ", - "Prophet", - "Living", - "Morning", - "Middle", - "Archives", - "Medicine", - "Dance", - "Man", - "Higher", "Lord'S", - "Harvest", - "Looks", - "Light", "Levitical", - "Laying", - "Hands", - "Laws", - "Gospel", - "Revelation", "Obedience", "Consecration", "Chastity", "Latter-Day", - "Latter", - "Lands", "Southward", - "Jerusalem", "Desolation", - "Lake", - "Islands", - "Hour", - "Hosts", - "Host", - "City", - "High", - "Priest", - "Region", - "Guide", - "Star", - "Growing", - "Salt", "Healer", - "Peace", - "Gift", - "Healing", - "General", "Nespelem", - "Friends", - "Fourth", - "Four", "Forty-Two", "Fortieth", - "Following", "Sixty-Seventh", - "First", - "Home", - "Pa", "Firmament", - "Final", - "Festival", - "Lights", - "Fair", - "Ones", - "End", - "Elect", "Eighty", - "Eastern", - "East", - "Earth", "Dreadful", "Coriantumr", "Savior", "Mayan", "Elders", - "Mothers", - "Community", - "Church", - "Certain", - "Common", - "Consent", - "Cold", - "Josh", "Gad", "Enoch", - "Saints", - "Chiefs", - "Indians", "Celestial", - "Glory", "Canyons", - "Buffalo", - "Breath", - "Brass", - "Plates", - "Bowl", "Incense", "Mormon", "Ether", - "Ancient", - "Quarter", - "Tenth", - "Tens", "Tempter", "Temnet", "Telleth", "Teemkt", - "Tee", "Tay", "Tarramarhah", - "Tan", "Tamahu", - "Talking", - "Talk", "Tah", "Sweetgrass", "Supposeth", "Supper", - "Superior", - "Sun", "Sufficeth", "Subdue", "Lucifer", - "Stones", "Stephat", - "Stars", - "Stakes", - "Spiritual", - "Spine", "Speaketh", - "Speaker", - "Sovereign", - "South", - "Time", - "Ago", - "Later", - "Date", - "Future", - "Sky", - "Sixteen", - "Age", - "Six", "Sineth", "Simeon", "Sidon", @@ -429,81 +169,50 @@ "Shadowing", "Sha", "Sevim", - "Several", - "Hours", - "Seventeen", - "Seven", "Setteth", - "Set", - "Session", - "Servant", "Seer", "Seeketh", - "Seek", - "Seat", "Sealing", "Saviors", "Satan", "Sanith", "Saneth", - "San", - "Stretch", "Spake", "Preach", - "Answered", "Samuel", "Samith", "Samal", "Salamander", - "Safety", - "Plants", - "Manner", "Sacrament", "Sabel-Nah", "Sabel", "Sabbaths", - "Room", "Robbers", "Rhen", "Resurrected", - "Resume", "Repent", - "Remove", "Rejoice", "Redeemer", - "Recall", - "Queens", "Prophets", "Moroni", "Prophecy", - "Promise", - "Priests", "Priestesses", "Priestess", - "President", "Preacher", "Prayeth", - "Pray", "Potal", "Porinor", "Por", - "Plan", - "Plains", - "Places", "Pingwit", "Pharaoh", "Peter", "James", "John", - "Person", "Perisheth", - "Altar", "Penith", "Pel", - "Pee", "Peacemaker", "Parim", - "Parents", "Parah", "Panith-Het", "Panith", @@ -517,101 +226,50 @@ "Hem", "Pagwit", "Pac-Sineth", - "Pac", "Ordinance", - "One", - "Forty", - "Half", - "Omega", - "Old", "Ohmer", - "Oh", - "Observe", "Nu", "Notwithstanding", "Nomiah-Min", "Nomiah", - "Min", "Noahs", "Noah", - "Ninety-Two Years", - "Nine", "Nin-Shepa", "Nin", - "Week", - "Name", - "Hills", "Nespelite", - "Nay", "Nathah", "Nemenhah", "Nemen", - "Neighbor", - "Nature", - "Natural", - "Narrator", - "Myself", - "Chosen", "Mulekites", "Mulekite", "Mulek", "Muel", "Moveth", - "Mouth", - "Mouse", - "Mountain", - "Mount", - "Fathers", "Moses", "Morrow", "Morin", "Moriantum", - "Moon", - "Millions", "Michael", "Methuselah", "Messengers", "Melek", - "Meet", - "Fall", - "Master", "Manna", - "Maker", - "Love", - "Lords", - "Look", - "Lone", "Lodges", - "Lo", - "Lives", "Limhi", - "Lightning", "Levites", "Levite", - "Lay", - "Lamb", - "Lakes", "Korim", "Knoweth", - "Know", "Kinsman", - "Kings", "Mosiah", - "Keen", - "Judgment", "Judgeth", - "Judge", "Judah", "Joseph", "Joram", "Revelator", - "Beloved", - "Jews", - "Himself", "Jehovah", "Jaredites", "Jaredite", - "Jared", "Jaguar", "Jacobite", "Israelite", @@ -621,50 +279,26 @@ "Isaiah", "Isabel", "Isaac", - "Instructor", - "Instruction", - "Inner", - "Indigenous", - "Americans", "Husbands", - "Husband", "Hundredth", - "Hundreds", - "Hudson", - "Bay", "Howbeit", "Hosanna", "Hopeth", - "Child", "Holiness", - "Hold", "Hin", "Himneth", "Hez", "Heth", "Het", - "Heroes", - "Hero", "Heirs", - "Hebrew", "Heavens", - "Beings", - "Heart", "Hearken", "Healers", - "Head", - "Hay", "Harlot", "Ham", "Hemen", - "Guides", - "Guardian", "Groweth", - "Grandmother", "Grandfathers", - "Grandfather", - "Governor", - "Gods", "Godliness", "Godhead", "Gideon", @@ -672,51 +306,28 @@ "Gentile", "Gee", "Gaudy", - "Gate", - "Garden", - "Fourteen", "Forty-Nine", "Forgetfulness", - "Minutes", - "Fifty", "Finisher", "Findeth", - "Figure", "Feather", - "Farewell", "Falleth", - "Faith", "Exalted", - "Being", "Exaltation", - "Evening", - "Eternal", "Ephraim", "Envieth", - "English", - "Else", - "Eleven", - "Election", - "Eight", "Egyptus", - "Egyptian", "Egypt", "Eden", - "Earlier", - "Eagle", "Dogwood", "Doeth", "Disciples", "Disciple", "Discernment", - "Devil", "Desolate", "Desireth", "Depart", - "Deep", - "Deaths", "Days'", - "Short", "Aaron", "Abel", "Abraham", @@ -724,65 +335,28 @@ "Adamant", "Adversary", "Afar", - "Afternoon", - "Alpha", - "America", "Amulek", - "Appointed", - "Angel", - "Angels", "Anith", "Anointed", - "Anti", "Apostle", - "Arise", - "Arm", - "Little", - "Least", "Atonement", "Availeth", "Babylon", "Baptism", - "Baptist", - "Begin", "Begotten", "Belay", "Believeth", - "Bend", "Benjamites", - "Big", - "Blessed", - "Blessing", - "Body", - "Break", "Brigham", "Bringeth", "Meekness", - "Brother", - "Bush", "Cain", - "Calling", - "Captain", "Cedar", - "Celebration", - "Celebrations", - "Chapters", - "Chief", - "Churches", - "Cities", "Laman", "Claimeth", - "Clan", "Coasts", - "Come", "Comforter", "Condemn", "Corian", - "Cosmos", - "Counsel", - "County", - "Creation", - "Cried", - "Daily", - "Dead" + "Cosmos" ] \ No newline at end of file diff --git a/output_proper_nouns/pronunciation_fixes.json b/output_proper_nouns/pronunciation_fixes.json index 56fb1ee..94e75dd 100644 --- a/output_proper_nouns/pronunciation_fixes.json +++ b/output_proper_nouns/pronunciation_fixes.json @@ -1,11 +1,8 @@ { - "Gadianton Robbers": "Gadeeantun Robbers", "Gadianton": "Gadeeantun", "Coriantumr": "Coryantomer", "Laman": "Layman", - "Lehi And Nephi": "Leehi And Nephi", "Lehi": "Leehi", - "Lehi Mathonihah": "Leehi Mathonihah", "Lehis": "Leehis", "Lehies": "Leehis", "Liahona": "Leeahona", @@ -14,15 +11,14 @@ "Gadiantons": "Gadeeantuns", "Laban": "Layban", "Mosiah": "Moziah", - "Mosiah The King": "Moziah The King", "Nehors": "Kneehores", - "Samuel The Lamanite": "Samuel The Laymanite", "Tarry": "Tarery", - "The Lamanite Twins": "The Laymanite Twins", - "The Lamanites Of Ammon": "The Laymanites Of Ammon", - "The Lamanites Of The Land Of Zarahemla": "The Laymanites Of The Land Of Zarahemla", - "The Lamanites Of The Land Southward": "The Laymanites Of The Land Southward", - "The Lamanites Of The People Of Ammon": "The Laymanites Of The People Of Ammon", - "The Lamb'S Book Of Life": "The Lamb's Book Of Life", - "The Land Of Nephi": "The Land Of Kneefi" + "Nephihah": "Kneefihah", + "Nephihet": "Kneefihet", + "Nephite": "Kneefite", + "Nephites": "Kneefites", + "Nephi-Im": "Kneefi-Im", + "Nephitish": "Kneefitish", + "Zenephi": "Zekneefi", + "Nephi": "Kneefi" } \ No newline at end of file