Matthew Kaney at ITP

Assignment 4: Pronouncing Module

Reading and Writing Electronic Text


18

For this assignment, I focused on extending the functionality of my CMU pronouncing dictionary work from earlier in the semester, and wrapping up everything in a module I called “pronouncer.py”.

Rhyme

My module can be used to test whether two words rhyme. Note that both words must be in the CMU speaking dictionary. If they’re not, then the function returns false.

>>> pronouncer.rhymingWords(‘apple’, ‘orange’)
False

You can also search the pronouncing dictionary for rhymes:

>>> pronouncer.findWordsWithRhyme(‘persuasive’)
[‘INVASIVE’, ‘PERVASIVE’, ‘SUPERABRASIVE’, ‘ABRASIVE’, ‘EVASIVE’]

Or, if you want to work within an existing corpus, you can specify a list of words to search within:

>>> pronouncer.findWordsWithRhyme(‘lemon’, [‘demon’, ‘yemen’, ‘salmon’])
[‘yemen’]

Meter

Based on the stress information in the pronouncing dictionary, the module can do incredibly simple scansion-type analysis (expressed as a list of 1s, 2s, and 0s, for primary stress, secondary stress, and no stress, respectively). Currently, the system makes no attempt to guess meter for words it doesn’t know, so this isn’t always that helpful.

>>> pronouncer.getMeter(‘To sit in solemn silence’)
[1, 1, 0, 1, 0, 1, 0]

More helpful is the ability to search for words that have a given stress. Like the rhyme functions, this can either search the entire pronouncing dictionary, or a provided word list.

>>> pronouncer.findWordsWithMeter([1, 0, 1, 0, 0])
[‘VIVISEPULTURE’, ‘NONEXECUTIVE’, ‘SUNAMERICA’, ‘GENEMEDICINE’, ‘PUBLIC-SPIRITED’, ‘SELF-DELIVERANCE’, ‘PORT-VICTORIA’, ‘OVERSHADOWING’, ‘SELF-SUFFICIENCY’, ‘PHOTOFINISHING’, ‘MOCK-HEROICALLY’]

Module Code

import string

# Array of all vowel sounds in the CMU speaking dictionary
vowelSounds = ["AA", "AE", "AH", "AO", "AW", "AY", "EH", "ER", "EY",
               "IH", "IY", "OW", "OY", "UH", "UW"]

# Now, import and populate the CMU speaking dictionary
cmu = open('cmudict', 'r')

phoneticDict = {}

for line in cmu:
    tokens = line.split()
    
    # Only grab the first pronunciation in the dictionary, for now
    if tokens[1] == "1":
        key = tokens[0]
        phonemes = []
        stresses = []

        # Some phonemes have a number indicating stress (e.g. "EH1").
        for phoneme in tokens[2:]:
            # If this is one of those, split the phoneme from the stress
            if not phoneme.isalpha():
                stresses.append(int(phoneme[-1]))
                phoneme = phoneme[:-1]

            phonemes.append(phoneme)

        phoneticDict[key] = (phonemes, stresses)

cmu.close()


# Convert tokens (with attached whitespace, punctuation, and irregular
# capitalization) to a clean, all-caps form
def cleanWord(word):
    newWord = word.upper()
    newWord = newWord.strip(string.punctuation)
    return newWord

# Check whether two words are both a) in the pronouncing dictionary and
# b) rhyming. Returns True or False.
def rhymingWords(firstWord, secondWord):
    if firstWord == secondWord:
        return False
    
    firstWord = cleanWord(firstWord)
    secondWord = cleanWord(secondWord)
    
    if firstWord in phoneticDict:
        searchSyllables, searchStresses = phoneticDict[firstWord]
    else:
        return False
    
    if secondWord in phoneticDict:
        wordSyllables, wordStresses = phoneticDict[secondWord]
    else:
        return False
    
    lastPhoneme = ''
    stressCounter = 1
    lastStress = 0

    for i in range(1, 1 + min(len(searchSyllables), len(wordSyllables))):
        if (searchSyllables[-i] == wordSyllables[-i] and
           stressCounter <= len(wordStresses) and
           stressCounter <= len(searchStresses)):
            lastPhoneme = searchSyllables[-i]

            if lastPhoneme in vowelSounds:
                lastStress = (wordStresses[-1 * stressCounter] and
                             searchStresses[-1 * stressCounter])

                stressCounter += 1
        else:
            break

    if (lastPhoneme in vowelSounds) and (lastStress > 0):
        return True
    else:
        return False

# For a given string, split the string into individual words and then return
# the meter of the entire string of words, in terms of stresses where
# 0 = no stress, 1 = primary stress, and 2 = secondary stress.
# For example, [1, 0, 1, 1, 0, 2]
def getMeter(line):
    words = line.strip().split()
    meter = [];
    
    for word in words:
        currWord = cleanWord(word);
        
        if currWord in phoneticDict:
            meter += phoneticDict[currWord][1]
    
    return meter

# Get a list of words that rhyme with a certain word. The first parameter
# is the word that the results should rhyme with. The optional second
# parameter is the list of words for searching in. If no list is specified,
# the function will search the entire pronouncing dictionary.
def findWordsWithRhyme(rhyme, searchList=phoneticDict.keys()):
    result = [];
    
    for word in searchList:
        if rhymingWords(rhyme, word):
            result.append(word);
    
    return result;

# Return a list of words that have the given pattern of stresses. The first
# parameter is a list of stresses (0, 1, or 2). The optional second parameter
# is the list of words for searching in. If no list is specified, the
# function will search the entire pronouncing dictionary.
def findWordsWithMeter(meter, searchList=phoneticDict.keys()):
    result = [];
    
    for word in searchList:
        cleaned = cleanWord(word);
        
        if cleaned in phoneticDict and phoneticDict[cleaned][1] == meter:
        	result.append(word);
    
    return result;

Comments

  1. cheap ffxiv gil on November 23, 2015 at 9:30 am

    cheap ffxiv gil

    If he shows up, we stick with him.

  2. eso gold store on November 26, 2015 at 9:34 pm

    eso gold store

    I’ll take care of it.

  3. cheap fifa coins on December 3, 2015 at 6:40 pm

    cheap fifa coins

    The youre very professional .

  4. resource on December 30, 2015 at 6:45 pm

    resource

    Up yours!

  5. fifa coins for sale on December 31, 2015 at 8:24 pm

    fifa coins for sale

    That’s not the point.

  6. buy MUT Coins on January 3, 2016 at 11:55 am

    buy MUT Coins

    You are so cute.

  7. blade & soul gold on May 14, 2016 at 3:59 am

    blade & soul gold

    Do you have a good sense of humor .

  8. u4fifa twitter on June 7, 2016 at 1:56 pm

    u4fifa twitter

    You always know the right thing to say.

  9. u4fifa on June 7, 2016 at 7:15 pm

    u4fifa

    nice going!

  10. nba2k16store.com on June 14, 2016 at 12:48 pm

    nba2k16store.com

    My way or the highway.

  11. nba2k16store.com on June 17, 2016 at 11:02 am

    nba2k16store.com

    hi!this is very good site!

  12. UPAlbion.com on July 9, 2016 at 4:16 am

    UPAlbion.com

    Leave me alone !

  13. u4fifa.com on July 19, 2016 at 1:50 pm

    u4fifa.com

    You did a good job .

  14. cheapest fifa 17 points on July 20, 2016 at 1:45 pm

    cheapest fifa 17 points

    The youre really talented .

  15. FIFA17 Android 900k coins on August 24, 2016 at 2:49 am

    FIFA17 Android 900k coins

    You have a good taste.

  16. cheapest and fastest nba 2k mt store on October 6, 2016 at 11:12 am

    cheapest and fastest nba 2k mt store

    it’s very helpful for me searching for this website!

  17. albion online gold on December 23, 2016 at 8:25 pm

    albion online gold

    The youre very eloquent .

  18. buy Final Fantasy XIV Gil on June 5, 2017 at 11:13 am

    buy Final Fantasy XIV Gil

    I have no idea what you have said

The comments are closed.