blob: e1002be55e94b6d313d8e781906f54bce3ff0680 [file] [log] [blame]
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN"
"http://www.w3.org/TR/SVG/DTD/svg10.dtd" >
<svg width='100%' height='100%'
xmlns='http://www.w3.org/2000/svg'
xmlns:xlink='http://www.w3.org/1999/xlink'
onload='Init(evt)'>
<title>Phonetics Guide</title>
<desc>
An animated multimedia guide to the formation of
sounds in natural human languages, version 1.5.
Based on data from Clark and Yallop (2nd ed.).
This application was created by Douglas Alan Schepers
(doug@schepers.cc) for use in SVG-based linguistics
applications. For non-commerical purposes, you may
use or distribute this application free of charge,
provided you include this notice; for commercial
usage, please obtain a license.
All code copyright (c) D.A. Schepers, 2002-3.
</desc>
<script language='JavaScript'><![CDATA[
var SVGDocument = null;
var SVGRoot = null;
var Tongue = null;
var Palette = null;
var Jaw = null;
var VocalFolds = null;
var Cartilage = null;
//var Sound = null;
function Init(evt)
{
SVGDocument = evt.target.ownerDocument;
SVGRoot = SVGDocument.documentElement;
Tongue = SVGDocument.getElementById('tongue');
Palette = SVGDocument.getElementById('palette');
Jaw = SVGDocument.getElementById('jaw');
VocalFolds = SVGDocument.getElementById('vocalFolds');
Cartilage = SVGDocument.getElementById('CuneiformCorniculateCartilage');
//Sound = SVGDocument.getElementById('sound');
//PlaySound();
};
/*
next, I'm gonna animate the vocal chords and (top-down) and lips (front on) as well, and show air flow and air pressure gradients, all synced with the sound. if I can, anyway...
function PlaySound()
{
Sound.beginElement();
setTimeout('PlaySound()', 5000);
};
*/
function ShowPosition(evt, isShow)
{
try
{
var button = evt.target;
var buttonId = button.getAttribute('id');
var place = buttonId.split('-')[0];
var labelText = place;
var labelColor = 'gold';
if (!isShow)
{
labelColor = 'white';
place = 'rest';
}
var label = SVGDocument.getElementById(labelText + '-Label');
label.setAttributeNS(null, 'fill', labelColor);
if ('voiced' == place || 'voiceless' == place)
{
var vocalFoldsPosition = place;
if (!vocalFoldsArray[place])
{
vocalFoldsPosition = 'voiceless';
cartilagePosition = 'voiceless';
}
var vocalFoldsDesc = vocalFoldsArray[vocalFoldsPosition];
newVocalFolds = vocalFoldsDesc;
var cartilagePosition = place;
if (!cartilageArray[place])
{
cartilagePosition = 'voiceless';
}
var cartilageDesc = cartilageArray[cartilagePosition];
newCartilage = cartilageDesc;
AnimateVocalFolds();
AnimateCartilage();
}
else
{
var jawPosition = place;
if (!jawArray[place])
{
jawPosition = 'rest';
}
var jawDesc = jawArray[jawPosition];
var palettePosition = place;
if (!paletteArray[place])
{
palettePosition = 'pharyngeal';
}
var paletteDesc = paletteArray[palettePosition];
var tonguePosition = place;
if (!tongueArray[place])
{
tonguePosition = 'rest';
}
var tongueDesc = tongueArray[tonguePosition];
newTongue = tongueDesc;
AnimateTongue();
newJaw = jawDesc;
AnimateJaw();
newPalette = paletteDesc;
AnimatePalette();
}
}
catch(er)
{
alert('Error in function ShowPosition:\n' + er.message)
}
};
function AnimateMouth(mouthPart, currentPos, newPos)
{
try
{
var currentPos = mouthPart.getAttributeNS(null, 'd');
newPos = newPos.replace(/,/g, ' ');
currentPos = currentPos.replace(/,/g, ' ');
if (newPos != currentPos)
{
var changed = false;
var currentArray = currentPos.split(/\W+/);
var newArray = newPos.split(/\W+/);
for (var n = 0; currentArray.length > n; n++)
{
if (currentArray[n])
{
header = currentArray[n].match(/\D/);
eachCurrentNum = Number(currentArray[n].match(/\d+/));
eachNewNum = Number(newArray[n].match(/\d+/));
if (eachNewNum > eachCurrentNum)
{
eachCurrentNum++;
changed = true;
//alert(eachNewNum +' : ' + eachCurrentNum)
}
else if (eachNewNum < eachCurrentNum)
{
eachCurrentNum--;
changed = true;
}
currentArray[n] = header + eachCurrentNum;
}
}
var currentPos = currentArray.join(' ');
mouthPart.setAttributeNS(null, 'd', currentPos);
if (changed)
{
//alert(0)
//window.status = newPos +' :: ' + currentPos;
window.setTimeout(AnimateMouth(mouthPart, currentPos, newPos), 1000000);
}
}
}
catch(er)
{
alert('Error in function AnimateMouth:\n' + er.message)
}
};
var newTongue = null;
function AnimateTongue()
{
try
{
var currentTongue = Tongue.getAttributeNS(null, 'd');
newTongue = newTongue.replace(/,/g, ' ');
currentTongue = currentTongue.replace(/,/g, ' ');
if (newTongue != currentTongue)
{
var changed = false;
var descArray = currentTongue.split(/\W+/);
var newArray = newTongue.split(/\W+/);
for (var n = 0; descArray.length > n; n++)
{
if (descArray[n])
{
header = descArray[n].match(/\D/);
eachDescNum = Number(descArray[n].match(/\d+/));
eachNewNum = Number(newArray[n].match(/\d+/));
if (eachNewNum > eachDescNum)
{
eachDescNum++;
changed = true;
}
else if (eachNewNum < eachDescNum)
{
eachDescNum--;
changed = true;
}
descArray[n] = header + eachDescNum;
}
}
var tempDesc = descArray.join(' ');
Tongue.setAttributeNS(null, 'd', tempDesc);
if (changed)
{
window.setTimeout('AnimateTongue()', 1);
}
}
}
catch(er)
{
alert('Error in function AnimateTongue:\n' + er.message)
}
};
var newJaw = null;
function AnimateJaw()
{
try
{
var currentJaw = Jaw.getAttributeNS(null, 'd');
newJaw = newJaw.replace(/,/g, ' ');
currentJaw = currentJaw.replace(/,/g, ' ');
if (newJaw != currentJaw)
{
var changed = false;
var descArray = currentJaw.split(/\W+/);
var newArray = newJaw.split(/\W+/);
for (var n = 0; descArray.length > n; n++)
{
if (descArray[n])
{
header = descArray[n].match(/\D/);
eachDescNum = Number(descArray[n].match(/\d+/));
eachNewNum = Number(newArray[n].match(/\d+/));
if (eachNewNum > eachDescNum)
{
eachDescNum++;
changed = true;
}
else if (eachNewNum < eachDescNum)
{
eachDescNum--;
changed = true;
}
descArray[n] = header + eachDescNum;
}
}
var tempDesc = descArray.join(' ');
Jaw.setAttributeNS(null, 'd', tempDesc);
if (changed)
{
window.setTimeout('AnimateJaw()', 1);
}
}
}
catch(er)
{
alert('Error in function AnimateJaw:\n' + er.message)
}
};
var newPalette = null;
function AnimatePalette()
{
try
{
var currentPalette = Palette.getAttributeNS(null, 'd');
newPalette = newPalette.replace(/,/g, ' ');
currentPalette = currentPalette.replace(/,/g, ' ');
if (newPalette != currentPalette)
{
var changed = false;
var descArray = currentPalette.split(/\W+/);
var newArray = newPalette.split(/\W+/);
for (var n = 0; descArray.length > n; n++)
{
if (descArray[n])
{
header = descArray[n].match(/\D/);
eachDescNum = Number(descArray[n].match(/\d+/));
eachNewNum = Number(newArray[n].match(/\d+/));
if (eachNewNum > eachDescNum)
{
eachDescNum++;
changed = true;
}
else if (eachNewNum < eachDescNum)
{
eachDescNum--;
changed = true;
}
descArray[n] = header + eachDescNum;
}
}
var tempDesc = descArray.join(' ');
Palette.setAttributeNS(null, 'd', tempDesc);
if (changed)
{
window.setTimeout('AnimatePalette()', 0);
}
}
}
catch(er)
{
alert('Error in function AnimatePalette:\n' + er.message)
}
};
var newVocalFolds = null;
function AnimateVocalFolds()
{
try
{
var currentVocalFolds = VocalFolds.getAttributeNS(null, 'd');
newVocalFolds = newVocalFolds.replace(/,/g, ' ');
currentVocalFolds = currentVocalFolds.replace(/,/g, ' ');
if (newVocalFolds != currentVocalFolds)
{
var changed = false;
var descArray = currentVocalFolds.split(/\W+/);
var newArray = newVocalFolds.split(/\W+/);
for (var n = 0; descArray.length > n; n++)
{
if (descArray[n])
{
header = descArray[n].match(/\D/);
eachDescNum = Number(descArray[n].match(/\d+/));
eachNewNum = Number(newArray[n].match(/\d+/));
if (eachNewNum > eachDescNum)
{
eachDescNum++;
changed = true;
}
else if (eachNewNum < eachDescNum)
{
eachDescNum--;
changed = true;
}
descArray[n] = header + eachDescNum;
}
}
var tempDesc = descArray.join(' ');
VocalFolds.setAttributeNS(null, 'd', tempDesc);
if (changed)
{
window.setTimeout('AnimateVocalFolds()', 0);
}
}
}
catch(er)
{
alert('Error in function AnimateVocalFolds:\n' + er.message)
}
};
var newCartilage = null;
function AnimateCartilage()
{
try
{
var currentCartilage = Cartilage.getAttributeNS(null, 'd');
newCartilage = newCartilage.replace(/,/g, ' ');
currentCartilage = currentCartilage.replace(/,/g, ' ');
if (newCartilage != currentCartilage)
{
var changed = false;
var descArray = currentCartilage.split(/\W+/);
var newArray = newCartilage.split(/\W+/);
for (var n = 0; descArray.length > n; n++)
{
if (descArray[n])
{
//alert(descArray[n])
header = descArray[n].match(/\D/);
eachDescNum = Number(descArray[n].match(/\d+/));
eachNewNum = Number(newArray[n].match(/\d+/));
if ('Z' == header)
{
eachDescNum = '';
}
else if (eachNewNum > eachDescNum)
{
eachDescNum++;
changed = true;
}
else if (eachNewNum < eachDescNum)
{
eachDescNum--;
changed = true;
}
descArray[n] = header + eachDescNum;
}
}
var tempDesc = descArray.join(' ');
Cartilage.setAttributeNS(null, 'd', tempDesc);
if (changed)
{
window.setTimeout('AnimateCartilage()', 0);
}
}
}
catch(er)
{
alert('Error in function AnimateCartilage:\n' + er.message)
}
};
var tongueArray = new Array();
tongueArray['rest'] = 'M159,283 C179,254 128,235 91,243 S59,264 86,280 ';
tongueArray['dental'] = 'M159,283 C173,248 129,246 85,241 S58,259 86,280';
tongueArray['interdental'] = 'M159,283 C174,244 130,236 79,250 S67,259 86,280';
tongueArray['alveolar'] = 'M159,283 C174,244 131,254 87,242 S68,254 86,280';
tongueArray['alveopalatal'] = 'M159,283 C145,247 91,206 74,246 S103,224 86,280';
tongueArray['palatal'] = 'M159,283 C177,213 113,214 87,248 S107,247 86,280';
tongueArray['velar'] = 'M159,283 C158,162 126,236 88,249 S93,261 86,280';
tongueArray['uvular'] = 'M159,283 C183,177 147,230 94,249 S93,261 86,280';
tongueArray['pharyngeal'] = 'M159,283 C204,257 196,219 120,246 S109,261 86,280';
var jawArray = new Array();
jawArray['rest'] = 'M175,418 C152,370 155,346 177,305 S172,299 163,298 C183,273 161,277 159,282 Q117,264 86,280 Q69,283 64,270 T61,283 C49,279 54,259 38,267 S44,285 39,301 C27,352 55,341 101,340 S131,364 136,375 Q143,399 140,420';
jawArray['bilabial'] = 'M175,418 C152,370 155,346 177,305 S172,299 163,298 C183,273 161,277 159,282 Q117,264 86,280 Q69,278 64,262 T60,274 C47,273 53,251 37,256 S41,268 37,291 C26,342 55,332 101,340 S131,364 136,375 Q143,399 140,420';
jawArray['labiodental'] = 'M175,418 C152,370 155,346 177,305 S172,299 163,298 C183,273 161,277 159,282 Q117,264 86,280 Q69,278 64,262 T60,274 C47,273 70,262 49,254 S47,267 37,291 C26,342 55,332 101,340 S131,364 136,375 Q143,399 140,420';
jawArray['pharyngeal'] = 'M175,418 C152,370 155,346 177,305 S172,299 163,298 C183,273 161,277 159,282 Q117,264 88,278 Q70,298 63,280 T60,290 C48,288 54,268 38,276 S44,294 39,310 C27,361 55,350 99,349 S131,364 136,375 Q143,399 140,420';
var paletteArray = new Array();
paletteArray['rest'] = 'M30,221 C119,224 140,201 166,207 C177,223 173,245 163,228 S144,220 90,228 Q76,238 63,240 C55,243 58,261 55,256 S51,247 48,236 C44,243 48,258 34,254 S37,238 29,221';
paletteArray['glottal'] = 'M30,221 C119,224 140,201 166,207 C177,223 173,245 163,228 S144,220 90,228 Q76,238 63,240 C55,243 58,261 55,256 S51,247 48,236 C44,243 48,258 34,254 S37,238 29,221';
paletteArray['bilabial'] = 'M30,221 C118,220 140,199 175,211 C182,232 182,254 170,230 S126,225 90,228 Q76,238 63,240 C55,243 58,261 55,256 S51,247 48,236 C43,241 48,258 34,255 S36,241 29,221';
paletteArray['labiodental'] = 'M30,221 C118,220 138,193 170,203 C179,221 178,245 165,222 S126,225 90,228 Q76,238 63,240 C55,243 58,261 55,256 S51,247 48,236 C43,229 48,258 33,250 S37,238 29,221';
paletteArray['pharyngeal'] = 'M30,221 C118,220 138,193 170,203 C179,221 178,245 165,222 S126,225 90,228 Q76,238 63,240 C55,243 58,261 55,256 S51,247 48,236 C44,243 48,258 34,254 S37,238 29,221';
var vocalFoldsArray = new Array();
vocalFoldsArray['voiceless'] = 'M270,309 Q281,334 284,364 L295,360 Q291,324 275,301 H265 Q249,324 245,360 L256,364 Q259,334 270,309';
vocalFoldsArray['voiced'] = 'M270,309 Q271,334 271,371 L283,364 Q285,324 275,301 H265 Q254,324 257,364 L269,371 Q269,334 270,309';
var cartilageArray = new Array();
cartilageArray['voiceless'] = 'M225,322 L230,339 Q243,347 250,359 262,364 270,371 279,364 290,359 298,347 310,339 L314,322 320,326 315,339 Q310,354 298,364 288,378 270,374 252,378 242,364 230,354 225,339 L219,326 Z';
cartilageArray['voiced'] = 'M225,322 L230,339 Q246,351 250,359 263,359 270,371 278,359 290,359 295,351 310,339 L314,322 320,326 315,339 Q309,360 298,364 288,379 270,374 252,379 242,364 231,360 225,339 L219,326 Z';
]]></script>
<g stroke='brown' stroke-width='2' fill='pink'>
<path id='head'
d='M226,411 C190,338 201,286 182,231 C164,174 173,213 132,178 C125,172 126,153 94,160 S68,143 17,206 Q14,212 16,219 C-10,212 17,188 40,166 S36,132 46,105 C63,23 205,-9 264,13 S419,95 340,212 Q313,254 346,367 '
/>
<path id='palette'
d='M30,221 C119,224 140,201 166,207 C177,223 173,245 163,228 S144,220 90,228 Q76,238 63,240 C55,243 58,261 55,256 S51,247 48,236 C44,243 48,258 34,254 S37,238 29,221 '
/>
<path id='jaw'
d='M175,418 C152,370 155,346 177,305 S172,299 163,298 C183,273 161,277 159,282 Q117,264 86,280 Q69,283 64,270 T61,283 C49,279 54,259 38,267 S44,285 39,301 C27,352 55,341 101,340 S131,364 136,375 Q143,399 140,420 '
/>
<path id='esophagus'
d='M207,416 C205,404 198,368 193,353 C184,348 159,355 160,350 C172,344 187,346 188,345 C190,343 187,331 194,334 C197,334 208,394 212,415'
/>
<!--
<path id='esophagus'
d='M207,416 C205,404 198,368 193,353 C184,348 182,353 179,350 C172,344 187,346 188,345 C190,343 187,331 194,334 C197,334 208,394 212,415'
/>
<path id='vocalChords'
d='M184,350 L160,356 M160,352 L179,345'
fill-rule='evenodd'
/>
-->
<path id='tongue'
d='M159,283 C179,254 128,235 91,243 S59,264 86,280 '
/>
</g>
<!--
<text id='TongueText' x='-126' y='-91'>
<textPath id='tonguePath' xlink:href='#tongue' startOffset='50%'>text on path
</textPath>
</text>
<animate id='firsttpath' attributeName='startOffset' values='0%;77.5%' keyTimes='0;1' dur='20s' repeatCount='indefinite' fill='freeze'/>
-->
<circle cx='175' cy='350' r='22' stroke='gray' fill='white' opacity='0.5'/>
<circle cx='270' cy='330' r='50' stroke='gray' fill='white' opacity='0.7'/>
<line x1='166' y1='330' x2='248' y2='285' stroke='gray' fill='none' opacity='0.5' stroke-linecap='round'/>
<line x1='175' y1='372' x2='267' y2='380' stroke='gray' fill='none' opacity='0.5' stroke-linecap='round'/>
<defs>
<radialGradient id='fade'>
<stop offset='90%' stop-color='white' stop-opacity='1.0'/>
<stop offset='95%' stop-color='white' stop-opacity='0.5'/>
<stop offset='100%' stop-color='white' stop-opacity='0.0'/>
</radialGradient>
<mask id='fademask'>
<circle cx='270' cy='330' r='50' fill='url(#fade)'/>
</mask>
</defs>
<g id='phraynx' mask='url(#fademask)'>
<ellipse id='vocalBack' cx='270' cy='330' rx='44' ry='40' fill='pink'/>
<path id='gap'
d='M270,309 Q285,334 284,361
Q279,364 270,371 262,364 256,361
Q256,334 270,309'
fill='#87cefa' fill-opacity='0.5'
/>
<g fill='pink' fill-rule='evenodd' stroke='brown' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'>
<path id='vocalFolds'
d='M270,309 Q281,334 284,364
L295,360 Q291,324 275,301
H265 Q249,324 245,360
L256,364 Q259,334 270,309'
fill='white' stroke='#ff6347'
/>
<path id='CuneiformCorniculateCartilage'
d='M225,322 L230,339
Q243,347 250,359 262,364 270,371 279,364 290,359 298,347 310,339
L314,322 320,326 315,339
Q310,354 298,364 288,378 270,374 252,378 242,364 230,354 225,339
L219,326 Z'
fill='#eee8aa' stroke='#daa520'
/>
<path id='oddThing'
d='M250,299 Q270,319 290,299'
/>
<path id="epiglottis"
d='M215,327 C238,324 243,302 270,300 297,302 302,324 325,327 V324
C301,321 310,278 270,289 230,278 241,321 215,324 Z'
/>
</g>
</g>
<g stroke='blue' fill='cornflowerblue'
onmouseover='ShowPosition(evt, true)'
onmouseout='ShowPosition(evt, false)'>
<rect id='bilabial-Button' x='400' y='10' width='100' height='20' rx='5' ry='5'/>
<rect id='labiodental-Button' x='400' y='40' width='100' height='20' rx='5' ry='5'/>
<rect id='dental-Button' x='400' y='70' width='100' height='20' rx='5' ry='5'/>
<rect id='interdental-Button' x='400' y='100' width='100' height='20' rx='5' ry='5'/>
<rect id='alveolar-Button' x='400' y='130' width='100' height='20' rx='5' ry='5'/>
<rect id='alveopalatal-Button' x='400' y='160' width='100' height='20' rx='5' ry='5'/>
<rect id='palatal-Button' x='400' y='190' width='100' height='20' rx='5' ry='5'/>
<rect id='velar-Button' x='400' y='220' width='100' height='20' rx='5' ry='5'/>
<rect id='uvular-Button' x='400' y='250' width='100' height='20' rx='5' ry='5'/>
<rect id='pharyngeal-Button' x='400' y='280' width='100' height='20' rx='5' ry='5'/>
<rect id='glottal-Button' x='400' y='310' width='100' height='20' rx='5' ry='5'/>
<rect id='voiced-Button' x='400' y='370' width='100' height='20' rx='5' ry='5'/>
<rect id='voiceless-Button' x='400' y='400' width='100' height='20' rx='5' ry='5'/>
</g>
<g fill='white' pointer-events='none' text-anchor='middle' font-size='14px'>
<text id='bilabial-Label' x='450' y='25'>Bilabial</text>
<text id='labiodental-Label' x='450' y='55'>Labiodental</text>
<text id='dental-Label' x='450' y='85'>Dental</text>
<text id='interdental-Label' x='450' y='115'>Interdental</text>
<text id='alveolar-Label' x='450' y='145'>Alveolar</text>
<text id='alveopalatal-Label' x='450' y='175'>Alveopalatal</text>
<text id='palatal-Label' x='450' y='205'>Palatal</text>
<text id='velar-Label' x='450' y='235'>Velar</text>
<text id='uvular-Label' x='450' y='265'>Uvular</text>
<text id='pharyngeal-Label' x='450' y='295'>Pharyngeal</text>
<text id='glottal-Label' x='450' y='325'>Glottal</text>
<text id='voiced-Label' x='450' y='385'>Voiced</text>
<text id='voiceless-Label' x='450' y='415'>Voiceless</text>
</g>
<!--
<asv='audio id='sound' xlink='href='bilabialClick.mp3' begin='indefinite' />
-->
</svg>