summaryrefslogtreecommitdiff
path: root/language/vispeech
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /language/vispeech
Initial commit
Diffstat (limited to 'language/vispeech')
-rw-r--r--language/vispeech/info.tex194
-rw-r--r--language/vispeech/info2.tex195
-rw-r--r--language/vispeech/viscons.mf236
-rw-r--r--language/vispeech/visglides.mf99
-rw-r--r--language/vispeech/vismacs.tex148
-rw-r--r--language/vispeech/vismods.mf230
-rw-r--r--language/vispeech/vispeech.mf401
-rw-r--r--language/vispeech/vispeech2.mf404
-rw-r--r--language/vispeech/visvowels.mf53
9 files changed, 1960 insertions, 0 deletions
diff --git a/language/vispeech/info.tex b/language/vispeech/info.tex
new file mode 100644
index 0000000000..0fb21b258c
--- /dev/null
+++ b/language/vispeech/info.tex
@@ -0,0 +1,194 @@
+\input vismacs.tex
+\font\vis=vispeech
+\font\bigbf=cmbx12
+\centerline{\bigbf Visible Speech Font}
+\bigskip
+The Visible Speech is a phonetic alphabet invented by Alexander Melville
+Bell (you may have heard of his son, Alexander Graham Bell, who invented a
+fairly widely-used contraption). Bell was a teacher of the Deaf (as was
+the younger Bell, incidentally), and this alphabet was intended as an aid
+to teaching the Deaf how to pronounce words, by reducing sounds to a
+presumably unambiguous representation. This file would be ridiculously
+long if I reprinted all Bell's description of the alphabet, but I'll
+summarize it here. My information is all from Bell's book {\vis
+\pm\vmbw\glipback\pnv\psv\pmv\ \vlfw\pnv\psv\ \pbv\vmfw\gpoint\
+\ppv\vhfp\pdv\vmfp\gtop\tm\vmbp\pnv\pmv} ({\sl Sounds and their
+Relations\/}), published in~1881.
+
+The consonants in Visible Speech are all non-ascending, non-descending
+letters, which consist mainly of a loop indicating the point of
+articulation. Bell classified consonants into four points of articulation:
+the back of the tongue ({\vis\bp}), the top of the tongue ({\vis\tp}), the
+point of the tongue ({\vis\pp}), and the lip ({\vis\lp}). In the basic
+state, as they are, the loops just mean that that's where the air is
+flowing. Bell describes a slightly more open and longer version of
+{\vis\lp} as ``cooling'' ({\it i.e.}~blowing to cool). If the curve is
+shut ({\vis\ls}), that means the airflow is also stopped (in this case, an
+unexpelled~{\it p\/}). Closing the loop with a squiggle indicates that the
+air passes out the nose, giving you a nasal ({\vis\ln}~is therefore a
+voiceless~{\it m\/}). Adding a horizontal or vertical bar to the letter
+indicates voice ({\vis\lpv}~is an unfinished~{\it b}, {\vis\lnv} is an~{\it
+m\/}, and {\vis\pnv}~an~{\it n}). ``Divided'' curves, like~{\vis\ld},
+indicate ``lateral or interstitial apertures for the emission of the
+breath.'' So {\vis\ld} represents the sound of an English~{\it f}, and
+{\vis\ldv}~a~{\it v}. The points of the curve may also point back,
+indicating modification by the mouth-part on the other side of the curve.
+So {\vis\lmv}~is like {\vis\lpv} except that the tongue is pulled back
+somewhat, and is thus more like the English~{\it w\/} (according to Bell,
+at any rate). These are a little harder to explain; I will try to make a
+table showing very briefly Bell's examples for each sound and some
+variants, and you can work it out for yourself. Sounds may be both
+modified and divided, as~{\vis\pb}: the~{\it th\/} in ``thin.''
+
+Vowels are all vertically-oriented glyphs, with high vowels rising above
+the consonants, low vowels descending, and middle vowels doing both. The
+curls on the ends are on the right side for front vowels, the left for back
+vowels, and both sides for mixed vowels. A bar across the middle of a
+vowel indicates lip-rounding. If the curls are open, the vowel is
+``wide.'' So {\vis\vhfp\mholder}~is the {\it ee\/}~in ``feel'' (the
+modifier~{\vis\mholder} indicates greater length), while {\vis\vhfw}~is the
+{\it i\/}~sound in~``ill'' (all examples are paraphrases of Bell's; your
+ideolect may vary).
+
+There is also a selection of glides, sometimes hinting at their point of
+articulation, as well as many modifiers to change the sounds slightly ({\it
+e.g.}~for ``blowing an object from the point of the tongue,'' you could use
+{\vis\ps\mprotruded\lp}, where~{\vis\mprotruded} indicates that the tongue
+is protruded all the way to the lips. Similarly, {\vis\minverted}~means
+the tongue goes toward the back of the mouth. I'll list Bell's one-word
+descriptions in the table, and try to clarify where possible. One more
+that doesn't appear on the table: the plus sign joins sounds that are
+articulated simultaneously.
+\medskip
+{\bf Things to do:} (Not that I'll do them, but it makes me look
+responsible.) (1) fix the left-right (up-down) symmetry on many of the
+glyphs. There are attempts to in some of them, but they're kludges and
+don't always work. (2) fix that deep white cut in the dints of the divided
+letters. (3) Supply more examples. (5) re-arrange the glyphs so they're
+in reasonable spots in the font table. (6) invent a scheme of inputting
+them that doesn't require neural surgery to understand. (7) and so on\dots
+\vfil\eject
+\centerline{\bf Visible Speech Consonants}
+\medskip
+(All examples are Bell's or paraphrases thereof)
+\medskip
+{\parindent=0pt\parfillskip=0pt
+\halign{&\vis #\hskip 1em&\dotfill\sevenrm #\hskip .25in\cr
+\omit&\omit\hbox to 2in{\hfil\vbox to 0pt{\vss}}&
+ \omit&\omit\hbox to 2in{\hfil\vbox to 0pt{\vss}}\cr
+\noalign {\vskip -\baselineskip}
+\lp&blowing to cool &\bn&non-vocal ng\cr
+\lpv&w (German) &\bnv&ng\cr
+\lm&wh &\tp&h in ``hue'', ch in German ``ich''\cr
+\lmv&w &\tpv&y in ``yet''\cr
+\ld&f &\tm&sh\cr
+\ldv&v &\tmv&(zh) in ``azure''\cr
+\lb&gutteralized f (draw back tongue) &\td&``defective form of s''\cr
+\lbv&gutteralized v (draw back tongue) &\tdv&gl in Italian ``gli''\cr
+\ls&p (shut) &\tb&Welsh ll\cr
+\ls\memission&final p, lips separating afterwards &\tbv&Zulu dhl\cr
+\lsv&b &\ts&Sanskrit ``cerebral'' (retroflex) t\cr
+\ln&non-vocal m &\tsv&Sanskrit ``cerebral'' d, ``thick'' d\cr
+\lnv&m &\tn&``thick'' n (non-vocal)\cr
+\bp&ch (German ``nach'', Scottish ``loch'') &\tnv&thick n\cr
+\bp\minner&low formation, further back
+ &\pp&non-vocal r, in French ``theatre''\cr
+\bp\mouter&high formation, further up &\ppv&r in ``ray''\cr
+\bpv&French r in ``grassey\'e'' &\ppv\mtrill&trilled r\cr
+\bpv\mtrill&rough burr (back-trilled) r &\pm&s\cr
+\bm&gh in Scottish ``sough'' (above, lip-rounded)& \pmv&z\cr
+\bmv&labialized burr &\pd&non-vocal l in French ``table''\cr
+\bd&hiss of water-fowl &\pdv&l\cr
+\bdv&l in Gaelic ``laogh'' &\pb&th in ``thin''\cr
+\pdv\mplus\bp&nearly equal to {\vis\bdv} &\pbv&th in ``then''\cr
+\bb&``do not occur as linguistic sounds'' &\ps&t\cr
+\bbv&``do not occur as linguistic sounds'' &\psv&d\cr
+\bs&k &\pn&non-vocal n\cr
+\bsv&g &\pnv&n\cr
+\fp&h &\fP&rough aspiration, whisper\cr
+\fPv&vocalized whisper, hoarseness &\fs&``Catch'' in the throat, cough\cr
+}}
+\medskip
+\centerline{\bf Vowels}
+\medskip
+{\parindent=0pt\parfillskip=0pt
+\halign{&\vis #\hskip 1em&\dotfill\sevenrm #\hskip .25in\cr
+\omit&\omit\hbox to 2in{\hfil\vbox to 0pt{\vss}}&
+ \omit&\omit\hbox to 2in{\hfil\vbox to 0pt{\vss}}\cr
+\noalign {\vskip -\baselineskip}
+\vhfp&(short) i in French ``fille''
+ &\vhbpr&(short) oo in Scotch ``food''\cr
+\vhfw&(short) i in ``ill'' &\vhbwr&(short) oo in ``foot''\cr
+\vmfp&(short) e in French ``est'' &\vmbpr&(short) o in Scotch ``note''\cr
+\vmfp\gtop&name of letter A &\vmbwr&(short) o in ``opinion''\cr
+\vmfw&(short) i in Scotch [sic] ``ill'' &\vlbpr\mholder&(long) a in ``all''\cr
+\vlfp&(short) e in ``let'' &\vlbpr&(short) a in ``what''\cr
+\vlfw&(short) a in ``hat'' &\vlbwr&(short) o in ``on''\cr
+\vhbp&sound you get if you unround the oo in ``room''.
+ &\vhfpr&(short) \"u in German ``\"uber''\cr
+\vhbp\mholder&ao in Gaelic ``laogh'' &\vhfwr&(short) u in French ``une''\cr
+\vhbw&(short) ou in -ous (courageous)
+ &\vmfpr&(short) \^u in French ``b\^ut''\cr
+\vmbp&(short) u in ``up'' &\vmfwr&no examples given\cr
+\vmbw&sound from unrounding o in ``ore'', a in ``pathetic''
+ &\vlfpr&(short) eu in French ``jeune''\cr
+\vlbp&(short) u in Scotch [sic] ``up'' &\vlfwr&Cockney ou in ``about''\cr
+\vlbw&(short) a in Scotch ``man'', a in ``alms''
+ &\vhmpr&(short) oo in North Irish ``look''\cr
+\vhmp\mholder&(long) i in ``sir'' (American)
+ &\vhmwr&(short) u in colloquial ``awful''\cr
+\vhmw&e in ``the'' &\vmmpr&(short) o in French ``homme''\cr
+\vmmp&French ``e mute'' &\vmmwr&(short) o in American ``whole''\cr
+\vmmw&(short) ``a'' (article) &\vlmpr&(short) i in Irish ``sir''\cr
+\vlmp&(short) e in Cockney ``penny'' &\vlmwr&(short) o in ``obtain''\cr
+\vlmw&(short) e in ``perform''\cr
+}}
+\goodbreak
+\centerline{\bf Glides}
+\medskip
+{\parindent=0pt\parfillskip=0pt
+\halign{\hskip 1in#\dotfill&\hskip 1em\vis#&\ as in #\hfil\cr
+Breath&\gbreath&{\vis\ls\gbreath\vhfw\bsv}, ``pig'' (Irish)\cr
+Voice&\gvoice&{\vis\lmv\vhfp\gvoice\ppv\vhfw}, ``weary''\cr
+Round&\ground&{\vis\pnv\vlfw\ground}, ``now'' (Cockney)\cr
+Throat&\gthroat&{\vis\vmbw\gthroat}, ``are'' (variety of smooth Burr)\cr
+Back&\gback&{\vis\vmbw\gback}, ``are'' (variety of smooth Burr)\cr
+Back Round&\gbackround
+ &{\vis\vmbw\gbackround}, ``are'' (variety of smooth Burr)\cr
+Top&\gtop&{\vis\psv\vmbw\gtop}, ``die''\cr
+Top Round&\gtopround&{\vis\pnv\gtopround\vhmpr}, ``new'' (North Irish)\cr
+Point&\gpoint&{\vis\vlbw\gpoint}, ``are''\cr
+Point Round&\gpointround
+ &{\vis\vmbw\glipback\gpointround}, ``our'' (Common)\cr
+Lip&\glip&{\vis\pdv\glip\vhfp}, ``lui'' (French)\cr
+Lip \& Back&\glipback&{\vis\pnv\vmbw\glipback}, ``now''\cr
+}}
+\bigskip
+\centerline{\bf Modifiers}
+\medskip
+{\parindent=0pt
+\halign{#\dotfill&\hskip 1em\vis#&\ #\hfil\cr
+Inner&\minner&(Produced farther back)\cr
+Outer&\mouter&(Produced farther forward)\cr
+Close&\mclose&(More closed)\cr
+Open&\mopen&(More open)\cr
+Trill&\mtrill\cr
+Nasal&\mnasal\cr
+Side Open&\moneside&(Air escapes one side)\cr
+Side Open&\mbothsides&(Air escapes both sides)\cr
+Inverted&\minverted&(Tongue curled back)\cr
+Protruded&\mprotruded&(Tongue protruded toward lips)\cr
+Stop&\mstop\cr
+Suction&\msuction&(Produced with air moving inwards)\cr
+Emission&\memission\cr
+Suction Stopped&\msuctionstopped\cr
+Emission Stopped&\memissionstopped\cr
+Hiatus&\mhiatus\cr
+Abrupt&\mabrupt\cr
+Holder&\mholder\cr
+Accent&\maccent&(On non-initial syllable, placed to the left)\cr
+Emphasis&\memphasis&(On whole word)\cr
+Whistle&\mwhistle\cr
+Voiced Whistle&\mvwhistle\cr
+}}
+\vfill\eject
diff --git a/language/vispeech/info2.tex b/language/vispeech/info2.tex
new file mode 100644
index 0000000000..1cc87da261
--- /dev/null
+++ b/language/vispeech/info2.tex
@@ -0,0 +1,195 @@
+\input vismacs.tex
+\font\vis=vispeech
+\font\bigbf=cmbx12
+\centerline{\bigbf Visible Speech Font}
+\line{\hfill from: Mark Shoulson (shoulson@ctr.columbia.edu)
+\bigskip
+The Visible Speech is a phonetic alphabet invented by Alexander Melville
+Bell (you may have heard of his son, Alexander Graham Bell, who invented a
+fairly widely-used contraption). Bell was a teacher of the Deaf (as was
+the younger Bell, incidentally), and this alphabet was intended as an aid
+to teaching the Deaf how to pronounce words, by reducing sounds to a
+presumably unambiguous representation. This file would be ridiculously
+long if I reprinted all Bell's description of the alphabet, but I'll
+summarize it here. My information is all from Bell's book {\vis
+\pm\vmbw\glipback\pnv\psv\pmv\ \vlfw\pnv\psv\ \pbv\vmfw\gpoint\
+\ppv\vhfp\pdv\vmfp\gtop\tm\vmbp\pnv\pmv} ({\sl Sounds and their
+Relations\/}), published in~1881.
+
+The consonants in Visible Speech are all non-ascending, non-descending
+letters, which consist mainly of a loop indicating the point of
+articulation. Bell classified consonants into four points of articulation:
+the back of the tongue ({\vis\bp}), the top of the tongue ({\vis\tp}), the
+point of the tongue ({\vis\pp}), and the lip ({\vis\lp}). In the basic
+state, as they are, the loops just mean that that's where the air is
+flowing. Bell describes a slightly more open and longer version of
+{\vis\lp} as ``cooling'' ({\it i.e.}~blowing to cool). If the curve is
+shut ({\vis\ls}), that means the airflow is also stopped (in this case, an
+unexpelled~{\it p\/}). Closing the loop with a squiggle indicates that the
+air passes out the nose, giving you a nasal ({\vis\ln}~is therefore a
+voiceless~{\it m\/}). Adding a horizontal or vertical bar to the letter
+indicates voice ({\vis\lpv}~is an unfinished~{\it b}, {\vis\lnv} is an~{\it
+m\/}, and {\vis\pnv}~an~{\it n}). ``Divided'' curves, like~{\vis\ld},
+indicate ``lateral or interstitial apertures for the emission of the
+breath.'' So {\vis\ld} represents the sound of an English~{\it f}, and
+{\vis\ldv}~a~{\it v}. The points of the curve may also point back,
+indicating modification by the mouth-part on the other side of the curve.
+So {\vis\lmv}~is like {\vis\lpv} except that the tongue is pulled back
+somewhat, and is thus more like the English~{\it w\/} (according to Bell,
+at any rate). These are a little harder to explain; I will try to make a
+table showing very briefly Bell's examples for each sound and some
+variants, and you can work it out for yourself. Sounds may be both
+modified and divided, as~{\vis\pb}: the~{\it th\/} in ``thin.''
+
+Vowels are all vertically-oriented glyphs, with high vowels rising above
+the consonants, low vowels descending, and middle vowels doing both. The
+curls on the ends are on the right side for front vowels, the left for back
+vowels, and both sides for mixed vowels. A bar across the middle of a
+vowel indicates lip-rounding. If the curls are open, the vowel is
+``wide.'' So {\vis\vhfp\mholder}~is the {\it ee\/}~in ``feel'' (the
+modifier~{\vis\mholder} indicates greater length), while {\vis\vhfw}~is the
+{\it i\/}~sound in~``ill'' (all examples are paraphrases of Bell's; your
+ideolect may vary).
+
+There is also a selection of glides, sometimes hinting at their point of
+articulation, as well as many modifiers to change the sounds slightly ({\it
+e.g.}~for ``blowing an object from the point of the tongue,'' you could use
+{\vis\ps\mprotruded\lp}, where~{\vis\mprotruded} indicates that the tongue
+is protruded all the way to the lips. Similarly, {\vis\minverted}~means
+the tongue goes toward the back of the mouth. I'll list Bell's one-word
+descriptions in the table, and try to clarify where possible. One more
+that doesn't appear on the table: the plus sign joins sounds that are
+articulated simultaneously.
+\medskip
+{\bf Things to do:} (Not that I'll do them, but it makes me look
+responsible.) (1) fix the left-right (up-down) symmetry on many of the
+glyphs. There are attempts to in some of them, but they're kludges and
+don't always work. (2) fix that deep white cut in the dints of the divided
+letters. (3) Supply more examples. (5) re-arrange the glyphs so they're
+in reasonable spots in the font table. (6) invent a scheme of inputting
+them that doesn't require neural surgery to understand. (7) and so on\dots
+\vfil\eject
+\centerline{\bf Visible Speech Consonants}
+\medskip
+(All examples are Bell's or paraphrases thereof)
+\medskip
+{\parindent=0pt\parfillskip=0pt
+\halign{&\vis #\hskip 1em&\dotfill\sevenrm #\hskip .25in\cr
+\omit&\omit\hbox to 2in{\hfil\vbox to 0pt{\vss}}&
+ \omit&\omit\hbox to 2in{\hfil\vbox to 0pt{\vss}}\cr
+\noalign {\vskip -\baselineskip}
+\lp&blowing to cool &\bn&non-vocal ng\cr
+\lpv&w (German) &\bnv&ng\cr
+\lm&wh &\tp&h in ``hue'', ch in German ``ich''\cr
+\lmv&w &\tpv&y in ``yet''\cr
+\ld&f &\tm&sh\cr
+\ldv&v &\tmv&(zh) in ``azure''\cr
+\lb&gutteralized f (draw back tongue) &\td&``defective form of s''\cr
+\lbv&gutteralized v (draw back tongue) &\tdv&gl in Italian ``gli''\cr
+\ls&p (shut) &\tb&Welsh ll\cr
+\ls\memission&final p, lips separating afterwards &\tbv&Zulu dhl\cr
+\lsv&b &\ts&Sanskrit ``cerebral'' (retroflex) t\cr
+\ln&non-vocal m &\tsv&Sanskrit ``cerebral'' d, ``thick'' d\cr
+\lnv&m &\tn&``thick'' n (non-vocal)\cr
+\bp&ch (German ``nach'', Scottish ``loch'') &\tnv&thick n\cr
+\bp\minner&low formation, further back
+ &\pp&non-vocal r, in French ``theatre''\cr
+\bp\mouter&high formation, further up &\ppv&r in ``ray''\cr
+\bpv&French r in ``grassey\'e'' &\ppv\mtrill&trilled r\cr
+\bpv\mtrill&rough burr (back-trilled) r &\pm&s\cr
+\bm&gh in Scottish ``sough'' (above, lip-rounded)& \pmv&z\cr
+\bmv&labialized burr &\pd&non-vocal l in French ``table''\cr
+\bd&hiss of water-fowl &\pdv&l\cr
+\bdv&l in Gaelic ``laogh'' &\pb&th in ``thin''\cr
+\pdv\mplus\bp&nearly equal to {\vis\bdv} &\pbv&th in ``then''\cr
+\bb&``do not occur as linguistic sounds'' &\ps&t\cr
+\bbv&``do not occur as linguistic sounds'' &\psv&d\cr
+\bs&k &\pn&non-vocal n\cr
+\bsv&g &\pnv&n\cr
+\fp&h &\fP&rough aspiration, whisper\cr
+\fPv&vocalized whisper, hoarseness &\fs&``Catch'' in the throat, cough\cr
+}}
+\medskip
+\centerline{\bf Vowels}
+\medskip
+{\parindent=0pt\parfillskip=0pt
+\halign{&\vis #\hskip 1em&\dotfill\sevenrm #\hskip .25in\cr
+\omit&\omit\hbox to 2in{\hfil\vbox to 0pt{\vss}}&
+ \omit&\omit\hbox to 2in{\hfil\vbox to 0pt{\vss}}\cr
+\noalign {\vskip -\baselineskip}
+\vhfp&(short) i in French ``fille''
+ &\vhbpr&(short) oo in Scotch ``food''\cr
+\vhfw&(short) i in ``ill'' &\vhbwr&(short) oo in ``foot''\cr
+\vmfp&(short) e in French ``est'' &\vmbpr&(short) o in Scotch ``note''\cr
+\vmfp\gtop&name of letter A &\vmbwr&(short) o in ``opinion''\cr
+\vmfw&(short) i in Scotch [sic] ``ill'' &\vlbpr\mholder&(long) a in ``all''\cr
+\vlfp&(short) e in ``let'' &\vlbpr&(short) a in ``what''\cr
+\vlfw&(short) a in ``hat'' &\vlbwr&(short) o in ``on''\cr
+\vhbp&sound you get if you unround the oo in ``room''.
+ &\vhfpr&(short) \"u in German ``\"uber''\cr
+\vhbp\mholder&ao in Gaelic ``laogh'' &\vhfwr&(short) u in French ``une''\cr
+\vhbw&(short) ou in -ous (courageous)
+ &\vmfpr&(short) \^u in French ``b\^ut''\cr
+\vmbp&(short) u in ``up'' &\vmfwr&no examples given\cr
+\vmbw&sound from unrounding o in ``ore'', a in ``pathetic''
+ &\vlfpr&(short) eu in French ``jeune''\cr
+\vlbp&(short) u in Scotch [sic] ``up'' &\vlfwr&Cockney ou in ``about''\cr
+\vlbw&(short) a in Scotch ``man'', a in ``alms''
+ &\vhmpr&(short) oo in North Irish ``look''\cr
+\vhmp\mholder&(long) i in ``sir'' (American)
+ &\vhmwr&(short) u in colloquial ``awful''\cr
+\vhmw&e in ``the'' &\vmmpr&(short) o in French ``homme''\cr
+\vmmp&French ``e mute'' &\vmmwr&(short) o in American ``whole''\cr
+\vmmw&(short) ``a'' (article) &\vlmpr&(short) i in Irish ``sir''\cr
+\vlmp&(short) e in Cockney ``penny'' &\vlmwr&(short) o in ``obtain''\cr
+\vlmw&(short) e in ``perform''\cr
+}}
+\goodbreak
+\centerline{\bf Glides}
+\medskip
+{\parindent=0pt\parfillskip=0pt
+\halign{\hskip 1in#\dotfill&\hskip 1em\vis#&\ as in #\hfil\cr
+Breath&\gbreath&{\vis\ls\gbreath\vhfw\bsv}, ``pig'' (Irish)\cr
+Voice&\gvoice&{\vis\lmv\vhfp\gvoice\ppv\vhfw}, ``weary''\cr
+Round&\ground&{\vis\pnv\vlfw\ground}, ``now'' (Cockney)\cr
+Throat&\gthroat&{\vis\vmbw\gthroat}, ``are'' (variety of smooth Burr)\cr
+Back&\gback&{\vis\vmbw\gback}, ``are'' (variety of smooth Burr)\cr
+Back Round&\gbackround
+ &{\vis\vmbw\gbackround}, ``are'' (variety of smooth Burr)\cr
+Top&\gtop&{\vis\psv\vmbw\gtop}, ``die''\cr
+Top Round&\gtopround&{\vis\pnv\gtopround\vhmpr}, ``new'' (North Irish)\cr
+Point&\gpoint&{\vis\vlbw\gpoint}, ``are''\cr
+Point Round&\gpointround
+ &{\vis\vmbw\glipback\gpointround}, ``our'' (Common)\cr
+Lip&\glip&{\vis\pdv\glip\vhfp}, ``lui'' (French)\cr
+Lip \& Back&\glipback&{\vis\pnv\vmbw\glipback}, ``now''\cr
+}}
+\bigskip
+\centerline{\bf Modifiers}
+\medskip
+{\parindent=0pt
+\halign{#\dotfill&\hskip 1em\vis#&\ #\hfil\cr
+Inner&\minner&(Produced farther back)\cr
+Outer&\mouter&(Produced farther forward)\cr
+Close&\mclose&(More closed)\cr
+Open&\mopen&(More open)\cr
+Trill&\mtrill\cr
+Nasal&\mnasal\cr
+Side Open&\moneside&(Air escapes one side)\cr
+Side Open&\mbothsides&(Air escapes both sides)\cr
+Inverted&\minverted&(Tongue curled back)\cr
+Protruded&\mprotruded&(Tongue protruded toward lips)\cr
+Stop&\mstop\cr
+Suction&\msuction&(Produced with air moving inwards)\cr
+Emission&\memission\cr
+Suction Stopped&\msuctionstopped\cr
+Emission Stopped&\memissionstopped\cr
+Hiatus&\mhiatus\cr
+Abrupt&\mabrupt\cr
+Holder&\mholder\cr
+Accent&\maccent&(On non-initial syllable, placed to the left)\cr
+Emphasis&\memphasis&(On whole word)\cr
+Whistle&\mwhistle\cr
+Voiced Whistle&\mvwhistle\cr
+}}
+\vfill\eject
diff --git a/language/vispeech/viscons.mf b/language/vispeech/viscons.mf
new file mode 100644
index 0000000000..ecc9f89e74
--- /dev/null
+++ b/language/vispeech/viscons.mf
@@ -0,0 +1,236 @@
+% Visible speech consonants (loop-shaped characters)
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+bothvloop
+ autoloopchar;
+ rl:=t;
+ simplevloop;
+ if u=2: vvoice; fi
+ endchar;
+endfor; endfor;
+
+bothvloop
+ autoloopchar;
+ rl:=t;
+ simplevloop;
+ vclose;
+ if u=2: vvoice; fi
+ endchar;
+endfor; endfor;
+
+for t=1,2:
+autoloopchar;
+rl:="r";
+vlooppoints;
+pickup thinpen;
+draw z1..controls postcontrol 0 of p and precontrol 1 of p..z2;
+draw z4..controls postcontrol 3 of p and precontrol 4 of p..point 3.7 of p;
+cullit;
+pickup pencircle scaled 1.1thin;
+cutoff (point 3.7 of p,angle direction 3.7 of p);
+penstroke z2e..z3e{down}..z4e;
+labels(1,2,3,4,5);
+if t=2: vvoice; fi
+vsqig;
+endchar;
+
+autoloopchar;
+rl:="l";
+vlooppoints;
+pickup thinpen;
+draw point .3 of p..controls postcontrol 0 of p and precontrol 1 of p..z2;
+draw z4..controls postcontrol 3 of p and precontrol 4 of p..z5;
+cullit;
+pickup pencircle scaled 1.1thin;
+cutoff (point .3 of p,180+angle direction .3 of p);
+penstroke z2e..z3e{down}..z4e;
+labels(1,2,3,4,5);
+if t=2: vvoice; fi
+vsqig;
+endchar;
+endfor;
+
+bothhloop
+ autoloopchar;
+ tb:=t;
+ simplehloop;
+ if u=2: hvoice; fi
+ endchar;
+endfor; endfor;
+
+bothhloop
+ autoloopchar;
+ tb:=t;
+ simplehloop;
+ hclose;
+ if u=2: hvoice; fi
+ endchar;
+endfor; endfor;
+
+for t=1,2:
+autoloopchar;
+tb:="t";
+hlooppoints;
+pickup thinpen;
+draw point .3 of p..controls postcontrol 0 of p and precontrol 1 of p..z2;
+draw z4..controls postcontrol 3 of p and precontrol 4 of p..z5;
+cullit;
+pickup pencircle scaled 1.1thin;
+cutoff (point .3 of p,180+angle direction .3 of p);
+penstroke z2e..z3e{left}..z4e;
+labels(1,2,3,4,5);
+if t=2: hvoice; fi
+hsqig;
+endchar;
+
+autoloopchar;
+tb:="b";
+hlooppoints;
+pickup thinpen;
+draw z1..controls postcontrol 0 of p and precontrol 1 of p..z2;
+draw z4..controls postcontrol 3 of p and precontrol 4 of p..point 3.7 of p;
+cullit;
+pickup pencircle scaled 1.1thin;
+cutoff (point 3.7 of p,angle direction 3.7 of p);
+penstroke z2e..z3e{left}..z4e;
+labels(1,2,3,4,5);
+if t=2: hvoice; fi
+hsqig;
+endchar;
+endfor;
+
+bothvloop
+ autoloopchar;
+ rl:=t;
+ vlooppoints;
+ vcurl;
+ penstroke z2e..z3e{down}..z4e;
+ if u=2: vvoice; fi
+ labels(1,2,3,4,5,1.1,1.2,5.1,5.2);
+ endchar;
+endfor; endfor;
+
+bothhloop
+ autoloopchar;
+ tb:=t;
+ hlooppoints;
+ hcurl;
+ penstroke z2e..z3e{left}..z4e;
+ if u=2: hvoice; fi
+ labels(1,2,3,4,5,1.1,1.2,5.1,5.2);
+ endchar;
+endfor; endfor;
+
+bothvloop
+ autoloopchar;
+ rl:=t;
+ vdintpoints;
+ penstroke z1e{curl 5}..z2e..z3e{down}..z4e&
+ z4e..z5e{down}..z6e..{curl 5}z7e;
+ if u=2: vvoice; fi
+ endchar;
+endfor; endfor;
+
+bothhloop
+ autoloopchar;
+ tb:=t;
+ hdintpoints;
+ penstroke z1e{curl 5}..z2e..z3e{left}..z4e&
+ z4e..z5e{left}..z6e..{curl 5}z7e;
+ if u=2: hvoice; fi
+ labels(1,2,3,4,5,6,7);
+ endchar;
+endfor; endfor;
+
+bothvloop
+ autoloopchar;
+ rl:=t;
+ vdintpoints;
+ vcurlpoints;
+ p1:=z1.1..z1..z1.2..tension 2 and 1..z2..z3{down}..z4&
+ z4..z5{down}..z6..tension 1 and 2..z5.2..z7..z5.1;
+ penpos1.1(thin,angle direction 0 of p1 vmorp 90);
+ penpos1.2(thin,angle direction 2 of p1 vmorp 90);
+ penpos5.2(thin,angle direction 8 of p1 vmorp 90);
+ penpos5.1(thin,angle direction 10 of p1 vmorp 90);
+ x1e:=whatever; x1r:=whatever; x1l:=whatever;
+ y1e:=whatever; y1r:=whatever; y1l:=whatever;
+ x7e:=whatever; x7r:=whatever; x7l:=whatever;
+ y7e:=whatever; y7r:=whatever; y7l:=whatever;
+ penpos1(thin,angle direction 1 of p1 vmorp 90);
+ penpos7(thin,angle direction 9 of p1 vmorp 90);
+ penstroke z1.1e..z1e..z1.2e..tension 2 and 1..z2e..z3e{down}..z4e&
+ z4e..z5e{down}..z6e..tension 1 and 2..z5.2e..z7e..z5.1e;
+ labels(1,2,3,4,5,6,7,5.1,5.2,1.1,1.2);
+ if u=2: vvoice; fi
+ endchar;
+endfor; endfor;
+
+bothhloop
+ autoloopchar;
+ tb:=t;
+ hdintpoints;
+ hcurlpoints;
+ p1:=z1.1..z1..z1.2..tension 2 and 1..z2..z3{left}..z4&
+ z4..z5{left}..z6..tension 1 and 2..z5.2..z7..z5.1;
+ penpos1.1(thin,angle direction 0 of p1 - hmorp 90);
+ penpos1.2(thin,angle direction 2 of p1 - hmorp 90);
+ penpos5.2(thin,angle direction 8 of p1 - hmorp 90);
+ penpos5.1(thin,angle direction 10 of p1 - hmorp 90);
+ x1e:=whatever; x1r:=whatever; x1l:=whatever;
+ y1e:=whatever; y1r:=whatever; y1l:=whatever;
+ x7e:=whatever; x7r:=whatever; x7l:=whatever;
+ y7e:=whatever; y7r:=whatever; y7l:=whatever;
+ penpos1(thin,angle direction 1 of p1 - hmorp 90);
+ penpos7(thin,angle direction 9 of p1 - hmorp 90);
+ penstroke z1.1e..z1e..z1.2e..tension 2 and 1..z2e..z3e{left}..z4e&
+ z4e..z5e{left}..z6e..tension 1 and 2..z5.2e..z7e..z5.1e;
+ labels(1,2,3,4,5,6,7,5.1,5.2,1.1,1.2);
+ if u=2: hvoice; fi
+ endchar;
+endfor; endfor;
+
+autoloopchar;
+pickup pencircle xscaled thick yscaled fine;
+x1=x3=.5[lside,rside];
+top y1=h+curve_overshoot;
+bot y3=0-curve_overshoot;
+y2=y4=1/2h;
+rt x4=rside+curve_overshoot;
+lft x2=lside-curve_overshoot;
+draw z1..z2..z3..z4..cycle;
+labels(1,2,3,4);
+endchar;
+
+for u=1,2:
+beginchar(incr ccode,3/4loop_w#+2sidebar#,loop_h#,0);
+x1=x3=x.i1=x.i3=.5[lside,rside];
+y1=h+apex_overshoot;
+y3=0-apex_overshoot;
+y.i3-y3=y1-y.i1=3/4fine;
+y2=y4=y.i2=y.i4=1/2h;
+x4=rside+curve_overshoot;
+x2=lside-curve_overshoot;
+x4-x.i4=x.i2-x2=curve;
+fill superellipse(z4,z1,z2,z3,.655);
+cullit;
+unfill superellipse(z.i4,z.i1,z.i2,z.i3,.66);
+if u=2: pickup thickpen; draw z.i2--z.i4; fi
+labels(1,2,3,4);
+endchar;
+endfor;
+
+beginchar(incr ccode,2/3loop_w#+2sidebar#,loop_h#,10u#);
+pickup thickpen;
+y1=y2;
+top y1=h+2apex_overshoot;
+lft x1=lside;
+rt x2=rside;
+x2=x4;
+x1=x3;
+y3=y4;
+bot y4=-3apex_overshoot;
+z5=(1/2[x1,x2],1/2[y1,y3]);
+draw z1..z5..z3;
+draw z2..z5..z4;
+endchar;
diff --git a/language/vispeech/visglides.mf b/language/vispeech/visglides.mf
new file mode 100644
index 0000000000..49d8d6ba30
--- /dev/null
+++ b/language/vispeech/visglides.mf
@@ -0,0 +1,99 @@
+% Visible speech glides
+%%%%%%%%%%%%%%%%%%%%%%%%%%
+beginchar(incr ccode,3/2curve#+2sidebar#,2/3loop_h#,0);
+pickup hrazorpen;
+x.stem=1/2[lside,rside];
+draw (x.stem,0)--(x.stem,h);
+pickup smallserifpen;
+bot y1=0;
+top y2=h;
+width_serif(y1);
+width_serif(y2);
+endchar;
+
+beginchar(incr ccode,9/4curve#+2sidebar#,3/4loop_h#,0);
+pickup hrazorpen;
+fix_height;
+x.stem=1/2[lside,rside];
+draw (x.stem,0)--(x.stem,h);
+pickup penrazor scaled thin rotated 90; % thick bar here.
+draw (lside,1/2h)--(rside,1/2h);
+endchar;
+
+beginchar(incr ccode,3/2curve#+2sidebar#,loop_h#,0);
+pickup hrazorpen;
+fix_height;
+y1=h;
+y4=0;
+y1-y2=y3-y4;
+y2-y3=3/2(y1-y2);
+x.stem=1/2[lside,rside];
+draw (x.stem,y1)--(x.stem,y2);
+draw (x.stem,y3)--(x.stem,y4);
+pickup smallserifpen;
+top y5=y1;
+bot y6=y4;
+width_serif(y5);
+width_serif(y6);
+pickup pencircle scaled 2/3fine;
+lft x7=lside;
+rt x8=rside;
+draw (x8,h/2){up}..(x.stem,y2){left}..(x7,h/2){down}..
+ (x.stem,y3){right}..cycle;
+endchar;
+
+for ud=1,-1:
+for b=0,1:
+beginchar(incr ccode,2curve#+2sidebar#,
+ 2/3loop_h# if ud>0: -1/2curve# fi,
+ if ud>0: 1/2curve# else: 0 fi);
+pickup pencircle xscaled thin yscaled fine;
+ud*y3-ud*y1=5/4curve;
+if ud>0: bot else: top fi y1=if ud>0: -d+ else: h- fi 1/3fine;
+y4=if ud>0: h else: 0 fi;
+y2=1/2[y3,y1];
+if ud>0: rt else: lft fi x1=if ud>0: rside else: lside fi;
+if ud>0: lft else: rt fi x2=if ud>0: lside else: rside fi;
+x3=x4=1/2[lside,rside];
+cutdraw z1..(x3,y1-ud*1/3fine){ud*left}..z2{ud*up}...z3{ud*right}&z3--z4;
+pickup smallserifpen;
+if ud>0: top else: bot fi y5=if ud>0: h else: 0 fi;
+draw (lside,y5)--(rside,y5);
+if b=1:
+ if ud>0: bot else: top fi y6=y3 + ud*fine;
+ draw (lside,y6)--(rside,y6);
+fi
+labels (1,2,3,4,5);
+endchar;
+endfor; endfor;
+
+for ud=1,-1:
+for b=0,1:
+beginchar(incr ccode,2curve#+2sidebar#,
+ 2/3loop_h# if ud<0: -1/2curve# fi,
+ if ud<0: 1/2curve# else: 0 fi);
+if not odd (rside-lside): w:=w+1 fi;
+pickup finepen;
+lft x1=lside;
+rt x2=rside;
+y1=y2=if ud>0: h else: -d fi;
+y3=1/2[-d,h];
+x4=x3=1/2[lside,rside];
+pickup thinpen;
+if ud>0: bot else: top fi y4=if ud>0: 0 else: h fi;
+draw z3--z4; cutoff(z3,ud*90);
+cullit;
+pickup finepen;
+cutdraw z1{ud*down}..z3..{ud*up}z2;
+pickup thinpen; % redo the cutting, or there are rounding bugs.
+cutoff(z1,ud*90);
+cutoff(z2,ud*90);
+pickup smallserifpen;
+if ud>0: bot else: top fi y5=if ud>0: 0 else: h fi;
+draw (lside,y5)--(rside,y5);
+if b=1:
+ if ud>0: top else: bot fi y6=y3 - ud*fine;
+ draw (lside,y6)--(rside,y6);
+fi
+endchar;
+endfor; endfor;
diff --git a/language/vispeech/vismacs.tex b/language/vispeech/vismacs.tex
new file mode 100644
index 0000000000..a1ac553769
--- /dev/null
+++ b/language/vispeech/vismacs.tex
@@ -0,0 +1,148 @@
+% Macros for Visible Speech
+% OK, conventions: for consonants:
+% first char: b(ack) l(ip) t(op) p(oint) [f(pharynx)]
+% then: p(rimary) s(hut) n(asal) m(ixed) d(ivided) b(oth)
+% then: optionally v(oiced)
+% [throat has two primaries: p and P.]
+%%%
+% for vowels:
+% first, v for vowel.
+% then: h(igh) m(id) l(ow)
+% then: b(ack) m(ixed) f(ront)
+% then: p(rimary) w(ide)
+% then: optionally r(ound)
+%%%
+% Glides and modifiers will be separate.
+
+\def\c#1=#2.{\chardef#1='#2}
+
+\c\bp=001.
+\c\bpv=002.
+\c\lp=003.
+\c\lpv=004.
+\c\bs=005.
+\c\bsv=006.
+\c\ls=007.
+\c\lsv=010.
+\c\bn=011.
+\c\ln=012.
+\c\bnv=013.
+\c\lnv=014.
+\c\pp=015.
+\c\ppv=016.
+\c\tp=017.
+\c\tpv=020.
+\c\ps=021.
+\c\psv=022.
+\c\ts=023.
+\c\tsv=024.
+\c\pn=025.
+\c\tn=026.
+\c\pnv=027.
+\c\tnv=030.
+\c\bm=031.
+\c\bmv=032.
+\c\lm=033.
+\c\lmv=034.
+\c\pm=035.
+\c\pmv=036.
+\c\tm=037.
+\c\tmv=040.
+\c\bd=041.
+\c\bdv=042.
+\c\ld=043.
+\c\ldv=044.
+\c\pd=045.
+\c\pdv=046.
+\c\td=047.
+\c\tdv=050.
+\c\bb=051.
+\c\bbv=052.
+\c\lb=053.
+\c\lbv=054.
+\c\pb=055.
+\c\pbv=056.
+\c\tb=057.
+\c\tbv=060.
+\c\fp=061.
+\c\fP=062.
+\c\fPv=063.
+\c\fs=064.
+%%%%
+% Vowels:
+\c\vhfw=065.
+\c\vhbw=066.
+\c\vhmw=067.
+\c\vhfwr=070.
+\c\vhbwr=071.
+\c\vhmwr=072.
+\c\vlfw=073.
+\c\vlbw=074.
+\c\vlmw=075.
+\c\vlfwr=076.
+\c\vlbwr=077.
+\c\vlmwr=100.
+\c\vmfw=101.
+\c\vmbw=102.
+\c\vmmw=103.
+\c\vmfwr=104.
+\c\vmbwr=105.
+\c\vmmwr=106.
+\c\vhfp=107.
+\c\vhbp=110.
+\c\vhmp=111.
+\c\vhfpr=112.
+\c\vhbpr=113.
+\c\vhmpr=114.
+\c\vlfp=115.
+\c\vlbp=116.
+\c\vlmp=117.
+\c\vlfpr=120.
+\c\vlbpr=121.
+\c\vlmpr=122.
+\c\vmfp=123.
+\c\vmbp=124.
+\c\vmmp=125.
+\c\vmfpr=126.
+\c\vmbpr=127.
+\c\vmmpr=130.
+%%%%%%%
+% Glides
+\c\gbreath=157. % shares char with Emission mod.
+\c\gvoice=131.
+\c\ground=132.
+\c\gthroat=133.
+\c\gback=134.
+\c\gbackround=135.
+\c\glip=136.
+\c\glipback=137.
+\c\gpoint=140.
+\c\gpointround=141.
+\c\gtop=142.
+\c\gtopround=143.
+%%%%%%%
+% Modifiers
+\c\minner=144.
+\c\mouter=145.
+\c\mclose=146.
+\c\mopen=147.
+\c\mtrill=150.
+\c\mnasal=151.
+\c\moneside=152.
+\c\mbothsides=153.
+\c\minverted=154.
+\c\mprotruded=155.
+\c\mstop=156.
+\c\memission=157.
+\c\memissionstopped=160.
+\c\msuction=161.
+\c\msuctionstopped=162.
+\c\mhiatus=163.
+\c\mabrupt=164.
+\c\mholder=165.
+\c\maccent=166.
+\c\memphasis=167.
+\c\mwhistle=170.
+\c\mvwhistle=171.
+\c\mplus=172.
+%%%%%%%%%%%%
diff --git a/language/vispeech/vismods.mf b/language/vispeech/vismods.mf
new file mode 100644
index 0000000000..c232eeb36a
--- /dev/null
+++ b/language/vispeech/vismods.mf
@@ -0,0 +1,230 @@
+% Visible Speech Modifiers
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% Inner
+beginchar(incr ccode,curve#+lmodside#+rmodside#,mod_height#,0);
+pickup finepen;
+top rt z1=(rrside,h);
+bot z3=(x1,0);
+lft z2=(llside,1/2[0,h]);
+draw z1--z2..{down}z3;
+endchar;
+
+% Outer
+beginchar(incr ccode,curve#+lmodside#+rmodside#,mod_height#,0);
+pickup finepen;
+bot lft z1=(llside,0);
+top z3=(x1,h);
+rt z2=(rrside,1/2[0,h]);
+draw z1--z2..{up}z3;
+endchar;
+
+% Close, Open
+for ud=-1,1:
+beginchar(incr ccode,3/2curve#+lmodside#+rmodside#,mod_height#,0);
+fix_width;
+pickup finepen;
+lft z1=(llside,if ud>0: h else: 0 fi);
+rt z2=(rrside,y1);
+if ud>0: bot else: top fi z3=(1/2[llside,rrside],if ud>0: 0 else: h fi);
+draw z1--z3--z2;
+cutoff(z1,90*ud); cutoff(z2,90*ud);
+endchar;
+endfor;
+
+% Trill
+beginchar(incr ccode,5/4curve#+lmodside#+rmodside#,loop_h#,0);
+pickup pencircle xscaled thin yscaled 2/3fine rotated 55;
+top y1=h;
+x1=1/2[llside,rrside];
+lft x2=llside;
+rt x3=rrside;
+z3-z4=whatever*(dir 55);
+x4=1/3[llside,rrside];
+y1-y3=y4-y6;
+bot z6=(1/2[llside,rrside],0);
+showdependencies;
+vardef leftwards(expr it)=
+ xpart direction 1 of (z1..(x2,it)..{right}z3) < 0 enddef;
+y2=solve leftwards(y1,y3);
+draw z1..z2..{right}z3;
+draw z3--z4;
+rt x5=rrside;
+vardef rightwards(expr it)=
+ xpart direction 1 of (z4..(x5,it)..z6) > 0 enddef;
+y5=solve rightwards(y4,y6);
+draw z4..z5..z6;
+endchar;
+
+% Nasal
+beginchar(incr ccode,3/2curve#+lmodside#+rmodside#,loop_h#,0);
+pickup pencircle xscaled thick yscaled fine rotated 30;
+top z1=(1/2[llside,rrside],h);
+bot z4=(x1,0);
+lft x2=llside;
+rt x3=rrside;
+y1-y2=y3-y4;
+pair d[];
+d1=d4=dir (180+30);
+vardef leftwards(expr it)=
+ xpart direction 1 of (z1{d1}..(x2,h-it)..
+ (x3,it)..{d4}z4) < 0 enddef;
+y3=solve leftwards(y4,y1);
+draw z1{d1}..z2..z3..{d4}z4;
+labels(1,2,3,4);
+endchar;
+
+% Side open (1)
+beginchar(incr ccode,3/2curve#+lmodside#+rmodside#,mod_height#,0);
+pickup penrazor scaled fine;
+top lft z1=(llside,h);
+bot lft z2=(llside,0);
+top rt z3=(rrside,h);
+bot rt z4=(rrside,0);
+draw z1--z2;
+draw z3--z4;
+fill z4--(z4+(0,curve))--(z2+(0,curve))--z2--cycle;
+endchar;
+
+% Side open (2)
+beginchar(incr ccode,3/2curve#+lmodside#+rmodside#,
+ mod_height#+thin#,curve#);
+pickup penrazor scaled fine;
+top lft z1=(llside,h);
+bot lft z2=(llside,-d);
+top rt z3=(rrside,h);
+bot rt z4=(rrside,-d);
+draw z1--z2;
+draw z3--z4;
+pickup penrazor scaled 3/2curve rotated 90;
+y5=1/2[-d,h];
+draw (x1,y5)--(x3,y5);
+endchar;
+
+% Inverted/Protruded
+for ud=1,-1:
+beginchar(incr ccode,2/3loop_w#+lmodside#+rmodside#,
+ 2/3loop_h#+thick#,0);
+pickup pencircle xscaled thin yscaled slab rotated (-20*ud);
+x1=x5;
+if ud=1: rt else: lft fi x1=if ud=1: rrside else: llside fi;
+y1-y5=3/8loop_h;
+h-y1=y5-thick;
+x2=x4=wide_spot[if ud=1: llside,rrside else: rrside,llside fi];
+top y2=h+curve_overshoot;
+bot y4=thick-curve_overshoot;
+if ud=1: lft else: rt fi z3=(if ud=1: llside else: rrside fi,1/2[thick,h]);
+draw z1..{ud*left}z2..{down}z3..{ud*right}z4..z5;
+endchar;
+endfor;
+
+% Stop
+beginchar(incr ccode,thick#+lmodside#+rmodside#,
+ 1/2mod_height#,0);
+pickup thickpen;
+drawdot(1/2[llside,rrside],h);
+endchar;
+
+% Emission, and breath glide/Suction
+for ud=1,-1:
+% ...stopped/not stopped
+for st=0,1:
+beginchar(incr ccode,3/4loop_w#+lmodside#+rmodside#,2/3loop_h#,0);
+pickup thinpen;
+x1=x3;
+x1=if ud=1: llside else: rrside fi;
+if ud=1: rt else: lft fi x2=if ud=1: rrside else: llside fi;
+bot y3=0u;
+top y1=h;
+fix_height;
+y3-y2=y2-y1;
+draw z1--z2--z3;
+cutoff (z1,90+ud*90);
+cutoff (z3,90+ud*90);
+if st=1:
+ pickup thickpen;
+ if ud=1: lft else: rt fi x4=if ud=1: llside else: rrside fi;
+ y4=1/2[y1,y3];
+ drawdot z4;
+fi
+endchar;
+endfor; endfor;
+
+% Hiatus/Abrupt
+for ud=1,-1:
+beginchar(incr ccode,curve#+lmodside#+rmodside#,loop_h#,0);
+pickup finepen;
+if ud=1:
+ top lft z1=(llside,h);
+ z2=(1/2[llside,rrside],2/3h);
+ rt z3=z2+(1/2curve,0);
+else:
+ bot rt z1=(rrside,2/3h-1/2curve);
+ z2=(1/2[llside,rrside],h-1/2curve);
+ lft z3=z2-(1/2curve,0);
+fi
+fill fullcircle scaled curve shifted z2;
+draw z1..{ud*down}z3;
+endchar;
+endfor;
+
+% Holder
+beginchar(incr ccode,curve#+lmodside#+rmodside#,mod_height#,thick#);
+pickup finepen;
+top z1=(1/2[llside,rrside],h);
+bot z2=(1/2[llside,rrside],-d);
+z3=1/2[z1,z2];
+draw z1--z2;
+pickup curvepen;
+drawdot z3;
+endchar;
+
+% Accent
+beginchar(incr ccode,fine#+lmodside#+rmodside#,loop_h#+thick#,0);
+pickup finepen;
+top z1=(1/2[llside,rrside],h);
+bot z2=(x1,h-2curve);
+draw z1--z2;
+endchar;
+
+% Emphasis
+beginchar(incr ccode,fine#+lmodside#+rmodside#,curve#,curve#);
+pickup finepen;
+top z1=(1/2[llside,rrside],h);
+bot z2=(x1,-d);
+draw z1--z2;
+endchar;
+
+% Whistle/voiced whistle
+% Code similar to closed throat consonant
+for u=1,2:
+beginchar(incr ccode,loop_w#+2sidebar#,3/4loop_h#+thick#,0);
+y1=y3=y.i1=y.i3=.5[thick,h];
+x1=rside+apex_overshoot;
+x3=lside-apex_overshoot;
+x.i3-x3=x1-x.i1=3/4fine;
+x2=x4=x.i2=x.i4=1/2[lside,rside];
+y4=h+curve_overshoot;
+y2=thick-curve_overshoot;
+y4-y.i4=y.i2-y2=curve;
+fill superellipse(z1,z4,z3,z2,.655);
+cullit;
+unfill superellipse(z.i1,z.i4,z.i3,z.i2,.66);
+if u=2: pickup thickpen; draw z.i2--z.i4; fi
+labels(1,2,3,4);
+endchar;
+endfor;
+
+% Plus: simultaneous pronunciation
+beginchar(incr ccode,1/2loop_w#+2sidebar#,3/4loop_h#,0);
+pickup penrazor scaled fine;
+fix_height;
+fix_width;
+z1=(1/2[lside,rside],h);
+z2=(x1,1/4loop_h);
+z3=(lside,1/2[1/4loop_h,h]);
+z4=(rside,y3);
+draw z1--z2;
+pickup penrazor scaled fine rotated 90;
+draw z3--z4;
+endchar;
+
diff --git a/language/vispeech/vispeech.mf b/language/vispeech/vispeech.mf
new file mode 100644
index 0000000000..62f0700f23
--- /dev/null
+++ b/language/vispeech/vispeech.mf
@@ -0,0 +1,401 @@
+% Visible Speech, header file, with macros and everything.
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+mode_setup;
+
+15u#=1pt#; % Looks pretty good.
+loop_h#=loop_w#=100u#; % seem to be square
+vowel_asc#=30u#;
+vowel_d#=30u#;
+curve_overshoot#=0u#; % zero, but maybe will change.
+apex_overshoot#=4u#;
+horiz_gap#=vert_gap#=50u#; % appear equal.
+sidebar#=10u#;
+vowel_curl#=20u#;
+curve#=20u#;
+thin#=10u#;
+fine#=7u#;
+thick#=13u#;
+lmodside#=3/4sidebar#;
+rmodside#=sidebar#;
+mod_height#=7/8loop_h#;
+define_pixels(u,vowel_asc,vowel_d,loop_h,loop_w,curve_overshoot,
+ apex_overshoot,vert_gap,horiz_gap,sidebar,vowel_curl,
+ curve,thin,fine,thick,lmodside,rmodside,mod_height);
+
+wide_spot=.5; % widest point on loop, as ratio of other dim.
+voice_length=.67; % length of voicing line, as ratio.
+
+pickup pencircle scaled fine; finepen:=savepen;
+pickup pencircle scaled thin; thinpen:=savepen;
+pickup pencircle scaled thick; thickpen:=savepen;
+pickup pencircle scaled curve; curvepen:=savepen;
+pickup penrazor scaled thick; hrazorpen:=savepen;
+pickup penrazor scaled thick rotated 90; vrazorpen:=savepen;
+
+path p;
+path p[];
+string rl;
+rl="r";
+string tb;
+tb="t";
+ccode=0;
+
+vardef lside=(sidebar) enddef;
+vardef rside=(w-sidebar) enddef;
+
+def fix_width= if odd (rside-lside): w:=w+1 fi enddef;
+def fix_height= if odd (h+d): h:=h+1 fi enddef;
+
+% set string rl to "r" or "l" for gap on left or right.
+def rtorlft=if rl="r": rt else: lft fi enddef;
+def lftorrt=if rl="r": lft else: rt fi enddef;
+def zorw=if rl="r": lside else: rside fi enddef;
+def worz=if rl="r": rside else: lside fi enddef;
+def vmorp=if rl="r": - else: + fi enddef;
+
+def vlooppoints =
+fix_height;
+h-y1=y5;
+y1-y5=vert_gap;
+pickup thinpen;
+rtorlft x1=worz;
+rtorlft x5=worz;
+x2=x4=wide_spot[zorw,worz];
+top y2=h+curve_overshoot;
+bot y4=-curve_overshoot;
+pickup curvepen;
+lftorrt x3=zorw vmorp curve_overshoot;
+y3=.5h;
+p:=z1..z2..z3{down}..z4..z5;
+penpos1(thin,(angle direction 0 of p) vmorp 90);
+penpos2(thin,90);
+penpos3(curve,90 - vmorp 90);
+penpos4(thin,270);
+penpos5(thin,(angle direction 4 of p) vmorp 90);
+enddef;
+
+def simplevloop =
+vlooppoints;
+pickup thinpen;
+draw z1..controls postcontrol 0 of p and precontrol 1 of p..z2;
+draw z4..controls postcontrol 3 of p and precontrol 4 of p..z5;
+cutoff (z1,180+angle direction 0 of p);
+cutoff (z5,angle direction 4 of p);
+penstroke z2e..z3e{down}..z4e;
+labels(1,2,3,4,5);
+enddef;
+
+% set string tb to "t" or "b" for gap on top or bottom.
+def toporbot=if tb="t": top else: bot fi enddef;
+def botortop=if tb="t": bot else: top fi enddef;
+def zorh=if tb="t": 0 else: h fi enddef;
+def horz=if tb="t": h else: 0 fi enddef;
+def hmorp=if tb="t": - else: + fi enddef;
+
+def hlooppoints =
+fix_width;
+rside-x1=x5-lside;
+x1-x5=horiz_gap;
+pickup thinpen;
+toporbot y1=horz;
+toporbot y5=horz;
+y2=y4=wide_spot[zorh,horz];
+rt x2=rside+curve_overshoot;
+lft x4=lside-curve_overshoot;
+pickup curvepen;
+botortop y3=zorh hmorp curve_overshoot;
+x3=.5[lside,rside];
+p:=z1..z2..z3{left}..z4..z5;
+penpos1(thin,(angle direction 0 of p) hmorp 90);
+penpos2(thin,0);
+penpos3(curve,0 hmorp 90);
+penpos4(thin,180);
+penpos5(thin,(angle direction 4 of p) hmorp 90);
+enddef;
+
+def simplehloop =
+hlooppoints;
+pickup thinpen;
+draw z1..controls postcontrol 0 of p and precontrol 1 of p..z2;
+draw z4..controls postcontrol 3 of p and precontrol 4 of p..z5;
+cutoff (z1,180+angle direction 0 of p);
+cutoff (z5,angle direction 4 of p);
+penstroke z2e..z3e{left}..z4e;
+labels(1,2,3,4,5);
+enddef;
+
+def vsqig =
+transform vsqigtrans;
+(lside,0) transformed vsqigtrans = (rside,h);
+(lside,h) transformed vsqigtrans = (rside,0);
+(rside,0) transformed vsqigtrans = (lside,h);
+pickup thinpen;
+rt x.taga=rside;
+rt x.tagb=rside;
+top y.taga=h;
+top y.tagb=y.taga - 1/2(h-vert_gap);
+draw (z.taga--z.tagb)
+ if rl="r": else: rotatedaround(.5[(lside,0),(rside,h)],180) fi;
+pickup pencircle scaled .5[fine,thin];
+bot y.s.3=0;
+1.5*(y.s.3-y.s.2)=y.s.2-y.s.1=y.s.1-y.tagb;
+x.s.3=x.s.1+thin;
+x.s.2=x.taga+thin;
+x.s.1=x.taga-2fine;
+draw (z.tagb..z.s.1..z.s.2..z.s.3)
+ if rl="r": else: rotatedaround(.5[(lside,0),(rside,h)],180) fi;
+labels(taga,tagb,s.1,s.2,s.3)
+enddef;
+
+def hsqig =
+transform hsqigtrans;
+(lside,0) transformed hsqigtrans = (rside,h);
+(lside,h) transformed hsqigtrans = (rside,0);
+(rside,0) transformed hsqigtrans = (lside,h);
+pickup thinpen;
+top y.taga=h;
+top y.tagb=h;
+lft x.taga=lside;
+lft x.tagb=x.taga + 1/2(rside-lside-horiz_gap);
+draw (z.taga--z.tagb)
+ if tb="t": else: rotatedaround(.5[(lside,0),(rside,h)],180) fi;
+pickup pencircle scaled .5[fine,thin];
+rt x.s.3=rside+fine;
+1.5*(x.s.3-x.s.2)=x.s.2-x.s.1=x.s.1-x.tagb;
+y.s.3=y.s.1+thin;
+y.s.2=y.taga+thin;
+y.s.1=y.taga-2fine;
+draw (z.tagb..z.s.1..z.s.2..z.s.3)
+ if tb="t": else: rotatedaround(.5[(lside,0),(rside,h)],180) fi;
+labels(taga,tagb,s.1,s.2,s.3)
+enddef;
+
+def vcurlpoints =
+ x1.1=x1.2=x5.1=x5.2=x1 vmorp thin;
+ lasty:=ypart point infinity of p;
+ y1.1=y1 + 1.5thin;
+ y1.2=y1 - .5thin;
+ y5.1=lasty - 1.5thin;
+ y5.2=lasty + .5thin;
+enddef;
+
+def vcurl =
+ vcurlpoints;
+ pickup thinpen;
+ cutdraw z1.1{z1-z2}..z1..z1.2..tension 2 and 1..{vmorp right}z2;
+ cutdraw z5.1{point infinity of p-(point ((length p)-1) of p)}..
+ point infinity of p..z5.2
+ ..tension 2 and 1..{vmorp right}(point ((length p)-1) of p);
+ cullit;
+enddef;
+
+def hcurlpoints =
+ y1.1=y1.2=y5.1=y5.2=y1 hmorp thin;
+ lastx:=xpart point infinity of p;
+ x1.1=x1 + 1.7thin;
+ x1.2=x1 - .5thin;
+ x5.1=lastx - 1.7thin;
+ x5.2=lastx + .5thin;
+enddef;
+
+def hcurl =
+ hcurlpoints;
+ pickup thinpen;
+ cutdraw z1.1{z1-z2}..z1..z1.2..tension 2 and 1..{hmorp up}z2;
+ cutdraw z5.1{point infinity of p-(point ((length p)-1) of p)}..
+ point infinity of p..z5.2
+ ..tension 2 and 1..{hmorp up}(point ((length p)-1) of p);
+ cullit;
+enddef;
+
+def begloopchar(expr code) =
+beginchar(code,loop_w#+2sidebar#,loop_h#,0u#); enddef;
+
+def autoloopchar = begloopchar(incr ccode) enddef;
+
+def vvoice =
+ z.larynx=if known x7: z4 vmorp (1/2curve,0) else: z3 fi;
+ y.voice=y.larynx;
+ x.voice=voice_length[if rl="r": lside,rside else: rside,lside fi];
+ pickup vrazorpen;
+ draw z.voice--z.larynx;
+enddef;
+
+def hvoice =
+ z.larynx=if known x7: z4 hmorp (0,1/2curve) else: z3 fi;
+ x.voice=x.larynx;
+ y.voice=voice_length[if tb="t": 0,h else: h,0 fi];
+ pickup hrazorpen;
+ draw z.voice--z.larynx;
+enddef;
+
+vardef upward(expr x) =
+ ypart direction 1 of (z1{curl 5}..(x,y2)..z3{down}..z4) > 0
+enddef;
+
+def vdintpoints =
+h-y1=y7;
+y1-y7=vert_gap;
+pickup thinpen;
+rtorlft x1=worz;
+rtorlft x7=worz;
+x2=x6;
+top y2=h+curve_overshoot;
+bot y6=-curve_overshoot;
+pickup curvepen;
+lftorrt x3=zorw vmorp curve_overshoot;
+x5=x3;
+y3-y5=.5h;
+y5=1/4h;
+lftorrt x4=(zorw - vmorp 1.2curve) vmorp curve_overshoot;
+y4=.5h;
+x2=solve upward(x1,x3);
+p:=z1{curl 5}..z2..z3{down}..z4&
+ z4..z5{down}..z6..{curl 5}z7;
+penpos1(thin,(angle direction 0 of p) vmorp 90);
+penpos2(thin,90);
+penpos3(curve,90 - vmorp 90);
+penpos4(curve,90 - vmorp 90);
+penpos5(curve,90 - vmorp 90);
+penpos6(thin,270);
+penpos7(thin,(angle direction 6 of p) vmorp 90);
+enddef;
+
+
+vardef rightward(expr y) =
+ xpart direction 1 of (z1{curl 5}..(x2,y)..z3{left}..z4) > 0
+enddef;
+
+def hdintpoints =
+rside-x1=x7-lside;
+x1-x7=horiz_gap;
+pickup thinpen;
+toporbot y1=horz;
+toporbot y7=horz;
+y2=y6;
+rt x2=rside+curve_overshoot;
+lft x6=lside-curve_overshoot;
+pickup curvepen;
+botortop y3=zorh hmorp curve_overshoot;
+y5=y3;
+x3-x5=.5(rside-lside);
+x5=1/4[lside,rside];
+botortop y4=(zorh - hmorp 1.2curve) hmorp curve_overshoot;
+x4=.5[lside,rside];
+y2=solve rightward(y1,y3);
+p:=z1{curl 5}..z2..z3{left}..z4&
+ z4..z5{left}..z6..{curl 5}z7;
+penpos1(thin,(angle direction 0 of p) - hmorp 90);
+penpos2(thin,0);
+penpos3(curve,0 hmorp 90);
+penpos4(curve,0 hmorp 90);
+penpos5(curve,0 hmorp 90);
+penpos6(thin,180);
+penpos7(thin,(angle direction 6 of p) - hmorp 90);
+enddef;
+
+def vclose=
+ pickup thinpen;
+ top rtorlft z.one=(worz,h);
+ bot rtorlft z.two=(worz,0);
+ draw z.one--z.two;
+enddef;
+
+def hclose=
+ pickup thinpen;
+ lft toporbot z.one=(lside,horz);
+ rt toporbot z.two=(rside,horz);
+ draw z.one--z.two;
+enddef;
+
+def bothvloop = for t="r","l": for u=1,2: enddef;
+
+def bothhloop = for t="t","b": for u=1,2: enddef;
+
+
+full_serif=curve; % *half* the width of a full-sized serif.
+slab=fine;
+curl_w=3/2curve;
+
+pickup penrazor scaled slab rotated 90; serifpen:=savepen;
+
+def serifize(expr y) =
+ pickup serifpen;
+ draw (x.stem-full_serif,y)--(x.stem+full_serif,y);
+enddef;
+
+def roundingbar =
+ serifize(1/2[-d,h]) enddef;
+
+def vowelstem =
+ pickup hrazorpen;
+ draw (x.stem,0)--(x.stem,loop_h);
+enddef;
+
+curl_top=3/8curl_w;
+
+def widecurl(expr pt,ud,rl) =
+ % ud and rl are 1 or -1 for up and right or down and left, resp.
+ begingroup save x; save y;
+ z1=pt;
+ % allow for top or bot...
+ z2=pt+(curl_top*rl,if ud>0: vowel_asc - else: -vowel_d + fi 1/2thin);
+ % allow for lft or rt...
+ z3=pt+(curl_w*rl-1/2thin*rl,0);
+% penpos1(thick,90-ud*90);
+% penpos2(thin,-90*rl);
+% penstroke z1e{up*ud}..z2e{right*rl};
+ pickup pencircle xscaled thick yscaled thin;
+ draw z1{up*ud}..z2{right*rl};
+ pickup thinpen;
+ draw z2{right*rl}..{down*ud}z3;
+ cullit;
+ cutoff(z3,270*ud);
+ endgroup;
+enddef;
+
+def closebulb(expr pt,ud,rl) =
+ begingroup save x; save y;
+% pickup pencircle scaled 1u;
+ z1=pt-(rl*1/2thick,0);
+% z2=pt+(curl_top*rl,if ud>0: vowel_asc else: -vowel_d fi);
+% z3=pt+(curl_w*rl,fine*ud);
+% z4=z2+(-rl*1/4fine,-ud*fine);
+% z5=z1+(rl*thick,0);
+% draw z1{up*ud}..{rl*right}z2..{ud*down}z3..{ud*up}z4&
+% z4..{ud*down}z5;
+% labels(1,2,3,4,5);
+ p1:=fullcircle scaled curve shifted
+ (pt + (rl*(curl_w-1/2curve),
+ (if ud>0: vowel_asc - else: -vowel_d + fi 1/2curve)));
+ fill p1;
+ z2=point if ud>0: 2 else: 6 fi of p1;
+ z3=z1+(rl*thick,0);
+ z4=point if rl>0: 4 else: 0 fi of p1;
+ fill z1{ud*up}..{rl*right}z2--z4..z3{ud*down}--cycle;
+ endgroup;
+enddef;
+
+vardef llside=(3/4lmodside) enddef; % modifiers and breath glide
+ % are shifted left.
+vardef rrside=(w-rmodside) enddef;
+
+pickup penrazor scaled 2/3fine rotated 90; smallserifpen:=savepen;
+
+def width_serif(expr ht)= draw (lside,ht)--(rside,ht) enddef;
+
+%%%%%%%%%%%
+font_slant 0;
+font_normal_space 70u#;
+font_normal_stretch 15u#;
+font_normal_shrink 10u#;
+font_x_height loop_h#;
+font_quad loop_w#;
+font_extra_space 0;
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+input viscons;
+input visvowels;
+input visglides;
+input vismods;
+
diff --git a/language/vispeech/vispeech2.mf b/language/vispeech/vispeech2.mf
new file mode 100644
index 0000000000..8330dcc48e
--- /dev/null
+++ b/language/vispeech/vispeech2.mf
@@ -0,0 +1,404 @@
+% Visible Speech, header file, with macros and everything.
+% Input by Mark Shoulson, shoulson@ctr.columbia.edu. Please do not sell
+% this product, and please keep the header with it. Please inform me
+% if you modify this product in any way.
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+mode_setup;
+
+15u#=1pt#; % Looks pretty good.
+loop_h#=loop_w#=100u#; % seem to be square
+vowel_asc#=30u#;
+vowel_d#=30u#;
+curve_overshoot#=0u#; % zero, but maybe will change.
+apex_overshoot#=4u#;
+horiz_gap#=vert_gap#=50u#; % appear equal.
+sidebar#=10u#;
+vowel_curl#=20u#;
+curve#=20u#;
+thin#=10u#;
+fine#=7u#;
+thick#=13u#;
+lmodside#=3/4sidebar#;
+rmodside#=sidebar#;
+mod_height#=7/8loop_h#;
+define_pixels(u,vowel_asc,vowel_d,loop_h,loop_w,curve_overshoot,
+ apex_overshoot,vert_gap,horiz_gap,sidebar,vowel_curl,
+ curve,thin,fine,thick,lmodside,rmodside,mod_height);
+
+wide_spot=.5; % widest point on loop, as ratio of other dim.
+voice_length=.67; % length of voicing line, as ratio.
+
+pickup pencircle scaled fine; finepen:=savepen;
+pickup pencircle scaled thin; thinpen:=savepen;
+pickup pencircle scaled thick; thickpen:=savepen;
+pickup pencircle scaled curve; curvepen:=savepen;
+pickup penrazor scaled thick; hrazorpen:=savepen;
+pickup penrazor scaled thick rotated 90; vrazorpen:=savepen;
+
+path p;
+path p[];
+string rl;
+rl="r";
+string tb;
+tb="t";
+ccode=0;
+
+vardef lside=(sidebar) enddef;
+vardef rside=(w-sidebar) enddef;
+
+def fix_width= if odd (rside-lside): w:=w+1 fi enddef;
+def fix_height= if odd (h+d): h:=h+1 fi enddef;
+
+% set string rl to "r" or "l" for gap on left or right.
+def rtorlft=if rl="r": rt else: lft fi enddef;
+def lftorrt=if rl="r": lft else: rt fi enddef;
+def zorw=if rl="r": lside else: rside fi enddef;
+def worz=if rl="r": rside else: lside fi enddef;
+def vmorp=if rl="r": - else: + fi enddef;
+
+def vlooppoints =
+fix_height;
+h-y1=y5;
+y1-y5=vert_gap;
+pickup thinpen;
+rtorlft x1=worz;
+rtorlft x5=worz;
+x2=x4=wide_spot[zorw,worz];
+top y2=h+curve_overshoot;
+bot y4=-curve_overshoot;
+pickup curvepen;
+lftorrt x3=zorw vmorp curve_overshoot;
+y3=.5h;
+p:=z1..z2..z3{down}..z4..z5;
+penpos1(thin,(angle direction 0 of p) vmorp 90);
+penpos2(thin,90);
+penpos3(curve,90 - vmorp 90);
+penpos4(thin,270);
+penpos5(thin,(angle direction 4 of p) vmorp 90);
+enddef;
+
+def simplevloop =
+vlooppoints;
+pickup thinpen;
+draw z1..controls postcontrol 0 of p and precontrol 1 of p..z2;
+draw z4..controls postcontrol 3 of p and precontrol 4 of p..z5;
+cutoff (z1,180+angle direction 0 of p);
+cutoff (z5,angle direction 4 of p);
+penstroke z2e..z3e{down}..z4e;
+labels(1,2,3,4,5);
+enddef;
+
+% set string tb to "t" or "b" for gap on top or bottom.
+def toporbot=if tb="t": top else: bot fi enddef;
+def botortop=if tb="t": bot else: top fi enddef;
+def zorh=if tb="t": 0 else: h fi enddef;
+def horz=if tb="t": h else: 0 fi enddef;
+def hmorp=if tb="t": - else: + fi enddef;
+
+def hlooppoints =
+fix_width;
+rside-x1=x5-lside;
+x1-x5=horiz_gap;
+pickup thinpen;
+toporbot y1=horz;
+toporbot y5=horz;
+y2=y4=wide_spot[zorh,horz];
+rt x2=rside+curve_overshoot;
+lft x4=lside-curve_overshoot;
+pickup curvepen;
+botortop y3=zorh hmorp curve_overshoot;
+x3=.5[lside,rside];
+p:=z1..z2..z3{left}..z4..z5;
+penpos1(thin,(angle direction 0 of p) hmorp 90);
+penpos2(thin,0);
+penpos3(curve,0 hmorp 90);
+penpos4(thin,180);
+penpos5(thin,(angle direction 4 of p) hmorp 90);
+enddef;
+
+def simplehloop =
+hlooppoints;
+pickup thinpen;
+draw z1..controls postcontrol 0 of p and precontrol 1 of p..z2;
+draw z4..controls postcontrol 3 of p and precontrol 4 of p..z5;
+cutoff (z1,180+angle direction 0 of p);
+cutoff (z5,angle direction 4 of p);
+penstroke z2e..z3e{left}..z4e;
+labels(1,2,3,4,5);
+enddef;
+
+def vsqig =
+transform vsqigtrans;
+(lside,0) transformed vsqigtrans = (rside,h);
+(lside,h) transformed vsqigtrans = (rside,0);
+(rside,0) transformed vsqigtrans = (lside,h);
+pickup thinpen;
+rt x.taga=rside;
+rt x.tagb=rside;
+top y.taga=h;
+top y.tagb=y.taga - 1/2(h-vert_gap);
+draw (z.taga--z.tagb)
+ if rl="r": else: rotatedaround(.5[(lside,0),(rside,h)],180) fi;
+pickup pencircle scaled .5[fine,thin];
+bot y.s.3=0;
+1.5*(y.s.3-y.s.2)=y.s.2-y.s.1=y.s.1-y.tagb;
+x.s.3=x.s.1+thin;
+x.s.2=x.taga+thin;
+x.s.1=x.taga-2fine;
+draw (z.tagb..z.s.1..z.s.2..z.s.3)
+ if rl="r": else: rotatedaround(.5[(lside,0),(rside,h)],180) fi;
+labels(taga,tagb,s.1,s.2,s.3)
+enddef;
+
+def hsqig =
+transform hsqigtrans;
+(lside,0) transformed hsqigtrans = (rside,h);
+(lside,h) transformed hsqigtrans = (rside,0);
+(rside,0) transformed hsqigtrans = (lside,h);
+pickup thinpen;
+top y.taga=h;
+top y.tagb=h;
+lft x.taga=lside;
+lft x.tagb=x.taga + 1/2(rside-lside-horiz_gap);
+draw (z.taga--z.tagb)
+ if tb="t": else: rotatedaround(.5[(lside,0),(rside,h)],180) fi;
+pickup pencircle scaled .5[fine,thin];
+rt x.s.3=rside+fine;
+1.5*(x.s.3-x.s.2)=x.s.2-x.s.1=x.s.1-x.tagb;
+y.s.3=y.s.1+thin;
+y.s.2=y.taga+thin;
+y.s.1=y.taga-2fine;
+draw (z.tagb..z.s.1..z.s.2..z.s.3)
+ if tb="t": else: rotatedaround(.5[(lside,0),(rside,h)],180) fi;
+labels(taga,tagb,s.1,s.2,s.3)
+enddef;
+
+def vcurlpoints =
+ x1.1=x1.2=x5.1=x5.2=x1 vmorp thin;
+ lasty:=ypart point infinity of p;
+ y1.1=y1 + 1.5thin;
+ y1.2=y1 - .5thin;
+ y5.1=lasty - 1.5thin;
+ y5.2=lasty + .5thin;
+enddef;
+
+def vcurl =
+ vcurlpoints;
+ pickup thinpen;
+ cutdraw z1.1{z1-z2}..z1..z1.2..tension 2 and 1..{vmorp right}z2;
+ cutdraw z5.1{point infinity of p-(point ((length p)-1) of p)}..
+ point infinity of p..z5.2
+ ..tension 2 and 1..{vmorp right}(point ((length p)-1) of p);
+ cullit;
+enddef;
+
+def hcurlpoints =
+ y1.1=y1.2=y5.1=y5.2=y1 hmorp thin;
+ lastx:=xpart point infinity of p;
+ x1.1=x1 + 1.7thin;
+ x1.2=x1 - .5thin;
+ x5.1=lastx - 1.7thin;
+ x5.2=lastx + .5thin;
+enddef;
+
+def hcurl =
+ hcurlpoints;
+ pickup thinpen;
+ cutdraw z1.1{z1-z2}..z1..z1.2..tension 2 and 1..{hmorp up}z2;
+ cutdraw z5.1{point infinity of p-(point ((length p)-1) of p)}..
+ point infinity of p..z5.2
+ ..tension 2 and 1..{hmorp up}(point ((length p)-1) of p);
+ cullit;
+enddef;
+
+def begloopchar(expr code) =
+beginchar(code,loop_w#+2sidebar#,loop_h#,0u#); enddef;
+
+def autoloopchar = begloopchar(incr ccode) enddef;
+
+def vvoice =
+ z.larynx=if known x7: z4 vmorp (1/2curve,0) else: z3 fi;
+ y.voice=y.larynx;
+ x.voice=voice_length[if rl="r": lside,rside else: rside,lside fi];
+ pickup vrazorpen;
+ draw z.voice--z.larynx;
+enddef;
+
+def hvoice =
+ z.larynx=if known x7: z4 hmorp (0,1/2curve) else: z3 fi;
+ x.voice=x.larynx;
+ y.voice=voice_length[if tb="t": 0,h else: h,0 fi];
+ pickup hrazorpen;
+ draw z.voice--z.larynx;
+enddef;
+
+vardef upward(expr x) =
+ ypart direction 1 of (z1{curl 5}..(x,y2)..z3{down}..z4) > 0
+enddef;
+
+def vdintpoints =
+h-y1=y7;
+y1-y7=vert_gap;
+pickup thinpen;
+rtorlft x1=worz;
+rtorlft x7=worz;
+x2=x6;
+top y2=h+curve_overshoot;
+bot y6=-curve_overshoot;
+pickup curvepen;
+lftorrt x3=zorw vmorp curve_overshoot;
+x5=x3;
+y3-y5=.5h;
+y5=1/4h;
+lftorrt x4=(zorw - vmorp 1.2curve) vmorp curve_overshoot;
+y4=.5h;
+x2=solve upward(x1,x3);
+p:=z1{curl 5}..z2..z3{down}..z4&
+ z4..z5{down}..z6..{curl 5}z7;
+penpos1(thin,(angle direction 0 of p) vmorp 90);
+penpos2(thin,90);
+penpos3(curve,90 - vmorp 90);
+penpos4(curve,90 - vmorp 90);
+penpos5(curve,90 - vmorp 90);
+penpos6(thin,270);
+penpos7(thin,(angle direction 6 of p) vmorp 90);
+enddef;
+
+
+vardef rightward(expr y) =
+ xpart direction 1 of (z1{curl 5}..(x2,y)..z3{left}..z4) > 0
+enddef;
+
+def hdintpoints =
+rside-x1=x7-lside;
+x1-x7=horiz_gap;
+pickup thinpen;
+toporbot y1=horz;
+toporbot y7=horz;
+y2=y6;
+rt x2=rside+curve_overshoot;
+lft x6=lside-curve_overshoot;
+pickup curvepen;
+botortop y3=zorh hmorp curve_overshoot;
+y5=y3;
+x3-x5=.5(rside-lside);
+x5=1/4[lside,rside];
+botortop y4=(zorh - hmorp 1.2curve) hmorp curve_overshoot;
+x4=.5[lside,rside];
+y2=solve rightward(y1,y3);
+p:=z1{curl 5}..z2..z3{left}..z4&
+ z4..z5{left}..z6..{curl 5}z7;
+penpos1(thin,(angle direction 0 of p) - hmorp 90);
+penpos2(thin,0);
+penpos3(curve,0 hmorp 90);
+penpos4(curve,0 hmorp 90);
+penpos5(curve,0 hmorp 90);
+penpos6(thin,180);
+penpos7(thin,(angle direction 6 of p) - hmorp 90);
+enddef;
+
+def vclose=
+ pickup thinpen;
+ top rtorlft z.one=(worz,h);
+ bot rtorlft z.two=(worz,0);
+ draw z.one--z.two;
+enddef;
+
+def hclose=
+ pickup thinpen;
+ lft toporbot z.one=(lside,horz);
+ rt toporbot z.two=(rside,horz);
+ draw z.one--z.two;
+enddef;
+
+def bothvloop = for t="r","l": for u=1,2: enddef;
+
+def bothhloop = for t="t","b": for u=1,2: enddef;
+
+
+full_serif=curve; % *half* the width of a full-sized serif.
+slab=fine;
+curl_w=3/2curve;
+
+pickup penrazor scaled slab rotated 90; serifpen:=savepen;
+
+def serifize(expr y) =
+ pickup serifpen;
+ draw (x.stem-full_serif,y)--(x.stem+full_serif,y);
+enddef;
+
+def roundingbar =
+ serifize(1/2[-d,h]) enddef;
+
+def vowelstem =
+ pickup hrazorpen;
+ draw (x.stem,0)--(x.stem,loop_h);
+enddef;
+
+curl_top=3/8curl_w;
+
+def widecurl(expr pt,ud,rl) =
+ % ud and rl are 1 or -1 for up and right or down and left, resp.
+ begingroup save x; save y;
+ z1=pt;
+ % allow for top or bot...
+ z2=pt+(curl_top*rl,if ud>0: vowel_asc - else: -vowel_d + fi 1/2thin);
+ % allow for lft or rt...
+ z3=pt+(curl_w*rl-1/2thin*rl,0);
+% penpos1(thick,90-ud*90);
+% penpos2(thin,-90*rl);
+% penstroke z1e{up*ud}..z2e{right*rl};
+ pickup pencircle xscaled thick yscaled thin;
+ draw z1{up*ud}..z2{right*rl};
+ pickup thinpen;
+ draw z2{right*rl}..{down*ud}z3;
+ cullit;
+ cutoff(z3,270*ud);
+ endgroup;
+enddef;
+
+def closebulb(expr pt,ud,rl) =
+ begingroup save x; save y;
+% pickup pencircle scaled 1u;
+ z1=pt-(rl*1/2thick,0);
+% z2=pt+(curl_top*rl,if ud>0: vowel_asc else: -vowel_d fi);
+% z3=pt+(curl_w*rl,fine*ud);
+% z4=z2+(-rl*1/4fine,-ud*fine);
+% z5=z1+(rl*thick,0);
+% draw z1{up*ud}..{rl*right}z2..{ud*down}z3..{ud*up}z4&
+% z4..{ud*down}z5;
+% labels(1,2,3,4,5);
+ p1:=fullcircle scaled curve shifted
+ (pt + (rl*(curl_w-1/2curve),
+ (if ud>0: vowel_asc - else: -vowel_d + fi 1/2curve)));
+ fill p1;
+ z2=point if ud>0: 2 else: 6 fi of p1;
+ z3=z1+(rl*thick,0);
+ z4=point if rl>0: 4 else: 0 fi of p1;
+ fill z1{ud*up}..{rl*right}z2--z4..z3{ud*down}--cycle;
+ endgroup;
+enddef;
+
+vardef llside=(3/4lmodside) enddef; % modifiers and breath glide
+ % are shifted left.
+vardef rrside=(w-rmodside) enddef;
+
+pickup penrazor scaled 2/3fine rotated 90; smallserifpen:=savepen;
+
+def width_serif(expr ht)= draw (lside,ht)--(rside,ht) enddef;
+
+%%%%%%%%%%%
+font_slant 0;
+font_normal_space 70u#;
+font_normal_stretch 15u#;
+font_normal_shrink 10u#;
+font_x_height loop_h#;
+font_quad loop_w#;
+font_extra_space 0;
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+input viscons;
+input visvowels;
+input visglides;
+input vismods;
+
diff --git a/language/vispeech/visvowels.mf b/language/vispeech/visvowels.mf
new file mode 100644
index 0000000000..fda2f56950
--- /dev/null
+++ b/language/vispeech/visvowels.mf
@@ -0,0 +1,53 @@
+% Visible speech vowels.
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+for opcl=0,1:
+for bar=0,1:
+for hor=1,2,3:
+beginchar(incr ccode,3/2curve#+ if hor=3: 2 fi vowel_curl#+2sidebar#,
+ loop_h#+vowel_asc#,0);
+if hor=3: fix_width; fi
+x.stem=if hor=3: 1/2[lside,rside] elseif
+ hor=1: lside+full_serif else: rside-full_serif fi;
+vowelstem;
+pickup serifpen;
+bot y.stem=0;
+serifize(y.stem);
+if bar=1: roundingbar; fi
+if opcl=0: widecurl else: closebulb fi
+ ((x.stem,loop_h),1,if hor=1: 1 else: -1 fi);
+if hor=3: if opcl=0: widecurl else: closebulb fi((x.stem,loop_h),1,1); fi
+endchar;
+endfor;endfor;
+
+for bar=0,1:
+for hor=1,2,3:
+beginchar(incr ccode, 3/2curve#+ if hor=3: 2 fi vowel_curl#+2sidebar#,
+ loop_h#,vowel_d#);
+if hor=3: fix_width; fi
+x.stem=if hor=3: 1/2[lside,rside] elseif
+ hor=1: lside+full_serif else: rside-full_serif fi;
+vowelstem;
+pickup serifpen;
+top y.stem=h;
+serifize(y.stem);
+if bar=1: roundingbar; fi
+if opcl=0: widecurl else: closebulb fi((x.stem,0),-1,if hor=1: 1 else: -1 fi);
+if hor=3: if opcl=0: widecurl else: closebulb fi((x.stem,0),-1,1); fi
+endchar;
+endfor;endfor;
+
+for bar=0,1:
+for hor=1,2,3:
+beginchar(incr ccode, 3/2curve#+ if hor=3: 2 fi vowel_curl#+2sidebar#,
+ loop_h#+vowel_asc#,vowel_d#);
+if hor=3: fix_width; fi
+x.stem=if hor=3: 1/2[lside,rside] elseif
+ hor=1: lside+full_serif else: rside-full_serif fi;
+vowelstem;
+if bar=1: roundingbar; fi
+if opcl=0: widecurl else: closebulb fi
+ ((x.stem,loop_h),1,if hor=1: 1 else: -1 fi);
+if opcl=0: widecurl else: closebulb fi((x.stem,0),-1,if hor=2: -1 else: 1 fi);
+endchar;
+endfor;endfor;
+endfor;