From 345b7daf4509ac89f70790c71cb2cba9b7a4f300 Mon Sep 17 00:00:00 2001 From: sanine Date: Mon, 6 May 2024 13:55:32 -0500 Subject: add basic vowel features --- src/language.test.ts | 33 +++++++++++++++++ src/language.ts | 103 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 136 insertions(+) create mode 100644 src/language.test.ts create mode 100644 src/language.ts (limited to 'src') diff --git a/src/language.test.ts b/src/language.test.ts new file mode 100644 index 0000000..e9845a1 --- /dev/null +++ b/src/language.test.ts @@ -0,0 +1,33 @@ +import * as lang from './language'; + +test('correctly output basic vowels', () => { + expect(lang.vowelFeaturesToIpa({ + height: lang.VowelHeight.Close, + depth: lang.VowelDepth.Front, + round: false, + long: false, + nasal: false, + })).toBe('i'); + expect(lang.vowelFeaturesToIpa({ + height: lang.VowelHeight.Mid, + depth: lang.VowelDepth.Central, + round: false, + long: false, + nasal: false, + })).toBe('ə'); + expect(lang.vowelFeaturesToIpa({ + height: lang.VowelHeight.Open, + depth: lang.VowelDepth.Back, + round: true, + long: false, + nasal: true, + })).toBe('ɒ̃'); + expect(lang.vowelFeaturesToIpa({ + height: lang.VowelHeight.CloseMid, + depth: lang.VowelDepth.Front, + round: false, + long: true, + nasal: false, + })).toBe('eː'); + +}); diff --git a/src/language.ts b/src/language.ts new file mode 100644 index 0000000..2d0f547 --- /dev/null +++ b/src/language.ts @@ -0,0 +1,103 @@ +export enum VowelHeight { + Open, + NearOpen, + OpenMid, + Mid, + CloseMid, + NearClose, + Close, +} +export enum VowelDepth { + Front, + Central, + Back, +} +export interface VowelFeatures { + height: VowelHeight; + depth: VowelDepth; + round: boolean; + long: boolean; + nasal: boolean; +} +export function vowelFeaturesToIpa(features: VowelFeatures): string { + const ipa = () => { + switch (features.height) { + case VowelHeight.Open: + switch (features.depth) { + case VowelDepth.Front: + return features.round ? 'ɶ' : 'a'; + case VowelDepth.Central: + return features.round ? 'ɞ' : 'ä'; + case VowelDepth.Back: + return features.round ? 'ɒ' : 'ɑ'; + } + + case VowelHeight.NearOpen: + switch (features.depth) { + case VowelDepth.Front: + return features.round ? 'ɶ' : 'æ'; + case VowelDepth.Central: + return features.round ? 'ɞ' : 'ɐ'; + case VowelDepth.Back: + return features.round ? 'ɒ' : 'ɑ'; + } + + case VowelHeight.OpenMid: + switch (features.depth) { + case VowelDepth.Front: + return features.round ? 'œ' : 'ɛ'; + case VowelDepth.Central: + return features.round ? 'ɞ' : 'ɜ'; + case VowelDepth.Back: + return features.round ? 'ɒ' : 'ɑ'; + } + + case VowelHeight.Mid: + switch (features.depth) { + case VowelDepth.Front: + return features.round ? 'ø̞' : 'e̞'; + case VowelDepth.Central: + return features.round ? 'ɵ' : 'ə'; + case VowelDepth.Back: + return features.round ? 'o̞' : 'ɤ̞'; + } + + case VowelHeight.CloseMid: + switch (features.depth) { + case VowelDepth.Front: + return features.round ? 'ø' : 'e'; + case VowelDepth.Central: + return features.round ? 'ɵ' : 'ɘ'; + case VowelDepth.Back: + return features.round ? 'o' : 'ɤ'; + } + + case VowelHeight.NearClose: + switch (features.depth) { + case VowelDepth.Front: + return features.round ? 'ʏ' : 'ɪ'; + case VowelDepth.Central: + return features.round ? 'ʉ' : 'ɨ'; + case VowelDepth.Back: + return features.round ? 'u' : 'ʊ'; + } + + case VowelHeight.Close: + switch (features.depth) { + case VowelDepth.Front: + return features.round ? 'y' : 'i'; + case VowelDepth.Central: + return features.round ? 'ʉ' : 'ɨ'; + case VowelDepth.Back: + return features.round ? 'u' : 'ɯ'; + } + + default: + throw new Error(`bad vowel height: ${features.height}`); + } + }; + + const nasal = features.nasal ? '̃' : ''; + const vlong = features.long ? 'ː' : ''; + return ipa() + nasal + vlong; +} -- cgit v1.2.1