I'm trying to make a fun little "Halloweenify" feature where a user types in his or her name and gets a scary version. (Julie becomes "Ghoulie", Robert becomes "Macabert").

I have a huge list of Halloween works and a huge list of names, all with their phonemes from CMUDict. (Let's put aside for a second uncommon names.) For example:

"julie": "JH UW1 L IY0"
"ghoul": "G UW1 L"

It's relatively easy to write some code to align the "UW1 L" in these words. But since I don't explicitly know that the "IY0" in "Julie" corresponds to "ie," I can't get from "Ghoul" to "Ghoulie."

I think what I need is a version of CMUDict, or any other robust grapheme-to-phoneme dictionary, that splits up both the orthography and the phonemes, like so:

"j u l ie": "JH UW1 L IY0"
"r o b er t": "R AA1 B ER0 T"

That way, it would be easy to reconstruct the original name after adulterating it to make it scary.

Has anyone seen such a dictionary? I'm also open to more generic g2p solutions, but since this runs in a browser I can use any live heavy-duty ML methods. Thanks!


This is a fairly hard problem (well, 2: the g2p problem, and the word-formation problem). Per-grapheme:phoneme (fun fact: such mappings are sometimes called ‘graphones') dictionaries for English don’t (can’t) exist, because there’s lots of ambiguity and issues of multiple n-gram sizes (as in your example, ‘ie’ = /IY/, but sometime ‘i’ = /IY/, or /IH/, or whatever). Dealing with stress placement is even worse, and possible not solvable by the method I suggest below.

I had some success with Phonetisaurus, a more generic g2p (and, if you reverse the inputs, p2g) tool. It needs to be trained on a dictionary like you describe (orthography list with matched phonemic list).

I guess you’ll also have to match the spooky versions for stress and rhyming, but I don’t know of an existing solution for that.

The most realistic solution is for humans to prepare these spooky versions ahead of time (by hand); the distribution of names is such that you could get reasonably good coverage for most people with a reasonable amount of work.

  • Thanks! I knew there must be a reason this wasn't easy to locate. – Chris Wilson Oct 24 '15 at 15:25

We just finished a project for which we developed a Phonics Engine (see paper https://www.researchgate.net/publication/280147388_Building_a_Phonics_Engine_for_Automated_Text_Guidance) that does exactly that. We have a dictionary (BrEng) that produces mappings such as b:b,a:@,tch:tS - both the code and the final dictionary are available but, unfortunately, the mapping code is very rough and ready and required lots of manual tweaks. Here's the code on GitHub: https://github.com/mpakarlsson/ilearnrw/tree/master/src/ilearnrw/languagetools/english.

Edit: The key files are probably just embedded in the Java code somewhere, so I started a separate repo for the language source files here: github.com/techczech/phonicsengine.

  • I'll check it out -- awesome!! – Chris Wilson Oct 24 '15 at 19:44
  • Are the actual mappings in the repo? I'm not much of a Java guy unfortunately. – Chris Wilson Oct 24 '15 at 22:18
  • @ChrisWilson I just realized that the key files are probably just embedded in the Java code somewhere, so I started a separate repo for the language source files here: github.com/techczech/phonicsengine. – Dominik Lukes Oct 25 '15 at 7:02

There's a paper by Jiampojamarn and Kondrak: Letter-Phoneme Alignment: An Exploration that comes with software: m2m-aligner. This can work on cmudict (but you need to reformat cmudict). I ran it without the emphasis markers and got:

j|u|l|i:e|      JH|UW|L|IY|
g|h|o:u|l|      G|_|UW|L|
r|o|b|e:r|t|    R|AA|B|ER|T|


Here's what I ran:

git clone --depth 1 \
cd m2m-aligner
perl -pi -e 's/-lgcc_s//' makefile
curl -O \

Here's how I converted the cmudict format to what m2m-aligner wanted:

import re
f = open('cmudict.txt', 'w')
for line in open('cmudict-0.7b', 'r', encoding='latin1'):
    if not re.match(r'^[a-zA-Z\d\s]+$', line): continue
    word, phonemes = line.strip().split(' ', 1)
    if not re.match(r'^[a-zA-Z]+$', word): continue
    print(' '.join(word.lower()), '\t',
          re.sub(r'\d\b', '', phonemes.strip()),
          sep='', file=f)

And then I ran

./m2m-aligner --delX --maxX 2 --maxY 2 -i cmudict.txt

The output is in cmudict.txt.m-mAlign.2-2.delX.1-best.conYX.align.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.