Generating a vowel inventory as a JSON structure

I was reading this interesting article:

And a couple details caught my attention. First, couldn’t find any other instances of the variant name Dënedédlı ̨́né Yëtı (which I presume has an erroneous space in there, read Dënedédlį́né Yëtı?) on the web, which is interesting (any folks around here familiar with this language?). Second, the article mentions the “48 tonal vowel sounds” — wow!

Being the data-obsessed person I am, I thought it would be fun to try to generate all the possibilities. The article mentions that Dënedédlį́né Yëtı is a variant of Chipweyan (which Wikipedia calls Chipewyan), and there is a vowel table there:

So that’s 24, but it also mentions that there is a high/low tone distinction, so

2 :heavy_multiplication_x: 24 :heavy_equals_sign: 48 vowel sounds.

:muscle:

Generating a data structure

This is kind of an interesting data structure, because when you’re looking at anything above a couple dozen, hand-inputting data gets to be an error-prone pain. So I thought it might be fun to share how I would go about generating a JSON structure that encodes this information. (If you would like to port the code to another language or even re-write it in JS here, please share!)

Basically, we’ve got four variables, and we want to generate all the possible combinations of those variables. One way to do this is to use a bunch of nested maps, like so:

let phones =  [ "i", "ë", "e", "a", "u", "o" ]
let nasalities =   [ "oral", "nasal" ]
let lengths = [ "long", "short" ]
let heights = [ "high", "low" ]

let vowels = phones.map(phone => 
  nasalities.map(nasality => 
    lengths.map(length => 
      heights.map(height => ({
          phone,
          nasality,
          length,
          height
        })
    )
  )
)
.map(vowel => { // the bit below generates an appropriate orthographic representation 
  let orthographic = vowel.phone
  if(vowel.nasality == 'nasal'){ orthographic += '\u0303' }
  if(vowel.tone == 'high'){ orthographic += '\u0301' }
  if(vowel.length == 'long'){ orthographic += orthographic }

  vowel.phone = orthographic
  return vowel
})

)

Which gives us data that looks like this:

Generated vowel data as JSON
[
  {
    "nasality": "oral",
    "tone": "high",
    "length": "long",
    "phone": "íí"
  },
  {
    "nasality": "oral",
    "tone": "low",
    "length": "long",
    "phone": "ii"
  },
  {
    "nasality": "oral",
    "tone": "high",
    "length": "short",
    "phone": "í"
  },
  {
    "nasality": "oral",
    "tone": "low",
    "length": "short",
    "phone": "i"
  },
  {
    "nasality": "nasal",
    "tone": "high",
    "length": "long",
    "phone": "ĩ́ĩ́"
  },
  {
    "nasality": "nasal",
    "tone": "low",
    "length": "long",
    "phone": "ĩĩ"
  },
  {
    "nasality": "nasal",
    "tone": "high",
    "length": "short",
    "phone": "ĩ́"
  },
  {
    "nasality": "nasal",
    "tone": "low",
    "length": "short",
    "phone": "ĩ"
  },
  {
    "nasality": "oral",
    "tone": "high",
    "length": "long",
    "phone": "ë́ë́"
  },
  {
    "nasality": "oral",
    "tone": "low",
    "length": "long",
    "phone": "ëë"
  },
  {
    "nasality": "oral",
    "tone": "high",
    "length": "short",
    "phone": "ë́"
  },
  {
    "nasality": "oral",
    "tone": "low",
    "length": "short",
    "phone": "ë"
  },
  {
    "nasality": "nasal",
    "tone": "high",
    "length": "long",
    "phone": "ë̃́ë̃́"
  },
  {
    "nasality": "nasal",
    "tone": "low",
    "length": "long",
    "phone": "ë̃ë̃"
  },
  {
    "nasality": "nasal",
    "tone": "high",
    "length": "short",
    "phone": "ë̃́"
  },
  {
    "nasality": "nasal",
    "tone": "low",
    "length": "short",
    "phone": "ë̃"
  },
  {
    "nasality": "oral",
    "tone": "high",
    "length": "long",
    "phone": "éé"
  },
  {
    "nasality": "oral",
    "tone": "low",
    "length": "long",
    "phone": "ee"
  },
  {
    "nasality": "oral",
    "tone": "high",
    "length": "short",
    "phone": "é"
  },
  {
    "nasality": "oral",
    "tone": "low",
    "length": "short",
    "phone": "e"
  },
  {
    "nasality": "nasal",
    "tone": "high",
    "length": "long",
    "phone": "ẽ́ẽ́"
  },
  {
    "nasality": "nasal",
    "tone": "low",
    "length": "long",
    "phone": "ẽẽ"
  },
  {
    "nasality": "nasal",
    "tone": "high",
    "length": "short",
    "phone": "ẽ́"
  },
  {
    "nasality": "nasal",
    "tone": "low",
    "length": "short",
    "phone": "ẽ"
  },
  {
    "nasality": "oral",
    "tone": "high",
    "length": "long",
    "phone": "áá"
  },
  {
    "nasality": "oral",
    "tone": "low",
    "length": "long",
    "phone": "aa"
  },
  {
    "nasality": "oral",
    "tone": "high",
    "length": "short",
    "phone": "á"
  },
  {
    "nasality": "oral",
    "tone": "low",
    "length": "short",
    "phone": "a"
  },
  {
    "nasality": "nasal",
    "tone": "high",
    "length": "long",
    "phone": "ã́ã́"
  },
  {
    "nasality": "nasal",
    "tone": "low",
    "length": "long",
    "phone": "ãã"
  },
  {
    "nasality": "nasal",
    "tone": "high",
    "length": "short",
    "phone": "ã́"
  },
  {
    "nasality": "nasal",
    "tone": "low",
    "length": "short",
    "phone": "ã"
  },
  {
    "nasality": "oral",
    "tone": "high",
    "length": "long",
    "phone": "úú"
  },
  {
    "nasality": "oral",
    "tone": "low",
    "length": "long",
    "phone": "uu"
  },
  {
    "nasality": "oral",
    "tone": "high",
    "length": "short",
    "phone": "ú"
  },
  {
    "nasality": "oral",
    "tone": "low",
    "length": "short",
    "phone": "u"
  },
  {
    "nasality": "nasal",
    "tone": "high",
    "length": "long",
    "phone": "ṹṹ"
  },
  {
    "nasality": "nasal",
    "tone": "low",
    "length": "long",
    "phone": "ũũ"
  },
  {
    "nasality": "nasal",
    "tone": "high",
    "length": "short",
    "phone": "ṹ"
  },
  {
    "nasality": "nasal",
    "tone": "low",
    "length": "short",
    "phone": "ũ"
  },
  {
    "nasality": "oral",
    "tone": "high",
    "length": "long",
    "phone": "óó"
  },
  {
    "nasality": "oral",
    "tone": "low",
    "length": "long",
    "phone": "oo"
  },
  {
    "nasality": "oral",
    "tone": "high",
    "length": "short",
    "phone": "ó"
  },
  {
    "nasality": "oral",
    "tone": "low",
    "length": "short",
    "phone": "o"
  },
  {
    "nasality": "nasal",
    "tone": "high",
    "length": "long",
    "phone": "ṍṍ"
  },
  {
    "nasality": "nasal",
    "tone": "low",
    "length": "long",
    "phone": "õõ"
  },
  {
    "nasality": "nasal",
    "tone": "high",
    "length": "short",
    "phone": "ṍ"
  },
  {
    "nasality": "nasal",
    "tone": "low",
    "length": "short",
    "phone": "õ"
  }
]
nasal? tone length vowel
oral high long íí
oral low long ii
oral high short í
oral low short i
nasal high long ĩ́ĩ́
nasal low long ĩĩ
nasal high short ĩ́
nasal low short ĩ
oral high long ë́ë́
oral low long ëë
oral high short ë́
oral low short ë
nasal high long ë̃́ë̃́
nasal low long ë̃ë̃
nasal high short ë̃́
nasal low short ë̃
oral high long éé
oral low long ee
oral high short é
oral low short e
nasal high long ẽ́ẽ́
nasal low long ẽẽ
nasal high short ẽ́
nasal low short
oral high long áá
oral low long aa
oral high short á
oral low short a
nasal high long ã́ã́
nasal low long ãã
nasal high short ã́
nasal low short ã
oral high long úú
oral low long uu
oral high short ú
oral low short u
nasal high long ṹṹ
nasal low long ũũ
nasal high short
nasal low short ũ
oral high long óó
oral low long oo
oral high short ó
oral low short o
nasal high long ṍṍ
nasal low long õõ
nasal high short
nasal low short õ

There you go, a representation of 48 vowels in Dënedédlį́né Yëtı.

Now what you can do with data like that is another post!

2 Likes

Somewhat related: If you have phonemes mapped to CLTS, you can use pyclts to slot a phoneme inventory into the common IPA charts: Code is here pyclts/ipachart.py at master · cldf-clts/pyclts · GitHub
Basically, a Diagram knows to select matching segments from an inventory and how to render itself in HTML, e.g. the “Vowel Trapezoid”: pyclts/ipachart.py at c7420d9c59122210422ae249f00a37284cda98c8 · cldf-clts/pyclts · GitHub

2 Likes

That’s used e.g. here: PHOIBLE 2.0 -

1 Like

Nice.

SVG is so useful for stuff like this.

Lots of interesting code in here. The SVG vowel trapezoid is very cool. In my own stuff I’ve been lazy so far and stuck with generating plain vowel tables; the trapezoid is better because it’s what linguists are familiar with.

It occurs to me that my JSON structure above is incomplete, because it also needs the primary vowel features of height, backness, and rounding to be specified in order to be able to plot the vowels to a chart or a table, as you have done.