├── .gitignore ├── README.md ├── config └── config.go ├── demos ├── Guess Number.bat ├── demo1.bat ├── demo2.bat ├── demo3.bat ├── demo4.bat ├── demo5.bat ├── demo6.bat ├── demo7.bat ├── demo8.bat ├── demo9.bat ├── demoA.bat ├── demoB.bat ├── demoC.bat └── demoD.bat ├── demos_bash ├── demo1.sh ├── demo2.sh ├── demo3.sh ├── demo4.sh ├── demo5.sh ├── demo6.sh ├── demo7.sh ├── demo8.sh ├── demo9.sh ├── demoA.sh ├── demoB.sh ├── demoC.sh └── demoD.sh ├── go.mod ├── go.sum ├── main.go ├── reciter ├── reciter.go ├── tabs.go └── util.go ├── render ├── createtransitions.go ├── processframes.go ├── render.go └── tabs.go └── sammain ├── sam.go └── tabs.go /.gitignore: -------------------------------------------------------------------------------- 1 | *.wav 2 | *.mp3 3 | .vscode/ 4 | sam 5 | debug 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | SAM 2 | === 3 | 4 | Software Automatic Mouth - Tiny Speech Synthesizer 5 | 6 | This is a Go port of the great SAM speech synthesizer. It's basically a semi-automatic rewrite from C to Go of what was, in turn, a semi-automatic rewrite from Assembly to C :). Consequently, this is not meant to be readable. 7 | 8 | 9 | Original repo: https://github.com/vidarh/SAM. Based on [this commit](https://github.com/vidarh/SAM/commit/8a8219e2cfef5f4ec5db2af55470e8d402937fea). 10 | 11 | Why port this to go? 12 | -------------------- 13 | 14 | As a challenge and just for fun. 15 | 16 | ----------------------------- 17 | 18 | Original README 19 | =============== 20 | 21 | What is SAM? 22 | ============ 23 | 24 | Sam is a very small Text-To-Speech (TTS) program written in C, that runs on most popular platforms. 25 | It is an adaption to C of the speech software SAM (Software Automatic Mouth) for the Commodore C64 published 26 | in the year 1982 by Don't Ask Software (now SoftVoice, Inc.). It includes a Text-To-Phoneme converter called reciter and a Phoneme-To-Speech routine for the 27 | final output. It is so small that it will work also on embedded computers. On my computer it takes 28 | less than 39KB (much smaller on embedded devices as the executable-overhead is not necessary) of disk space and is a fully stand alone program. 29 | For immediate output it uses the SDL-library, otherwise it can save .wav files. 30 | 31 | An online version and executables for Windows can be found on the web site: http://simulationcorner.net/index.php?page=sam 32 | 33 | Compile 34 | ======= 35 | 36 | Simply type "make" in your command prompt. 37 | In order to compile without SDL remove the SDL statements from the CFLAGS and LFLAGS variables in the file "Makefile". 38 | 39 | It should compile on every UNIX-like operating system. For Windows you need Cygwin or MinGW( + libsdl). 40 | 41 | 42 | Usage 43 | ===== 44 | 45 | type 46 | 47 | ./sam I am Sam 48 | 49 | for the first output. 50 | 51 | If you have disabled SDL try 52 | 53 | ./sam -wav i_am_sam.wav I am Sam 54 | 55 | to get a wav file. This file can be played by many media players available for the PC. 56 | 57 | you can try other options like 58 | -pitch number 59 | -speed number 60 | -throat number 61 | -mouth number 62 | 63 | Some typical values written in the original manual are: 64 | 65 | DESCRIPTION SPEED PITCH THROAT MOUTH 66 | Elf 72 64 110 160 67 | Little Robot 92 60 190 190 68 | Stuffy Guy 82 72 110 105 69 | Little Old Lady 82 32 145 145 70 | Extra-Terrestrial 100 64 150 200 71 | SAM 72 64 128 128 72 | 73 | 74 | It can even sing 75 | look at the file "sing" 76 | for a small example. 77 | 78 | For the phoneme input table look in the Wiki. 79 | 80 | 81 | A description of additional features can be found in the original manual at 82 | http://www.retrobits.net/atari/sam.shtml 83 | or in the manual of the equivalent Apple II program 84 | http://www.apple-iigs.info/newdoc/sam.pdf 85 | 86 | 87 | Adaption To C 88 | ============= 89 | 90 | This program was converted semi-automatic into C by converting each assembler opcode. 91 | e. g. 92 | 93 | lda 56 => A = mem[56]; 94 | jmp 38018 => goto pos38018; 95 | inc 38 => mem[38]++; 96 | . . 97 | . . 98 | 99 | Then it was manually rewritten to remove most of the 100 | jumps and register variables in the code and rename the variables to proper names. 101 | Most of the description below is a result of this rewriting process. 102 | 103 | Unfortunately its still a not very good readable. But you should see where I started :) 104 | 105 | 106 | 107 | Short description 108 | ================= 109 | 110 | First of all I will limit myself here to a very coarse description. 111 | There are very many exceptions defined in the source code that I will not explain. 112 | Also a lot of code is unknown for me e. g. Code47503. 113 | For a complete understanding of the code I need more time and especially more eyes have a look on the code. 114 | 115 | Reciter 116 | ------- 117 | 118 | It changes the english text to phonemes by a ruleset shown in the wiki. 119 | 120 | The rule 121 | " ANT(I)", "AY", 122 | means that if he find an "I" with previous letters " ANT", exchange the I by the phoneme "AY". 123 | 124 | There are some special signs in this rules like 125 | # 126 | & 127 | @ 128 | ^ 129 | + 130 | : 131 | % 132 | which can mean e. g. that there must be a vocal or a consonant or something else. 133 | 134 | With the -debug option you will get the corresponding rules and the resulting phonemes. 135 | 136 | 137 | Output 138 | ------ 139 | 140 | Here is the full tree of subroutine calls: 141 | 142 | SAMMain() 143 | Parser1() 144 | Parser2() 145 | Insert() 146 | CopyStress() 147 | SetPhonemeLength() 148 | Code48619() 149 | Code41240() 150 | Insert() 151 | Code48431() 152 | Insert() 153 | 154 | Code48547 155 | Code47574 156 | Special1 157 | Code47503 158 | Code48227 159 | 160 | 161 | SAMMain() is the entry routine and calls all further routines. 162 | Parser1 transforms the phoneme input and transforms it to three tables 163 | phonemeindex[] 164 | stress[] 165 | phonemelength[] (zero at this moment) 166 | 167 | This tables are now changed: 168 | 169 | Parser2 exchanges some phonemes by others and inserts new. 170 | CopyStress adds 1 to the stress under some circumstances 171 | SetPhonemeLength sets phoneme lengths. 172 | Code48619 changes the phoneme lengths 173 | Code41240 adds some additional phonemes 174 | Code48431 has some extra rules 175 | 176 | 177 | The wiki shows all possible phonemes and some flag fields. 178 | The final content of these tables can be seen with the -debug command. 179 | 180 | 181 | In the function PrepareOutput() these tables are partly copied into the small tables: 182 | phonemeindexOutput[] 183 | stressOutput[] 184 | phonemelengthOutput[] 185 | for output. 186 | 187 | Final Output 188 | ------------ 189 | 190 | Except of some special phonemes the output is build by a linear combination: 191 | 192 | A = A1 * sin ( f1 * t ) + 193 | A2 * sin ( f2 * t ) + 194 | A3 * rect( f3 * t ) 195 | 196 | where rect is a rectangular function with the same periodicity like sin. 197 | It seems really strange, but this is really enough for most types of phonemes. 198 | 199 | Therefore the above phonemes are converted with some tables to 200 | pitches[] 201 | frequency1[] = f1 202 | frequency2[] = f2 203 | frequency3[] = f3 204 | amplitude1[] = A1 205 | amplitude2[] = A2 206 | amplitude3[] = A3 207 | 208 | Above formula is calculated in one very good omptimized routine. 209 | It only consist of 26 commands: 210 | 211 | 48087: LDX 43 ; get phase 212 | CLC 213 | LDA 42240,x ; load sine value (high 4 bits) 214 | ORA TabAmpl1,y ; get amplitude (in low 4 bits) 215 | TAX 216 | LDA 42752,x ; multiplication table 217 | STA 56 ; store 218 | 219 | LDX 42 ; get phase 220 | LDA 42240,x ; load sine value (high 4 bits) 221 | ORA TabAmpl2,y ; get amplitude (in low 4 bits) 222 | TAX 223 | LDA 42752,x ; multiplication table 224 | ADC Var56 ; add with previous values 225 | STA 56 ; and store 226 | 227 | LDX 41 ; get phase 228 | LDA 42496,x ; load rect value (high 4 bits) 229 | ORA TabAmpl3,y ; get amplitude (in low 4 bits) 230 | TAX 231 | LDA 42752,x ; multiplication table 232 | ADC 56 ; add with previous values 233 | 234 | ADC #136 235 | LSR A ; get highest 4 bits 236 | LSR A 237 | LSR A 238 | LSR A 239 | STA 54296 ;SID main output command 240 | 241 | 242 | The rest is handled in a special way. At the moment I cannot figure out in which way. 243 | But it seems that it uses some noise (e. g. for "s") using a table with random values. 244 | 245 | License 246 | ======= 247 | 248 | The software is a reverse-engineered version of a commercial software published more than 30 years ago. 249 | The current copyright holder is SoftVoice, Inc. (www.text2speech.com) 250 | 251 | Any attempt to contact the company failed. The website was last updated in the year 2009. 252 | The status of the original software can therefore best described as Abandonware 253 | (http://en.wikipedia.org/wiki/Abandonware) 254 | 255 | As long this is the case I cannot put my code under any specific open source software license 256 | Use it at your own risk. 257 | 258 | 259 | 260 | Contact 261 | ======= 262 | 263 | If you have questions don' t hesitate to ask me. 264 | If you discovered some new knowledge about the code please mail me. 265 | 266 | Sebastian Macke 267 | Email: sebastian@macke.de 268 | -------------------------------------------------------------------------------- /config/config.go: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | type Config struct { 4 | Speed byte `arg:"-s" help:"set speed value"` 5 | Pitch byte `arg:"-p" help:"set pitch value"` 6 | Mouth byte `arg:"-m" help:"set mouth value"` 7 | Throat byte `arg:"-t" help:"set throat value"` 8 | Sing bool `arg:"-S" help:"enable singing mode (special treatment of pitch)"` 9 | Debug bool `arg:"-D" help:"print additional debug messages"` 10 | } 11 | 12 | func DefaultConfig() *Config { 13 | return &Config{ 14 | Speed: 72, 15 | Pitch: 64, 16 | Mouth: 128, 17 | Throat: 128, 18 | Sing: false, 19 | Debug: false, 20 | } 21 | } 22 | 23 | func (с *Config) SetSpeed(_speed byte) { 24 | с.Speed = _speed 25 | } 26 | func (с *Config) SetPitch(_pitch byte) { 27 | с.Pitch = _pitch 28 | } 29 | func (с *Config) SetMouth(_mouth byte) { 30 | с.Mouth = _mouth 31 | } 32 | func (с *Config) SetThroat(_throat byte) { 33 | с.Throat = _throat 34 | } 35 | func (с *Config) EnableSingmode() { 36 | с.Sing = true 37 | } 38 | -------------------------------------------------------------------------------- /demos/Guess Number.bat: -------------------------------------------------------------------------------- 1 | cd .. 2 | @echo off 3 | rem color 0a 4 | 5 | :MAIN 6 | cls 7 | set number=%random:~0,2% 8 | rem goto WINNER 9 | ping localhost -n 1 >nul 10 | echo Sam's NUMBER GUESSING GAME! 11 | SAM "Sam's NUMBER GUESSING GAME!" 12 | ping localhost -n 1 >nul 13 | echo. 14 | ping localhost -n 1 >nul 15 | echo. 16 | ping localhost -n 1 >nul 17 | echo. 18 | ping localhost -n 1 >nul 19 | echo It's easy to play! 20 | SAM "It's easy to play!" 21 | ping localhost -n 1 >nul 22 | echo. 23 | ping localhost -n 1 >nul 24 | echo The computer generates a number between 1 and 100, and you try to guess it! 25 | SAM "The computer generates a number between 1 and one hundred, and you try to guess it!" 26 | ping localhost -n 1 >nul 27 | echo. 28 | ping localhost -n 1 >nul 29 | echo. 30 | ping localhost -n 1 >nul 31 | echo. 32 | echo "To begin the game, type your name and press Enter": 33 | SAM "To begin the game, type your name and press Enter": 34 | set /p web= 35 | :HOME 36 | cls 37 | echo Well %web% Now GUESS THE NUMBER! 38 | SAM Well 39 | SAM %web% 40 | SAM "Now GUESS THE NUMBER!" 41 | echo. 42 | echo. 43 | set /p guess= 44 | echo 45 | if %guess% LSS %number% goto LOWER 46 | if %guess% GTR %number% goto HIGHER 47 | if %guess% EQU %number% goto WINNER 48 | :LOWER 49 | cls 50 | echo Your guess is lower than the number! 51 | SAM "Your guess is lower than the number!" 52 | echo. 53 | echo. 54 | pause 55 | goto HOME 56 | :HIGHER 57 | cls 58 | echo Your guess is higher than the number! 59 | SAM "Your guess is higher than the number!" 60 | echo. 61 | echo. 62 | pause 63 | goto HOME 64 | :WINNER 65 | cls 66 | echo. 67 | SAM -speed 55 -pitch 92 -throat 128 -mouth 128 "Ha ha ha ha ha ha ha? Ha ha ha ha ha ha ha!" 68 | echo Congratulations %web%! You guessed the number correctly! 69 | SAM "Congratulations" 70 | SAM %web%! 71 | SAM "You guessed the number correctly!" 72 | echo. 73 | echo. 74 | echo The number was %number% 75 | SAM "The number was" 76 | SAM %number% 77 | echo Thanks for playing! 78 | SAM "Thanks for playing?" 79 | SAM %web%! 80 | SAM "Thanks for playing." 81 | ping localhost -n 2 >nul 82 | exit 83 | -------------------------------------------------------------------------------- /demos/demo1.bat: -------------------------------------------------------------------------------- 1 | cd .. 2 | sam -debug to bee or not to bee, that is the question 3 | sam -phonetic "MAY4 NEYM IHZ SAE4M." -------------------------------------------------------------------------------- /demos/demo2.bat: -------------------------------------------------------------------------------- 1 | cd .. 2 | 3 | sam -pitch 64 -speed 72 -phonetic "/HEH4LOW DHEHR. YUW4 NOW MIY4Y, AY4 AEM SAE5M," 4 | sam -pitch 64 -speed 72 -phonetic "DHAH SAO4FTWEHR MAW5TH" 5 | sam -pitch 64 -speed 72 -phonetic "FOHR YOHR KAA4MIXDOH6R SIH4KSTIYFOH6R KUMPYUW4TER." 6 | sam -pitch 64 -speed 72 -phonetic "AY4 KUHD AO4LWEYZ DUW LAA3TS AHV AHMEY4ZIHNX THIHNXGZ." 7 | sam -pitch 64 -speed 35 -phonetic "AY5 KUHD TAO5K VEH4RIY KWIH4KLIY WHEHN AY WAA4NTIHD." 8 | sam -pitch 64 -speed 140 -phonetic "AE4ND AY KUHD TAO4K VEH3RIY SLOW4LIY TUW." 9 | sam -pitch 30 -speed 72 -phonetic "AY5 KUHD SPIY5K IHNAH VEH3RIY /HAY5 VOYS." 10 | sam -pitch 169 -speed 72 -phonetic "AE4ND AY KUHD SPIY5K RIY3L LOW." 11 | sam -pitch 64 -speed 72 -phonetic "BAHT NAW4 AY KAEN DUW5 SAH4MPTHIHNX IY5VUN MOH4R AHMEY3ZIHNX." 12 | 13 | sam -mouth 110 -throat 160 -pitch 64 -speed 72 -phonetic "AY4 KAEN CHEY4NJ MAY VOY5S KUMPLIY3TLIY.Q." 14 | sam -mouth 110 -throat 160 -pitch 64 -speed 72 -phonetic "AY4 KAEN BIY5 AH LIH4TUL EH5LF /HUW TAO5KS LAYK DHIH5S. OH3R." 15 | 16 | sam -mouth 190 -throat 190 -pitch 60 -speed 42 -phonetic "AY5 KAEN BIHKAH5M AH STREY4NJ EY4LIYUN." 17 | sam -mouth 190 -throat 190 -pitch 60 -speed 42 -phonetic "YUW5 KAEN YUW4Z DHIHS VOY5S IHN AH SPEY4S GEY5M." 18 | 19 | sam -mouth 110 -throat 105 -pitch 72 -speed 82 -phonetic "OHR /HAW5 AHBAW5T DHIH3S STAH4FIY LIH5TUL KEH4RIXKTER." 20 | sam -mouth 110 -throat 105 -pitch 72 -speed 82 -phonetic "EY SIH4LIY VOY5S FOHR AH KUMPYUW4TER." 21 | 22 | sam -mouth 145 -throat 145 -pitch 32 -speed 72 -phonetic "AY5 KAEN TAO5K LAYK AH LIH5TUL OH5LD LEY5DIY." 23 | sam -mouth 145 -throat 145 -pitch 32 -speed 72 -phonetic "NAAT MEH5NIY KUMPYUW5TERZ KAEN DUW DHIH4S - SWIY5TIY." 24 | 25 | sam -mouth 128 -throat 128 -pitch 64 -speed 72 -phonetic "AE4ND AEZ AH MAE5TER AHV FAE4KT," 26 | sam -mouth 128 -throat 128 -pitch 64 -speed 72 -phonetic "AY4 KAEN BIYKAH5M DHAX LEY4TIXST MUW4VIY /HIY4ROW - AEND SEH8EY4," 27 | 28 | sam -mouth 150 -throat 200 -pitch 58 -speed 120 -phonetic "IY4IY6 TTIY6 -FOW5N /HOW5MM. IY4IY6 TTIY6 - FOW5N /HOW5MM." 29 | 30 | sam -mouth 128 -throat 128 -pitch 64 -speed 72 -phonetic "DHEH4RZ NOW4 TEH5LIHNX WHAH5T SAE5M WIHL DUW NEH5KST." 31 | -------------------------------------------------------------------------------- /demos/demo3.bat: -------------------------------------------------------------------------------- 1 | cd .. 2 | sam -pitch 64 -speed 74 -phonetic "/HEHLOW3 EH5VRIXWAHN. IHT SHUH4R IHZ NAY3S - TAX BIY /HIY4R TUH7DEY." 3 | sam -pitch 64 -speed 74 -phonetic "AY3 AEM SAE4M -" 4 | sam -pitch 64 -speed 74 -phonetic "DHAX BRAE4ND NUW5 VOY4S FOHR DHAX KAA4MIXDOH6R" 5 | sam -pitch 64 -speed 74 -phonetic "SIH4KSTIYFOH6R KUMPYUW4TER." 6 | sam -pitch 64 -speed 74 -phonetic "AY4 AEM DHAX MOW5ST VER4SIXTUL -" 7 | sam -pitch 64 -speed 74 -phonetic "AH5NDERSTAE4NDIXBUL SPIY5CH SIH3NTHAXSAY7ZER" 8 | sam -pitch 64 -speed 74 -phonetic "AAN DHAX MAA3RKIXT." 9 | sam -pitch 64 -speed 74 -phonetic "AE4AE7ND- AY4 AEM DHAX LOHOW4EHST PRAY4ST- AHV DHEHM AO4UL." 10 | sam -pitch 64 -speed 74 -phonetic "BAH6T WHAH4T KAEN YUW DUW3 WHIHTH MIYIY." 11 | sam -pitch 64 -speed 74 -phonetic "WAY7 YUW3 KAEN PUH5T MIY-IH5NTUX YOHR OW7N PROH3GRAEMZ." 12 | sam -pitch 64 -speed 74 -phonetic "/HAW4 WUHD YUW4 LAYK YOHR BIH3ZNIXS SAO5FTWEHR TUX SEY-" 13 | sam -pitch 64 -speed 74 -phonetic "PLIY4Z EH5NTER DHIH4S WIY6KS PER3CHAHSIXZ." 14 | sam -pitch 64 -speed 74 -phonetic "OH3ER- IHMAE3JIXN AEN EHDVEH4NCHER GEY6M DHAET DAH6Z DHIH4S." 15 | sam -pitch 64 -speed 74 -phonetic "DHIY EH3LF WAHZ KAE3PCHERD-BAY DHAX JAY3IXNT." 16 | sam -pitch 64 -speed 74 -phonetic "/HIY BIHGAE5N TUX KRAA3IY-AEND /HIY SEH4D." 17 | 18 | sam -pitch 31 -speed 72 -phonetic "OH5OW7 NAX5OW. PLIY5Z DOWNT /HER5T MIY-MIH6STER JAYIXNT?" 19 | 20 | sam -pitch 64 -speed 76 -phonetic "BAH6T DHAX JAY4IXNT WAHZ VEH3RIY MIY6N-" 21 | sam -pitch 64 -speed 76 -phonetic "AEND /HIY4 OW3NLIY SEHD-" 22 | 23 | sam -pitch 120 -speed 80 -phonetic "/HOW2- /HOW4- /HOW." 24 | 25 | sam -pitch 64 -speed 72 -phonetic "DHEH5R IHZ NOW LIH3MIXT-TUX DHAX PAA4SAXBUL AE5PLIXKEY3SHUNZ-" 26 | sam -pitch 64 -speed 72 -phonetic "AHV SPIY4CH IHN YOH7R PROH3GRAEMZ." 27 | sam -pitch 64 -speed 72 -phonetic "AO3LSOW7W3- AY4 AEM VEH3RIY IY4ZIY TUX YUW4Z." 28 | sam -pitch 64 -speed 72 -phonetic "EH2NIYWAH6N KAEN AE5DSPIY5CH-TUX6 AH BEY4SIHKQPROH4GRAEM." 29 | sam -pitch 64 -speed 72 -phonetic "AY4 KAEN IY3VIXN TAOK VEH4RIY KWIH4KLIY." 30 | sam -pitch 64 -speed 72 -phonetic "LIH4SUN TUX6 DHIH3S WAHN." 31 | 32 | sam -speed 30 -phonetic "PIY4TER PAY3PER- PIH4KT AH PEH4K AHV PIH4KULD PEH4PERZ." 33 | 34 | sam -speed 28 -phonetic "/HAW3 MEHNIY PEH4KS AHV PIH4KULD PEH4PERZ-DIHD PIY4TER PAY3PER PIH6K." 35 | 36 | sam -speed 100 -phonetic "QQQQ WWAW7IY1IY3IY. DHAE3T WHAHZ AH TAH4FIY." 37 | 38 | sam -speed 72 -phonetic "EH2NIYWEY6- YUW4 GEHT DHIY AYDIY5AH." 39 | sam -speed 72 -phonetic "SAE3M IHZ DHIY MOW3STEHKSAY4TIHNX NUW4 PRAA4DAHKT - AHV DHIHS YIY4R." 40 | sam -speed 72 -phonetic "SOH3OW7-/HAW4AHBAW3T IHT. WOH3NT YUW PLIY2Z TEY6KMIY /HOW6M?" 41 | sam -speed 72 -phonetic "Q SAE4M IHZ /HIY3R TUX STEY4IY." 42 | sam -speed 72 -phonetic "THAE2NXKS FOHR LIH4SUNIHNX EHVRIXBAH5DIY." 43 | sam -speed 72 -phonetic "AY /HOW3P YUW EHNJOY4D-MAYLIH4TUL TAOK." 44 | 45 | -------------------------------------------------------------------------------- /demos/demo4.bat: -------------------------------------------------------------------------------- 1 | cd .. 2 | sam Four score and seven years ago. 3 | sam Our fathers brought forth on this continent, a new nation. 4 | sam Conceived in Libberty. And dedicated to the prop-position that all men are created equal. 5 | 6 | sam Now we are engaged in a great civvil war! Testing whether that nation, or any nation. 7 | sam So conceived, and so dedicated, can long endure. 8 | -------------------------------------------------------------------------------- /demos/demo5.bat: -------------------------------------------------------------------------------- 1 | cd .. 2 | 3 | sam -mouth 110 -throat 160 -pitch 64 -speed 72 -phonetic "AY4 KAEN CHEY4NJ MAY VOY5S KUMPLIY3TLIY.Q." 4 | 5 | sam -mouth 150 -throat 200 -pitch 58 -speed 120 "Eee Tea! Phone home." 6 | sam -mouth 150 -throat 200 -pitch 58 -speed 120 "Eee Tea? Phone home?" 7 | 8 | sam -mouth 150 -throat 200 -pitch 58 -speed 140 "Ha ha ha ha ha ha ha!" 9 | sam -mouth 150 -throat 100 -pitch 58 -speed 140 "Ha ha ha ha ha ha ha?" 10 | 11 | sam -speed 140 -pitch 64 -throat 110 -mouth 160 "Ho ha ha ha!" 12 | sam -speed 140 -pitch 60 -throat 190 -mouth 190 "Ha ha ha ha ha ha ha?" 13 | 14 | sam -speed 140 -pitch 72 -throat 110 -mouth 105 "He he ha ha he he ha!" 15 | sam -speed 140 -pitch 32 -throat 145 -mouth 145 "Ha ha ho he he ha?" 16 | 17 | sam -speed 140 -pitch 64 -throat 150 -mouth 200 "Ha ha ho ho ha ho?" 18 | sam -speed 35 -pitch 92 -throat 128 -mouth 128 "Ha ha ha ha ha ha ha? Ha ha ha ha ha ha ha!" 19 | 20 | sam That's not funny. 21 | 22 | -------------------------------------------------------------------------------- /demos/demo6.bat: -------------------------------------------------------------------------------- 1 | cd .. 2 | sam Hello my name is SAM. 3 | sam I will sing the national anthem of the united states of America. 4 | sam The star spangled banner! 5 | sam -sing -speed 40 -pitch 64 -phonetic ohohoh 6 | sam -sing -speed 40 -pitch 76 -phonetic ohohoh 7 | sam -sing -speed 40 -pitch 96 -phonetic sehehehehehehehehehey 8 | sam -sing -speed 40 -pitch 76 -phonetic kaeaeaeaeaeaeaeaeaen 9 | sam -sing -speed 40 -pitch 64 -phonetic yuxuxuxuxuxuxw 10 | sam -sing -speed 40 -pitch 48 -phonetic siyiyiyiyiyiyiyiyiyiyiyiyiyiyiyiyiyiy 11 | sam -sing -speed 40 -pitch 38 -phonetic baaaaay 12 | sam -sing -speed 40 -pitch 42 -phonetic dhaaaxaxaxax 13 | sam -sing -speed 40 -pitch 48 -phonetic daoaoaoaoaoaoaonz 14 | sam -sing -speed 40 -pitch 76 -phonetic ererererererer 15 | sam -sing -speed 40 -pitch 68 -phonetic liyiyiyiyiyiyiyiyiy 16 | sam -sing -speed 40 -pitch 64 -phonetic laaaaaaaaaaaaaaaaaaaaaaaaayt 17 | sam -sing -speed 40 -pitch 64 -phonetic whahahaht 18 | sam -sing -speed 40 -pitch 64 -phonetic sohohuw 19 | sam -sing -speed 40 -pitch 38 -phonetic praaaaaaaaaaaaaaaauwd 20 | sam -sing -speed 40 -pitch 42 -phonetic liyiyiy 21 | sam -sing -speed 40 -pitch 48 -phonetic wiyiyiyiyiyiyiyiyiy 22 | sam -sing -speed 40 -pitch 51 -phonetic /heheheheheheheheheheheheheheheheheheyld 23 | sam -sing -speed 40 -pitch 56 -phonetic aeaeaeaet 24 | sam -sing -speed 40 -pitch 51 -phonetic dhaaaxaxaxax 25 | sam -sing -speed 40 -pitch 48 -phonetic twaaaaaaaaaaaaaaiy 26 | sam -sing -speed 40 -pitch 48 -phonetic laaaaaaaaaaaaiyts 27 | sam -sing -speed 40 -pitch 64 -phonetic laeaeaeaeaeaeaeaeaest 28 | sam -sing -speed 40 -pitch 76 -phonetic gliyiyiyiyiyiyiyiyiym 29 | sam -sing -speed 40 -pitch 96 -phonetic mihihihihihihihihihihnx 30 | sam -sing -speed 40 -pitch 64 -phonetic /huxuxuxuxuxuxuxuxuxuxwz 31 | sam -sing -speed 40 -pitch 76 -phonetic braoaoaod 32 | sam -sing -speed 40 -pitch 96 -phonetic straaaaaaaaaaaaiyps 33 | sam -sing -speed 40 -pitch 76 -phonetic aeaeaeaeaeaeaeaeaeaend 34 | sam -sing -speed 40 -pitch 64 -phonetic braaaaaaaaaaaaaaiyt 35 | sam -sing -speed 40 -pitch 48 -phonetic staaaaaaaaaaaaaaaaaaaaaaaaaarz 36 | sam -sing -speed 40 -pitch 38 -phonetic thruxuxw 37 | sam -sing -speed 40 -pitch 42 -phonetic dhaaaxaxaxax 38 | sam -sing -speed 40 -pitch 48 -phonetic pehehehehehehehehehehr 39 | sam -sing -speed 40 -pitch 76 -phonetic rixixixixixixixixixixixixl 40 | sam -sing -speed 40 -pitch 68 -phonetic lahahahahahahahahahs 41 | sam -sing -speed 40 -pitch 64 -phonetic faaaaaaaaaaaaaaaaaaaaaaaaaaiyt 42 | sam -sing -speed 40 -pitch 64 -phonetic ohohohr 43 | sam -sing -speed 40 -pitch 64 -phonetic dhaaaxaxaxax 44 | sam -sing -speed 40 -pitch 38 -phonetic raeaeaeaeaeaeaeaeaeaeaeaem 45 | sam -sing -speed 40 -pitch 42 -phonetic paaaarts 46 | sam -sing -speed 40 -pitch 48 -phonetic wiyiyiyiyiyiyiyiyiy 47 | sam -sing -speed 40 -pitch 51 -phonetic waaaaaaaaaaaaaaaaaaaaaaaaaachd 48 | sam -sing -speed 40 -pitch 56 -phonetic werer 49 | sam -sing -speed 40 -pitch 51 -phonetic sohohw 50 | sam -sing -speed 40 -pitch 48 -phonetic gaeaeaeaeaeaeaeaeaeael 51 | sam -sing -speed 40 -pitch 48 -phonetic lixixixixixixixixixixixixixnt 52 | sam -sing -speed 40 -pitch 64 -phonetic liyiyiyiyiyiyiyiyiy 53 | sam -sing -speed 40 -pitch 76 -phonetic striyiyiyiyiyiyiyiyiym 54 | sam -sing -speed 40 -pitch 96 -phonetic mihihihihihihihihihnx 55 | sam -sing -speed 40 -pitch 38 -phonetic aeaeaeaeaend 56 | sam -sing -speed 40 -pitch 38 -phonetic dhaaaxaxaxax 57 | sam -sing -speed 40 -pitch 38 -phonetic raaaaaaaaaaaak 58 | sam -sing -speed 40 -pitch 36 -phonetic kixixixixixixixixixixixts 59 | sam -sing -speed 40 -pitch 32 -phonetic rehehehehehehehehehd 60 | sam -sing -speed 40 -pitch 32 -phonetic gleheheheheheheheheheheheheheheherer 61 | sam -sing -speed 40 -pitch 36 -phonetic dhaaaxaxaxax 62 | sam -sing -speed 40 -pitch 38 -phonetic baaaamz 63 | sam -sing -speed 40 -pitch 42 -phonetic bererererererst 64 | sam -sing -speed 40 -pitch 38 -phonetic tihihihihihihihihihnx 65 | sam -sing -speed 40 -pitch 36 -phonetic ihihihihihihihihihihn 66 | sam -sing -speed 40 -pitch 36 -phonetic eheheheheheheheheheheheheheheheheheyr 67 | sam -sing -speed 40 -pitch 36 -phonetic geheheheyv 68 | sam -sing -speed 40 -pitch 38 -phonetic pruxuxuxuxuxuxuxuxuxuxuxuxwf 69 | sam -sing -speed 40 -pitch 42 -phonetic thruxuxw 70 | sam -sing -speed 40 -pitch 48 -phonetic dhaaaxaxax 71 | sam -sing -speed 40 -pitch 51 -phonetic naaaaaaaaaaaaaaaaaaaaaaayiyt 72 | sam -sing -speed 40 -pitch 56 -phonetic dhaeaeaeaet 73 | sam -sing -speed 40 -pitch 51 -phonetic aaaaaauwr 74 | sam -sing -speed 40 -pitch 48 -phonetic flaeaeaeaeaeaeaeaeaeg 75 | sam -sing -speed 40 -pitch 76 -phonetic wahahahahahahahahahz 76 | sam -sing -speed 40 -pitch 68 -phonetic stihihihihihihihihihl 77 | sam -sing -speed 40 -pitch 64 -phonetic dhehehehehehehehehehehehehehehehehehehehr 78 | sam -sing -speed 40 -pitch 64 -phonetic ohohohohohohow 79 | sam -sing -speed 40 -pitch 48 -phonetic sehehehehehehehehehey 80 | sam -sing -speed 40 -pitch 48 -phonetic dahahahahahahahahahz 81 | sam -sing -speed 40 -pitch 48 -phonetic dhaeaeae 82 | sam -sing -speed 40 -pitch 51 -phonetic aeaeaet 83 | sam -sing -speed 40 -pitch 56 -phonetic staaaaaaaaaaaar 84 | sam -sing -speed 40 -pitch 56 -phonetic spehehehehehehehehehiynx 85 | sam -sing -speed 40 -pitch 56 -phonetic gaxaxaxaxaxaxaxaxaxaxaxaxld 86 | sam -sing -speed 40 -pitch 42 -phonetic baeaeaeaeaeaeaeaeaen 87 | sam -sing -speed 40 -pitch 36 -phonetic nerer 88 | sam -sing -speed 40 -pitch 38 -phonetic ererer 89 | sam -sing -speed 40 -pitch 42 -phonetic yeheheh 90 | sam -sing -speed 40 -pitch 48 -phonetic eheheheht 91 | sam -sing -speed 40 -pitch 48 -phonetic weheheheheheheheheheheh 92 | sam -sing -speed 40 -pitch 51 -phonetic ehehehehehehehiyiyiyv 93 | sam -sing -speed 40 -pitch 64 -phonetic ohohohr 94 | sam -sing -speed 40 -pitch 64 -phonetic dhaaaxaxaxax 95 | sam -sing -speed 40 -pitch 48 -phonetic laeaeaeaeaeaeaeaeaeaeaeae 96 | sam -sing -speed 40 -pitch 42 -phonetic aeaeaend 97 | sam -sing -speed 40 -pitch 38 -phonetic ahahahv 98 | sam -sing -speed 40 -pitch 36 -phonetic dhaaaxaxaxax 99 | sam -sing -speed 40 -pitch 32 -phonetic friyiyiyiyiyiyiyiyiyiyiyiyiyiyiyiyiyiy 100 | sam -sing -speed 40 -pitch 48 -phonetic aeaeaend 101 | sam -sing -speed 40 -pitch 42 -phonetic dhaaaxaxaxax 102 | sam -sing -speed 40 -pitch 38 -phonetic /hohohohohohohohohowm 103 | sam -sing -speed 40 -pitch 36 -phonetic ahahahahv 104 | sam -sing -speed 40 -pitch 42 -phonetic dhaaaxaxaxaxaxaxaxaxaxaxaxaxax 105 | sam -sing -speed 40 -pitch 48 -phonetic brehehehehehehehehehehiyiyiyv 106 | -------------------------------------------------------------------------------- /demos/demo7.bat: -------------------------------------------------------------------------------- 1 | cd .. 2 | sam -sing -pitch 96 -speed 50 It's Jazzy Jazzy Jazzy 3 | sam -sing -pitch 68 -speed 50 Jazzy Jazzy Jazzy 4 | sam -sing -pitch 48 -speed 50 Jazzy Jazzy Jazzy 5 | sam -sing -pitch 32 -speed 50 Jazzy Jazzy Jazzy 6 | sam -sing -pitch 96 -speed 50 Jazzy 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /demos/demo8.bat: -------------------------------------------------------------------------------- 1 | cd .. 2 | sam More than ever before. Americans are suff-er-ing from back, problems. 3 | sam Back. tach-sis. 4 | sam Back. rent? 5 | sam Back. car payments. 6 | sam What we need is to get back. to the basics. 7 | 8 | sam And say chilldren. "What does it all mean." 9 | 10 | sam And remember. 11 | sam If you want to see a comic strip? You should see me in the shouwer. 12 | 13 | -------------------------------------------------------------------------------- /demos/demo9.bat: -------------------------------------------------------------------------------- 1 | cd .. 2 | sam -mouth 145 -throat 135 -pitch 40 -speed 72 -phonetic "AY5 KAEN TAO5K LAYK AH LIH5TUL OH5LD LEY5DIY.- SWIY5TIY." 3 | 4 | sam -mouth 145 -throat 125 -pitch 40 -speed 72 "You can do anything, but not everything." 5 | sam -mouth 135 -throat 135 -pitch 35 -speed 72 "The richest man is not he who has the most. But he who wants the least." 6 | sam -mouth 145 -throat 135 -pitch 40 -speed 72 "To the man who only has a hammer, everything he encounters looks like a nail." 7 | sam -mouth 145 -throat 125 -pitch 35 -speed 72 "Before I got married I had six ideas about bringing up kids; now I have six kids. And no idea?" 8 | sam -mouth 135 -throat 135 -pitch 40 -speed 72 "Always forgive your enemies. Nothing annoys them more." 9 | sam -mouth 145 -throat 125 -pitch 35 -speed 72 "All people are frauds. The only difference between them is that some admit it. I myself totally dee-nigh. it." 10 | sam -mouth 135 -throat 135 -pitch 40 -speed 72 "I do not mind what Con-gress does. As long as they do not do it. in the streets. And frighten the kids!" 11 | 12 | sam -speed 55 -pitch 92 -throat 128 -mouth 128 "Ha ha ha ha ha ha ha? Ha ha ha ha ha ha ha!" 13 | sam That's not funny grandma. 14 | 15 | sam -mouth 145 -throat 125 -pitch 40 -speed 72 "O.K. Let grandma take it from here." 16 | sam -mouth 145 -throat 135 -pitch 40 -speed 72 -phonetic "SWIY5TIY." 17 | 18 | -------------------------------------------------------------------------------- /demos/demoA.bat: -------------------------------------------------------------------------------- 1 | cd .. 2 | sam -mouth 128 -throat 128 -pitch 64 -speed 72 -phonetic "/HEHLOH3OW. MAY4 NEY4M IHZ SAE4M." 3 | sam -mouth 128 -throat 128 -pitch 64 -speed 72 -phonetic "AY4 EHM DHAX SAO4FTWEH4R SPIY4CH SIH3NTHAXSAY4ZER FOH4R DHAX KAA3MAXDOH4R KUMPYUWTER." 4 | 5 | sam -mouth 128 -throat 128 -pitch 64 -speed 72 -phonetic "AY4 PROWDUW3S /HAY4 KWAALAXTIY SPIY4CH FRAXM SIHMPAXL FAXNEHTIHK IH3NPUHT." 6 | sam -mouth 128 -throat 128 -pitch 64 -speed 72 -phonetic "OH3R, AY4 KAEN TRAE3NZLEYT IYNGLIHSH DAXREHKTLIY TUH SPIYCH." 7 | 8 | 9 | -------------------------------------------------------------------------------- /demos/demoB.bat: -------------------------------------------------------------------------------- 1 | cd .. 2 | sam -mouth 128 -throat 128 -pitch 64 -speed 72 -phonetic "DHAX SOHLIHLAXKWIY FRAXM /HAE3MLEHT. BAY WIHLYAXM SHEY4KSPIHR." 3 | sam -mouth 128 -throat 128 -pitch 64 -speed 72 -phonetic "TUH BIYIYIY2--OHR NAAT-TUH BIYIYIY." 4 | sam -mouth 128 -throat 128 -pitch 64 -speed 72 -phonetic "DHAET IHZ THAX KWEHSCHAXN." 5 | sam -mouth 128 -throat 128 -pitch 64 -speed 72 -phonetic "WEHDHER TIHZ NOHBLER IHN DHAX MAY4ND, TUH SAH4FER THAX SLIY3NGZ AEN3D" 6 | sam -mouth 128 -throat 128 -pitch 64 -speed 72 -phonetic "EH4ROWZ AXV AWT REY3JAXS FOH4RCHAXN." 7 | 8 | sam -mouth 128 -throat 128 -pitch 64 -speed 72 -phonetic "OHR TUH TEYK AARMZ AXGEHNST AX4 SIY AXV TRAH4BAXLZ." 9 | sam -mouth 128 -throat 128 -pitch 64 -speed 72 -phonetic "AEND BAY AHPOWZIHNG, EHND DHEHM." -------------------------------------------------------------------------------- /demos/demoC.bat: -------------------------------------------------------------------------------- 1 | cd .. 2 | 3 | sam -mouth 145 -throat 125 -pitch 40 -speed 72 "This is the original file extracted from the Commodore 64." 4 | sam -mouth 145 -throat 125 -pitch 40 -speed 72 "O.K. Sam. You can take it from here." 5 | sam -mouth 145 -throat 135 -pitch 40 -speed 72 -phonetic "SWIY5TIY." 6 | 7 | sam -mouth 128 -throat 128 -pitch 64 -speed 72 -phonetic "AY4 WIHL NAW4 KWOWT-DHAX GEHTIYZBERG AXDREH3S." 8 | sam -mouth 128 -throat 128 -pitch 64 -speed 72 -phonetic "FOH4R SKOH4R AEND SEHVIXN YIH3RZ AXGOW- AAR FAA3DHERZ BRAAT FOHRTH" 9 | sam -mouth 128 -throat 128 -pitch 64 -speed 72 -phonetic "AXPAAN DHIHS KAANTIHNEHNT- EY NUH NEY4SHAXN." 10 | sam -mouth 128 -throat 128 -pitch 64 -speed 72 -phonetic "KAHNSIYVD IHN LIH4BERTIY, AEND DEH4DIHKEYTIHD TUH DHAX PRAAPAXSIHSHAXN" 11 | sam -mouth 128 -throat 128 -pitch 64 -speed 72 -phonetic "DHAET AAL MEHN AAR KRIYEY4TAXD IYKWUL." 12 | sam -mouth 128 -throat 128 -pitch 64 -speed 72 -phonetic "NAW4 WIY AAR EHNGEYJD IHN DHAX GREYT SIHVAXL WOHR. TEHSTIHNG WEHDHER" 13 | sam -mouth 128 -throat 128 -pitch 64 -speed 72 -phonetic "DHAE4T NEY4SHAXN, OHR EH4NIY NEYSHAXN SOH KAXNSIYVD AEND SOH" 14 | sam -mouth 128 -throat 128 -pitch 64 -speed 72 -phonetic "DEH4DAHKEYTIHD, KAEN LAONX EHNDUH6UHR." 15 | 16 | 17 | -------------------------------------------------------------------------------- /demos/demoD.bat: -------------------------------------------------------------------------------- 1 | cd .. 2 | sam -mouth 128 -throat 128 -pitch 64 -speed 72 -phonetic "AY4 PLEHJ AXLIYJAXNS TUH DHAX FLAEG, AXV DHIY YUWNAYTEHD STEYTS" 3 | sam -mouth 128 -throat 128 -pitch 64 -speed 72 -phonetic "AXV AXMEHRIYKAX. AEND TUH DHAX RIYPAHBLIHK FOHR WIHCH IHT STAENDZ." 4 | sam -mouth 128 -throat 128 -pitch 64 -speed 72 -phonetic "WAHN NEYSHAXN AHNDER GAA5AA8D" 5 | sam -mouth 128 -throat 128 -pitch 64 -speed 72 -phonetic "IHNDIHVIH4ZAXBAXL, WIHTH LIHBERTTIY, AEND JAH4STIHS- FOHR AAL." 6 | -------------------------------------------------------------------------------- /demos_bash/demo1.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ../sam --debug "to bee or not to bee, that is the question"; 4 | ../sam --phonetic "MAY4 NEYM IHZ SAE4M."; 5 | -------------------------------------------------------------------------------- /demos_bash/demo2.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ../sam --pitch 64 --speed 72 --phonetic "/HEH4LOW DHEHR. YUW4 NOW MIY4Y, AY4 AEM SAE5M,"; 4 | ../sam --pitch 64 --speed 72 --phonetic "DHAH SAO4FTWEHR MAW5TH"; 5 | ../sam --pitch 64 --speed 72 --phonetic "FOHR YOHR KAA4MIXDOH6R SIH4KSTIYFOH6R KUMPYUW4TER."; 6 | ../sam --pitch 64 --speed 72 --phonetic "AY4 KUHD AO4LWEYZ DUW LAA3TS AHV AHMEY4ZIHNX THIHNXGZ."; 7 | ../sam --pitch 64 --speed 35 --phonetic "AY5 KUHD TAO5K VEH4RIY KWIH4KLIY WHEHN AY WAA4NTIHD."; 8 | ../sam --pitch 64 --speed 140 --phonetic "AE4ND AY KUHD TAO4K VEH3RIY SLOW4LIY TUW."; 9 | ../sam --pitch 30 --speed 72 --phonetic "AY5 KUHD SPIY5K IHNAH VEH3RIY /HAY5 VOYS."; 10 | ../sam --pitch 169 --speed 72 --phonetic "AE4ND AY KUHD SPIY5K RIY3L LOW."; 11 | ../sam --pitch 64 --speed 72 --phonetic "BAHT NAW4 AY KAEN DUW5 SAH4MPTHIHNX IY5VUN MOH4R AHMEY3ZIHNX."; 12 | 13 | ../sam -mouth 110 -throat 160 --pitch 64 --speed 72 --phonetic "AY4 KAEN CHEY4NJ MAY VOY5S KUMPLIY3TLIY.Q."; 14 | ../sam -mouth 110 -throat 160 --pitch 64 --speed 72 --phonetic "AY4 KAEN BIY5 AH LIH4TUL EH5LF /HUW TAO5KS LAYK DHIH5S. OH3R."; 15 | 16 | ../sam -mouth 190 -throat 190 --pitch 60 --speed 42 --phonetic "AY5 KAEN BIHKAH5M AH STREY4NJ EY4LIYUN."; 17 | ../sam -mouth 190 -throat 190 --pitch 60 --speed 42 --phonetic "YUW5 KAEN YUW4Z DHIHS VOY5S IHN AH SPEY4S GEY5M."; 18 | 19 | ../sam -mouth 110 -throat 105 --pitch 72 --speed 82 --phonetic "OHR /HAW5 AHBAW5T DHIH3S STAH4FIY LIH5TUL KEH4RIXKTER."; 20 | ../sam -mouth 110 -throat 105 --pitch 72 --speed 82 --phonetic "EY SIH4LIY VOY5S FOHR AH KUMPYUW4TER."; 21 | 22 | ../sam -mouth 145 -throat 145 --pitch 32 --speed 72 --phonetic "AY5 KAEN TAO5K LAYK AH LIH5TUL OH5LD LEY5DIY."; 23 | ../sam -mouth 145 -throat 145 --pitch 32 --speed 72 --phonetic "NAAT MEH5NIY KUMPYUW5TERZ KAEN DUW DHIH4S - SWIY5TIY."; 24 | 25 | ../sam -mouth 128 -throat 128 --pitch 64 --speed 72 --phonetic "AE4ND AEZ AH MAE5TER AHV FAE4KT,"; 26 | ../sam -mouth 128 -throat 128 --pitch 64 --speed 72 --phonetic "AY4 KAEN BIYKAH5M DHAX LEY4TIXST MUW4VIY /HIY4ROW - AEND SEH8EY4,"; 27 | 28 | ../sam -mouth 150 -throat 200 --pitch 58 --speed 120 --phonetic "IY4IY6 TTIY6 -FOW5N /HOW5MM. IY4IY6 TTIY6 - FOW5N /HOW5MM."; 29 | 30 | ../sam -mouth 128 -throat 128 --pitch 64 --speed 72 --phonetic "DHEH4RZ NOW4 TEH5LIHNX WHAH5T SAE5M WIHL DUW NEH5KST."; 31 | -------------------------------------------------------------------------------- /demos_bash/demo3.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ../sam --pitch 64 --speed 74 --phonetic "/HEHLOW3 EH5VRIXWAHN. IHT SHUH4R IHZ NAY3S -- TAX BIY /HIY4R TUH7DEY."; 4 | ../sam --pitch 64 --speed 74 --phonetic "AY3 AEM SAE4M -"; 5 | ../sam --pitch 64 --speed 74 --phonetic "DHAX BRAE4ND NUW5 VOY4S FOHR DHAX KAA4MIXDOH6R"; 6 | ../sam --pitch 64 --speed 74 --phonetic "SIH4KSTIYFOH6R KUMPYUW4TER."; 7 | ../sam --pitch 64 --speed 74 --phonetic "AY4 AEM DHAX MOW5ST VER4SIXTUL -"; 8 | ../sam --pitch 64 --speed 74 --phonetic "AH5NDERSTAE4NDIXBUL SPIY5CH SIH3NTHAXSAY7ZER"; 9 | ../sam --pitch 64 --speed 74 --phonetic "AAN DHAX MAA3RKIXT."; 10 | ../sam --pitch 64 --speed 74 --phonetic "AE4AE7ND- AY4 AEM DHAX LOHOW4EHST PRAY4ST- AHV DHEHM AO4UL."; 11 | ../sam --pitch 64 --speed 74 --phonetic "BAH6T WHAH4T KAEN YUW DUW3 WHIHTH MIYIY."; 12 | ../sam --pitch 64 --speed 74 --phonetic "WAY7 YUW3 KAEN PUH5T MIY-IH5NTUX YOHR OW7N PROH3GRAEMZ."; 13 | ../sam --pitch 64 --speed 74 --phonetic "/HAW4 WUHD YUW4 LAYK YOHR BIH3ZNIXS SAO5FTWEHR TUX SEY-"; 14 | ../sam --pitch 64 --speed 74 --phonetic "PLIY4Z EH5NTER DHIH4S WIY6KS PER3CHAHSIXZ."; 15 | ../sam --pitch 64 --speed 74 --phonetic "OH3ER- IHMAE3JIXN AEN EHDVEH4NCHER GEY6M DHAET DAH6Z DHIH4S."; 16 | ../sam --pitch 64 --speed 74 --phonetic "DHIY EH3LF WAHZ KAE3PCHERD-BAY DHAX JAY3IXNT."; 17 | ../sam --pitch 64 --speed 74 --phonetic "/HIY BIHGAE5N TUX KRAA3IY-AEND /HIY SEH4D."; 18 | 19 | ../sam --pitch 31 --speed 72 --phonetic "OH5OW7 NAX5OW. PLIY5Z DOWNT /HER5T MIY-MIH6STER JAYIXNT?"; 20 | 21 | ../sam --pitch 64 --speed 76 --phonetic "BAH6T DHAX JAY4IXNT WAHZ VEH3RIY MIY6N-"; 22 | ../sam --pitch 64 --speed 76 --phonetic "AEND /HIY4 OW3NLIY SEHD-"; 23 | 24 | ../sam --pitch 120 --speed 80 --phonetic "/HOW2- /HOW4- /HOW."; 25 | 26 | ../sam --pitch 64 --speed 72 --phonetic "DHEH5R IHZ NOW LIH3MIXT-TUX DHAX PAA4SAXBUL AE5PLIXKEY3SHUNZ-"; 27 | ../sam --pitch 64 --speed 72 --phonetic "AHV SPIY4CH IHN YOH7R PROH3GRAEMZ."; 28 | ../sam --pitch 64 --speed 72 --phonetic "AO3LSOW7W3- AY4 AEM VEH3RIY IY4ZIY TUX YUW4Z."; 29 | ../sam --pitch 64 --speed 72 --phonetic "EH2NIYWAH6N KAEN AE5DSPIY5CH-TUX6 AH BEY4SIHKQPROH4GRAEM."; 30 | ../sam --pitch 64 --speed 72 --phonetic "AY4 KAEN IY3VIXN TAOK VEH4RIY KWIH4KLIY."; 31 | ../sam --pitch 64 --speed 72 --phonetic "LIH4SUN TUX6 DHIH3S WAHN."; 32 | 33 | ../sam --speed 30 --phonetic "PIY4TER PAY3PER- PIH4KT AH PEH4K AHV PIH4KULD PEH4PERZ."; 34 | 35 | ../sam --speed 28 --phonetic "/HAW3 MEHNIY PEH4KS AHV PIH4KULD PEH4PERZ-DIHD PIY4TER PAY3PER PIH6K."; 36 | 37 | ../sam --speed 100 --phonetic "QQQQ WWAW7IY1IY3IY. DHAE3T WHAHZ AH TAH4FIY."; 38 | 39 | ../sam --speed 72 --phonetic "EH2NIYWEY6- YUW4 GEHT DHIY AYDIY5AH."; 40 | ../sam --speed 72 --phonetic "SAE3M IHZ DHIY MOW3STEHKSAY4TIHNX NUW4 PRAA4DAHKT -- AHV DHIHS YIY4R."; 41 | ../sam --speed 72 --phonetic "SOH3OW7-/HAW4AHBAW3T IHT. WOH3NT YUW PLIY2Z TEY6KMIY /HOW6M?"; 42 | ../sam --speed 72 --phonetic "Q SAE4M IHZ /HIY3R TUX STEY4IY."; 43 | ../sam --speed 72 --phonetic "THAE2NXKS FOHR LIH4SUNIHNX EHVRIXBAH5DIY."; 44 | ../sam --speed 72 --phonetic "AY /HOW3P YUW EHNJOY4D-MAYLIH4TUL TAOK."; 45 | -------------------------------------------------------------------------------- /demos_bash/demo4.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ../sam "Four score and seven years ago."; 4 | ../sam "Our fathers brought forth on this continent, a new nation."; 5 | ../sam "Conceived in Libberty. And dedicated to the prop-position that all men are created equal."; 6 | 7 | ../sam "Now we are engaged in a great civvil war! Testing whether that nation, or any nation."; 8 | ../sam "So conceived, and so dedicated, can long endure."; 9 | -------------------------------------------------------------------------------- /demos_bash/demo5.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ../sam --mouth 110 --throat 160 --pitch 64 --speed 72 --phonetic "AY4 KAEN CHEY4NJ MAY VOY5S KUMPLIY3TLIY.Q."; 4 | 5 | ../sam --mouth 150 --throat 200 --pitch 58 --speed 120 "Eee Tea! Phone home."; 6 | ../sam --mouth 150 --throat 200 --pitch 58 --speed 120 "Eee Tea? Phone home?"; 7 | 8 | ../sam --mouth 150 --throat 200 --pitch 58 --speed 140 "Ha ha ha ha ha ha ha!"; 9 | ../sam --mouth 150 --throat 100 --pitch 58 --speed 140 "Ha ha ha ha ha ha ha?"; 10 | 11 | ../sam --speed 140 --pitch 64 --throat 110 --mouth 160 "Ho ha ha ha!"; 12 | ../sam --speed 140 --pitch 60 --throat 190 --mouth 190 "Ha ha ha ha ha ha ha?"; 13 | 14 | ../sam --speed 140 --pitch 72 --throat 110 --mouth 105 "He he ha ha he he ha!"; 15 | ../sam --speed 140 --pitch 32 --throat 145 --mouth 145 "Ha ha ho he he ha?"; 16 | 17 | ../sam --speed 140 --pitch 64 --throat 150 --mouth 200 "Ha ha ho ho ha ho?"; 18 | ../sam --speed 35 --pitch 92 --throat 128 --mouth 128 "Ha ha ha ha ha ha ha? Ha ha ha ha ha ha ha!"; 19 | 20 | ../sam "That's not funny."; 21 | -------------------------------------------------------------------------------- /demos_bash/demo6.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ../sam "Hello my name is Sam."; 4 | ../sam "I will sing the national anthem of the United States of America."; 5 | ../sam "The Star Spangled Banner!"; 6 | ../sam --sing --speed 40 --pitch 64 --phonetic "ohohoh"; 7 | ../sam --sing --speed 40 --pitch 76 --phonetic "ohohoh"; 8 | ../sam --sing --speed 40 --pitch 96 --phonetic "sehehehehehehehehehey"; 9 | ../sam --sing --speed 40 --pitch 76 --phonetic "kaeaeaeaeaeaeaeaeaen"; 10 | ../sam --sing --speed 40 --pitch 64 --phonetic "yuxuxuxuxuxuxw"; 11 | ../sam --sing --speed 40 --pitch 48 --phonetic "siyiyiyiyiyiyiyiyiyiyiyiyiyiyiyiyiyiy"; 12 | ../sam --sing --speed 40 --pitch 38 --phonetic "baaaaay"; 13 | ../sam --sing --speed 40 --pitch 42 --phonetic "dhaaaxaxaxax"; 14 | ../sam --sing --speed 40 --pitch 48 --phonetic "daoaoaoaoaoaoaonz"; 15 | ../sam --sing --speed 40 --pitch 76 --phonetic "ererererererer"; 16 | ../sam --sing --speed 40 --pitch 68 --phonetic "liyiyiyiyiyiyiyiyiy"; 17 | ../sam --sing --speed 40 --pitch 64 --phonetic "laaaaaaaaaaaaaaaaaaaaaaaaayt"; 18 | ../sam --sing --speed 40 --pitch 64 --phonetic "whahahaht"; 19 | ../sam --sing --speed 40 --pitch 64 --phonetic "sohohuw"; 20 | ../sam --sing --speed 40 --pitch 38 --phonetic "praaaaaaaaaaaaaaaauwd"; 21 | ../sam --sing --speed 40 --pitch 42 --phonetic "liyiyiy"; 22 | ../sam --sing --speed 40 --pitch 48 --phonetic "wiyiyiyiyiyiyiyiyiy"; 23 | ../sam --sing --speed 40 --pitch 51 --phonetic "/heheheheheheheheheheheheheheheheheheyld"; 24 | ../sam --sing --speed 40 --pitch 56 --phonetic "aeaeaeaet"; 25 | ../sam --sing --speed 40 --pitch 51 --phonetic "dhaaaxaxaxax"; 26 | ../sam --sing --speed 40 --pitch 48 --phonetic "twaaaaaaaaaaaaaaiy"; 27 | ../sam --sing --speed 40 --pitch 48 --phonetic "laaaaaaaaaaaaiyts"; 28 | ../sam --sing --speed 40 --pitch 64 --phonetic "laeaeaeaeaeaeaeaeaest"; 29 | ../sam --sing --speed 40 --pitch 76 --phonetic "gliyiyiyiyiyiyiyiyiym"; 30 | ../sam --sing --speed 40 --pitch 96 --phonetic "mihihihihihihihihihihnx"; 31 | ../sam --sing --speed 40 --pitch 64 --phonetic "/huxuxuxuxuxuxuxuxuxuxwz"; 32 | ../sam --sing --speed 40 --pitch 76 --phonetic "braoaoaod"; 33 | ../sam --sing --speed 40 --pitch 96 --phonetic "straaaaaaaaaaaaiyps"; 34 | ../sam --sing --speed 40 --pitch 76 --phonetic "aeaeaeaeaeaeaeaeaeaend"; 35 | ../sam --sing --speed 40 --pitch 64 --phonetic "braaaaaaaaaaaaaaiyt"; 36 | ../sam --sing --speed 40 --pitch 48 --phonetic "staaaaaaaaaaaaaaaaaaaaaaaaaarz"; 37 | ../sam --sing --speed 40 --pitch 38 --phonetic "thruxuxw"; 38 | ../sam --sing --speed 40 --pitch 42 --phonetic "dhaaaxaxaxax"; 39 | ../sam --sing --speed 40 --pitch 48 --phonetic "pehehehehehehehehehehr"; 40 | ../sam --sing --speed 40 --pitch 76 --phonetic "rixixixixixixixixixixixixl"; 41 | ../sam --sing --speed 40 --pitch 68 --phonetic "lahahahahahahahahahs"; 42 | ../sam --sing --speed 40 --pitch 64 --phonetic "faaaaaaaaaaaaaaaaaaaaaaaaaaiyt"; 43 | ../sam --sing --speed 40 --pitch 64 --phonetic "ohohohr"; 44 | ../sam --sing --speed 40 --pitch 64 --phonetic "dhaaaxaxaxax"; 45 | ../sam --sing --speed 40 --pitch 38 --phonetic "raeaeaeaeaeaeaeaeaeaeaeaem"; 46 | ../sam --sing --speed 40 --pitch 42 --phonetic "paaaarts"; 47 | ../sam --sing --speed 40 --pitch 48 --phonetic "wiyiyiyiyiyiyiyiyiy"; 48 | ../sam --sing --speed 40 --pitch 51 --phonetic "waaaaaaaaaaaaaaaaaaaaaaaaaachd"; 49 | ../sam --sing --speed 40 --pitch 56 --phonetic "werer"; 50 | ../sam --sing --speed 40 --pitch 51 --phonetic "sohohw"; 51 | ../sam --sing --speed 40 --pitch 48 --phonetic "gaeaeaeaeaeaeaeaeaeael"; 52 | ../sam --sing --speed 40 --pitch 48 --phonetic "lixixixixixixixixixixixixixnt"; 53 | ../sam --sing --speed 40 --pitch 64 --phonetic "liyiyiyiyiyiyiyiyiy"; 54 | ../sam --sing --speed 40 --pitch 76 --phonetic "striyiyiyiyiyiyiyiyiym"; 55 | ../sam --sing --speed 40 --pitch 96 --phonetic "mihihihihihihihihihnx"; 56 | ../sam --sing --speed 40 --pitch 38 --phonetic "aeaeaeaeaend"; 57 | ../sam --sing --speed 40 --pitch 38 --phonetic "dhaaaxaxaxax"; 58 | ../sam --sing --speed 40 --pitch 38 --phonetic "raaaaaaaaaaaak"; 59 | ../sam --sing --speed 40 --pitch 36 --phonetic "kixixixixixixixixixixixts"; 60 | ../sam --sing --speed 40 --pitch 32 --phonetic "rehehehehehehehehehd"; 61 | ../sam --sing --speed 40 --pitch 32 --phonetic "gleheheheheheheheheheheheheheheherer"; 62 | ../sam --sing --speed 40 --pitch 36 --phonetic "dhaaaxaxaxax"; 63 | ../sam --sing --speed 40 --pitch 38 --phonetic "baaaamz"; 64 | ../sam --sing --speed 40 --pitch 42 --phonetic "bererererererst"; 65 | ../sam --sing --speed 40 --pitch 38 --phonetic "tihihihihihihihihihnx"; 66 | ../sam --sing --speed 40 --pitch 36 --phonetic "ihihihihihihihihihihn"; 67 | ../sam --sing --speed 40 --pitch 36 --phonetic "eheheheheheheheheheheheheheheheheheyr"; 68 | ../sam --sing --speed 40 --pitch 36 --phonetic "geheheheyv"; 69 | ../sam --sing --speed 40 --pitch 38 --phonetic "pruxuxuxuxuxuxuxuxuxuxuxuxwf"; 70 | ../sam --sing --speed 40 --pitch 42 --phonetic "thruxuxw"; 71 | ../sam --sing --speed 40 --pitch 48 --phonetic "dhaaaxaxax"; 72 | ../sam --sing --speed 40 --pitch 51 --phonetic "naaaaaaaaaaaaaaaaaaaaaaayiyt"; 73 | ../sam --sing --speed 40 --pitch 56 --phonetic "dhaeaeaeaet"; 74 | ../sam --sing --speed 40 --pitch 51 --phonetic "aaaaaauwr"; 75 | ../sam --sing --speed 40 --pitch 48 --phonetic "flaeaeaeaeaeaeaeaeaeg"; 76 | ../sam --sing --speed 40 --pitch 76 --phonetic "wahahahahahahahahahz"; 77 | ../sam --sing --speed 40 --pitch 68 --phonetic "stihihihihihihihihihl"; 78 | ../sam --sing --speed 40 --pitch 64 --phonetic "dhehehehehehehehehehehehehehehehehehehehr"; 79 | ../sam --sing --speed 40 --pitch 64 --phonetic "ohohohohohohow"; 80 | ../sam --sing --speed 40 --pitch 48 --phonetic "sehehehehehehehehehey"; 81 | ../sam --sing --speed 40 --pitch 48 --phonetic "dahahahahahahahahahz"; 82 | ../sam --sing --speed 40 --pitch 48 --phonetic "dhaeaeae"; 83 | ../sam --sing --speed 40 --pitch 51 --phonetic "aeaeaet"; 84 | ../sam --sing --speed 40 --pitch 56 --phonetic "staaaaaaaaaaaar"; 85 | ../sam --sing --speed 40 --pitch 56 --phonetic "spehehehehehehehehehiynx"; 86 | ../sam --sing --speed 40 --pitch 56 --phonetic "gaxaxaxaxaxaxaxaxaxaxaxaxld"; 87 | ../sam --sing --speed 40 --pitch 42 --phonetic "baeaeaeaeaeaeaeaeaen"; 88 | ../sam --sing --speed 40 --pitch 36 --phonetic "nerer"; 89 | ../sam --sing --speed 40 --pitch 38 --phonetic "ererer"; 90 | ../sam --sing --speed 40 --pitch 42 --phonetic "yeheheh"; 91 | ../sam --sing --speed 40 --pitch 48 --phonetic "eheheheht"; 92 | ../sam --sing --speed 40 --pitch 48 --phonetic "weheheheheheheheheheheh"; 93 | ../sam --sing --speed 40 --pitch 51 --phonetic "ehehehehehehehiyiyiyv"; 94 | ../sam --sing --speed 40 --pitch 64 --phonetic "ohohohr"; 95 | ../sam --sing --speed 40 --pitch 64 --phonetic "dhaaaxaxaxax"; 96 | ../sam --sing --speed 40 --pitch 48 --phonetic "laeaeaeaeaeaeaeaeaeaeaeae"; 97 | ../sam --sing --speed 40 --pitch 42 --phonetic "aeaeaend"; 98 | ../sam --sing --speed 40 --pitch 38 --phonetic "ahahahv"; 99 | ../sam --sing --speed 40 --pitch 36 --phonetic "dhaaaxaxaxax"; 100 | ../sam --sing --speed 40 --pitch 32 --phonetic "friyiyiyiyiyiyiyiyiyiyiyiyiyiyiyiyiyiy"; 101 | ../sam --sing --speed 40 --pitch 48 --phonetic "aeaeaend"; 102 | ../sam --sing --speed 40 --pitch 42 --phonetic "dhaaaxaxaxax"; 103 | ../sam --sing --speed 40 --pitch 38 --phonetic "/hohohohohohohohohowm"; 104 | ../sam --sing --speed 40 --pitch 36 --phonetic "ahahahahv"; 105 | ../sam --sing --speed 40 --pitch 42 --phonetic "dhaaaxaxaxaxaxaxaxaxaxaxaxaxax"; 106 | ../sam --sing --speed 40 --pitch 48 --phonetic "brehehehehehehehehehehiyiyiyv"; 107 | -------------------------------------------------------------------------------- /demos_bash/demo7.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ../sam --sing --pitch 96 --speed 50 "It's Jazzy Jazzy Jazzy"; 4 | ../sam --sing --pitch 68 --speed 50 "Jazzy Jazzy Jazzy"; 5 | ../sam --sing --pitch 48 --speed 50 "Jazzy Jazzy Jazzy"; 6 | ../sam --sing --pitch 32 --speed 50 "Jazzy Jazzy Jazzy"; 7 | ../sam --sing --pitch 96 --speed 50 "Jazzy"; 8 | -------------------------------------------------------------------------------- /demos_bash/demo8.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ../sam "More than ever before. Americans are suff-er-ing from back, problems."; 4 | ../sam "Back. tach-sis."; 5 | ../sam "Back. rent?"; 6 | ../sam "Back. car payments."; 7 | ../sam "What we need is to get back. to the basics."; 8 | 9 | ../sam "And say chilldren: What does it all mean."; 10 | 11 | ../sam "And remember."; 12 | ../sam "If you want to see a comic strip? You should see me in the shouwer."; 13 | -------------------------------------------------------------------------------- /demos_bash/demo9.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ../sam --mouth 145 --throat 135 --pitch 40 --speed 72 --phonetic "AY5 KAEN TAO5K LAYK AH LIH5TUL OH5LD LEY5DIY.- SWIY5TIY."; 4 | 5 | ../sam --mouth 145 --throat 125 --pitch 40 --speed 72 "You can do anything, but not everything."; 6 | ../sam --mouth 135 --throat 135 --pitch 35 --speed 72 "The richest man is not he who has the most. But he who wants the least."; 7 | ../sam --mouth 145 --throat 135 --pitch 40 --speed 72 "To the man who only has a hammer, everything he encounters looks like a nail."; 8 | ../sam --mouth 145 --throat 125 --pitch 35 --speed 72 "Before I got married I had six ideas about bringing up kids; now I have six kids. And no idea?"; 9 | ../sam --mouth 135 --throat 135 --pitch 40 --speed 72 "Always forgive your enemies. Nothing annoys them more."; 10 | ../sam --mouth 145 --throat 125 --pitch 35 --speed 72 "All people are frauds. The only difference between them is that some admit it. I myself totally dee-nigh. it."; 11 | ../sam --mouth 135 --throat 135 --pitch 40 --speed 72 "I do not mind what Con-gress does. As long as they do not do it. in the streets. And frighten the kids!"; 12 | 13 | ../sam --speed 55 --pitch 92 --throat 128 --mouth 128 "Ha ha ha ha ha ha ha? Ha ha ha ha ha ha ha!"; 14 | ../sam "That's not funny grandma."; 15 | 16 | ../sam --mouth 145 --throat 125 --pitch 40 --speed 72 "O.K. Let grandma take it from here."; 17 | ../sam --mouth 145 --throat 135 --pitch 40 --speed 72 --phonetic "SWIY5TIY."; 18 | -------------------------------------------------------------------------------- /demos_bash/demoA.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ../sam --mouth 128 --throat 128 --pitch 64 --speed 72 --phonetic "/HEHLOH3OW. MAY4 NEY4M IHZ SAE4M."; 4 | ../sam --mouth 128 --throat 128 --pitch 64 --speed 72 --phonetic "AY4 EHM DHAX SAO4FTWEH4R SPIY4CH SIH3NTHAXSAY4ZER FOH4R DHAX KAA3MAXDOH4R KUMPYUWTER."; 5 | 6 | ../sam --mouth 128 --throat 128 --pitch 64 --speed 72 --phonetic "AY4 PROWDUW3S /HAY4 KWAALAXTIY SPIY4CH FRAXM SIHMPAXL FAXNEHTIHK IH3NPUHT."; 7 | ../sam --mouth 128 --throat 128 --pitch 64 --speed 72 --phonetic "OH3R, AY4 KAEN TRAE3NZLEYT IYNGLIHSH DAXREHKTLIY TUH SPIYCH."; 8 | -------------------------------------------------------------------------------- /demos_bash/demoB.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ../sam --mouth 128 --throat 128 --pitch 64 --speed 72 --phonetic "DHAX SOHLIHLAXKWIY FRAXM /HAE3MLEHT. BAY WIHLYAXM SHEY4KSPIHR."; 4 | ../sam --mouth 128 --throat 128 --pitch 64 --speed 72 --phonetic "TUH BIYIYIY2--OHR NAAT-TUH BIYIYIY."; 5 | ../sam --mouth 128 --throat 128 --pitch 64 --speed 72 --phonetic "DHAET IHZ THAX KWEHSCHAXN."; 6 | ../sam --mouth 128 --throat 128 --pitch 64 --speed 72 --phonetic "WEHDHER TIHZ NOHBLER IHN DHAX MAY4ND, TUH SAH4FER THAX SLIY3NGZ AEN3D"; 7 | ../sam --mouth 128 --throat 128 --pitch 64 --speed 72 --phonetic "EH4ROWZ AXV AWT REY3JAXS FOH4RCHAXN."; 8 | 9 | ../sam --mouth 128 --throat 128 --pitch 64 --speed 72 --phonetic "OHR TUH TEYK AARMZ AXGEHNST AX4 SIY AXV TRAH4BAXLZ."; 10 | ../sam --mouth 128 --throat 128 --pitch 64 --speed 72 --phonetic "AEND BAY AHPOWZIHNG, EHND DHEHM."; 11 | -------------------------------------------------------------------------------- /demos_bash/demoC.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ../sam --mouth 145 --throat 125 --pitch 40 --speed 72 "This is the original file extracted from the Commodore 64."; 4 | ../sam --mouth 145 --throat 125 --pitch 40 --speed 72 "O.K. ../sam. You can take it from here."; 5 | ../sam --mouth 145 --throat 135 --pitch 40 --speed 72 --phonetic "SWIY5TIY."; 6 | 7 | ../sam --mouth 128 --throat 128 --pitch 64 --speed 72 --phonetic "AY4 WIHL NAW4 KWOWT-DHAX GEHTIYZBERG AXDREH3S."; 8 | ../sam --mouth 128 --throat 128 --pitch 64 --speed 72 --phonetic "FOH4R SKOH4R AEND SEHVIXN YIH3RZ AXGOW- AAR FAA3DHERZ BRAAT FOHRTH"; 9 | ../sam --mouth 128 --throat 128 --pitch 64 --speed 72 --phonetic "AXPAAN DHIHS KAANTIHNEHNT- EY NUH NEY4SHAXN."; 10 | ../sam --mouth 128 --throat 128 --pitch 64 --speed 72 --phonetic "KAHNSIYVD IHN LIH4BERTIY, AEND DEH4DIHKEYTIHD TUH DHAX PRAAPAXSIHSHAXN"; 11 | ../sam --mouth 128 --throat 128 --pitch 64 --speed 72 --phonetic "DHAET AAL MEHN AAR KRIYEY4TAXD IYKWUL."; 12 | ../sam --mouth 128 --throat 128 --pitch 64 --speed 72 --phonetic "NAW4 WIY AAR EHNGEYJD IHN DHAX GREYT SIHVAXL WOHR. TEHSTIHNG WEHDHER"; 13 | ../sam --mouth 128 --throat 128 --pitch 64 --speed 72 --phonetic "DHAE4T NEY4SHAXN, OHR EH4NIY NEYSHAXN SOH KAXNSIYVD AEND SOH"; 14 | ../sam --mouth 128 --throat 128 --pitch 64 --speed 72 --phonetic "DEH4DAHKEYTIHD, KAEN LAONX EHNDUH6UHR."; 15 | -------------------------------------------------------------------------------- /demos_bash/demoD.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ../sam --mouth 128 --throat 128 --pitch 64 --speed 72 --phonetic "AY4 PLEHJ AXLIYJAXNS TUH DHAX FLAEG, AXV DHIY YUWNAYTEHD STEYTS"; 4 | ../sam --mouth 128 --throat 128 --pitch 64 --speed 72 --phonetic "AXV AXMEHRIYKAX. AEND TUH DHAX RIYPAHBLIHK FOHR WIHCH IHT STAENDZ."; 5 | ../sam --mouth 128 --throat 128 --pitch 64 --speed 72 --phonetic "WAHN NEYSHAXN AHNDER GAA5AA8D"; 6 | ../sam --mouth 128 --throat 128 --pitch 64 --speed 72 --phonetic "IHNDIHVIH4ZAXBAXL, WIHTH LIHBERTTIY, AEND JAH4STIHS- FOHR AAL."; 7 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/exploser/sam 2 | 3 | require ( 4 | github.com/alexflint/go-arg v0.0.0-20180516182405-f7c0423bd11e 5 | github.com/alexflint/go-scalar v0.0.0-20170216020425-e80c3b7ed292 // indirect 6 | github.com/faiface/beep v0.0.0-20180613152729-fe13953ab844 7 | github.com/hajimehoshi/oto v0.0.0-20180624070912-2aa63a8d0216 8 | github.com/pkg/errors v0.8.0 9 | github.com/youpy/go-riff v0.0.0-20131220112943-557d78c11efb 10 | github.com/youpy/go-wav v0.0.0-20160223082350-b63a9887d320 11 | ) 12 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/alexflint/go-arg v0.0.0-20180516182405-f7c0423bd11e/go.mod h1:PHxo6ZWOLVMZZgWSAqBynb/KhIqoGO6WKwOVX7rM9dg= 2 | github.com/alexflint/go-scalar v0.0.0-20170216020425-e80c3b7ed292 h1:0YTMOir1UPjebSvNmIrEKO9FFd+RZc1wwZHUrxfn4BI= 3 | github.com/alexflint/go-scalar v0.0.0-20170216020425-e80c3b7ed292/go.mod h1:dgifnFPveotJNpwJdl1hDPu5vSuqVVUPIr3isfcvgBA= 4 | github.com/faiface/beep v0.0.0-20180613152729-fe13953ab844/go.mod h1:A22Xnws4HqzY9DZEtQCbYRbS1858XfgH6SCFUeRiXDI= 5 | github.com/hajimehoshi/oto v0.0.0-20180624070912-2aa63a8d0216/go.mod h1:Co7jIdNa4+UYZF0whfBysf8qY6o7oV8dFC1Ld//5HmY= 6 | github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 7 | github.com/youpy/go-riff v0.0.0-20131220112943-557d78c11efb/go.mod h1:83nxdDV4Z9RzrTut9losK7ve4hUnxUR8ASSz4BsKXwQ= 8 | github.com/youpy/go-wav v0.0.0-20160223082350-b63a9887d320/go.mod h1:Zf+Ju+8Ofy5zx/YWWArfcGnl5FAsWumLq/uHeRGgL60= 9 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "io/ioutil" 7 | "os" 8 | "strings" 9 | "text/tabwriter" 10 | "time" 11 | 12 | arg "github.com/alexflint/go-arg" 13 | "github.com/exploser/sam/config" 14 | "github.com/exploser/sam/reciter" 15 | "github.com/exploser/sam/render" 16 | "github.com/exploser/sam/sammain" 17 | 18 | "github.com/faiface/beep" 19 | "github.com/faiface/beep/speaker" 20 | wavplayer "github.com/faiface/beep/wav" 21 | wav "github.com/youpy/go-wav" 22 | ) 23 | 24 | func main() { 25 | var args struct { 26 | config.Config 27 | Wav string `arg:"-w" help:"output to wav instead of sound card"` 28 | Input []string `arg:"positional"` 29 | Phonetic bool `arg:"-P" help:"enters phonetic mode (use -g to show phonetic guide)"` 30 | PhoneticHelp bool `arg:"-g" help:"show phonetic guide"` 31 | } 32 | 33 | args.Config = *config.DefaultConfig() 34 | p := arg.MustParse(&args) 35 | 36 | if args.PhoneticHelp { 37 | printPhoneticGuide() 38 | return 39 | } 40 | 41 | if len(args.Input) == 0 { 42 | p.WriteHelp(os.Stdout) 43 | return 44 | } 45 | 46 | text := strings.Join(args.Input, " ") 47 | 48 | if len(text) > 256 { 49 | fmt.Println("Input text should be no more than 256 characters long") 50 | 51 | // TODO: fail properly instead of doing this. everywhere. 52 | os.Exit(7) 53 | } 54 | 55 | r := generateSpeech(text, &args.Config, args.Phonetic) 56 | outputSpeech(r, args.Wav) 57 | } 58 | 59 | func generateSpeech(input string, cfg *config.Config, phonetic bool) *render.Render { 60 | var data [256]byte 61 | input = strings.ToUpper(input) 62 | 63 | copy(data[:], input) 64 | 65 | l := len(input) 66 | 67 | if cfg.Debug { 68 | if phonetic { 69 | fmt.Printf("phonetic input: %s\n", string(data[:])) 70 | } else { 71 | fmt.Printf("text input: %s\n", string(data[:])) 72 | } 73 | } 74 | 75 | if !phonetic { 76 | if l < 256 { 77 | data[l] = '[' 78 | } 79 | 80 | rec := reciter.Reciter{} 81 | 82 | if !rec.TextToPhonemes(data[:], cfg) { 83 | os.Exit(1) 84 | } 85 | if cfg.Debug { 86 | fmt.Printf("phonetic input: %s\n", data) 87 | } 88 | } else if l < 256 { 89 | data[l] = '\x9b' 90 | } 91 | 92 | sam := sammain.Sam{ 93 | Config: cfg, 94 | } 95 | 96 | sam.SetInput(data) 97 | if !sam.SAMMain() { 98 | os.Exit(2) 99 | } 100 | 101 | r := render.Render{ 102 | Buffer: make([]byte, 22050*10), 103 | } 104 | 105 | sam.PrepareOutput(&r) 106 | 107 | return &r 108 | } 109 | 110 | func outputSpeech(r *render.Render, destination string) { 111 | if destination != "" { 112 | file, err := os.Create(destination) 113 | if err != nil { 114 | fmt.Println("Error: ", err) 115 | os.Exit(3) 116 | } 117 | _, err = wav.NewWriter(file, uint32(r.GetBufferLength()), 1, 22050, 8).Write(r.GetBuffer()) 118 | if err != nil { 119 | fmt.Println("Error: ", err) 120 | os.Exit(4) 121 | } 122 | } else { 123 | buf := &bytes.Buffer{} 124 | _, err := wav.NewWriter(buf, uint32(r.GetBufferLength()), 1, 22050, 8).Write(r.GetBuffer()) 125 | if err != nil { 126 | fmt.Println("Error: ", err) 127 | os.Exit(5) 128 | } 129 | reader := ioutil.NopCloser(bytes.NewReader(buf.Bytes())) 130 | s, format, err := wavplayer.Decode(reader) 131 | if err != nil { 132 | fmt.Println("Error: ", err) 133 | os.Exit(6) 134 | } 135 | 136 | speaker.Init(format.SampleRate, format.SampleRate.N(time.Second/10)) 137 | done := make(chan int) 138 | speaker.Play(beep.Seq(s, beep.Callback(func() { 139 | done <- 0 140 | }))) 141 | <-done 142 | // sleep for 0.25 to allow audio output to finish 143 | time.Sleep(time.Second / 2) 144 | } 145 | } 146 | 147 | func printPhoneticGuide() { 148 | w := tabwriter.NewWriter(os.Stdout, 4, 8, 1, '\t', 0) 149 | w.Write([]byte( 150 | `VOWELS VOICED CONSONANTS 151 | IY f(ee)t R red 152 | IH p(i)n L allow 153 | EH beg W away 154 | AE Sam W whale 155 | AA pot Y you 156 | AH b(u)dget M Sam 157 | AO t(al)k N man 158 | OH cone NX so(ng) 159 | UH book B bad 160 | UX l(oo)t D dog 161 | ER bird G again 162 | AX gall(o)n J judge 163 | IX dig(i)t Z zoo 164 | ZH plea(s)ure 165 | V seven 166 | DH (th)en 167 | 168 | DIPHTHONGS UNVOICED CONSONANTS 169 | EY m(a)de S Sam 170 | AY h(igh) Sh fish 171 | OY boy F fish 172 | AW h(ow) TH thin 173 | OW slow P poke 174 | UW crew T talk 175 | K cake 176 | CH speech 177 | /H (h)ead 178 | 179 | SPECIAL PHONEMES 180 | UL sett(le) (=AXL) 181 | UM astron(omy) (=AXM) 182 | UN functi(on) (=AXN) 183 | Q kitt-en (glottal stop) 184 | `)) 185 | w.Flush() 186 | } 187 | -------------------------------------------------------------------------------- /reciter/reciter.go: -------------------------------------------------------------------------------- 1 | package reciter 2 | 3 | import ( 4 | "github.com/exploser/sam/config" 5 | ) 6 | 7 | type Reciter struct { 8 | inputtemp [256]byte 9 | } 10 | 11 | func (rec *Reciter) TextToPhonemes(input []byte, cfg *config.Config) bool { 12 | var mem56, //output position for phonemes 13 | mem58, 14 | mem60, 15 | mem61, 16 | 17 | mem64, // position of '=' or current character 18 | mem65, // position of ')' 19 | mem66 byte // position of '(' 20 | var mem62 uint16 // memory position of current rule 21 | 22 | rec.inputtemp[0] = ' ' 23 | 24 | // secure copy of input 25 | // because input will be overwritten by phonemes 26 | X = 0 27 | for X < 255 { 28 | A = input[X] & 127 29 | if A >= 112 { 30 | A = A & 95 31 | } else if A >= 96 { 32 | A = A & 79 33 | } 34 | X++ 35 | rec.inputtemp[X] = A 36 | } 37 | rec.inputtemp[255] = 27 38 | mem56 = 255 39 | mem61 = 255 40 | 41 | var mem57 byte 42 | pos36554: 43 | for { 44 | for { 45 | mem61++ 46 | X = mem61 47 | mem64 = rec.inputtemp[X] 48 | if mem64 == '[' { 49 | mem56++ 50 | X = mem56 51 | input[X] = 155 52 | return true 53 | } 54 | 55 | if mem64 != '.' { 56 | break 57 | } 58 | X++ 59 | A = flags36376[rec.inputtemp[X]] & 1 60 | if A != 0 { 61 | break 62 | } 63 | mem56++ 64 | X = mem56 65 | A = '.' 66 | input[X] = '.' 67 | } 68 | mem57 = flags36376[mem64] 69 | if (mem57 & 2) != 0 { 70 | mem62 = 37541 71 | goto pos36700 72 | } 73 | 74 | if mem57 != 0 { 75 | break 76 | } 77 | rec.inputtemp[X] = ' ' 78 | mem56++ 79 | X = mem56 80 | if X > 120 { 81 | input[X] = 155 82 | return true 83 | } 84 | input[X] = 32 85 | } 86 | 87 | if !(mem57&128 != 0) { 88 | return false 89 | } 90 | 91 | // go to the right rules for this character. 92 | X = mem64 - 'A' 93 | mem62 = uint16(Tab37489[X]) | uint16(Tab37515[X])<<8 94 | 95 | pos36700: 96 | mem62++ 97 | // find next rule 98 | for (getRuleByte(mem62, 0) & 128) == 0 { 99 | mem62++ 100 | } 101 | var Y byte 102 | Y++ 103 | for getRuleByte(mem62, Y) != '(' { 104 | Y++ 105 | } 106 | mem66 = Y 107 | Y++ 108 | for getRuleByte(mem62, Y) != ')' { 109 | Y++ 110 | } 111 | mem65 = Y 112 | Y++ 113 | for (getRuleByte(mem62, Y) & 127) != '=' { 114 | Y++ 115 | } 116 | mem64 = Y 117 | 118 | mem60 = mem61 119 | X = mem61 120 | // compare the string within the bracket 121 | Y = mem66 + 1 122 | 123 | for { 124 | if getRuleByte(mem62, Y) != rec.inputtemp[X] { 125 | goto pos36700 126 | } 127 | Y++ 128 | if Y == mem65 { 129 | break 130 | } 131 | X++ 132 | mem60 = X 133 | } 134 | 135 | // the string in the bracket is correct 136 | 137 | mem59 := mem61 138 | 139 | for { 140 | for { 141 | mem66-- 142 | mem57 = getRuleByte(mem62, mem66) 143 | if (mem57 & 128) != 0 { 144 | mem58 = mem60 145 | goto pos37184 146 | } 147 | X = mem57 & 127 148 | if (flags36376[X] & 128) == 0 { 149 | break 150 | } 151 | if rec.inputtemp[mem59-1] != mem57 { 152 | goto pos36700 153 | } 154 | mem59-- 155 | } 156 | 157 | ch := mem57 158 | 159 | r := rec.handle_ch2(ch, mem59-1) 160 | if r == -1 { 161 | switch ch { 162 | case '&': 163 | if rec.getFlag(mem59-1, 16) == 0 { 164 | if rec.inputtemp[X] != 'H' { 165 | r = 1 166 | } else { 167 | X-- 168 | A = rec.inputtemp[X] 169 | if (A != 'C') && (A != 'S') { 170 | r = 1 171 | } 172 | } 173 | } 174 | break 175 | 176 | case '@': 177 | if rec.getFlag(mem59-1, 4) == 0 { 178 | A = rec.inputtemp[X] 179 | if A != 72 { 180 | r = 1 181 | } 182 | if (A != 84) && (A != 67) && (A != 83) { 183 | r = 1 184 | } 185 | } 186 | break 187 | case '+': 188 | X = mem59 189 | X-- 190 | A = rec.inputtemp[X] 191 | if (A != 'E') && (A != 'I') && (A != 0) { 192 | r = 1 193 | } 194 | break 195 | case ':': 196 | for rec.getFlag(mem59-1, 32) != 0 { 197 | mem59-- 198 | } 199 | continue 200 | default: 201 | return false 202 | } 203 | } 204 | 205 | if r == 1 { 206 | goto pos36700 207 | } 208 | mem59 = X 209 | } 210 | 211 | doWhileAEqualsPercent: 212 | // do ... while(A=='%') 213 | // for ok := true; ok; ok = (A == '%') { 214 | X = mem58 + 1 215 | if rec.inputtemp[X] == 'E' { 216 | if (flags36376[rec.inputtemp[X+1]] & 128) != 0 { 217 | X++ 218 | A = rec.inputtemp[X] 219 | if A == 'L' { 220 | X++ 221 | if rec.inputtemp[X] != 'Y' { 222 | goto pos36700 223 | } 224 | } else if (A != 'R') && (A != 'S') && (A != 'D') && rec.match("FUL") == 0 { 225 | goto pos36700 226 | } 227 | } 228 | } else { 229 | if rec.match("ING") == 0 { 230 | goto pos36700 231 | } 232 | mem58 = X 233 | } 234 | 235 | pos37184: 236 | r := 0 237 | // do ... while (r == 0); 238 | for ok := true; ok; ok = (r == 0) { 239 | var mem57 byte 240 | for { 241 | Y := mem65 + 1 242 | if Y == mem64 { 243 | mem61 = mem60 244 | 245 | if cfg.Debug { 246 | printRule(int(mem62)) 247 | } 248 | 249 | for { 250 | A = getRuleByte(mem62, Y) 251 | mem57 = A 252 | A = A & 127 253 | if A != '=' { 254 | mem56++ 255 | input[mem56] = A 256 | } 257 | if (mem57 & 128) != 0 { 258 | goto pos36554 259 | } 260 | Y++ 261 | } 262 | } 263 | mem65 = Y 264 | mem57 = getRuleByte(mem62, Y) 265 | if (flags36376[mem57] & 128) == 0 { 266 | break 267 | } 268 | if rec.inputtemp[mem58+1] != mem57 { 269 | r = 1 270 | break 271 | } 272 | mem58++ 273 | } 274 | 275 | if r == 0 { 276 | A = mem57 277 | if A == '@' { 278 | if rec.getFlag(mem58+1, 4) == 0 { 279 | A = rec.inputtemp[X] 280 | if (A != 82) && (A != 84) && 281 | (A != 67) && (A != 83) { 282 | r = 1 283 | } 284 | } else { 285 | r = -2 286 | } 287 | } else if A == ':' { 288 | for rec.getFlag(mem58+1, 32) != 0 { 289 | mem58 = X 290 | } 291 | r = -2 292 | } else { 293 | r = rec.handle_ch(A, mem58+1) 294 | } 295 | } 296 | 297 | if r == 1 { 298 | goto pos36700 299 | } 300 | if r == -2 { 301 | r = 0 302 | continue 303 | } 304 | if r == 0 { 305 | mem58 = X 306 | } 307 | } 308 | // } 309 | if A == '%' { 310 | goto doWhileAEqualsPercent 311 | } 312 | return false 313 | } 314 | -------------------------------------------------------------------------------- /reciter/tabs.go: -------------------------------------------------------------------------------- 1 | package reciter 2 | 3 | var ( 4 | //26 items. From 'A' to 'Z' 5 | // positions for mem62 and mem63 for each character 6 | Tab37489 = []byte{ 7 | 0, 149, 247, 162, 57, 197, 6, 126, 8 | 199, 38, 55, 78, 145, 241, 85, 161, 9 | 254, 36, 69, 45, 167, 54, 83, 46, 10 | 71, 218, 11 | } 12 | 13 | Tab37515 = []byte{ 14 | 125, 126, 126, 127, 128, 129, 130, 130, 15 | 130, 132, 132, 132, 132, 132, 133, 135, 16 | 135, 136, 136, 137, 138, 139, 139, 140, 17 | 140, 140, 18 | } 19 | 20 | flags36376 = []byte{ 21 | 0, 0, 0, 0, 0, 0, 0, 0, // 0-7 22 | 0, 0, 0, 0, 0, 0, 0, 0, // 8-15 23 | 0, 0, 0, 0, 0, 0, 0, 0, 24 | 0, 0, 0, 0, 0, 0, 0, 0, 25 | 0, 2, 2, 2, 2, 2, 2, 130, // ' ', '!' 26 | 0, 0, 2, 2, 2, 2, 2, 2, 27 | 3, 3, 3, 3, 3, 3, 3, 3, 28 | 3, 3, 2, 2, 2, 2, 2, 2, 29 | 2, 192, 168, 176, 172, 192, 160, 184, // '@', 'A' 30 | 160, 192, 188, 160, 172, 168, 172, 192, 31 | 160, 160, 172, 180, 164, 192, 168, 168, 32 | 176, 192, 188, 0, 0, 0, 2, 0, // 'X', 'Y', 'Z', '[', 33 | 32, 32, 155, 32, 192, 185, 32, 205, 34 | 163, 76, 138, 142, 35 | } 36 | 37 | Rules = []byte{ 38 | ']', 'A' | 0x80, 39 | ' ', '(', 'A', '.', ')', '=', 'E', 'H', '4', 'Y', '.', ' ' | 0x80, 40 | '(', 'A', ')', ' ', '=', 'A', 'H' | 0x80, 41 | ' ', '(', 'A', 'R', 'E', ')', ' ', '=', 'A', 'A', 'R' | 0x80, 42 | ' ', '(', 'A', 'R', ')', 'O', '=', 'A', 'X', 'R' | 0x80, 43 | '(', 'A', 'R', ')', '#', '=', 'E', 'H', '4', 'R' | 0x80, 44 | ' ', '^', '(', 'A', 'S', ')', '#', '=', 'E', 'Y', '4', 'S' | 0x80, 45 | '(', 'A', ')', 'W', 'A', '=', 'A', 'X' | 0x80, 46 | '(', 'A', 'W', ')', '=', 'A', 'O', '5' | 0x80, 47 | ' ', ':', '(', 'A', 'N', 'Y', ')', '=', 'E', 'H', '4', 'N', 'I', 'Y' | 0x80, 48 | '(', 'A', ')', '^', '+', '#', '=', 'E', 'Y', '5' | 0x80, 49 | '#', ':', '(', 'A', 'L', 'L', 'Y', ')', '=', 'U', 'L', 'I', 'Y' | 0x80, 50 | ' ', '(', 'A', 'L', ')', '#', '=', 'U', 'L' | 0x80, 51 | '(', 'A', 'G', 'A', 'I', 'N', ')', '=', 'A', 'X', 'G', 'E', 'H', '4', 'N' | 0x80, 52 | '#', ':', '(', 'A', 'G', ')', 'E', '=', 'I', 'H', 'J' | 0x80, 53 | '(', 'A', ')', '^', '%', '=', 'E', 'Y' | 0x80, 54 | '(', 'A', ')', '^', '+', ':', '#', '=', 'A', 'E' | 0x80, 55 | ' ', ':', '(', 'A', ')', '^', '+', ' ', '=', 'E', 'Y', '4' | 0x80, 56 | ' ', '(', 'A', 'R', 'R', ')', '=', 'A', 'X', 'R' | 0x80, 57 | '(', 'A', 'R', 'R', ')', '=', 'A', 'E', '4', 'R' | 0x80, 58 | ' ', '^', '(', 'A', 'R', ')', ' ', '=', 'A', 'A', '5', 'R' | 0x80, 59 | '(', 'A', 'R', ')', '=', 'A', 'A', '5', 'R' | 0x80, 60 | '(', 'A', 'I', 'R', ')', '=', 'E', 'H', '4', 'R' | 0x80, 61 | '(', 'A', 'I', ')', '=', 'E', 'Y', '4' | 0x80, 62 | '(', 'A', 'Y', ')', '=', 'E', 'Y', '5' | 0x80, 63 | '(', 'A', 'U', ')', '=', 'A', 'O', '4' | 0x80, 64 | '#', ':', '(', 'A', 'L', ')', ' ', '=', 'U', 'L' | 0x80, 65 | '#', ':', '(', 'A', 'L', 'S', ')', ' ', '=', 'U', 'L', 'Z' | 0x80, 66 | '(', 'A', 'L', 'K', ')', '=', 'A', 'O', '4', 'K' | 0x80, 67 | '(', 'A', 'L', ')', '^', '=', 'A', 'O', 'L' | 0x80, 68 | ' ', ':', '(', 'A', 'B', 'L', 'E', ')', '=', 'E', 'Y', '4', 'B', 'U', 'L' | 0x80, 69 | '(', 'A', 'B', 'L', 'E', ')', '=', 'A', 'X', 'B', 'U', 'L' | 0x80, 70 | '(', 'A', ')', 'V', 'O', '=', 'E', 'Y', '4' | 0x80, 71 | '(', 'A', 'N', 'G', ')', '+', '=', 'E', 'Y', '4', 'N', 'J' | 0x80, 72 | '(', 'A', 'T', 'A', 'R', 'I', ')', '=', 'A', 'H', 'T', 'A', 'A', '4', 'R', 'I', 'Y' | 0x80, 73 | '(', 'A', ')', 'T', 'O', 'M', '=', 'A', 'E' | 0x80, 74 | '(', 'A', ')', 'T', 'T', 'I', '=', 'A', 'E' | 0x80, 75 | ' ', '(', 'A', 'T', ')', ' ', '=', 'A', 'E', 'T' | 0x80, 76 | ' ', '(', 'A', ')', 'T', '=', 'A', 'H' | 0x80, 77 | '(', 'A', ')', '=', 'A', 'E' | 0x80, 78 | 79 | ']', 'B' | 0x80, 80 | ' ', '(', 'B', ')', ' ', '=', 'B', 'I', 'Y', '4' | 0x80, 81 | ' ', '(', 'B', 'E', ')', '^', '#', '=', 'B', 'I', 'H' | 0x80, 82 | '(', 'B', 'E', 'I', 'N', 'G', ')', '=', 'B', 'I', 'Y', '4', 'I', 'H', 'N', 'X' | 0x80, 83 | ' ', '(', 'B', 'O', 'T', 'H', ')', ' ', '=', 'B', 'O', 'W', '4', 'T', 'H' | 0x80, 84 | ' ', '(', 'B', 'U', 'S', ')', '#', '=', 'B', 'I', 'H', '4', 'Z' | 0x80, 85 | '(', 'B', 'R', 'E', 'A', 'K', ')', '=', 'B', 'R', 'E', 'Y', '5', 'K' | 0x80, 86 | '(', 'B', 'U', 'I', 'L', ')', '=', 'B', 'I', 'H', '4', 'L' | 0x80, 87 | '(', 'B', ')', '=', 'B' | 0x80, 88 | 89 | ']', 'C' | 0x80, 90 | ' ', '(', 'C', ')', ' ', '=', 'S', 'I', 'Y', '4' | 0x80, 91 | ' ', '(', 'C', 'H', ')', '^', '=', 'K' | 0x80, 92 | '^', 'E', '(', 'C', 'H', ')', '=', 'K' | 0x80, 93 | '(', 'C', 'H', 'A', ')', 'R', '#', '=', 'K', 'E', 'H', '5' | 0x80, 94 | '(', 'C', 'H', ')', '=', 'C', 'H' | 0x80, 95 | ' ', 'S', '(', 'C', 'I', ')', '#', '=', 'S', 'A', 'Y', '4' | 0x80, 96 | '(', 'C', 'I', ')', 'A', '=', 'S', 'H' | 0x80, 97 | '(', 'C', 'I', ')', 'O', '=', 'S', 'H' | 0x80, 98 | '(', 'C', 'I', ')', 'E', 'N', '=', 'S', 'H' | 0x80, 99 | '(', 'C', 'I', 'T', 'Y', ')', '=', 'S', 'I', 'H', 'T', 'I', 'Y' | 0x80, 100 | '(', 'C', ')', '+', '=', 'S' | 0x80, 101 | '(', 'C', 'K', ')', '=', 'K' | 0x80, 102 | '(', 'C', 'O', 'M', 'M', 'O', 'D', 'O', 'R', 'E', ')', '=', 'K', 'A', 'A', '4', 'M', 'A', 'H', 'D', 'O', 'H', 'R' | 0x80, 103 | '(', 'C', 'O', 'M', ')', '=', 'K', 'A', 'H', 'M' | 0x80, 104 | '(', 'C', 'U', 'I', 'T', ')', '=', 'K', 'I', 'H', 'T' | 0x80, 105 | '(', 'C', 'R', 'E', 'A', ')', '=', 'K', 'R', 'I', 'Y', 'E', 'Y' | 0x80, 106 | '(', 'C', ')', '=', 'K' | 0x80, 107 | 108 | ']', 'D' | 0x80, 109 | ' ', '(', 'D', ')', ' ', '=', 'D', 'I', 'Y', '4' | 0x80, 110 | ' ', '(', 'D', 'R', '.', ')', ' ', '=', 'D', 'A', 'A', '4', 'K', 'T', 'E', 'R' | 0x80, 111 | '#', ':', '(', 'D', 'E', 'D', ')', ' ', '=', 'D', 'I', 'H', 'D' | 0x80, 112 | '.', 'E', '(', 'D', ')', ' ', '=', 'D' | 0x80, 113 | '#', ':', '^', 'E', '(', 'D', ')', ' ', '=', 'T' | 0x80, 114 | ' ', '(', 'D', 'E', ')', '^', '#', '=', 'D', 'I', 'H' | 0x80, 115 | ' ', '(', 'D', 'O', ')', ' ', '=', 'D', 'U', 'W' | 0x80, 116 | ' ', '(', 'D', 'O', 'E', 'S', ')', '=', 'D', 'A', 'H', 'Z' | 0x80, 117 | '(', 'D', 'O', 'N', 'E', ')', ' ', '=', 'D', 'A', 'H', '5', 'N' | 0x80, 118 | '(', 'D', 'O', 'I', 'N', 'G', ')', '=', 'D', 'U', 'W', '4', 'I', 'H', 'N', 'X' | 0x80, 119 | ' ', '(', 'D', 'O', 'W', ')', '=', 'D', 'A', 'W' | 0x80, 120 | '#', '(', 'D', 'U', ')', 'A', '=', 'J', 'U', 'W' | 0x80, 121 | '#', '(', 'D', 'U', ')', '^', '#', '=', 'J', 'A', 'X' | 0x80, 122 | '(', 'D', ')', '=', 'D' | 0x80, 123 | 124 | ']', 'E' | 0x80, 125 | ' ', '(', 'E', ')', ' ', '=', 'I', 'Y', 'I', 'Y', '4' | 0x80, 126 | '#', ':', '(', 'E', ')', ' ', '=' | 0x80, 127 | '\'', ':', '^', '(', 'E', ')', ' ', '=' | 0x80, 128 | ' ', ':', '(', 'E', ')', ' ', '=', 'I', 'Y' | 0x80, 129 | '#', '(', 'E', 'D', ')', ' ', '=', 'D' | 0x80, 130 | '#', ':', '(', 'E', ')', 'D', ' ', '=' | 0x80, 131 | '(', 'E', 'V', ')', 'E', 'R', '=', 'E', 'H', '4', 'V' | 0x80, 132 | '(', 'E', ')', '^', '%', '=', 'I', 'Y', '4' | 0x80, 133 | '(', 'E', 'R', 'I', ')', '#', '=', 'I', 'Y', '4', 'R', 'I', 'Y' | 0x80, 134 | '(', 'E', 'R', 'I', ')', '=', 'E', 'H', '4', 'R', 'I', 'H' | 0x80, 135 | '#', ':', '(', 'E', 'R', ')', '#', '=', 'E', 'R' | 0x80, 136 | '(', 'E', 'R', 'R', 'O', 'R', ')', '=', 'E', 'H', '4', 'R', 'O', 'H', 'R' | 0x80, 137 | '(', 'E', 'R', 'A', 'S', 'E', ')', '=', 'I', 'H', 'R', 'E', 'Y', '5', 'S' | 0x80, 138 | '(', 'E', 'R', ')', '#', '=', 'E', 'H', 'R' | 0x80, 139 | '(', 'E', 'R', ')', '=', 'E', 'R' | 0x80, 140 | ' ', '(', 'E', 'V', 'E', 'N', ')', '=', 'I', 'Y', 'V', 'E', 'H', 'N' | 0x80, 141 | '#', ':', '(', 'E', ')', 'W', '=' | 0x80, 142 | '@', '(', 'E', 'W', ')', '=', 'U', 'W' | 0x80, 143 | '(', 'E', 'W', ')', '=', 'Y', 'U', 'W' | 0x80, 144 | '(', 'E', ')', 'O', '=', 'I', 'Y' | 0x80, 145 | '#', ':', '&', '(', 'E', 'S', ')', ' ', '=', 'I', 'H', 'Z' | 0x80, 146 | '#', ':', '(', 'E', ')', 'S', ' ', '=' | 0x80, 147 | '#', ':', '(', 'E', 'L', 'Y', ')', ' ', '=', 'L', 'I', 'Y' | 0x80, 148 | '#', ':', '(', 'E', 'M', 'E', 'N', 'T', ')', '=', 'M', 'E', 'H', 'N', 'T' | 0x80, 149 | '(', 'E', 'F', 'U', 'L', ')', '=', 'F', 'U', 'H', 'L' | 0x80, 150 | '(', 'E', 'E', ')', '=', 'I', 'Y', '4' | 0x80, 151 | '(', 'E', 'A', 'R', 'N', ')', '=', 'E', 'R', '5', 'N' | 0x80, 152 | ' ', '(', 'E', 'A', 'R', ')', '^', '=', 'E', 'R', '5' | 0x80, 153 | '(', 'E', 'A', 'D', ')', '=', 'E', 'H', 'D' | 0x80, 154 | '#', ':', '(', 'E', 'A', ')', ' ', '=', 'I', 'Y', 'A', 'X' | 0x80, 155 | '(', 'E', 'A', ')', 'S', 'U', '=', 'E', 'H', '5' | 0x80, 156 | '(', 'E', 'A', ')', '=', 'I', 'Y', '5' | 0x80, 157 | '(', 'E', 'I', 'G', 'H', ')', '=', 'E', 'Y', '4' | 0x80, 158 | '(', 'E', 'I', ')', '=', 'I', 'Y', '4' | 0x80, 159 | ' ', '(', 'E', 'Y', 'E', ')', '=', 'A', 'Y', '4' | 0x80, 160 | '(', 'E', 'Y', ')', '=', 'I', 'Y' | 0x80, 161 | '(', 'E', 'U', ')', '=', 'Y', 'U', 'W', '5' | 0x80, 162 | '(', 'E', 'Q', 'U', 'A', 'L', ')', '=', 'I', 'Y', '4', 'K', 'W', 'U', 'L' | 0x80, 163 | '(', 'E', ')', '=', 'E', 'H' | 0x80, 164 | 165 | ']', 'F' | 0x80, 166 | ' ', '(', 'F', ')', ' ', '=', 'E', 'H', '4', 'F' | 0x80, 167 | '(', 'F', 'U', 'L', ')', '=', 'F', 'U', 'H', 'L' | 0x80, 168 | '(', 'F', 'R', 'I', 'E', 'N', 'D', ')', '=', 'F', 'R', 'E', 'H', '5', 'N', 'D' | 0x80, 169 | '(', 'F', 'A', 'T', 'H', 'E', 'R', ')', '=', 'F', 'A', 'A', '4', 'D', 'H', 'E', 'R' | 0x80, 170 | '(', 'F', ')', 'F', '=' | 0x80, 171 | '(', 'F', ')', '=', 'F' | 0x80, 172 | 173 | ']', 'G' | 0x80, 174 | ' ', '(', 'G', ')', ' ', '=', 'J', 'I', 'Y', '4' | 0x80, 175 | '(', 'G', 'I', 'V', ')', '=', 'G', 'I', 'H', '5', 'V' | 0x80, 176 | ' ', '(', 'G', ')', 'I', '^', '=', 'G' | 0x80, 177 | '(', 'G', 'E', ')', 'T', '=', 'G', 'E', 'H', '5' | 0x80, 178 | 'S', 'U', '(', 'G', 'G', 'E', 'S', ')', '=', 'G', 'J', 'E', 'H', '4', 'S' | 0x80, 179 | '(', 'G', 'G', ')', '=', 'G' | 0x80, 180 | ' ', 'B', '#', '(', 'G', ')', '=', 'G' | 0x80, 181 | '(', 'G', ')', '+', '=', 'J' | 0x80, 182 | '(', 'G', 'R', 'E', 'A', 'T', ')', '=', 'G', 'R', 'E', 'Y', '4', 'T' | 0x80, 183 | '(', 'G', 'O', 'N', ')', 'E', '=', 'G', 'A', 'O', '5', 'N' | 0x80, 184 | '#', '(', 'G', 'H', ')', '=' | 0x80, 185 | ' ', '(', 'G', 'N', ')', '=', 'N' | 0x80, 186 | '(', 'G', ')', '=', 'G' | 0x80, 187 | 188 | ']', 'H' | 0x80, 189 | ' ', '(', 'H', ')', ' ', '=', 'E', 'Y', '4', 'C', 'H' | 0x80, 190 | ' ', '(', 'H', 'A', 'V', ')', '=', '/', 'H', 'A', 'E', '6', 'V' | 0x80, 191 | ' ', '(', 'H', 'E', 'R', 'E', ')', '=', '/', 'H', 'I', 'Y', 'R' | 0x80, 192 | ' ', '(', 'H', 'O', 'U', 'R', ')', '=', 'A', 'W', '5', 'E', 'R' | 0x80, 193 | '(', 'H', 'O', 'W', ')', '=', '/', 'H', 'A', 'W' | 0x80, 194 | '(', 'H', ')', '#', '=', '/', 'H' | 0x80, 195 | '(', 'H', ')', '=' | 0x80, 196 | 197 | ']', 'I' | 0x80, 198 | ' ', '(', 'I', 'N', ')', '=', 'I', 'H', 'N' | 0x80, 199 | ' ', '(', 'I', ')', ' ', '=', 'A', 'Y', '4' | 0x80, 200 | '(', 'I', ')', ' ', '=', 'A', 'Y' | 0x80, 201 | '(', 'I', 'N', ')', 'D', '=', 'A', 'Y', '5', 'N' | 0x80, 202 | 'S', 'E', 'M', '(', 'I', ')', '=', 'I', 'Y' | 0x80, 203 | ' ', 'A', 'N', 'T', '(', 'I', ')', '=', 'A', 'Y' | 0x80, 204 | '(', 'I', 'E', 'R', ')', '=', 'I', 'Y', 'E', 'R' | 0x80, 205 | '#', ':', 'R', '(', 'I', 'E', 'D', ')', ' ', '=', 'I', 'Y', 'D' | 0x80, 206 | '(', 'I', 'E', 'D', ')', ' ', '=', 'A', 'Y', '5', 'D' | 0x80, 207 | '(', 'I', 'E', 'N', ')', '=', 'I', 'Y', 'E', 'H', 'N' | 0x80, 208 | '(', 'I', 'E', ')', 'T', '=', 'A', 'Y', '4', 'E', 'H' | 0x80, 209 | '(', 'I', '\'', ')', '=', 'A', 'Y', '5' | 0x80, 210 | ' ', ':', '(', 'I', ')', '^', '%', '=', 'A', 'Y', '5' | 0x80, 211 | ' ', ':', '(', 'I', 'E', ')', ' ', '=', 'A', 'Y', '4' | 0x80, 212 | '(', 'I', ')', '%', '=', 'I', 'Y' | 0x80, 213 | '(', 'I', 'E', ')', '=', 'I', 'Y', '4' | 0x80, 214 | ' ', '(', 'I', 'D', 'E', 'A', ')', '=', 'A', 'Y', 'D', 'I', 'Y', '5', 'A', 'H' | 0x80, 215 | '(', 'I', ')', '^', '+', ':', '#', '=', 'I', 'H' | 0x80, 216 | '(', 'I', 'R', ')', '#', '=', 'A', 'Y', 'R' | 0x80, 217 | '(', 'I', 'Z', ')', '%', '=', 'A', 'Y', 'Z' | 0x80, 218 | '(', 'I', 'S', ')', '%', '=', 'A', 'Y', 'Z' | 0x80, 219 | 'I', '^', '(', 'I', ')', '^', '#', '=', 'I', 'H' | 0x80, 220 | '+', '^', '(', 'I', ')', '^', '+', '=', 'A', 'Y' | 0x80, 221 | '#', ':', '^', '(', 'I', ')', '^', '+', '=', 'I', 'H' | 0x80, 222 | '(', 'I', ')', '^', '+', '=', 'A', 'Y' | 0x80, 223 | '(', 'I', 'R', ')', '=', 'E', 'R' | 0x80, 224 | '(', 'I', 'G', 'H', ')', '=', 'A', 'Y', '4' | 0x80, 225 | '(', 'I', 'L', 'D', ')', '=', 'A', 'Y', '5', 'L', 'D' | 0x80, 226 | ' ', '(', 'I', 'G', 'N', ')', '=', 'I', 'H', 'G', 'N' | 0x80, 227 | '(', 'I', 'G', 'N', ')', ' ', '=', 'A', 'Y', '4', 'N' | 0x80, 228 | '(', 'I', 'G', 'N', ')', '^', '=', 'A', 'Y', '4', 'N' | 0x80, 229 | '(', 'I', 'G', 'N', ')', '%', '=', 'A', 'Y', '4', 'N' | 0x80, 230 | '(', 'I', 'C', 'R', 'O', ')', '=', 'A', 'Y', '4', 'K', 'R', 'O', 'H' | 0x80, 231 | '(', 'I', 'Q', 'U', 'E', ')', '=', 'I', 'Y', '4', 'K' | 0x80, 232 | '(', 'I', ')', '=', 'I', 'H' | 0x80, 233 | 234 | ']', 'J' | 0x80, 235 | ' ', '(', 'J', ')', ' ', '=', 'J', 'E', 'Y', '4' | 0x80, 236 | '(', 'J', ')', '=', 'J' | 0x80, 237 | 238 | ']', 'K' | 0x80, 239 | ' ', '(', 'K', ')', ' ', '=', 'K', 'E', 'Y', '4' | 0x80, 240 | ' ', '(', 'K', ')', 'N', '=' | 0x80, 241 | '(', 'K', ')', '=', 'K' | 0x80, 242 | 243 | ']', 'L' | 0x80, 244 | ' ', '(', 'L', ')', ' ', '=', 'E', 'H', '4', 'L' | 0x80, 245 | '(', 'L', 'O', ')', 'C', '#', '=', 'L', 'O', 'W' | 0x80, 246 | 'L', '(', 'L', ')', '=' | 0x80, 247 | '#', ':', '^', '(', 'L', ')', '%', '=', 'U', 'L' | 0x80, 248 | '(', 'L', 'E', 'A', 'D', ')', '=', 'L', 'I', 'Y', 'D' | 0x80, 249 | ' ', '(', 'L', 'A', 'U', 'G', 'H', ')', '=', 'L', 'A', 'E', '4', 'F' | 0x80, 250 | '(', 'L', ')', '=', 'L' | 0x80, 251 | 252 | ']', 'M' | 0x80, 253 | ' ', '(', 'M', ')', ' ', '=', 'E', 'H', '4', 'M' | 0x80, 254 | ' ', '(', 'M', 'R', '.', ')', ' ', '=', 'M', 'I', 'H', '4', 'S', 'T', 'E', 'R' | 0x80, 255 | ' ', '(', 'M', 'S', '.', ')', '=', 'M', 'I', 'H', '5', 'Z' | 0x80, 256 | ' ', '(', 'M', 'R', 'S', '.', ')', ' ', '=', 'M', 'I', 'H', '4', 'S', 'I', 'X', 'Z' | 0x80, 257 | '(', 'M', 'O', 'V', ')', '=', 'M', 'U', 'W', '4', 'V' | 0x80, 258 | '(', 'M', 'A', 'C', 'H', 'I', 'N', ')', '=', 'M', 'A', 'H', 'S', 'H', 'I', 'Y', '5', 'N' | 0x80, 259 | 'M', '(', 'M', ')', '=' | 0x80, 260 | '(', 'M', ')', '=', 'M' | 0x80, 261 | 262 | ']', 'N' | 0x80, 263 | ' ', '(', 'N', ')', ' ', '=', 'E', 'H', '4', 'N' | 0x80, 264 | 'E', '(', 'N', 'G', ')', '+', '=', 'N', 'J' | 0x80, 265 | '(', 'N', 'G', ')', 'R', '=', 'N', 'X', 'G' | 0x80, 266 | '(', 'N', 'G', ')', '#', '=', 'N', 'X', 'G' | 0x80, 267 | '(', 'N', 'G', 'L', ')', '%', '=', 'N', 'X', 'G', 'U', 'L' | 0x80, 268 | '(', 'N', 'G', ')', '=', 'N', 'X' | 0x80, 269 | '(', 'N', 'K', ')', '=', 'N', 'X', 'K' | 0x80, 270 | ' ', '(', 'N', 'O', 'W', ')', ' ', '=', 'N', 'A', 'W', '4' | 0x80, 271 | 'N', '(', 'N', ')', '=' | 0x80, 272 | '(', 'N', 'O', 'N', ')', 'E', '=', 'N', 'A', 'H', '4', 'N' | 0x80, 273 | '(', 'N', ')', '=', 'N' | 0x80, 274 | 275 | ']', 'O' | 0x80, 276 | ' ', '(', 'O', ')', ' ', '=', 'O', 'H', '4', 'W' | 0x80, 277 | '(', 'O', 'F', ')', ' ', '=', 'A', 'H', 'V' | 0x80, 278 | ' ', '(', 'O', 'H', ')', ' ', '=', 'O', 'W', '5' | 0x80, 279 | '(', 'O', 'R', 'O', 'U', 'G', 'H', ')', '=', 'E', 'R', '4', 'O', 'W' | 0x80, 280 | '#', ':', '(', 'O', 'R', ')', ' ', '=', 'E', 'R' | 0x80, 281 | '#', ':', '(', 'O', 'R', 'S', ')', ' ', '=', 'E', 'R', 'Z' | 0x80, 282 | '(', 'O', 'R', ')', '=', 'A', 'O', 'R' | 0x80, 283 | ' ', '(', 'O', 'N', 'E', ')', '=', 'W', 'A', 'H', 'N' | 0x80, 284 | '#', '(', 'O', 'N', 'E', ')', ' ', '=', 'W', 'A', 'H', 'N' | 0x80, 285 | '(', 'O', 'W', ')', '=', 'O', 'W' | 0x80, 286 | ' ', '(', 'O', 'V', 'E', 'R', ')', '=', 'O', 'W', '5', 'V', 'E', 'R' | 0x80, 287 | 'P', 'R', '(', 'O', ')', 'V', '=', 'U', 'W', '4' | 0x80, 288 | '(', 'O', 'V', ')', '=', 'A', 'H', '4', 'V' | 0x80, 289 | '(', 'O', ')', '^', '%', '=', 'O', 'W', '5' | 0x80, 290 | '(', 'O', ')', '^', 'E', 'N', '=', 'O', 'W' | 0x80, 291 | '(', 'O', ')', '^', 'I', '#', '=', 'O', 'W', '5' | 0x80, 292 | '(', 'O', 'L', ')', 'D', '=', 'O', 'W', '4', 'L' | 0x80, 293 | '(', 'O', 'U', 'G', 'H', 'T', ')', '=', 'A', 'O', '5', 'T' | 0x80, 294 | '(', 'O', 'U', 'G', 'H', ')', '=', 'A', 'H', '5', 'F' | 0x80, 295 | ' ', '(', 'O', 'U', ')', '=', 'A', 'W' | 0x80, 296 | 'H', '(', 'O', 'U', ')', 'S', '#', '=', 'A', 'W', '4' | 0x80, 297 | '(', 'O', 'U', 'S', ')', '=', 'A', 'X', 'S' | 0x80, 298 | '(', 'O', 'U', 'R', ')', '=', 'O', 'H', 'R' | 0x80, 299 | '(', 'O', 'U', 'L', 'D', ')', '=', 'U', 'H', '5', 'D' | 0x80, 300 | '(', 'O', 'U', ')', '^', 'L', '=', 'A', 'H', '5' | 0x80, 301 | '(', 'O', 'U', 'P', ')', '=', 'U', 'W', '5', 'P' | 0x80, 302 | '(', 'O', 'U', ')', '=', 'A', 'W' | 0x80, 303 | '(', 'O', 'Y', ')', '=', 'O', 'Y' | 0x80, 304 | '(', 'O', 'I', 'N', 'G', ')', '=', 'O', 'W', '4', 'I', 'H', 'N', 'X' | 0x80, 305 | '(', 'O', 'I', ')', '=', 'O', 'Y', '5' | 0x80, 306 | '(', 'O', 'O', 'R', ')', '=', 'O', 'H', '5', 'R' | 0x80, 307 | '(', 'O', 'O', 'K', ')', '=', 'U', 'H', '5', 'K' | 0x80, 308 | 'F', '(', 'O', 'O', 'D', ')', '=', 'U', 'W', '5', 'D' | 0x80, 309 | 'L', '(', 'O', 'O', 'D', ')', '=', 'A', 'H', '5', 'D' | 0x80, 310 | 'M', '(', 'O', 'O', 'D', ')', '=', 'U', 'W', '5', 'D' | 0x80, 311 | '(', 'O', 'O', 'D', ')', '=', 'U', 'H', '5', 'D' | 0x80, 312 | 'F', '(', 'O', 'O', 'T', ')', '=', 'U', 'H', '5', 'T' | 0x80, 313 | '(', 'O', 'O', ')', '=', 'U', 'W', '5' | 0x80, 314 | '(', 'O', '\'', ')', '=', 'O', 'H' | 0x80, 315 | '(', 'O', ')', 'E', '=', 'O', 'W' | 0x80, 316 | '(', 'O', ')', ' ', '=', 'O', 'W' | 0x80, 317 | '(', 'O', 'A', ')', '=', 'O', 'W', '4' | 0x80, 318 | ' ', '(', 'O', 'N', 'L', 'Y', ')', '=', 'O', 'W', '4', 'N', 'L', 'I', 'Y' | 0x80, 319 | ' ', '(', 'O', 'N', 'C', 'E', ')', '=', 'W', 'A', 'H', '4', 'N', 'S' | 0x80, 320 | '(', 'O', 'N', '\'', 'T', ')', '=', 'O', 'W', '4', 'N', 'T' | 0x80, 321 | 'C', '(', 'O', ')', 'N', '=', 'A', 'A' | 0x80, 322 | '(', 'O', ')', 'N', 'G', '=', 'A', 'O' | 0x80, 323 | ' ', ':', '^', '(', 'O', ')', 'N', '=', 'A', 'H' | 0x80, 324 | 'I', '(', 'O', 'N', ')', '=', 'U', 'N' | 0x80, 325 | '#', ':', '(', 'O', 'N', ')', '=', 'U', 'N' | 0x80, 326 | '#', '^', '(', 'O', 'N', ')', '=', 'U', 'N' | 0x80, 327 | '(', 'O', ')', 'S', 'T', '=', 'O', 'W' | 0x80, 328 | '(', 'O', 'F', ')', '^', '=', 'A', 'O', '4', 'F' | 0x80, 329 | '(', 'O', 'T', 'H', 'E', 'R', ')', '=', 'A', 'H', '5', 'D', 'H', 'E', 'R' | 0x80, 330 | 'R', '(', 'O', ')', 'B', '=', 'R', 'A', 'A' | 0x80, 331 | '^', 'R', '(', 'O', ')', ':', '#', '=', 'O', 'W', '5' | 0x80, 332 | '(', 'O', 'S', 'S', ')', ' ', '=', 'A', 'O', '5', 'S' | 0x80, 333 | '#', ':', '^', '(', 'O', 'M', ')', '=', 'A', 'H', 'M' | 0x80, 334 | '(', 'O', ')', '=', 'A', 'A' | 0x80, 335 | 336 | ']', 'P' | 0x80, 337 | ' ', '(', 'P', ')', ' ', '=', 'P', 'I', 'Y', '4' | 0x80, 338 | '(', 'P', 'H', ')', '=', 'F' | 0x80, 339 | '(', 'P', 'E', 'O', 'P', 'L', ')', '=', 'P', 'I', 'Y', '5', 'P', 'U', 'L' | 0x80, 340 | '(', 'P', 'O', 'W', ')', '=', 'P', 'A', 'W', '4' | 0x80, 341 | '(', 'P', 'U', 'T', ')', ' ', '=', 'P', 'U', 'H', 'T' | 0x80, 342 | '(', 'P', ')', 'P', '=' | 0x80, 343 | '(', 'P', ')', 'S', '=' | 0x80, 344 | '(', 'P', ')', 'N', '=' | 0x80, 345 | '(', 'P', 'R', 'O', 'F', '.', ')', '=', 'P', 'R', 'O', 'H', 'F', 'E', 'H', '4', 'S', 'E', 'R' | 0x80, 346 | '(', 'P', ')', '=', 'P' | 0x80, 347 | 348 | ']', 'Q' | 0x80, 349 | ' ', '(', 'Q', ')', ' ', '=', 'K', 'Y', 'U', 'W', '4' | 0x80, 350 | '(', 'Q', 'U', 'A', 'R', ')', '=', 'K', 'W', 'O', 'H', '5', 'R' | 0x80, 351 | '(', 'Q', 'U', ')', '=', 'K', 'W' | 0x80, 352 | '(', 'Q', ')', '=', 'K' | 0x80, 353 | ']', 'R' | 0x80, 354 | ' ', '(', 'R', ')', ' ', '=', 'A', 'A', '5', 'R' | 0x80, 355 | ' ', '(', 'R', 'E', ')', '^', '#', '=', 'R', 'I', 'Y' | 0x80, 356 | '(', 'R', ')', 'R', '=' | 0x80, 357 | '(', 'R', ')', '=', 'R' | 0x80, 358 | 359 | ']', 'S' | 0x80, 360 | ' ', '(', 'S', ')', ' ', '=', 'E', 'H', '4', 'S' | 0x80, 361 | '(', 'S', 'H', ')', '=', 'S', 'H' | 0x80, 362 | '#', '(', 'S', 'I', 'O', 'N', ')', '=', 'Z', 'H', 'U', 'N' | 0x80, 363 | '(', 'S', 'O', 'M', 'E', ')', '=', 'S', 'A', 'H', 'M' | 0x80, 364 | '#', '(', 'S', 'U', 'R', ')', '#', '=', 'Z', 'H', 'E', 'R' | 0x80, 365 | '(', 'S', 'U', 'R', ')', '#', '=', 'S', 'H', 'E', 'R' | 0x80, 366 | '#', '(', 'S', 'U', ')', '#', '=', 'Z', 'H', 'U', 'W' | 0x80, 367 | '#', '(', 'S', 'S', 'U', ')', '#', '=', 'S', 'H', 'U', 'W' | 0x80, 368 | '#', '(', 'S', 'E', 'D', ')', '=', 'Z', 'D' | 0x80, 369 | '#', '(', 'S', ')', '#', '=', 'Z' | 0x80, 370 | '(', 'S', 'A', 'I', 'D', ')', '=', 'S', 'E', 'H', 'D' | 0x80, 371 | '^', '(', 'S', 'I', 'O', 'N', ')', '=', 'S', 'H', 'U', 'N' | 0x80, 372 | '(', 'S', ')', 'S', '=' | 0x80, 373 | '.', '(', 'S', ')', ' ', '=', 'Z' | 0x80, 374 | '#', ':', '.', 'E', '(', 'S', ')', ' ', '=', 'Z' | 0x80, 375 | '#', ':', '^', '#', '(', 'S', ')', ' ', '=', 'S' | 0x80, 376 | 'U', '(', 'S', ')', ' ', '=', 'S' | 0x80, 377 | ' ', ':', '#', '(', 'S', ')', ' ', '=', 'Z' | 0x80, 378 | '#', '#', '(', 'S', ')', ' ', '=', 'Z' | 0x80, 379 | ' ', '(', 'S', 'C', 'H', ')', '=', 'S', 'K' | 0x80, 380 | '(', 'S', ')', 'C', '+', '=' | 0x80, 381 | '#', '(', 'S', 'M', ')', '=', 'Z', 'U', 'M' | 0x80, 382 | '#', '(', 'S', 'N', ')', '\'', '=', 'Z', 'U', 'M' | 0x80, 383 | '(', 'S', 'T', 'L', 'E', ')', '=', 'S', 'U', 'L' | 0x80, 384 | '(', 'S', ')', '=', 'S' | 0x80, 385 | 386 | ']', 'T' | 0x80, 387 | ' ', '(', 'T', ')', ' ', '=', 'T', 'I', 'Y', '4' | 0x80, 388 | ' ', '(', 'T', 'H', 'E', ')', ' ', '#', '=', 'D', 'H', 'I', 'Y' | 0x80, 389 | ' ', '(', 'T', 'H', 'E', ')', ' ', '=', 'D', 'H', 'A', 'X' | 0x80, 390 | '(', 'T', 'O', ')', ' ', '=', 'T', 'U', 'X' | 0x80, 391 | ' ', '(', 'T', 'H', 'A', 'T', ')', '=', 'D', 'H', 'A', 'E', 'T' | 0x80, 392 | ' ', '(', 'T', 'H', 'I', 'S', ')', ' ', '=', 'D', 'H', 'I', 'H', 'S' | 0x80, 393 | ' ', '(', 'T', 'H', 'E', 'Y', ')', '=', 'D', 'H', 'E', 'Y' | 0x80, 394 | ' ', '(', 'T', 'H', 'E', 'R', 'E', ')', '=', 'D', 'H', 'E', 'H', 'R' | 0x80, 395 | '(', 'T', 'H', 'E', 'R', ')', '=', 'D', 'H', 'E', 'R' | 0x80, 396 | '(', 'T', 'H', 'E', 'I', 'R', ')', '=', 'D', 'H', 'E', 'H', 'R' | 0x80, 397 | ' ', '(', 'T', 'H', 'A', 'N', ')', ' ', '=', 'D', 'H', 'A', 'E', 'N' | 0x80, 398 | ' ', '(', 'T', 'H', 'E', 'M', ')', ' ', '=', 'D', 'H', 'A', 'E', 'N' | 0x80, 399 | '(', 'T', 'H', 'E', 'S', 'E', ')', ' ', '=', 'D', 'H', 'I', 'Y', 'Z' | 0x80, 400 | ' ', '(', 'T', 'H', 'E', 'N', ')', '=', 'D', 'H', 'E', 'H', 'N' | 0x80, 401 | '(', 'T', 'H', 'R', 'O', 'U', 'G', 'H', ')', '=', 'T', 'H', 'R', 'U', 'W', '4' | 0x80, 402 | '(', 'T', 'H', 'O', 'S', 'E', ')', '=', 'D', 'H', 'O', 'H', 'Z' | 0x80, 403 | '(', 'T', 'H', 'O', 'U', 'G', 'H', ')', ' ', '=', 'D', 'H', 'O', 'W' | 0x80, 404 | '(', 'T', 'O', 'D', 'A', 'Y', ')', '=', 'T', 'U', 'X', 'D', 'E', 'Y' | 0x80, 405 | '(', 'T', 'O', 'M', 'O', ')', 'R', 'R', 'O', 'W', '=', 'T', 'U', 'M', 'A', 'A', '5' | 0x80, 406 | '(', 'T', 'O', ')', 'T', 'A', 'L', '=', 'T', 'O', 'W', '5' | 0x80, 407 | ' ', '(', 'T', 'H', 'U', 'S', ')', '=', 'D', 'H', 'A', 'H', '4', 'S' | 0x80, 408 | '(', 'T', 'H', ')', '=', 'T', 'H' | 0x80, 409 | '#', ':', '(', 'T', 'E', 'D', ')', '=', 'T', 'I', 'X', 'D' | 0x80, 410 | 'S', '(', 'T', 'I', ')', '#', 'N', '=', 'C', 'H' | 0x80, 411 | '(', 'T', 'I', ')', 'O', '=', 'S', 'H' | 0x80, 412 | '(', 'T', 'I', ')', 'A', '=', 'S', 'H' | 0x80, 413 | '(', 'T', 'I', 'E', 'N', ')', '=', 'S', 'H', 'U', 'N' | 0x80, 414 | '(', 'T', 'U', 'R', ')', '#', '=', 'C', 'H', 'E', 'R' | 0x80, 415 | '(', 'T', 'U', ')', 'A', '=', 'C', 'H', 'U', 'W' | 0x80, 416 | ' ', '(', 'T', 'W', 'O', ')', '=', 'T', 'U', 'W' | 0x80, 417 | '&', '(', 'T', ')', 'E', 'N', ' ', '=' | 0x80, 418 | '(', 'T', ')', '=', 'T' | 0x80, 419 | 420 | ']', 'U' | 0x80, 421 | ' ', '(', 'U', ')', ' ', '=', 'Y', 'U', 'W', '4' | 0x80, 422 | ' ', '(', 'U', 'N', ')', 'I', '=', 'Y', 'U', 'W', 'N' | 0x80, 423 | ' ', '(', 'U', 'N', ')', '=', 'A', 'H', 'N' | 0x80, 424 | ' ', '(', 'U', 'P', 'O', 'N', ')', '=', 'A', 'X', 'P', 'A', 'O', 'N' | 0x80, 425 | '@', '(', 'U', 'R', ')', '#', '=', 'U', 'H', '4', 'R' | 0x80, 426 | '(', 'U', 'R', ')', '#', '=', 'Y', 'U', 'H', '4', 'R' | 0x80, 427 | '(', 'U', 'R', ')', '=', 'E', 'R' | 0x80, 428 | '(', 'U', ')', '^', ' ', '=', 'A', 'H' | 0x80, 429 | '(', 'U', ')', '^', '^', '=', 'A', 'H', '5' | 0x80, 430 | '(', 'U', 'Y', ')', '=', 'A', 'Y', '5' | 0x80, 431 | ' ', 'G', '(', 'U', ')', '#', '=' | 0x80, 432 | 'G', '(', 'U', ')', '%', '=' | 0x80, 433 | 'G', '(', 'U', ')', '#', '=', 'W' | 0x80, 434 | '#', 'N', '(', 'U', ')', '=', 'Y', 'U', 'W' | 0x80, 435 | '@', '(', 'U', ')', '=', 'U', 'W' | 0x80, 436 | '(', 'U', ')', '=', 'Y', 'U', 'W' | 0x80, 437 | 438 | ']', 'V' | 0x80, 439 | ' ', '(', 'V', ')', ' ', '=', 'V', 'I', 'Y', '4' | 0x80, 440 | '(', 'V', 'I', 'E', 'W', ')', '=', 'V', 'Y', 'U', 'W', '5' | 0x80, 441 | '(', 'V', ')', '=', 'V' | 0x80, 442 | 443 | ']', 'W' | 0x80, 444 | ' ', '(', 'W', ')', ' ', '=', 'D', 'A', 'H', '4', 'B', 'U', 'L', 'Y', 'U', 'W' | 0x80, 445 | ' ', '(', 'W', 'E', 'R', 'E', ')', '=', 'W', 'E', 'R' | 0x80, 446 | '(', 'W', 'A', ')', 'S', 'H', '=', 'W', 'A', 'A' | 0x80, 447 | '(', 'W', 'A', ')', 'S', 'T', '=', 'W', 'E', 'Y' | 0x80, 448 | '(', 'W', 'A', ')', 'S', '=', 'W', 'A', 'H' | 0x80, 449 | '(', 'W', 'A', ')', 'T', '=', 'W', 'A', 'A' | 0x80, 450 | '(', 'W', 'H', 'E', 'R', 'E', ')', '=', 'W', 'H', 'E', 'H', 'R' | 0x80, 451 | '(', 'W', 'H', 'A', 'T', ')', '=', 'W', 'H', 'A', 'H', 'T' | 0x80, 452 | '(', 'W', 'H', 'O', 'L', ')', '=', '/', 'H', 'O', 'W', 'L' | 0x80, 453 | '(', 'W', 'H', 'O', ')', '=', '/', 'H', 'U', 'W' | 0x80, 454 | '(', 'W', 'H', ')', '=', 'W', 'H' | 0x80, 455 | '(', 'W', 'A', 'R', ')', '#', '=', 'W', 'E', 'H', 'R' | 0x80, 456 | '(', 'W', 'A', 'R', ')', '=', 'W', 'A', 'O', 'R' | 0x80, 457 | '(', 'W', 'O', 'R', ')', '^', '=', 'W', 'E', 'R' | 0x80, 458 | '(', 'W', 'R', ')', '=', 'R' | 0x80, 459 | '(', 'W', 'O', 'M', ')', 'A', '=', 'W', 'U', 'H', 'M' | 0x80, 460 | '(', 'W', 'O', 'M', ')', 'E', '=', 'W', 'I', 'H', 'M' | 0x80, 461 | '(', 'W', 'E', 'A', ')', 'R', '=', 'W', 'E', 'H' | 0x80, 462 | '(', 'W', 'A', 'N', 'T', ')', '=', 'W', 'A', 'A', '5', 'N', 'T' | 0x80, 463 | 'A', 'N', 'S', '(', 'W', 'E', 'R', ')', '=', 'E', 'R' | 0x80, 464 | '(', 'W', ')', '=', 'W' | 0x80, 465 | 466 | ']', 'X' | 0x80, 467 | ' ', '(', 'X', ')', ' ', '=', 'E', 'H', '4', 'K', 'R' | 0x80, 468 | ' ', '(', 'X', ')', '=', 'Z' | 0x80, 469 | '(', 'X', ')', '=', 'K', 'S' | 0x80, 470 | 471 | ']', 'Y' | 0x80, 472 | ' ', '(', 'Y', ')', ' ', '=', 'W', 'A', 'Y', '4' | 0x80, 473 | '(', 'Y', 'O', 'U', 'N', 'G', ')', '=', 'Y', 'A', 'H', 'N', 'X' | 0x80, 474 | ' ', '(', 'Y', 'O', 'U', 'R', ')', '=', 'Y', 'O', 'H', 'R' | 0x80, 475 | ' ', '(', 'Y', 'O', 'U', ')', '=', 'Y', 'U', 'W' | 0x80, 476 | ' ', '(', 'Y', 'E', 'S', ')', '=', 'Y', 'E', 'H', 'S' | 0x80, 477 | ' ', '(', 'Y', ')', '=', 'Y' | 0x80, 478 | 'F', '(', 'Y', ')', '=', 'A', 'Y' | 0x80, 479 | 'P', 'S', '(', 'Y', 'C', 'H', ')', '=', 'A', 'Y', 'K' | 0x80, 480 | '#', ':', '^', '(', 'Y', ')', '=', 'I', 'Y' | 0x80, 481 | '#', ':', '^', '(', 'Y', ')', 'I', '=', 'I', 'Y' | 0x80, 482 | ' ', ':', '(', 'Y', ')', ' ', '=', 'A', 'Y' | 0x80, 483 | ' ', ':', '(', 'Y', ')', '#', '=', 'A', 'Y' | 0x80, 484 | ' ', ':', '(', 'Y', ')', '^', '+', ':', '#', '=', 'I', 'H' | 0x80, 485 | ' ', ':', '(', 'Y', ')', '^', '#', '=', 'A', 'Y' | 0x80, 486 | '(', 'Y', ')', '=', 'I', 'H' | 0x80, 487 | 488 | ']', 'Z' | 0x80, 489 | ' ', '(', 'Z', ')', ' ', '=', 'Z', 'I', 'Y', '4' | 0x80, 490 | '(', 'Z', ')', '=', 'Z' | 0x80, 491 | 'j' | 0x80, 492 | } 493 | 494 | Rules2 = []byte{ 495 | '(', 'A', ')', '=' | 0x80, 496 | '(', '!', ')', '=', '.' | 0x80, 497 | '(', '"', ')', ' ', '=', '-', 'A', 'H', '5', 'N', 'K', 'W', 'O', 'W', 'T', '-' | 0x80, 498 | '(', '"', ')', '=', 'K', 'W', 'O', 'W', '4', 'T', '-' | 0x80, 499 | '(', '#', ')', '=', ' ', 'N', 'A', 'H', '4', 'M', 'B', 'E', 'R' | 0x80, 500 | '(', '$', ')', '=', ' ', 'D', 'A', 'A', '4', 'L', 'E', 'R' | 0x80, 501 | '(', '%', ')', '=', ' ', 'P', 'E', 'R', 'S', 'E', 'H', '4', 'N', 'T' | 0x80, 502 | '(', '&', ')', '=', ' ', 'A', 'E', 'N', 'D' | 0x80, 503 | '(', '\'', ')', '=' | 0x80, 504 | '(', '*', ')', '=', ' ', 'A', 'E', '4', 'S', 'T', 'E', 'R', 'I', 'H', 'S', 'K' | 0x80, 505 | '(', '+', ')', '=', ' ', 'P', 'L', 'A', 'H', '4', 'S' | 0x80, 506 | '(', ',', ')', '=', ',' | 0x80, 507 | ' ', '(', '-', ')', ' ', '=', '-' | 0x80, 508 | '(', '-', ')', '=' | 0x80, 509 | '(', '.', ')', '=', ' ', 'P', 'O', 'Y', 'N', 'T' | 0x80, 510 | '(', '/', ')', '=', ' ', 'S', 'L', 'A', 'E', '4', 'S', 'H' | 0x80, 511 | '(', '0', ')', '=', ' ', 'Z', 'I', 'Y', '4', 'R', 'O', 'W' | 0x80, 512 | ' ', '(', '1', 'S', 'T', ')', '=', 'F', 'E', 'R', '4', 'S', 'T' | 0x80, 513 | ' ', '(', '1', '0', 'T', 'H', ')', '=', 'T', 'E', 'H', '4', 'N', 'T', 'H' | 0x80, 514 | '(', '1', ')', '=', ' ', 'W', 'A', 'H', '4', 'N' | 0x80, 515 | ' ', '(', '2', 'N', 'D', ')', '=', 'S', 'E', 'H', '4', 'K', 'U', 'N', 'D' | 0x80, 516 | '(', '2', ')', '=', ' ', 'T', 'U', 'W', '4' | 0x80, 517 | ' ', '(', '3', 'R', 'D', ')', '=', 'T', 'H', 'E', 'R', '4', 'D' | 0x80, 518 | '(', '3', ')', '=', ' ', 'T', 'H', 'R', 'I', 'Y', '4' | 0x80, 519 | '(', '4', ')', '=', ' ', 'F', 'O', 'H', '4', 'R' | 0x80, 520 | ' ', '(', '5', 'T', 'H', ')', '=', 'F', 'I', 'H', '4', 'F', 'T', 'H' | 0x80, 521 | '(', '5', ')', '=', ' ', 'F', 'A', 'Y', '4', 'V' | 0x80, 522 | ' ', '(', '6', '4', ')', ' ', '=', 'S', 'I', 'H', '4', 'K', 'S', 'T', 'I', 'Y', ' ', 'F', 'O', 'H', 'R' | 0x80, 523 | '(', '6', ')', '=', ' ', 'S', 'I', 'H', '4', 'K', 'S' | 0x80, 524 | '(', '7', ')', '=', ' ', 'S', 'E', 'H', '4', 'V', 'U', 'N' | 0x80, 525 | ' ', '(', '8', 'T', 'H', ')', '=', 'E', 'Y', '4', 'T', 'H' | 0x80, 526 | '(', '8', ')', '=', ' ', 'E', 'Y', '4', 'T' | 0x80, 527 | '(', '9', ')', '=', ' ', 'N', 'A', 'Y', '4', 'N' | 0x80, 528 | '(', ':', ')', '=', '.' | 0x80, 529 | '(', ';', ')', '=', '.' | 0x80, 530 | '(', '<', ')', '=', ' ', 'L', 'E', 'H', '4', 'S', ' ', 'D', 'H', 'A', 'E', 'N' | 0x80, 531 | '(', '=', ')', '=', ' ', 'I', 'Y', '4', 'K', 'W', 'U', 'L', 'Z' | 0x80, 532 | '(', '>', ')', '=', ' ', 'G', 'R', 'E', 'Y', '4', 'T', 'E', 'R', ' ', 'D', 'H', 'A', 'E', 'N' | 0x80, 533 | '(', '?', ')', '=', '?' | 0x80, 534 | '(', '@', ')', '=', ' ', 'A', 'E', '6', 'T' | 0x80, 535 | '(', '^', ')', '=', ' ', 'K', 'A', 'E', '4', 'R', 'I', 'X', 'T' | 0x80, 536 | ']', 'A' | 0x80, 537 | } 538 | ) 539 | -------------------------------------------------------------------------------- /reciter/util.go: -------------------------------------------------------------------------------- 1 | package reciter 2 | 3 | import "fmt" 4 | 5 | var A, X, Y byte 6 | 7 | /* Retrieve flags for character at mem59-1 */ 8 | func (r *Reciter) getFlag(npos, mask byte) byte { 9 | X = npos 10 | return flags36376[r.inputtemp[X]] & mask 11 | } 12 | 13 | func (r *Reciter) match(str string) int { 14 | for i := 0; i < len(str); i++ { 15 | ch := str[i] 16 | A = r.inputtemp[X] 17 | X++ 18 | if A != ch { 19 | return 0 20 | } 21 | } 22 | return 1 23 | } 24 | 25 | func printRule(offset int) { 26 | i := 1 27 | var A byte 28 | fmt.Printf("Applying rule: ") 29 | for (A & 128) == 0 { 30 | A = getRuleByte(uint16(offset), byte(i)) 31 | if (A & 127) == '=' { 32 | fmt.Printf(" -> ") 33 | } else { 34 | fmt.Printf("%c", A&127) 35 | } 36 | i++ 37 | } 38 | fmt.Printf("\n") 39 | } 40 | 41 | func (r *Reciter) handle_ch2(ch, mem byte) int { 42 | X = mem 43 | tmp := flags36376[r.inputtemp[mem]] 44 | if ch == ' ' { 45 | if tmp&128 != 0 { 46 | return 1 47 | } 48 | } else if ch == '#' { 49 | if !(tmp&64 != 0) { 50 | return 1 51 | } 52 | } else if ch == '.' { 53 | if !(tmp&8 != 0) { 54 | return 1 55 | } 56 | } else if ch == '^' { 57 | if !(tmp&32 != 0) { 58 | return 1 59 | } 60 | } else { 61 | return -1 62 | } 63 | return 0 64 | } 65 | 66 | func (r *Reciter) handle_ch(A, mem byte) int { 67 | X = mem 68 | tmp := flags36376[r.inputtemp[X]] 69 | if A == ' ' { 70 | if (tmp & 128) != 0 { 71 | return 1 72 | } 73 | } else if A == '#' { 74 | if (tmp & 64) == 0 { 75 | return 1 76 | } 77 | } else if A == '.' { 78 | if (tmp & 8) == 0 { 79 | return 1 80 | } 81 | } else if A == '&' { 82 | if (tmp & 16) == 0 { 83 | if r.inputtemp[X] != 72 { 84 | return 1 85 | } 86 | X++ 87 | } 88 | } else if A == '^' { 89 | if (tmp & 32) == 0 { 90 | return 1 91 | } 92 | } else if A == '+' { 93 | X = mem 94 | A = r.inputtemp[X] 95 | if (A != 69) && (A != 73) && (A != 89) { 96 | return 1 97 | } 98 | } else { 99 | return -1 100 | } 101 | return 0 102 | } 103 | 104 | func getRuleByte(mem62 uint16, Y byte) byte { 105 | var address uint = uint(mem62) 106 | if mem62 >= 37541 { 107 | address -= 37541 108 | return Rules2[address+uint(Y)] 109 | } 110 | address -= 32000 111 | return Rules[address+uint(Y)] 112 | } 113 | -------------------------------------------------------------------------------- /render/createtransitions.go: -------------------------------------------------------------------------------- 1 | package render 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | // CREATE TRANSITIONS 8 | // 9 | // Linear transitions are now created to smoothly connect each 10 | // phoeneme. This transition is spread between the ending frames 11 | // of the old phoneme (outBlendLength), and the beginning frames 12 | // of the new phoneme (inBlendLength). 13 | // 14 | // To determine how many frames to use, the two phonemes are 15 | // compared using the blendRank[] table. The phoneme with the 16 | // smaller score is used. In case of a tie, a blend of each is used: 17 | // 18 | // if blendRank[phoneme1] == blendRank[phomneme2] 19 | // // use lengths from each phoneme 20 | // outBlendFrames = outBlend[phoneme1] 21 | // inBlendFrames = outBlend[phoneme2] 22 | // else if blendRank[phoneme1] < blendRank[phoneme2] 23 | // // use lengths from first phoneme 24 | // outBlendFrames = outBlendLength[phoneme1] 25 | // inBlendFrames = inBlendLength[phoneme1] 26 | // else 27 | // // use lengths from the second phoneme 28 | // // note that in and out are swapped around! 29 | // outBlendFrames = inBlendLength[phoneme2] 30 | // inBlendFrames = outBlendLength[phoneme2] 31 | // 32 | // Blend lengths can't be less than zero. 33 | // 34 | // For most of the parameters, SAM interpolates over the range of the last 35 | // outBlendFrames-1 and the first inBlendFrames. 36 | // 37 | // The exception to this is the Pitch[] parameter, which is interpolates the 38 | // pitch from the center of the current phoneme to the center of the next 39 | // phoneme. 40 | 41 | //written by me because of different table positions. 42 | // mem[47] = ... 43 | // 168=pitches 44 | // 169=frequency1 45 | // 170=frequency2 46 | // 171=frequency3 47 | // 172=amplitude1 48 | // 173=amplitude2 49 | // 174=amplitude3 50 | func (r *Render) Read(p, Y byte) byte { 51 | switch p { 52 | case 168: 53 | return r.pitches[Y] 54 | case 169: 55 | return r.frequency1[Y] 56 | case 170: 57 | return r.frequency2[Y] 58 | case 171: 59 | return r.frequency3[Y] 60 | case 172: 61 | return r.amplitude1[Y] 62 | case 173: 63 | return r.amplitude2[Y] 64 | case 174: 65 | return r.amplitude3[Y] 66 | } 67 | fmt.Printf("Error reading to tables") 68 | return 0 69 | } 70 | 71 | func (r *Render) Write(p, Y, value byte) { 72 | 73 | switch p { 74 | case 168: 75 | r.pitches[Y] = value 76 | return 77 | case 169: 78 | r.frequency1[Y] = value 79 | return 80 | case 170: 81 | r.frequency2[Y] = value 82 | return 83 | case 171: 84 | r.frequency3[Y] = value 85 | return 86 | case 172: 87 | r.amplitude1[Y] = value 88 | return 89 | case 173: 90 | r.amplitude2[Y] = value 91 | return 92 | case 174: 93 | r.amplitude3[Y] = value 94 | return 95 | } 96 | fmt.Printf("Error writing to tables\n") 97 | } 98 | 99 | func abs(x int8) int8 { 100 | if x < 0 { 101 | return -x 102 | } 103 | return x 104 | } 105 | 106 | // linearly interpolate values 107 | func (r *Render) interpolate(width, table, frame, mem53 byte) { 108 | sign := int8(mem53) < 0 109 | remainder := byte(abs(int8(mem53))) % width 110 | div := byte(int(int8(mem53)) / int(width)) 111 | val := r.Read(table, frame) + div 112 | 113 | var intError byte 114 | 115 | for pos := width - 1; pos > 0; pos-- { 116 | intError += remainder 117 | if intError >= width { // accumulated a whole integer error, so adjust output 118 | intError -= width 119 | if sign { 120 | val-- 121 | } else if val != 0 { 122 | val++ 123 | } // if input is 0, we always leave it alone 124 | } 125 | frame++ 126 | r.Write(table, frame, val) // Write updated value back to next frame. 127 | val += div 128 | } 129 | } 130 | 131 | func (r *Render) interpolate_pitch(width, pos, mem49, phase3 byte) { 132 | // unlike the other values, the pitches[] interpolates from 133 | // the middle of the current phoneme to the middle of the 134 | // next phoneme 135 | 136 | // half the width of the current and next phoneme 137 | cur_width := r.PhonemeLengthOutput[pos] / 2 138 | next_width := r.PhonemeLengthOutput[pos+1] / 2 139 | // sum the values 140 | width = cur_width + next_width 141 | pitch := int(r.pitches[next_width+mem49]) - int(r.pitches[mem49-cur_width]) 142 | r.interpolate(width, 168, phase3, byte(pitch)) 143 | } 144 | 145 | func (r *Render) CreateTransitions() byte { 146 | var phase1, phase2, mem49, pos byte 147 | for { 148 | phoneme := r.PhonemeIndexOutput[pos] 149 | next_phoneme := r.PhonemeIndexOutput[pos+1] 150 | 151 | if next_phoneme == PhonemeEnd { 152 | break 153 | } // 255 == end_token 154 | 155 | // get the ranking of each phoneme 156 | next_rank := blendRank[next_phoneme] 157 | rank := blendRank[phoneme] 158 | 159 | // compare the rank - lower rank value is stronger 160 | if rank == next_rank { 161 | // same rank, so use out blend lengths from each phoneme 162 | phase1 = outBlendLength[phoneme] 163 | phase2 = outBlendLength[next_phoneme] 164 | } else if rank < next_rank { 165 | // next phoneme is stronger, so us its blend lengths 166 | phase1 = inBlendLength[next_phoneme] 167 | phase2 = outBlendLength[next_phoneme] 168 | } else { 169 | // current phoneme is stronger, so use its blend lengths 170 | // note the out/in are swapped 171 | phase1 = outBlendLength[phoneme] 172 | phase2 = inBlendLength[phoneme] 173 | } 174 | 175 | mem49 += r.PhonemeLengthOutput[pos] 176 | 177 | speedcounter := mem49 + phase2 178 | phase3 := mem49 - phase1 179 | transition := phase1 + phase2 // total transition? 180 | 181 | if ((transition - 2) & 128) == 0 { 182 | 183 | r.interpolate_pitch(transition, pos, mem49, phase3) 184 | for table := byte(169); table < 175; table++ { 185 | // tables: 186 | // 168 pitches[] 187 | // 169 frequency1 188 | // 170 frequency2 189 | // 171 frequency3 190 | // 172 amplitude1 191 | // 173 amplitude2 192 | // 174 amplitude3 193 | 194 | value := r.Read(table, speedcounter) - r.Read(table, phase3) 195 | r.interpolate(transition, table, phase3, value) 196 | } 197 | } 198 | pos++ 199 | } 200 | 201 | // add the length of this phoneme 202 | return mem49 + r.PhonemeLengthOutput[pos] 203 | } 204 | -------------------------------------------------------------------------------- /render/processframes.go: -------------------------------------------------------------------------------- 1 | package render 2 | 3 | import ( 4 | "github.com/exploser/sam/config" 5 | ) 6 | 7 | func (r *Render) CombineGlottalAndFormants(phase1, phase2, phase3, Y byte) { 8 | var array [5]byte 9 | p1 := int(phase1) * 256 10 | p2 := int(phase2) * 256 11 | p3 := int(phase3) * 256 12 | 13 | for i := 0; i < 5; i++ { 14 | sp1 := sinus[(p1/256)&0xff] 15 | sp2 := sinus[(p2/256)&0xff] 16 | rp3 := rectangle[(p3/256)&0xff] 17 | 18 | sin1 := int(sp1) * int(r.amplitude1[Y]&0x0f) 19 | sin2 := int(sp2) * int(r.amplitude2[Y]&0x0f) 20 | rect := int(rp3) * int(r.amplitude3[Y]&0x0f) 21 | 22 | mux := int(sin1) + int(sin2) + int(rect) 23 | 24 | mux /= 32 25 | mux += 128 26 | array[i] = byte(mux) 27 | p1 += int(r.frequency1[Y]) * 256 / 4 28 | p2 += int(r.frequency2[Y]) * 256 / 4 29 | p3 += int(r.frequency3[Y]) * 256 / 4 30 | } 31 | 32 | r.Output8BitArray(0, array) 33 | } 34 | 35 | // PROCESS THE FRAMES 36 | // 37 | // In traditional vocal synthesis, the glottal pulse drives filters, which 38 | // are attenuated to the frequencies of the formants. 39 | // 40 | // SAM generates these formants directly with sin and rectangular waves. 41 | // To simulate them being driven by the glottal pulse, the waveforms are 42 | // reset at the beginning of each glottal pulse. 43 | // 44 | func (r *Render) ProcessFrames(count byte, cfg *config.Config) { 45 | 46 | var speedcounter byte = 72 47 | var phase1 byte 48 | var phase2 byte 49 | var phase3 byte 50 | var mem66 byte 51 | 52 | var Y byte 53 | 54 | var glottal_pulse = r.pitches[0] 55 | var mem38 = glottal_pulse - (glottal_pulse >> 2) // mem44 * 0.75 56 | 57 | for count != 0 { 58 | var flags = r.sampledConsonantFlag[Y] 59 | 60 | // unvoiced sampled phoneme? 61 | if flags&248 != 0 { 62 | r.RenderSample(&mem66, flags, Y) 63 | // skip ahead two in the phoneme buffer 64 | Y += 2 65 | count -= 2 66 | speedcounter = cfg.Speed 67 | } else { 68 | r.CombineGlottalAndFormants(phase1, phase2, phase3, Y) 69 | 70 | speedcounter-- 71 | if speedcounter == 0 { 72 | Y++ //go to next amplitude 73 | // decrement the frame count 74 | count-- 75 | if count == 0 { 76 | return 77 | } 78 | speedcounter = cfg.Speed 79 | } 80 | 81 | glottal_pulse-- 82 | 83 | if glottal_pulse != 0 { 84 | // not finished with a glottal pulse 85 | 86 | mem38-- 87 | // within the first 75% of the glottal pulse? 88 | // is the count non-zero and the sampled flag is zero? 89 | if (mem38 != 0) || (flags == 0) { 90 | // reset the phase of the formants to match the pulse 91 | phase1 += r.frequency1[Y] 92 | phase2 += r.frequency2[Y] 93 | phase3 += r.frequency3[Y] 94 | continue 95 | } 96 | 97 | // voiced sampled phonemes interleave the sample with the 98 | // glottal pulse. The sample flag is non-zero, so render 99 | // the sample for the phoneme. 100 | r.RenderSample(&mem66, flags, Y) 101 | } 102 | } 103 | 104 | glottal_pulse = r.pitches[Y] 105 | mem38 = glottal_pulse - (glottal_pulse >> 2) // mem44 * 0.75 106 | 107 | // reset the formant wave generators to keep them in 108 | // sync with the glottal pulse 109 | phase1 = 0 110 | phase2 = 0 111 | phase3 = 0 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /render/render.go: -------------------------------------------------------------------------------- 1 | package render 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/exploser/sam/config" 7 | ) 8 | 9 | type Render struct { 10 | Bufferpos int 11 | Buffer []byte 12 | 13 | pitches [256]byte // tab43008 14 | 15 | frequency1 [256]byte 16 | frequency2 [256]byte 17 | frequency3 [256]byte 18 | 19 | amplitude1 [256]byte 20 | amplitude2 [256]byte 21 | amplitude3 [256]byte 22 | sampledConsonantFlag [256]byte // tab44800 23 | oldtimetableindex int 24 | 25 | PhonemeIndexOutput [256]byte //tab47296 26 | PhonemeLengthOutput [256]byte 27 | StressOutput [256]byte 28 | } 29 | 30 | func (r *Render) GetBuffer() []byte { 31 | return r.Buffer 32 | } 33 | func (r *Render) GetBufferLength() int { 34 | return r.Bufferpos/50 + 5 35 | } 36 | 37 | //extern byte A, X, Y; 38 | //extern byte mem44; 39 | 40 | //return = hibyte(mem39212*mem39213) << 1 41 | func trans(a, b byte) byte { 42 | return byte(((int(a) * int(b)) >> 8) << 1) 43 | } 44 | 45 | //timetable for more accurate c64 simulation 46 | var timetable = [5][5]int{ 47 | {162, 167, 167, 127, 128}, 48 | {226, 60, 60, 0, 0}, 49 | {225, 60, 59, 0, 0}, 50 | {200, 0, 0, 54, 55}, 51 | {199, 0, 0, 54, 54}, 52 | } 53 | 54 | func (r *Render) Output8Bit(index int, A byte) { 55 | var k int 56 | r.Bufferpos += timetable[r.oldtimetableindex][index] 57 | r.oldtimetableindex = index 58 | // write a little bit in advance 59 | r.Buffer[r.Bufferpos/50+k] = A 60 | for k = 1; k < 4; k++ { 61 | r.Buffer[r.Bufferpos/50+k] = A 62 | } 63 | r.Buffer[r.Bufferpos/50+4] = A 64 | } 65 | 66 | func (r *Render) Output8BitArray(index int, A [5]byte) { 67 | var k int 68 | r.Bufferpos += timetable[r.oldtimetableindex][index] 69 | r.oldtimetableindex = index 70 | 71 | if len(A) != 5 { 72 | panic("A should contain exactly 5 elements") 73 | } 74 | 75 | // write a little bit in advance 76 | for k = 0; k < 5; k++ { 77 | r.Buffer[r.Bufferpos/50+k] = A[k] 78 | } 79 | } 80 | 81 | func (r *Render) RenderVoicedSample(hi uint, off, phase1 byte) byte { 82 | for ; phase1 != 0; phase1++ { 83 | sample := sampleTable[hi+uint(off)] 84 | 85 | for bit := 8; bit != 0; bit-- { 86 | if (sample & 128) != 0 { 87 | r.Output8Bit(3, 0x70) 88 | } else { 89 | r.Output8Bit(4, 0x90) 90 | } 91 | sample <<= 1 92 | } 93 | off++ 94 | } 95 | return off 96 | } 97 | 98 | func (r *Render) RenderUnvoicedSample(hi uint, off byte) { 99 | for ; off != 0; off++ { 100 | sample := sampleTable[hi+uint(off)] 101 | 102 | for bit := 8; bit != 0; bit-- { 103 | if (sample & 128) != 0 { 104 | r.Output8Bit(3, 0x60) 105 | } else { 106 | r.Output8Bit(4, 0xA0) 107 | } 108 | sample <<= 1 109 | } 110 | } 111 | } 112 | 113 | // ------------------------------------------------------------------------- 114 | //Code48227 115 | // Render a sampled sound from the sampleTable. 116 | // 117 | // Phoneme Sample Start Sample End 118 | // 32: S* 15 255 119 | // 33: SH 257 511 120 | // 34: F* 559 767 121 | // 35: TH 583 767 122 | // 36: /H 903 1023 123 | // 37: /X 1135 1279 124 | // 38: Z* 84 119 125 | // 39: ZH 340 375 126 | // 40: V* 596 639 127 | // 41: DH 596 631 128 | // 129 | // 42: CH 130 | // 43: ** 399 511 131 | // 132 | // 44: J* 133 | // 45: ** 257 276 134 | // 46: ** 135 | // 136 | // 66: P* 137 | // 67: ** 743 767 138 | // 68: ** 139 | // 140 | // 69: T* 141 | // 70: ** 231 255 142 | // 71: ** 143 | // 144 | // The SampledPhonemesTable[] holds flags indicating if a phoneme is 145 | // voiced or not. If the upper 5 bits are zero, the sample is voiced. 146 | // 147 | // Samples in the sampleTable are compressed, with bits being converted to 148 | // bytes from high bit to low, as follows: 149 | // 150 | // unvoiced 0 bit -> X 151 | // unvoiced 1 bit -> 5 152 | // 153 | // voiced 0 bit -> 6 154 | // voiced 1 bit -> 24 155 | // 156 | // Where X is a value from the table: 157 | // 158 | // { 0x18, 0x1A, 0x17, 0x17, 0x17 }; 159 | // 160 | // The index into this table is determined by masking off the lower 161 | // 3 bits from the SampledPhonemesTable: 162 | // 163 | // index = (SampledPhonemesTable[i] & 7) - 1; 164 | // 165 | // For voices samples, samples are interleaved between voiced output. 166 | 167 | func (r *Render) RenderSample(mem66 *byte, consonantFlag, mem49 byte) { 168 | // mem49 == current phoneme's index 169 | 170 | // mask low three bits and subtract 1 get value to 171 | // convert 0 bits on unvoiced samples. 172 | hibyte := (consonantFlag & 7) - 1 173 | 174 | // determine which offset to use from table { 0x18, 0x1A, 0x17, 0x17, 0x17 } 175 | // T, S, Z 0 0x18 176 | // CH, J, SH, ZH 1 0x1A 177 | // P, F*, V, TH, DH 2 0x17 178 | // /H 3 0x17 179 | // /X 4 0x17 180 | 181 | hi := uint(hibyte) * 256 182 | // voiced sample? 183 | pitch := consonantFlag & 248 184 | if pitch == 0 { 185 | // voiced phoneme: Z*, ZH, V*, DH 186 | pitch = r.pitches[mem49] >> 4 187 | *mem66 = r.RenderVoicedSample(hi, *mem66, pitch^255) 188 | return 189 | } 190 | r.RenderUnvoicedSample(hi, pitch^255) 191 | } 192 | 193 | // CREATE FRAMES 194 | // 195 | // The length parameter in the list corresponds to the number of frames 196 | // to expand the phoneme to. Each frame represents 10 milliseconds of time. 197 | // So a phoneme with a length of 7 = 7 frames = 70 milliseconds duration. 198 | // 199 | // The parameters are copied from the phoneme to the frame verbatim. 200 | // 201 | func (r *Render) CreateFrames(cfg *config.Config) { 202 | var phase1, X byte 203 | 204 | i := 0 205 | for i < 256 { 206 | // get the phoneme at the index 207 | phoneme := r.PhonemeIndexOutput[i] 208 | 209 | // if terminal phoneme, exit the loop 210 | if phoneme == PhonemeEnd { 211 | break 212 | } 213 | 214 | if phoneme == PhonemePeriod { 215 | r.AddInflection(inflectionFalling, phase1, X) 216 | } else if phoneme == PhonemeQuestion { 217 | r.AddInflection(inflectionRising, phase1, X) 218 | } 219 | 220 | // get the stress amount (more stress = higher pitch) 221 | phase1 = tab47492[r.StressOutput[i]+1] 222 | 223 | // get number of frames to write 224 | 225 | // copy from the source to the frames list 226 | for phase2 := r.PhonemeLengthOutput[i]; phase2 != 0; phase2-- { 227 | r.frequency1[X] = freq1data[phoneme] // F1 frequency 228 | r.frequency2[X] = freq2data[phoneme] // F2 frequency 229 | r.frequency3[X] = freq3data[phoneme] // F3 frequency 230 | r.amplitude1[X] = ampl1data[phoneme] // F1 amplitude 231 | r.amplitude2[X] = ampl2data[phoneme] // F2 amplitude 232 | r.amplitude3[X] = ampl3data[phoneme] // F3 amplitude 233 | r.sampledConsonantFlag[X] = sampledConsonantFlags[phoneme] // phoneme data for sampled consonants 234 | r.pitches[X] = cfg.Pitch + phase1 // pitch 235 | X++ 236 | } 237 | i++ 238 | } 239 | } 240 | 241 | // RESCALE AMPLITUDE 242 | // 243 | // Rescale volume from a linear scale to decibels. 244 | // 245 | func (r *Render) RescaleAmplitude() { 246 | for i := 255; i >= 0; i-- { 247 | r.amplitude1[i] = amplitudeRescale[r.amplitude1[i]] 248 | r.amplitude2[i] = amplitudeRescale[r.amplitude2[i]] 249 | r.amplitude3[i] = amplitudeRescale[r.amplitude3[i]] 250 | } 251 | } 252 | 253 | // ASSIGN PITCH CONTOUR 254 | // 255 | // This subtracts the F1 frequency from the pitch to create a 256 | // pitch contour. Without this, the output would be at a single 257 | // pitch level (monotone). 258 | 259 | func (r *Render) AssignPitchContour() { 260 | for i := 0; i < 256; i++ { 261 | // subtract half the frequency of the formant 1. 262 | // this adds variety to the voice 263 | r.pitches[i] -= (r.frequency1[i] >> 1) 264 | } 265 | } 266 | 267 | // RENDER THE PHONEMES IN THE LIST 268 | // 269 | // The phoneme list is converted into sound through the steps: 270 | // 271 | // 1. Copy each phoneme number of times into the frames list, 272 | // where each frame represents 10 milliseconds of sound. 273 | // 274 | // 2. Determine the transitions lengths between phonemes, and linearly 275 | // interpolate the values across the frames. 276 | // 277 | // 3. Offset the pitches by the fundamental frequency. 278 | // 279 | // 4. Render the each frame. 280 | func (r *Render) Render(cfg *config.Config) { 281 | if r.PhonemeIndexOutput[0] == PhonemeEnd { 282 | return 283 | } //exit if no data 284 | 285 | r.CreateFrames(cfg) 286 | t := r.CreateTransitions() 287 | 288 | if !cfg.Sing { 289 | r.AssignPitchContour() 290 | } 291 | r.RescaleAmplitude() 292 | 293 | if cfg.Debug { 294 | PrintOutput(r.sampledConsonantFlag[:], r.frequency1[:], r.frequency2[:], r.frequency3[:], r.amplitude1[:], r.amplitude2[:], r.amplitude3[:], r.pitches[:]) 295 | } 296 | 297 | r.ProcessFrames(t, cfg) 298 | } 299 | 300 | // Create a rising or falling inflection 30 frames prior to 301 | // index X. A rising inflection is used for questions, and 302 | // a falling inflection is used for statements. 303 | 304 | func (r *Render) AddInflection(inflection, phase1, pos byte) { 305 | var A byte 306 | // store the location of the punctuation 307 | end := pos 308 | 309 | if pos < 30 { 310 | pos = 0 311 | } else { 312 | pos -= 30 313 | } 314 | 315 | // FIXME: Explain this fix better, it's not obvious 316 | // ML : A =, fixes a problem with invalid pitch with '.' 317 | for r.pitches[pos] == 127 { 318 | pos++ 319 | } 320 | 321 | // pos-1 can become 255 and cause weird shit to happen 322 | if pos == 0 { 323 | A = r.pitches[pos] 324 | } else { 325 | A = r.pitches[pos-1] 326 | } 327 | 328 | for pos != end { 329 | // add the inflection direction 330 | A += inflection 331 | 332 | // set the inflection 333 | r.pitches[pos] = A 334 | 335 | pos++ 336 | for (pos != end) && r.pitches[pos] == 255 { 337 | pos++ 338 | } 339 | } 340 | } 341 | 342 | /* 343 | SAM's voice can be altered by changing the frequencies of the 344 | mouth formant (F1) and the throat formant (F2). Only the voiced 345 | phonemes (5-29 and 48-53) are altered. 346 | */ 347 | func SetMouthThroat(mouth, throat byte) { 348 | var initialFrequency byte 349 | var newFrequency byte 350 | 351 | // mouth formants (F1) 5..29 352 | mouthFormants5_29 := [30]byte{ 353 | 0, 0, 0, 0, 0, 10, 354 | 14, 19, 24, 27, 23, 21, 16, 20, 14, 18, 14, 18, 18, 355 | 16, 13, 15, 11, 18, 14, 11, 9, 6, 6, 6} 356 | 357 | // throat formants (F2) 5..29 358 | throatFormants5_29 := [30]byte{ 359 | 255, 255, 360 | 255, 255, 255, 84, 73, 67, 63, 40, 44, 31, 37, 45, 73, 49, 361 | 36, 30, 51, 37, 29, 69, 24, 50, 30, 24, 83, 46, 54, 86, 362 | } 363 | 364 | // there must be no zeros in this 2 tables 365 | // formant 1 frequencies (mouth) 48..53 366 | mouthFormants48_53 := [6]byte{19, 27, 21, 27, 18, 13} 367 | 368 | // formant 2 frequencies (throat) 48..53 369 | throatFormants48_53 := [6]byte{72, 39, 31, 43, 30, 34} 370 | 371 | var pos byte = 5 372 | 373 | // recalculate formant frequencies 5..29 for the mouth (F1) and throat (F2) 374 | for pos < 30 { 375 | // recalculate mouth frequency 376 | initialFrequency = mouthFormants5_29[pos] 377 | if initialFrequency != 0 { 378 | newFrequency = trans(mouth, initialFrequency) 379 | } 380 | freq1data[pos] = newFrequency 381 | 382 | // recalculate throat frequency 383 | initialFrequency = throatFormants5_29[pos] 384 | if initialFrequency != 0 { 385 | newFrequency = trans(throat, initialFrequency) 386 | } 387 | freq2data[pos] = newFrequency 388 | pos++ 389 | } 390 | 391 | // recalculate formant frequencies 48..53 392 | pos = 0 393 | for pos < 6 { 394 | // recalculate F1 (mouth formant) 395 | initialFrequency = mouthFormants48_53[pos] 396 | newFrequency = trans(mouth, initialFrequency) 397 | freq1data[pos+48] = newFrequency 398 | 399 | // recalculate F2 (throat formant) 400 | initialFrequency = throatFormants48_53[pos] 401 | newFrequency = trans(throat, initialFrequency) 402 | freq2data[pos+48] = newFrequency 403 | pos++ 404 | } 405 | } 406 | 407 | func PrintOutput(flag, f1, f2, f3, a1, a2, a3, p []byte) { 408 | fmt.Printf("===========================================\n") 409 | fmt.Printf("Final data for speech output:\n\n") 410 | i := 0 411 | fmt.Printf(" flags ampl1 freq1 ampl2 freq2 ampl3 freq3 pitch\n") 412 | fmt.Printf("------------------------------------------------\n") 413 | for i < 255 { 414 | fmt.Printf("%5d %5d %5d %5d %5d %5d %5d %5d\n", flag[i], a1[i], f1[i], a2[i], f2[i], a3[i], f3[i], p[i]) 415 | i++ 416 | } 417 | fmt.Printf("===========================================\n") 418 | 419 | } 420 | -------------------------------------------------------------------------------- /render/tabs.go: -------------------------------------------------------------------------------- 1 | package render 2 | 3 | const ( 4 | PhonemePeriod = 1 5 | PhonemeQuestion = 2 6 | PhonemeEnd = 255 7 | 8 | inflectionFalling = 1 9 | inflectionRising = 255 10 | ) 11 | 12 | var ( 13 | tab47492 = [11]byte{ 14 | 0, 0, 0xE0, 0xE6, 0xEC, 0xF3, 0xF9, 0, 15 | 6, 0xC, 6, 16 | } 17 | 18 | amplitudeRescale = [16]byte{ 19 | 0, 1, 2, 2, 2, 3, 3, 4, 20 | 4, 5, 6, 8, 9, 0xB, 0xD, 0xF, 21 | } 22 | 23 | // Used to decide which phoneme's blend lengths. The candidate with the lower score is selected. 24 | // tab45856 25 | blendRank = []byte{ 26 | 0, 0x1F, 0x1F, 0x1F, 0x1F, 2, 2, 2, 27 | 2, 2, 2, 2, 2, 2, 5, 5, 28 | 2, 0xA, 2, 8, 5, 5, 0xB, 0xA, 29 | 9, 8, 8, 0xA0, 8, 8, 0x17, 0x1F, 30 | 0x12, 0x12, 0x12, 0x12, 0x1E, 0x1E, 0x14, 0x14, 31 | 0x14, 0x14, 0x17, 0x17, 0x1A, 0x1A, 0x1D, 0x1D, 32 | 2, 2, 2, 2, 2, 2, 0x1A, 0x1D, 33 | 0x1B, 0x1A, 0x1D, 0x1B, 0x1A, 0x1D, 0x1B, 0x1A, 34 | 0x1D, 0x1B, 0x17, 0x1D, 0x17, 0x17, 0x1D, 0x17, 35 | 0x17, 0x1D, 0x17, 0x17, 0x1D, 0x17, 0x17, 0x17, 36 | } 37 | 38 | // Number of frames at the end of a phoneme devoted to interpolating to next phoneme's final value 39 | //tab45696, 40 | outBlendLength = []byte{ 41 | 0, 2, 2, 2, 2, 4, 4, 4, 42 | 4, 4, 4, 4, 4, 4, 4, 4, 43 | 4, 4, 3, 2, 4, 4, 2, 2, 44 | 2, 2, 2, 1, 1, 1, 1, 1, 45 | 1, 1, 1, 1, 1, 1, 2, 2, 46 | 2, 1, 0, 1, 0, 1, 0, 5, 47 | 5, 5, 5, 5, 4, 4, 2, 0, 48 | 1, 2, 0, 1, 2, 0, 1, 2, 49 | 0, 1, 2, 0, 2, 2, 0, 1, 50 | 3, 0, 2, 3, 0, 2, 0xA0, 0xA0, 51 | } 52 | 53 | // Number of frames at beginning of a phoneme devoted to interpolating to phoneme's final value 54 | // tab45776, 55 | inBlendLength = []byte{ 56 | 0, 2, 2, 2, 2, 4, 4, 4, 57 | 4, 4, 4, 4, 4, 4, 4, 4, 58 | 4, 4, 3, 3, 4, 4, 3, 3, 59 | 3, 3, 3, 1, 2, 3, 2, 1, 60 | 3, 3, 3, 3, 1, 1, 3, 3, 61 | 3, 2, 2, 3, 2, 3, 0, 0, 62 | 5, 5, 5, 5, 4, 4, 2, 0, 63 | 2, 2, 0, 3, 2, 0, 4, 2, 64 | 0, 3, 2, 0, 2, 2, 0, 2, 65 | 3, 0, 3, 3, 0, 3, 0xB0, 0xA0, 66 | } 67 | 68 | // Looks like it's used as bit flags 69 | // High bits masked by 248 (11111000) 70 | // 71 | // 32: S* 241 11110001, 72 | // 33: SH 226 11100010 73 | // 34: F* 211 11010011, 74 | // 35: TH 187 10111011, 75 | // 36: /H 124 01111100, 76 | // 37: /X 149 10010101, 77 | // 38: Z* 1 00000001, 78 | // 39: ZH 2 00000010, 79 | // 40: V* 3 00000011, 80 | // 41: DH 3 00000011, 81 | // 43: ** 114 01110010, 82 | // 45: ** 2 00000010, 83 | // 67: ** 27 00011011, 84 | // 70: ** 25 00011001, 85 | // tab45936, 86 | sampledConsonantFlags = []byte{ 87 | 0, 0, 0, 0, 0, 0, 0, 0, 88 | 0, 0, 0, 0, 0, 0, 0, 0, 89 | 0, 0, 0, 0, 0, 0, 0, 0, 90 | 0, 0, 0, 0, 0, 0, 0, 0, 91 | 0xF1, 0xE2, 0xD3, 0xBB, 0x7C, 0x95, 1, 2, 92 | 3, 3, 0, 0x72, 0, 2, 0, 0, 93 | 0, 0, 0, 0, 0, 0, 0, 0, 94 | 0, 0, 0, 0, 0, 0, 0, 0, 95 | 0, 0, 0, 0x1B, 0, 0, 0x19, 0, 96 | 0, 0, 0, 0, 0, 0, 0, 0, 97 | } 98 | 99 | //tab45056, 100 | freq1data = []byte{ 101 | 0x00, 0x13, 0x13, 0x13, 0x13, 0xA, 0xE, 0x12, 102 | 0x18, 0x1A, 0x16, 0x14, 0x10, 0x14, 0xE, 0x12, 103 | 0xE, 0x12, 0x12, 0x10, 0xC, 0xE, 0xA, 0x12, 104 | 0xE, 0xA, 8, 6, 6, 6, 6, 0x11, 105 | 6, 6, 6, 6, 0xE, 0x10, 9, 0xA, 106 | 8, 0xA, 6, 6, 6, 5, 6, 0, 107 | 0x12, 0x1A, 0x14, 0x1A, 0x12, 0xC, 6, 6, 108 | 6, 6, 6, 6, 6, 6, 6, 6, 109 | 6, 6, 6, 6, 6, 6, 6, 6, 110 | 6, 0xA, 0xA, 6, 6, 6, 0x2C, 0x13, 111 | } 112 | 113 | //tab451356, 114 | freq2data = []byte{ 115 | 0x00, 0x43, 0x43, 0x43, 0x43, 0x54, 0x48, 0x42, 116 | 0x3E, 0x28, 0x2C, 0x1E, 0x24, 0x2C, 0x48, 0x30, 117 | 0x24, 0x1E, 0x32, 0x24, 0x1C, 0x44, 0x18, 0x32, 118 | 0x1E, 0x18, 0x52, 0x2E, 0x36, 0x56, 0x36, 0x43, 119 | 0x49, 0x4F, 0x1A, 0x42, 0x49, 0x25, 0x33, 0x42, 120 | 0x28, 0x2F, 0x4F, 0x4F, 0x42, 0x4F, 0x6E, 0x00, 121 | 0x48, 0x26, 0x1E, 0x2A, 0x1E, 0x22, 0x1A, 0x1A, 122 | 0x1A, 0x42, 0x42, 0x42, 0x6E, 0x6E, 0x6E, 0x54, 123 | 0x54, 0x54, 0x1A, 0x1A, 0x1A, 0x42, 0x42, 0x42, 124 | 0x6D, 0x56, 0x6D, 0x54, 0x54, 0x54, 0x7F, 0x7F, 125 | } 126 | 127 | //tab45216, 128 | freq3data = []byte{ 129 | 0x00, 0x5B, 0x5B, 0x5B, 0x5B, 0x6E, 0x5D, 0x5B, 130 | 0x58, 0x59, 0x57, 0x58, 0x52, 0x59, 0x5D, 0x3E, 131 | 0x52, 0x58, 0x3E, 0x6E, 0x50, 0x5D, 0x5A, 0x3C, 132 | 0x6E, 0x5A, 0x6E, 0x51, 0x79, 0x65, 0x79, 0x5B, 133 | 0x63, 0x6A, 0x51, 0x79, 0x5D, 0x52, 0x5D, 0x67, 134 | 0x4C, 0x5D, 0x65, 0x65, 0x79, 0x65, 0x79, 0x00, 135 | 0x5A, 0x58, 0x58, 0x58, 0x58, 0x52, 0x51, 0x51, 136 | 0x51, 0x79, 0x79, 0x79, 0x70, 0x6E, 0x6E, 0x5E, 137 | 0x5E, 0x5E, 0x51, 0x51, 0x51, 0x79, 0x79, 0x79, 138 | 0x65, 0x65, 0x70, 0x5E, 0x5E, 0x5E, 0x08, 0x01, 139 | } 140 | 141 | ampl1data = []byte{ 142 | 0, 0, 0, 0, 0, 0xD, 0xD, 0xE, 143 | 0xF, 0xF, 0xF, 0xF, 0xF, 0xC, 0xD, 0xC, 144 | 0xF, 0xF, 0xD, 0xD, 0xD, 0xE, 0xD, 0xC, 145 | 0xD, 0xD, 0xD, 0xC, 9, 9, 0, 0, 146 | 0, 0, 0, 0, 0, 0, 0xB, 0xB, 147 | 0xB, 0xB, 0, 0, 1, 0xB, 0, 2, 148 | 0xE, 0xF, 0xF, 0xF, 0xF, 0xD, 2, 4, 149 | 0, 2, 4, 0, 1, 4, 0, 1, 150 | 4, 0, 0, 0, 0, 0, 0, 0, 151 | 0, 0xC, 0, 0, 0, 0, 0xF, 0xF, 152 | } 153 | 154 | ampl2data = []byte{ 155 | 0, 0, 0, 0, 0, 0xA, 0xB, 0xD, 156 | 0xE, 0xD, 0xC, 0xC, 0xB, 9, 0xB, 0xB, 157 | 0xC, 0xC, 0xC, 8, 8, 0xC, 8, 0xA, 158 | 8, 8, 0xA, 3, 9, 6, 0, 0, 159 | 0, 0, 0, 0, 0, 0, 3, 5, 160 | 3, 4, 0, 0, 0, 5, 0xA, 2, 161 | 0xE, 0xD, 0xC, 0xD, 0xC, 8, 0, 1, 162 | 0, 0, 1, 0, 0, 1, 0, 0, 163 | 1, 0, 0, 0, 0, 0, 0, 0, 164 | 0, 0xA, 0, 0, 0xA, 0, 0, 0, 165 | } 166 | 167 | ampl3data = []byte{ 168 | 0, 0, 0, 0, 0, 8, 7, 8, 169 | 8, 1, 1, 0, 1, 0, 7, 5, 170 | 1, 0, 6, 1, 0, 7, 0, 5, 171 | 1, 0, 8, 0, 0, 3, 0, 0, 172 | 0, 0, 0, 0, 0, 0, 0, 1, 173 | 0, 0, 0, 0, 0, 1, 0xE, 1, 174 | 9, 1, 0, 1, 0, 0, 0, 0, 175 | 0, 0, 0, 0, 0, 0, 0, 0, 176 | 0, 0, 0, 0, 0, 0, 0, 0, 177 | 0, 7, 0, 0, 5, 0, 0x13, 0x10, 178 | } 179 | 180 | //tab42240, 181 | sinus = [256]int8{ 182 | 0, 3, 6, 9, 12, 16, 19, 22, 25, 28, 31, 34, 37, 183 | 40, 43, 46, 49, 51, 54, 57, 60, 63, 65, 68, 71, 184 | 73, 76, 78, 81, 83, 85, 88, 90, 92, 94, 96, 98, 185 | 100, 102, 104, 106, 107, 109, 111, 112, 113, 115, 186 | 116, 117, 118, 120, 121, 122, 122, 123, 124, 125, 187 | 125, 126, 126, 126, 127, 127, 127, 127, 127, 127, 188 | 127, 126, 126, 126, 125, 125, 124, 123, 122, 122, 189 | 121, 120, 118, 117, 116, 115, 113, 112, 111, 109, 190 | 107, 106, 104, 102, 100, 98, 96, 94, 92, 90, 88, 191 | 85, 83, 81, 78, 76, 73, 71, 68, 65, 63, 60, 57, 192 | 54, 51, 49, 46, 43, 40, 37, 34, 31, 28, 25, 22, 193 | 19, 16, 12, 9, 6, 3, 0, -3, -6, -9, -12, -16, -19, 194 | -22, -25, -28, -31, -34, -37, -40, -43, -46, -49, 195 | -51, -54, -57, -60, -63, -65, -68, -71, -73, -76, 196 | -78, -81, -83, -85, -88, -90, -92, -94, -96, -98, 197 | -100, -102, -104, -106, -107, -109, -111, -112, 198 | -113, -115, -116, -117, -118, -120, -121, -122, 199 | -122, -123, -124, -125, -125, -126, -126, -126, 200 | -127, -127, -127, -127, -127, -127, -127, -126, 201 | -126, -126, -125, -125, -124, -123, -122, -122, 202 | -121, -120, -118, -117, -116, -115, -113, -112, 203 | -111, -109, -107, -106, -104, -102, -100, -98, -96, 204 | -94, -92, -90, -88, -85, -83, -81, -78, -76, -73, 205 | -71, -68, -65, -63, -60, -57, -54, -51, -49, -46, 206 | -43, -40, -37, -34, -31, -28, -25, -22, -19, -16, -12, -9, -6, -3, 207 | } 208 | 209 | //tab42496, 210 | rectangle = []byte{ 211 | 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 212 | 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 213 | 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 214 | 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 215 | 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 216 | 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 217 | 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 218 | 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 219 | 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 220 | 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 221 | 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 222 | 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 223 | 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 224 | 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 225 | 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 226 | 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 227 | 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 228 | 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 229 | 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 230 | 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 231 | 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 232 | 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 233 | 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 234 | 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 235 | 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 236 | 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 237 | 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 238 | 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 239 | 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 240 | 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 241 | 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 242 | 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 243 | } 244 | 245 | //random data ? 246 | sampleTable = [0x500]byte{ 247 | //00, 248 | 249 | 0x38, 0x84, 0x6B, 0x19, 0xC6, 0x63, 0x18, 0x86, 250 | 0x73, 0x98, 0xC6, 0xB1, 0x1C, 0xCA, 0x31, 0x8C, 251 | 0xC7, 0x31, 0x88, 0xC2, 0x30, 0x98, 0x46, 0x31, 252 | 0x18, 0xC6, 0x35, 0xC, 0xCA, 0x31, 0xC, 0xC6, 253 | //20, 254 | 0x21, 0x10, 0x24, 0x69, 0x12, 0xC2, 0x31, 0x14, 255 | 0xC4, 0x71, 8, 0x4A, 0x22, 0x49, 0xAB, 0x6A, 256 | 0xA8, 0xAC, 0x49, 0x51, 0x32, 0xD5, 0x52, 0x88, 257 | 0x93, 0x6C, 0x94, 0x22, 0x15, 0x54, 0xD2, 0x25, 258 | //40, 259 | 0x96, 0xD4, 0x50, 0xA5, 0x46, 0x21, 8, 0x85, 260 | 0x6B, 0x18, 0xC4, 0x63, 0x10, 0xCE, 0x6B, 0x18, 261 | 0x8C, 0x71, 0x19, 0x8C, 0x63, 0x35, 0xC, 0xC6, 262 | 0x33, 0x99, 0xCC, 0x6C, 0xB5, 0x4E, 0xA2, 0x99, 263 | //60, 264 | 0x46, 0x21, 0x28, 0x82, 0x95, 0x2E, 0xE3, 0x30, 265 | 0x9C, 0xC5, 0x30, 0x9C, 0xA2, 0xB1, 0x9C, 0x67, 266 | 0x31, 0x88, 0x66, 0x59, 0x2C, 0x53, 0x18, 0x84, 267 | 0x67, 0x50, 0xCA, 0xE3, 0xA, 0xAC, 0xAB, 0x30, 268 | //80, 269 | 0xAC, 0x62, 0x30, 0x8C, 0x63, 0x10, 0x94, 0x62, 270 | 0xB1, 0x8C, 0x82, 0x28, 0x96, 0x33, 0x98, 0xD6, 271 | 0xB5, 0x4C, 0x62, 0x29, 0xA5, 0x4A, 0xB5, 0x9C, 272 | 0xC6, 0x31, 0x14, 0xD6, 0x38, 0x9C, 0x4B, 0xB4, 273 | //A0, 274 | 0x86, 0x65, 0x18, 0xAE, 0x67, 0x1C, 0xA6, 0x63, 275 | 0x19, 0x96, 0x23, 0x19, 0x84, 0x13, 8, 0xA6, 276 | 0x52, 0xAC, 0xCA, 0x22, 0x89, 0x6E, 0xAB, 0x19, 277 | 0x8C, 0x62, 0x34, 0xC4, 0x62, 0x19, 0x86, 0x63, 278 | //C0, 279 | 0x18, 0xC4, 0x23, 0x58, 0xD6, 0xA3, 0x50, 0x42, 280 | 0x54, 0x4A, 0xAD, 0x4A, 0x25, 0x11, 0x6B, 0x64, 281 | 0x89, 0x4A, 0x63, 0x39, 0x8A, 0x23, 0x31, 0x2A, 282 | 0xEA, 0xA2, 0xA9, 0x44, 0xC5, 0x12, 0xCD, 0x42, 283 | //E0, 284 | 0x34, 0x8C, 0x62, 0x18, 0x8C, 0x63, 0x11, 0x48, 285 | 0x66, 0x31, 0x9D, 0x44, 0x33, 0x1D, 0x46, 0x31, 286 | 0x9C, 0xC6, 0xB1, 0xC, 0xCD, 0x32, 0x88, 0xC4, 287 | 0x73, 0x18, 0x86, 0x73, 8, 0xD6, 0x63, 0x58, 288 | //100, 289 | 7, 0x81, 0xE0, 0xF0, 0x3C, 7, 0x87, 0x90, 290 | 0x3C, 0x7C, 0xF, 0xC7, 0xC0, 0xC0, 0xF0, 0x7C, 291 | 0x1E, 7, 0x80, 0x80, 0, 0x1C, 0x78, 0x70, 292 | 0xF1, 0xC7, 0x1F, 0xC0, 0xC, 0xFE, 0x1C, 0x1F, 293 | //120, 294 | 0x1F, 0xE, 0xA, 0x7A, 0xC0, 0x71, 0xF2, 0x83, 295 | 0x8F, 3, 0xF, 0xF, 0xC, 0, 0x79, 0xF8, 296 | 0x61, 0xE0, 0x43, 0xF, 0x83, 0xE7, 0x18, 0xF9, 297 | 0xC1, 0x13, 0xDA, 0xE9, 0x63, 0x8F, 0xF, 0x83, 298 | //140, 299 | 0x83, 0x87, 0xC3, 0x1F, 0x3C, 0x70, 0xF0, 0xE1, 300 | 0xE1, 0xE3, 0x87, 0xB8, 0x71, 0xE, 0x20, 0xE3, 301 | 0x8D, 0x48, 0x78, 0x1C, 0x93, 0x87, 0x30, 0xE1, 302 | 0xC1, 0xC1, 0xE4, 0x78, 0x21, 0x83, 0x83, 0xC3, 303 | //160, 304 | 0x87, 6, 0x39, 0xE5, 0xC3, 0x87, 7, 0xE, 305 | 0x1C, 0x1C, 0x70, 0xF4, 0x71, 0x9C, 0x60, 0x36, 306 | 0x32, 0xC3, 0x1E, 0x3C, 0xF3, 0x8F, 0xE, 0x3C, 307 | 0x70, 0xE3, 0xC7, 0x8F, 0xF, 0xF, 0xE, 0x3C, 308 | //180, 309 | 0x78, 0xF0, 0xE3, 0x87, 6, 0xF0, 0xE3, 7, 310 | 0xC1, 0x99, 0x87, 0xF, 0x18, 0x78, 0x70, 0x70, 311 | 0xFC, 0xF3, 0x10, 0xB1, 0x8C, 0x8C, 0x31, 0x7C, 312 | 0x70, 0xE1, 0x86, 0x3C, 0x64, 0x6C, 0xB0, 0xE1, 313 | //1A0, 314 | 0xE3, 0xF, 0x23, 0x8F, 0xF, 0x1E, 0x3E, 0x38, 315 | 0x3C, 0x38, 0x7B, 0x8F, 7, 0xE, 0x3C, 0xF4, 316 | 0x17, 0x1E, 0x3C, 0x78, 0xF2, 0x9E, 0x72, 0x49, 317 | 0xE3, 0x25, 0x36, 0x38, 0x58, 0x39, 0xE2, 0xDE, 318 | //1C0, 319 | 0x3C, 0x78, 0x78, 0xE1, 0xC7, 0x61, 0xE1, 0xE1, 320 | 0xB0, 0xF0, 0xF0, 0xC3, 0xC7, 0xE, 0x38, 0xC0, 321 | 0xF0, 0xCE, 0x73, 0x73, 0x18, 0x34, 0xB0, 0xE1, 322 | 0xC7, 0x8E, 0x1C, 0x3C, 0xF8, 0x38, 0xF0, 0xE1, 323 | //1E0, 324 | 0xC1, 0x8B, 0x86, 0x8F, 0x1C, 0x78, 0x70, 0xF0, 325 | 0x78, 0xAC, 0xB1, 0x8F, 0x39, 0x31, 0xDB, 0x38, 326 | 0x61, 0xC3, 0xE, 0xE, 0x38, 0x78, 0x73, 0x17, 327 | 0x1E, 0x39, 0x1E, 0x38, 0x64, 0xE1, 0xF1, 0xC1, 328 | //200, 329 | 0x4E, 0xF, 0x40, 0xA2, 2, 0xC5, 0x8F, 0x81, 330 | 0xA1, 0xFC, 0x12, 8, 0x64, 0xE0, 0x3C, 0x22, 331 | 0xE0, 0x45, 7, 0x8E, 0xC, 0x32, 0x90, 0xF0, 332 | 0x1F, 0x20, 0x49, 0xE0, 0xF8, 0xC, 0x60, 0xF0, 333 | //220, 334 | 0x17, 0x1A, 0x41, 0xAA, 0xA4, 0xD0, 0x8D, 0x12, 335 | 0x82, 0x1E, 0x1E, 3, 0xF8, 0x3E, 3, 0xC, 336 | 0x73, 0x80, 0x70, 0x44, 0x26, 3, 0x24, 0xE1, 337 | 0x3E, 4, 0x4E, 4, 0x1C, 0xC1, 9, 0xCC, 338 | //240, 339 | 0x9E, 0x90, 0x21, 7, 0x90, 0x43, 0x64, 0xC0, 340 | 0xF, 0xC6, 0x90, 0x9C, 0xC1, 0x5B, 3, 0xE2, 341 | 0x1D, 0x81, 0xE0, 0x5E, 0x1D, 3, 0x84, 0xB8, 342 | 0x2C, 0xF, 0x80, 0xB1, 0x83, 0xE0, 0x30, 0x41, 343 | //260, 344 | 0x1E, 0x43, 0x89, 0x83, 0x50, 0xFC, 0x24, 0x2E, 345 | 0x13, 0x83, 0xF1, 0x7C, 0x4C, 0x2C, 0xC9, 0xD, 346 | 0x83, 0xB0, 0xB5, 0x82, 0xE4, 0xE8, 6, 0x9C, 347 | 7, 0xA0, 0x99, 0x1D, 7, 0x3E, 0x82, 0x8F, 348 | //280, 349 | 0x70, 0x30, 0x74, 0x40, 0xCA, 0x10, 0xE4, 0xE8, 350 | 0xF, 0x92, 0x14, 0x3F, 6, 0xF8, 0x84, 0x88, 351 | 0x43, 0x81, 0xA, 0x34, 0x39, 0x41, 0xC6, 0xE3, 352 | 0x1C, 0x47, 3, 0xB0, 0xB8, 0x13, 0xA, 0xC2, 353 | //2A0, 354 | 0x64, 0xF8, 0x18, 0xF9, 0x60, 0xB3, 0xC0, 0x65, 355 | 0x20, 0x60, 0xA6, 0x8C, 0xC3, 0x81, 0x20, 0x30, 356 | 0x26, 0x1E, 0x1C, 0x38, 0xD3, 1, 0xB0, 0x26, 357 | 0x40, 0xF4, 0xB, 0xC3, 0x42, 0x1F, 0x85, 0x32, 358 | //2C0, 359 | 0x26, 0x60, 0x40, 0xC9, 0xCB, 1, 0xEC, 0x11, 360 | 0x28, 0x40, 0xFA, 4, 0x34, 0xE0, 0x70, 0x4C, 361 | 0x8C, 0x1D, 7, 0x69, 3, 0x16, 0xC8, 4, 362 | 0x23, 0xE8, 0xC6, 0x9A, 0xB, 0x1A, 3, 0xE0, 363 | //2E0, 364 | 0x76, 6, 5, 0xCF, 0x1E, 0xBC, 0x58, 0x31, 365 | 0x71, 0x66, 0, 0xF8, 0x3F, 4, 0xFC, 0xC, 366 | 0x74, 0x27, 0x8A, 0x80, 0x71, 0xC2, 0x3A, 0x26, 367 | 6, 0xC0, 0x1F, 5, 0xF, 0x98, 0x40, 0xAE, 368 | //300, 369 | 1, 0x7F, 0xC0, 7, 0xFF, 0, 0xE, 0xFE, 370 | 0, 3, 0xDF, 0x80, 3, 0xEF, 0x80, 0x1B, 371 | 0xF1, 0xC2, 0, 0xE7, 0xE0, 0x18, 0xFC, 0xE0, 372 | 0x21, 0xFC, 0x80, 0x3C, 0xFC, 0x40, 0xE, 0x7E, 373 | //320, 374 | 0, 0x3F, 0x3E, 0, 0xF, 0xFE, 0, 0x1F, 375 | 0xFF, 0, 0x3E, 0xF0, 7, 0xFC, 0, 0x7E, 376 | 0x10, 0x3F, 0xFF, 0, 0x3F, 0x38, 0xE, 0x7C, 377 | 1, 0x87, 0xC, 0xFC, 0xC7, 0, 0x3E, 4, 378 | //340, 379 | 0xF, 0x3E, 0x1F, 0xF, 0xF, 0x1F, 0xF, 2, 380 | 0x83, 0x87, 0xCF, 3, 0x87, 0xF, 0x3F, 0xC0, 381 | 7, 0x9E, 0x60, 0x3F, 0xC0, 3, 0xFE, 0, 382 | 0x3F, 0xE0, 0x77, 0xE1, 0xC0, 0xFE, 0xE0, 0xC3, 383 | //360, 384 | 0xE0, 1, 0xDF, 0xF8, 3, 7, 0, 0x7E, 385 | 0x70, 0, 0x7C, 0x38, 0x18, 0xFE, 0xC, 0x1E, 386 | 0x78, 0x1C, 0x7C, 0x3E, 0xE, 0x1F, 0x1E, 0x1E, 387 | 0x3E, 0, 0x7F, 0x83, 7, 0xDB, 0x87, 0x83, 388 | //380, 389 | 7, 0xC7, 7, 0x10, 0x71, 0xFF, 0, 0x3F, 390 | 0xE2, 1, 0xE0, 0xC1, 0xC3, 0xE1, 0, 0x7F, 391 | 0xC0, 5, 0xF0, 0x20, 0xF8, 0xF0, 0x70, 0xFE, 392 | 0x78, 0x79, 0xF8, 2, 0x3F, 0xC, 0x8F, 3, 393 | //3a0, 394 | 0xF, 0x9F, 0xE0, 0xC1, 0xC7, 0x87, 3, 0xC3, 395 | 0xC3, 0xB0, 0xE1, 0xE1, 0xC1, 0xE3, 0xE0, 0x71, 396 | 0xF0, 0, 0xFC, 0x70, 0x7C, 0xC, 0x3E, 0x38, 397 | 0xE, 0x1C, 0x70, 0xC3, 0xC7, 3, 0x81, 0xC1, 398 | //3c0, 399 | 0xC7, 0xE7, 0, 0xF, 0xC7, 0x87, 0x19, 9, 400 | 0xEF, 0xC4, 0x33, 0xE0, 0xC1, 0xFC, 0xF8, 0x70, 401 | 0xF0, 0x78, 0xF8, 0xF0, 0x61, 0xC7, 0, 0x1F, 402 | 0xF8, 1, 0x7C, 0xF8, 0xF0, 0x78, 0x70, 0x3C, 403 | //3e0, 404 | 0x7C, 0xCE, 0xE, 0x21, 0x83, 0xCF, 8, 7, 405 | 0x8F, 8, 0xC1, 0x87, 0x8F, 0x80, 0xC7, 0xE3, 406 | 0, 7, 0xF8, 0xE0, 0xEF, 0, 0x39, 0xF7, 407 | 0x80, 0xE, 0xF8, 0xE1, 0xE3, 0xF8, 0x21, 0x9F, 408 | //400, 409 | 0xC0, 0xFF, 3, 0xF8, 7, 0xC0, 0x1F, 0xF8, 410 | 0xC4, 4, 0xFC, 0xC4, 0xC1, 0xBC, 0x87, 0xF0, 411 | 0xF, 0xC0, 0x7F, 5, 0xE0, 0x25, 0xEC, 0xC0, 412 | 0x3E, 0x84, 0x47, 0xF0, 0x8E, 3, 0xF8, 3, 413 | //420, 414 | 0xFB, 0xC0, 0x19, 0xF8, 7, 0x9C, 0xC, 0x17, 415 | 0xF8, 7, 0xE0, 0x1F, 0xA1, 0xFC, 0xF, 0xFC, 416 | 1, 0xF0, 0x3F, 0, 0xFE, 3, 0xF0, 0x1F, 417 | 0, 0xFD, 0, 0xFF, 0x88, 0xD, 0xF9, 1, 418 | //440, 419 | 0xFF, 0, 0x70, 7, 0xC0, 0x3E, 0x42, 0xF3, 420 | 0xD, 0xC4, 0x7F, 0x80, 0xFC, 7, 0xF0, 0x5E, 421 | 0xC0, 0x3F, 0, 0x78, 0x3F, 0x81, 0xFF, 1, 422 | 0xF8, 1, 0xC3, 0xE8, 0xC, 0xE4, 0x64, 0x8F, 423 | ////460, 424 | 0xE4, 0xF, 0xF0, 7, 0xF0, 0xC2, 0x1F, 0, 425 | 0x7F, 0xC0, 0x6F, 0x80, 0x7E, 3, 0xF8, 7, 426 | 0xF0, 0x3F, 0xC0, 0x78, 0xF, 0x82, 7, 0xFE, 427 | 0x22, 0x77, 0x70, 2, 0x76, 3, 0xFE, 0, 428 | //480, 429 | 0xFE, 0x67, 0, 0x7C, 0xC7, 0xF1, 0x8E, 0xC6, 430 | 0x3B, 0xE0, 0x3F, 0x84, 0xF3, 0x19, 0xD8, 3, 431 | 0x99, 0xFC, 9, 0xB8, 0xF, 0xF8, 0, 0x9D, 432 | 0x24, 0x61, 0xF9, 0xD, 0, 0xFD, 3, 0xF0, 433 | //4a0, 434 | 0x1F, 0x90, 0x3F, 1, 0xF8, 0x1F, 0xD0, 0xF, 435 | 0xF8, 0x37, 1, 0xF8, 7, 0xF0, 0xF, 0xC0, 436 | 0x3F, 0, 0xFE, 3, 0xF8, 0xF, 0xC0, 0x3F, 437 | 0, 0xFA, 3, 0xF0, 0xF, 0x80, 0xFF, 1, 438 | //4c0, 439 | 0xB8, 7, 0xF0, 1, 0xFC, 1, 0xBC, 0x80, 440 | 0x13, 0x1E, 0, 0x7F, 0xE1, 0x40, 0x7F, 0xA0, 441 | 0x7F, 0xB0, 0, 0x3F, 0xC0, 0x1F, 0xC0, 0x38, 442 | 0xF, 0xF0, 0x1F, 0x80, 0xFF, 1, 0xFC, 3, 443 | //4e0, 444 | 0xF1, 0x7E, 1, 0xFE, 1, 0xF0, 0xFF, 0, 445 | 0x7F, 0xC0, 0x1D, 7, 0xF0, 0xF, 0xC0, 0x7E, 446 | 6, 0xE0, 7, 0xE0, 0xF, 0xF8, 6, 0xC1, 447 | 0xFE, 1, 0xFC, 3, 0xE0, 0xF, 0, 0xFC, 448 | } 449 | ) 450 | -------------------------------------------------------------------------------- /sammain/sam.go: -------------------------------------------------------------------------------- 1 | package sammain 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/exploser/sam/config" 7 | "github.com/exploser/sam/render" 8 | ) 9 | 10 | type Sam struct { 11 | stress [256]byte //numbers from 0 to 8 12 | phonemeLength [256]byte //tab40160 13 | phonemeindex [256]byte 14 | 15 | Input [256]byte //tab39445 16 | //standard sam sound 17 | Config *config.Config 18 | } 19 | 20 | // contains the final soundbuffer 21 | 22 | func (s *Sam) SetInput(input [256]byte) { 23 | copy(s.Input[:], input[:]) 24 | } 25 | 26 | func (s *Sam) Init() { 27 | var i int 28 | render.SetMouthThroat(s.Config.Mouth, s.Config.Throat) 29 | 30 | for i = 0; i < 256; i++ { 31 | s.stress[i] = 0 32 | s.phonemeLength[i] = 0 33 | } 34 | 35 | s.phonemeindex[255] = render.PhonemeEnd //to prevent buffer overflow // ML : changed from 32 to 255 to stop freezing with long inputs 36 | } 37 | 38 | func (s *Sam) SAMMain() bool { 39 | s.Init() 40 | /* FIXME: At odds with assignment in Init() */ 41 | s.phonemeindex[255] = 32 //to prevent buffer overflow 42 | 43 | if !s.Parser1() { 44 | return false 45 | } 46 | if s.Config.Debug { 47 | PrintPhonemes(s.phonemeindex[:], s.phonemeLength[:], s.stress[:]) 48 | } 49 | s.Parser2() 50 | s.CopyStress() 51 | s.SetPhonemeLength() 52 | s.AdjustLengths() 53 | s.Code41240() 54 | 55 | var X byte 56 | for ok := true; ok; ok = (X != 0) { 57 | if s.phonemeindex[X] > 80 { 58 | s.phonemeindex[X] = render.PhonemeEnd 59 | break // error: delete all behind it 60 | } 61 | X++ 62 | } 63 | s.InsertBreath(0) 64 | 65 | if s.Config.Debug { 66 | PrintPhonemes(s.phonemeindex[:], s.phonemeLength[:], s.stress[:]) 67 | } 68 | 69 | // s.PrepareOutput(&s.r) 70 | return true 71 | } 72 | 73 | func (s *Sam) PrepareOutput(r *render.Render) { 74 | var srcpos byte = 0 // Position in source 75 | var destpos byte = 0 // Position in output 76 | 77 | for { 78 | A := s.phonemeindex[srcpos] 79 | r.PhonemeIndexOutput[destpos] = A 80 | switch A { 81 | case render.PhonemeEnd: 82 | r.Render(s.Config) 83 | return 84 | case BREAK: 85 | r.PhonemeIndexOutput[destpos] = render.PhonemeEnd 86 | r.Render(s.Config) 87 | destpos = 0 88 | break 89 | case 0: 90 | break 91 | default: 92 | r.PhonemeLengthOutput[destpos] = s.phonemeLength[srcpos] 93 | r.StressOutput[destpos] = s.stress[srcpos] 94 | destpos++ 95 | } 96 | srcpos++ 97 | } 98 | } 99 | 100 | func (s *Sam) InsertBreath(mem59 byte) { 101 | var mem54 byte = 255 102 | var len byte 103 | var index byte //variable Y 104 | 105 | var pos byte 106 | 107 | index = s.phonemeindex[pos] 108 | for s.phonemeindex[pos] != render.PhonemeEnd { 109 | index = s.phonemeindex[pos] 110 | len += s.phonemeLength[pos] 111 | if len < 232 { 112 | if index == BREAK { 113 | } else if !(flags[index]&FLAG_PUNCT != 0) { 114 | if index == 0 { 115 | mem54 = pos 116 | } 117 | } else { 118 | len = 0 119 | pos++ 120 | s.Insert(pos, BREAK, mem59, 0) 121 | } 122 | } else { 123 | pos = mem54 124 | s.phonemeindex[pos] = 31 // 'Q*' glottal stop 125 | s.phonemeLength[pos] = 4 126 | s.stress[pos] = 0 127 | 128 | len = 0 129 | pos++ 130 | s.Insert(pos, BREAK, mem59, 0) 131 | } 132 | pos++ 133 | } 134 | } 135 | 136 | // Iterates through the phoneme buffer, copying the stress value from 137 | // the following phoneme under the following circumstance: 138 | 139 | // 1. The current phoneme is voiced, excluding plosives and fricatives 140 | // 2. The following phoneme is voiced, excluding plosives and fricatives, and 141 | // 3. The following phoneme is stressed 142 | // 143 | // In those cases, the stress value+1 from the following phoneme is copied. 144 | // 145 | // For example, the word LOITER is represented as LOY5TER, with as stress 146 | // of 5 on the dipthong OY. This routine will copy the stress value of 6 (5+1) 147 | // to the L that precedes it. 148 | 149 | func (s *Sam) CopyStress() { 150 | // loop thought all the phonemes to be output 151 | var pos byte //mem66 152 | var Y byte 153 | Y = s.phonemeindex[pos] 154 | for s.phonemeindex[pos] != render.PhonemeEnd { 155 | Y = s.phonemeindex[pos] 156 | // if CONSONANT_FLAG set, skip - only vowels get stress 157 | if flags[Y]&64 != 0 { 158 | Y = s.phonemeindex[pos+1] 159 | 160 | // if the following phoneme is the end, or a vowel, skip 161 | if Y != render.PhonemeEnd && (flags[Y]&128) != 0 { 162 | // get the stress value at the next position 163 | Y = s.stress[pos+1] 164 | if Y != 0 && !(Y&128 != 0) { 165 | // if next phoneme is stressed, and a VOWEL OR ER 166 | // copy stress from next phoneme to this one 167 | s.stress[pos] = Y + 1 168 | } 169 | } 170 | } 171 | 172 | pos++ 173 | } 174 | } 175 | 176 | func (s *Sam) Insert(position /*var57*/, mem60, mem59, mem58 byte) { 177 | var i int 178 | for i = 253; i >= int(position); i-- { // ML : always keep last safe-guarding 255 179 | s.phonemeindex[i+1] = s.phonemeindex[i] 180 | s.phonemeLength[i+1] = s.phonemeLength[i] 181 | s.stress[i+1] = s.stress[i] 182 | } 183 | 184 | s.phonemeindex[position] = mem60 185 | s.phonemeLength[position] = mem59 186 | s.stress[position] = mem58 187 | return 188 | } 189 | 190 | func full_match(sign1, sign2 byte) int { 191 | var Y byte 192 | for ok := true; ok; ok = (Y != 81) { 193 | // GET FIRST CHARACTER AT POSITION Y IN signInputTable 194 | // --> should change name to PhonemeNameTable1 195 | A := SignInputTable1[Y] 196 | 197 | if A == sign1 { 198 | A = SignInputTable2[Y] 199 | // NOT A SPECIAL AND MATCHES SECOND CHARACTER? 200 | if (A != '*') && (A == sign2) { 201 | return int(Y) 202 | } 203 | } 204 | Y++ 205 | } 206 | return -1 207 | } 208 | 209 | func wild_match(sign1, sign2 byte) int { 210 | var Y int 211 | for ok := true; ok; ok = (Y != 81) { 212 | if SignInputTable2[Y] == '*' { 213 | if SignInputTable1[Y] == sign1 { 214 | return Y 215 | } 216 | } 217 | Y++ 218 | } 219 | return -1 220 | } 221 | 222 | func PrintPhonemes(phonemeindex []byte, phonemeLength []byte, stress []byte) { 223 | i := 0 224 | fmt.Printf("===========================================\n") 225 | 226 | fmt.Printf("Internal Phoneme presentation:\n\n") 227 | fmt.Printf(" idx phoneme length stress\n") 228 | fmt.Printf("------------------------------\n") 229 | 230 | for (phonemeindex[i] != render.PhonemeEnd) && (i < 255) { 231 | if phonemeindex[i] < 81 { 232 | fmt.Printf(" %3v %c%c %3v %v\n", 233 | phonemeindex[i], 234 | SignInputTable1[phonemeindex[i]], 235 | SignInputTable2[phonemeindex[i]], 236 | phonemeLength[i], 237 | stress[i], 238 | ) 239 | } else { 240 | fmt.Printf(" %3v ?? %3v %v\n", phonemeindex[i], phonemeLength[i], stress[i]) 241 | } 242 | i++ 243 | } 244 | fmt.Printf("===========================================\n") 245 | fmt.Printf("\n") 246 | } 247 | 248 | // The input[] buffer contains a string of phonemes and stress markers along 249 | // the lines of: 250 | // 251 | // DHAX KAET IHZ AH5GLIY. <0x9B> 252 | // 253 | // The byte 0x9B marks the end of the buffer. Some phonemes are 2 bytes 254 | // long, such as "DH" and "AX". Others are 1 byte long, such as "T" and "Z". 255 | // There are also stress markers, such as "5" and ".". 256 | // 257 | // The first character of the phonemes are stored in the table SignInputTable1[]. 258 | // The second character of the phonemes are stored in the table SignInputTable2[]. 259 | // The stress characters are arranged in low to high stress order in stressInputTable[]. 260 | // 261 | // The following process is used to parse the input[] buffer: 262 | // 263 | // Repeat until the <0x9B> character is reached: 264 | // 265 | // First, a search is made for a 2 character match for phonemes that do not 266 | // end with the '*' (wildcard) character. On a match, the index of the phoneme 267 | // is added tos.phonemeindex[] and the buffer position is advanced 2 bytes. 268 | // 269 | // If this fails, a search is made for a 1 character match against all 270 | // phoneme names ending with a '*' (wildcard). If this succeeds, the 271 | // phoneme is added tos.phonemeindex[] and the buffer position is advanced 272 | // 1 byte. 273 | // 274 | // If this fails, search for a 1 character match in the stressInputTable[]. 275 | // If this succeeds, the stress value is placed in the last stress[] table 276 | // at the same index of the last added phoneme, and the buffer position is 277 | // advanced by 1 byte. 278 | // 279 | // If this fails, return a 0. 280 | // 281 | // On success: 282 | // 283 | // 1.s.phonemeindex[] will contain the index of all the phonemes. 284 | // 2. The last index ins.phonemeindex[] will be 255. 285 | // 3. stress[] will contain the stress value for each phoneme 286 | 287 | // input[] holds the string of phonemes, each two bytes wide 288 | // SignInputTable1[] holds the first character of each phoneme 289 | // SignInputTable2[] holds te second character of each phoneme 290 | //s.phonemeindex[] holds the indexes of the phonemes after parsing input[] 291 | // 292 | // The parser scans through the input[], finding the names of the phonemes 293 | // by searching SignInputTable1[] and SignInputTable2[]. On a match, it 294 | // copies the index of the phoneme into thes.phonemeindexTable[]. 295 | // 296 | // The character <0x9B> marks the end of text in input[]. When it is reached, 297 | // the index 255 is placed at the end of thes.phonemeindexTable[], and the 298 | // function returns with a 1 indicating success. 299 | func (s *Sam) Parser1() bool { 300 | for i := 0; i < 256; i++ { 301 | s.stress[i] = 0 302 | } // Clear the stress table. 303 | 304 | var position byte 305 | var srcpos byte 306 | sign1 := s.Input[srcpos] 307 | var sign2 byte 308 | for s.Input[srcpos] != 155 { // 155 (\233) is end of line marker 309 | sign1 = s.Input[srcpos] 310 | srcpos++ 311 | sign2 = s.Input[srcpos] 312 | match := full_match(sign1, sign2) 313 | if match != -1 { 314 | // Matched both characters (no wildcards) 315 | s.phonemeindex[position] = byte(match) 316 | position++ 317 | srcpos++ // Skip the second character of the input as we've matched it 318 | continue 319 | } 320 | match = wild_match(sign1, sign2) 321 | if match != -1 { 322 | // Matched just the first character (with second character matching '*' 323 | s.phonemeindex[position] = byte(match) 324 | position++ 325 | } else { 326 | // Should be a stress character. Search through the 327 | // stress table backwards. 328 | match = 8 // End of stress table. FIXME: Don't hardcode. 329 | for (sign1 != StressInputTable[match]) && (match > 0) { 330 | match-- 331 | } 332 | 333 | if match == 0 { 334 | return false 335 | } // failure 336 | 337 | s.stress[position-1] = byte(match) // Set stress for prior phoneme 338 | } 339 | } //while 340 | 341 | s.phonemeindex[position] = render.PhonemeEnd 342 | return true 343 | } 344 | 345 | //change phonemelength depedendent on stress 346 | func (s *Sam) SetPhonemeLength() { 347 | position := 0 348 | for s.phonemeindex[position] != 255 { 349 | var A = s.stress[position] 350 | if (A == 0) || ((A & 128) != 0) { 351 | s.phonemeLength[position] = phonemeLengthTable[s.phonemeindex[position]] 352 | } else { 353 | s.phonemeLength[position] = phonemeStressedLengthTable[s.phonemeindex[position]] 354 | } 355 | position++ 356 | } 357 | } 358 | 359 | func (s *Sam) Code41240() { 360 | var pos byte = 0 361 | 362 | for s.phonemeindex[pos] != render.PhonemeEnd { 363 | var index = s.phonemeindex[pos] 364 | 365 | if flags[index]&FLAG_STOPCONS != 0 { 366 | if flags[index]&FLAG_PLOSIVE != 0 { 367 | var A byte 368 | X := pos + 1 369 | for s.phonemeindex[X] == 0 { 370 | X++ 371 | A = s.phonemeindex[X] 372 | } /* Skip pause */ 373 | 374 | if A != render.PhonemeEnd { 375 | if (flags[A]&8 != 0) || (A == 36) || (A == 37) { 376 | pos++ 377 | continue 378 | } // '/H' '/X' 379 | } 380 | 381 | } 382 | s.Insert(pos+1, index+1, phonemeLengthTable[index+1], s.stress[pos]) 383 | s.Insert(pos+2, index+2, phonemeLengthTable[index+2], s.stress[pos]) 384 | pos += 2 385 | } 386 | pos++ 387 | } 388 | } 389 | 390 | func (s *Sam) ChangeRule(position, rule, mem60, mem59, stress byte, descr string) { 391 | if s.Config.Debug { 392 | fmt.Printf("RULE: %s\n", descr) 393 | } 394 | s.phonemeindex[position] = rule 395 | s.Insert(position+1, mem60, mem59, stress) 396 | } 397 | 398 | func (s *Sam) drule(str string) { 399 | if s.Config.Debug { 400 | fmt.Printf("RULE: %s\n", str) 401 | } 402 | } 403 | 404 | func (s *Sam) drule_pre(descr string, X byte) { 405 | s.drule(descr) 406 | if s.Config.Debug { 407 | fmt.Printf("PRE\n") 408 | } 409 | if s.Config.Debug { 410 | fmt.Printf("phoneme %d (%c%c) length %d\n", X, SignInputTable1[s.phonemeindex[X]], SignInputTable2[s.phonemeindex[X]], s.phonemeLength[X]) 411 | } 412 | } 413 | 414 | func (s *Sam) drule_post(X byte) { 415 | if s.Config.Debug { 416 | fmt.Printf("POST\n") 417 | } 418 | if s.Config.Debug { 419 | fmt.Printf("phoneme %d (%c%c) length %d\n", X, SignInputTable1[s.phonemeindex[X]], SignInputTable2[s.phonemeindex[X]], s.phonemeLength[X]) 420 | } 421 | } 422 | 423 | // Rewrites the phonemes using the following rules: 424 | // 425 | // -> WX 426 | // -> YX 427 | // UL -> AX L 428 | // UM -> AX M 429 | // -> Q 430 | // T R -> CH R 431 | // D R -> J R 432 | // R -> RX 433 | // L -> LX 434 | // G S -> G Z 435 | // K -> KX 436 | // G -> GX 437 | // S P -> S B 438 | // S T -> S D 439 | // S K -> S G 440 | // S KX -> S GX 441 | // UW -> UX 442 | // CH -> CH CH' (CH requires two phonemes to represent it) 443 | // J -> J J' (J requires two phonemes to represent it) 444 | // T -> DX 445 | // D -> DX 446 | 447 | func (s *Sam) rule_alveolar_uw(X byte) { 448 | // ALVEOLAR flag set? 449 | if flags[s.phonemeindex[X-1]]&FLAG_ALVEOLAR != 0 { 450 | s.drule(" UW -> UX") 451 | s.phonemeindex[X] = 16 452 | } 453 | } 454 | 455 | func (s *Sam) rule_ch(X, mem59 byte) { 456 | s.drule("CH -> CH CH+1") 457 | s.Insert(X+1, 43, mem59, s.stress[X]) 458 | } 459 | 460 | func (s *Sam) rule_j(X, mem59 byte) { 461 | s.drule("J -> J J+1") 462 | s.Insert(X+1, 45, mem59, s.stress[X]) 463 | } 464 | 465 | func (s *Sam) rule_g(pos byte) { 466 | // G -> GX 467 | // Example: GO 468 | 469 | var index = s.phonemeindex[pos+1] 470 | 471 | // If dipthong ending with YX, move continue processing next phoneme 472 | if (index != 255) && ((flags[index] & FLAG_DIP_YX) == 0) { 473 | // replace G with GX and continue processing next phoneme 474 | s.drule("G -> GX ") 475 | s.phonemeindex[pos] = 63 // 'GX' 476 | } 477 | } 478 | 479 | func (s *Sam) change(pos, val byte, rule string) { 480 | s.drule(rule) 481 | s.phonemeindex[pos] = val 482 | } 483 | 484 | func (s *Sam) rule_dipthong(p, pf, pos, mem59 byte) { 485 | // -> WX 486 | // -> YX 487 | // Example: OIL, COW 488 | 489 | // If ends with IY, use YX, else use WX 490 | A := 20 // 'WX' = 20 'YX' = 21 491 | if pf&FLAG_DIP_YX != 0 { 492 | A++ 493 | } 494 | 495 | // Insert at WX or YX following, copying the stress 496 | if A == 20 { 497 | s.drule("insert WX following dipthong NOT ending in IY sound") 498 | } 499 | if A == 21 { 500 | s.drule("insert YX following dipthong ending in IY sound") 501 | } 502 | s.Insert(pos+1, byte(A), mem59, s.stress[pos]) 503 | 504 | if p == 53 || p == 42 || p == 44 { 505 | if p == 53 { 506 | s.rule_alveolar_uw(pos) // Example: NEW, DEW, SUE, ZOO, THOO, TOO 507 | } else if p == 42 { 508 | s.rule_ch(pos, mem59) // Example: CHEW 509 | } else if p == 44 { 510 | s.rule_j(pos, mem59) 511 | } // Example: JAY 512 | } 513 | } 514 | 515 | func (s *Sam) Parser2() { 516 | var pos byte = 0 //mem66; 517 | var p byte 518 | 519 | if s.Config.Debug { 520 | fmt.Printf("Parser2\n") 521 | } 522 | p = s.phonemeindex[pos] 523 | for s.phonemeindex[pos] != render.PhonemeEnd { 524 | p = s.phonemeindex[pos] 525 | if s.Config.Debug { 526 | fmt.Printf("%d: %c%c\n", pos, SignInputTable1[p], SignInputTable2[p]) 527 | } 528 | 529 | if p == 0 { // Is phoneme pause? 530 | pos++ 531 | continue 532 | } 533 | 534 | var pf = flags[p] 535 | var prior = s.phonemeindex[pos-1] 536 | 537 | if pf&FLAG_DIPTHONG != 0 { 538 | s.rule_dipthong(p, byte(pf), pos, 0) 539 | } else if p == 78 { 540 | s.ChangeRule(pos, 13, 24, 0, s.stress[pos], "UL -> AX L") // Example: MEDDLE 541 | } else if p == 79 { 542 | s.ChangeRule(pos, 13, 27, 0, s.stress[pos], "UM -> AX M") // Example: ASTRONOMY 543 | } else if p == 80 { 544 | s.ChangeRule(pos, 13, 28, 0, s.stress[pos], "UN -> AX N") // Example: FUNCTION 545 | } else if (pf&FLAG_VOWEL != 0) && s.stress[pos] != 0 { 546 | // RULE: 547 | // -> Q 548 | // EXAMPLE: AWAY EIGHT 549 | if s.phonemeindex[pos+1] == 0 { // If following phoneme is a pause, get next 550 | p = s.phonemeindex[pos+2] 551 | if p != render.PhonemeEnd && (flags[p]&FLAG_VOWEL != 0) && s.stress[pos+2] != 0 { 552 | s.drule("Insert glottal stop between two stressed vowels with space between them") 553 | s.Insert(pos+2, 31, 0, 0) // 31 = 'Q' 554 | } 555 | } 556 | } else if p == pR { // RULES FOR PHONEMES BEFORE R 557 | if prior == pT { 558 | s.change(pos-1, 42, "T R -> CH R") // Example: TRACK 559 | } else if prior == pD { 560 | s.change(pos-1, 44, "D R -> J R") // Example: DRY 561 | } else if flags[prior]&FLAG_VOWEL != 0 { 562 | s.change(pos, 18, " R -> RX") 563 | } // Example: ART 564 | } else if p == 24 && (flags[prior]&FLAG_VOWEL != 0) { 565 | s.change(pos, 19, " L -> LX") // Example: ALL 566 | } else if prior == 60 && p == 32 { // 'G' 'S' 567 | // Can't get to fire - 568 | // 1. The G -> GX rule intervenes 569 | // 2. Reciter already replaces GS -> GZ 570 | s.change(pos, 38, "G S -> G Z") 571 | } else if p == 60 { 572 | s.rule_g(pos) 573 | } else { 574 | if p == 72 { // 'K' 575 | // K -> KX 576 | // Example: COW 577 | var Y = s.phonemeindex[pos+1] 578 | // If at end, replace current phoneme with KX 579 | if Y == render.PhonemeEnd || (flags[Y]&FLAG_DIP_YX) == 0 { // VOWELS AND DIPTHONGS ENDING WITH IY SOUND flag set? 580 | s.change(pos, 75, "K -> KX ") 581 | p = 75 582 | pf = flags[p] 583 | } 584 | } 585 | 586 | // Replace with softer version? 587 | if (flags[p]&FLAG_PLOSIVE != 0) && (prior == 32) { // 'S' 588 | // RULE: 589 | // S P -> S B 590 | // S T -> S D 591 | // S K -> S G 592 | // S KX -> S GX 593 | // Examples: SPY, STY, SKY, SCOWL 594 | 595 | if s.Config.Debug { 596 | fmt.Printf("RULE: S* %c%c -> S* %c%c\n", SignInputTable1[p], SignInputTable2[p], SignInputTable1[p-12], SignInputTable2[p-12]) 597 | } 598 | s.phonemeindex[pos] = p - 12 599 | } else if !(pf&FLAG_PLOSIVE != 0) { 600 | p = s.phonemeindex[pos] 601 | if p == 53 { 602 | s.rule_alveolar_uw(pos) // Example: NEW, DEW, SUE, ZOO, THOO, TOO 603 | } else if p == 42 { 604 | s.rule_ch(pos, 0) // Example: CHEW 605 | } else if p == 44 { 606 | s.rule_j(pos, 0) // Example: JAY 607 | } 608 | } 609 | 610 | if p == 69 || p == 57 { // 'T', 'D' 611 | // RULE: Soften T following vowel 612 | // NOTE: This rule fails for cases such as "ODD" 613 | // T -> DX 614 | // D -> DX 615 | // Example: PARTY, TARDY 616 | if flags[s.phonemeindex[pos-1]]&FLAG_VOWEL != 0 { 617 | p = s.phonemeindex[pos+1] 618 | if p == 0 { 619 | p = s.phonemeindex[pos+2] 620 | } 621 | if p != render.PhonemeEnd && (flags[p]&FLAG_VOWEL != 0) && s.stress[pos+1] == 0 { 622 | s.change(pos, 30, "Soften T or D following vowel or ER and preceding a pause -> DX") 623 | } 624 | } 625 | } 626 | } 627 | pos++ 628 | } // while 629 | } 630 | 631 | // Applies various rules that adjust the lengths of phonemes 632 | // 633 | // Lengthen or between and by 1.5 634 | // - decrease length by 1 635 | // - decrease vowel by 1/8th 636 | // - increase vowel by 1/2 + 1 637 | // - set nasal = 5, consonant = 6 638 | // {optional silence} - shorten both to 1/2 + 1 639 | // - decrease by 2 640 | // 641 | func (s *Sam) AdjustLengths() { 642 | // LENGTHEN VOWELS PRECEDING PUNCTUATION 643 | // 644 | // Search for punctuation. If found, back up to the first vowel, then 645 | // process all phonemes between there and up to (but not including) the punctuation. 646 | // If any phoneme is found that is a either a fricative or voiced, the duration is 647 | // increased by (length * 1.5) + 1 648 | 649 | // loop index 650 | var X byte = 0 651 | var index byte 652 | index = s.phonemeindex[X] 653 | for s.phonemeindex[X] != render.PhonemeEnd { 654 | index = s.phonemeindex[X] 655 | // not punctuation? 656 | if (flags[index] & FLAG_PUNCT) == 0 { 657 | X++ 658 | continue 659 | } 660 | 661 | var loopIndex byte = X 662 | 663 | X-- 664 | for X != 0 && !(flags[s.phonemeindex[X]]&FLAG_VOWEL != 0) { 665 | X-- 666 | } // back up while not a vowel 667 | if X == 0 { 668 | break 669 | } 670 | 671 | for ok := true; ok; ok = (X != loopIndex) { 672 | // test for vowel 673 | index = s.phonemeindex[X] 674 | 675 | // test for fricative/unvoiced or not voiced 676 | if !(flags[index]&FLAG_FRICATIVE != 0) || (flags[index]&FLAG_VOICED != 0) { //nochmal �berpr�fen 677 | var A = s.phonemeLength[X] 678 | // change phoneme length to (length * 1.5) + 1 679 | s.drule_pre("Lengthen or between and by 1.5", X) 680 | s.phonemeLength[X] = (A >> 1) + A + 1 681 | s.drule_post(X) 682 | } 683 | X++ 684 | } 685 | X++ 686 | } // while 687 | 688 | // Similar to the above routine, but shorten vowels under some circumstances 689 | 690 | // Loop throught all phonemes 691 | var loopIndex byte = 0 692 | index = s.phonemeindex[loopIndex] 693 | for s.phonemeindex[loopIndex] != render.PhonemeEnd { 694 | index = s.phonemeindex[loopIndex] 695 | X := loopIndex 696 | 697 | if flags[index]&FLAG_VOWEL != 0 { 698 | index = s.phonemeindex[loopIndex+1] 699 | if index == render.PhonemeEnd { 700 | break 701 | } 702 | if !(flags[index]&FLAG_CONSONANT != 0) { 703 | if (index == 18) || (index == 19) { // 'RX', 'LX' 704 | index = s.phonemeindex[loopIndex+2] 705 | if index != render.PhonemeEnd && flags[index]&FLAG_CONSONANT != 0 { 706 | s.drule_pre(" - decrease length of vowel by 1\n", loopIndex) 707 | s.phonemeLength[loopIndex]-- 708 | s.drule_post(loopIndex) 709 | } 710 | } 711 | } else { // Got here if not 712 | var flag = flags[index] // 65 if end marker 713 | if index == render.PhonemeEnd { 714 | flag = 65 715 | } 716 | 717 | if !(flag&FLAG_VOICED != 0) { // Unvoiced 718 | // *, .*, ?*, ,*, -*, DX, S*, SH, F*, TH, /H, /X, CH, P*, T*, K*, KX 719 | if flag&FLAG_PLOSIVE != 0 { // unvoiced plosive 720 | // RULE: 721 | // 722 | s.drule_pre(" - decrease vowel by 1/8th", loopIndex) 723 | s.phonemeLength[loopIndex] -= (s.phonemeLength[loopIndex] >> 3) 724 | s.drule_post(loopIndex) 725 | } 726 | } else { 727 | s.drule_pre(" - increase vowel by 1/2 + 1\n", X-1) 728 | // decrease length 729 | var A = s.phonemeLength[loopIndex] 730 | s.phonemeLength[loopIndex] = (A >> 2) + A + 1 // 5/4*A + 1 731 | s.drule_post(loopIndex) 732 | } 733 | } 734 | } else if (flags[index] & FLAG_NASAL) != 0 { // nasal? 735 | // RULE: 736 | // Set punctuation length to 6 737 | // Set stop consonant length to 5 738 | X++ 739 | index = s.phonemeindex[X] 740 | if index != render.PhonemeEnd && (flags[index]&FLAG_STOPCONS != 0) { 741 | s.drule(" - set nasal = 5, consonant = 6") 742 | s.phonemeLength[X] = 6 // set stop consonant length to 6 743 | s.phonemeLength[X-1] = 5 // set nasal length to 5 744 | } 745 | } else if flags[index]&FLAG_STOPCONS != 0 { // (voiced) stop consonant? 746 | // RULE: {optional silence} 747 | // Shorten both to (length/2 + 1) 748 | 749 | // move past silence 750 | X++ 751 | index = s.phonemeindex[X] 752 | for s.phonemeindex[X] == 0 { 753 | X++ 754 | index = s.phonemeindex[X] 755 | } 756 | 757 | if index != render.PhonemeEnd && (flags[index]&FLAG_STOPCONS != 0) { 758 | // FIXME, this looks wrong? 759 | // RULE: {optional silence} 760 | s.drule(" {optional silence} - shorten both to 1/2 + 1") 761 | s.phonemeLength[X] = (s.phonemeLength[X] >> 1) + 1 762 | s.phonemeLength[loopIndex] = (s.phonemeLength[loopIndex] >> 1) + 1 763 | X = loopIndex 764 | } 765 | } else if flags[index]&FLAG_LIQUIC != 0 { // liquic consonant? 766 | // RULE: 767 | // Decrease by 2 768 | index = s.phonemeindex[X-1] // prior phoneme; 769 | 770 | // FIXME: The global.Debug code here breaks the rule. 771 | // prior phoneme a stop consonant> 772 | if (flags[index] & FLAG_STOPCONS) != 0 { 773 | s.drule_pre(" - decrease by 2", X) 774 | s.phonemeLength[X] -= 2 // 20ms 775 | s.drule_post(X) 776 | } 777 | } 778 | 779 | loopIndex++ 780 | } 781 | } 782 | -------------------------------------------------------------------------------- /sammain/tabs.go: -------------------------------------------------------------------------------- 1 | package sammain 2 | 3 | //loc_9F8C 4 | const ( 5 | FLAG_PLOSIVE = 0x0001 6 | FLAG_STOPCONS = 0x0002 /* stop consonant */ 7 | FLAG_VOICED = 0x0004 8 | /* 0x08 */ 9 | FLAG_DIPTHONG = 0x0010 10 | FLAG_DIP_YX = 0x0020 /* dipthong ending with YX */ 11 | FLAG_CONSONANT = 0x0040 12 | FLAG_VOWEL = 0x0080 13 | FLAG_PUNCT = 0x0100 14 | /* 0x200 */ 15 | FLAG_ALVEOLAR = 0x0400 16 | FLAG_NASAL = 0x0800 17 | FLAG_LIQUIC = 0x1000 /* liquic consonant */ 18 | FLAG_FRICATIVE = 0x2000 19 | ) 20 | 21 | const ( 22 | pR = 23 23 | pD = 57 24 | pT = 69 25 | BREAK = 254 26 | ) 27 | 28 | var ( 29 | StressInputTable = []byte{ 30 | '*', '1', '2', '3', '4', '5', '6', '7', '8', 31 | } 32 | 33 | flags = []uint16{ 34 | 0x8000, 0xC100, 0xC100, 0xC100, 0xC100, 0x00A4, 0x00A4, 0x00A4, 35 | 0x00A4, 0x00A4, 0x00A4, 0x0084, 0x0084, 0x00A4, 0x00A4, 0x0084, 36 | 0x0084, 0x0084, 0x0084, 0x0084, 0x0084, 0x0084, 0x0044, 0x1044, 37 | 0x1044, 0x1044, 0x1044, 0x084C, 0x0C4C, 0x084C, 0x0448, 0x404C, 38 | 39 | 0x2440, 0x2040, 0x2040, 0x2440, 0x0040, 0x0040, 0x2444, 0x2044, 40 | 0x2044, 0x2444, 0x2048, 0x2040, 0x004C, 0x2044, 0x0000, 0x0000, 41 | 0x00B4, 0x00B4, 0x00B4, 0x0094, 0x0094, 0x0094, 0x004E, 0x004E, 42 | 43 | 0x004E, 0x044E, 0x044E, 0x044E, 0x004E, 0x004E, 0x004E, 0x004E, 44 | 0x004E, 0x004E, 0x004B, 0x004B, 0x004B, 0x044B, 0x044B, 0x044B, 45 | 0x004B, 0x004B, 0x004B, 0x004B, 0x004B, 0x004B, 0x0080, 0x00C1, 46 | 0x00C1, 47 | } 48 | 49 | //tab45616??? 50 | phonemeStressedLengthTable = []byte{ 51 | 0x00, 0x12, 0x12, 0x12, 8, 0xB, 9, 0xB, 52 | 0xE, 0xF, 0xB, 0x10, 0xC, 6, 6, 0xE, 53 | 0xC, 0xE, 0xC, 0xB, 8, 8, 0xB, 0xA, 54 | 9, 8, 8, 8, 8, 8, 3, 5, 55 | 2, 2, 2, 2, 2, 2, 6, 6, 56 | 8, 6, 6, 2, 9, 4, 2, 1, 57 | 0xE, 0xF, 0xF, 0xF, 0xE, 0xE, 8, 2, 58 | 2, 7, 2, 1, 7, 2, 2, 7, 59 | 2, 2, 8, 2, 2, 6, 2, 2, 60 | 7, 2, 4, 7, 1, 4, 5, 5, 61 | } 62 | 63 | //tab45536??? 64 | phonemeLengthTable = []byte{ 65 | 0, 0x12, 0x12, 0x12, 8, 8, 8, 8, 66 | 8, 0xB, 6, 0xC, 0xA, 5, 5, 0xB, 67 | 0xA, 0xA, 0xA, 9, 8, 7, 9, 7, 68 | 6, 8, 6, 7, 7, 7, 2, 5, 69 | 2, 2, 2, 2, 2, 2, 6, 6, 70 | 7, 6, 6, 2, 8, 3, 1, 0x1E, 71 | 0xD, 0xC, 0xC, 0xC, 0xE, 9, 6, 1, 72 | 2, 5, 1, 1, 6, 1, 2, 6, 73 | 1, 2, 8, 2, 2, 4, 2, 2, 74 | 6, 1, 4, 6, 1, 4, 0xC7, 0xFF, 75 | } 76 | 77 | //tab40682 78 | SignInputTable1 = []byte{ 79 | ' ', '.', '?', ',', '-', 'I', 'I', 'E', 80 | 'A', 'A', 'A', 'A', 'U', 'A', 'I', 'E', 81 | 'U', 'O', 'R', 'L', 'W', 'Y', 'W', 'R', 82 | 'L', 'W', 'Y', 'M', 'N', 'N', 'D', 'Q', 83 | 'S', 'S', 'F', 'T', '/', '/', 'Z', 'Z', 84 | 'V', 'D', 'C', '*', 'J', '*', '*', '*', 85 | 'E', 'A', 'O', 'A', 'O', 'U', 'B', '*', 86 | '*', 'D', '*', '*', 'G', '*', '*', 'G', 87 | '*', '*', 'P', '*', '*', 'T', '*', '*', 88 | 'K', '*', '*', 'K', '*', '*', 'U', 'U', 89 | 'U', 90 | } 91 | 92 | //tab40763 93 | SignInputTable2 = []byte{ 94 | '*', '*', '*', '*', '*', 'Y', 'H', 'H', 95 | 'E', 'A', 'H', 'O', 'H', 'X', 'X', 'R', 96 | 'X', 'H', 'X', 'X', 'X', 'X', 'H', '*', 97 | '*', '*', '*', '*', '*', 'X', 'X', '*', 98 | '*', 'H', '*', 'H', 'H', 'X', '*', 'H', 99 | '*', 'H', 'H', '*', '*', '*', '*', '*', 100 | 'Y', 'Y', 'Y', 'W', 'W', 'W', '*', '*', 101 | '*', '*', '*', '*', '*', '*', '*', 'X', 102 | '*', '*', '*', '*', '*', '*', '*', '*', 103 | '*', '*', '*', 'X', '*', '*', 'L', 'M', 104 | 'N', 105 | } 106 | ) 107 | 108 | /* 109 | 110 | Ind | phoneme | flags | 111 | -----|---------|----------| 112 | 0 | * | 00000000 | 113 | 1 | .* | 00000000 | 114 | 2 | ?* | 00000000 | 115 | 3 | ,* | 00000000 | 116 | 4 | -* | 00000000 | 117 | 118 | VOWELS 119 | 5 | IY | 10100100 | 120 | 6 | IH | 10100100 | 121 | 7 | EH | 10100100 | 122 | 8 | AE | 10100100 | 123 | 9 | AA | 10100100 | 124 | 10 | AH | 10100100 | 125 | 11 | AO | 10000100 | 126 | 17 | OH | 10000100 | 127 | 12 | UH | 10000100 | 128 | 16 | UX | 10000100 | 129 | 15 | ER | 10000100 | 130 | 13 | AX | 10100100 | 131 | 14 | IX | 10100100 | 132 | 133 | DIPTHONGS 134 | 48 | EY | 10110100 | 135 | 49 | AY | 10110100 | 136 | 50 | OY | 10110100 | 137 | 51 | AW | 10010100 | 138 | 52 | OW | 10010100 | 139 | 53 | UW | 10010100 | 140 | 141 | 142 | 21 | YX | 10000100 | 143 | 20 | WX | 10000100 | 144 | 18 | RX | 10000100 | 145 | 19 | LX | 10000100 | 146 | 37 | /X | 01000000 | 147 | 30 | DX | 01001000 | 148 | 149 | 150 | 22 | WH | 01000100 | 151 | 152 | 153 | VOICED CONSONANTS 154 | 23 | R* | 01000100 | 155 | 24 | L* | 01000100 | 156 | 25 | W* | 01000100 | 157 | 26 | Y* | 01000100 | 158 | 27 | M* | 01001100 | 159 | 28 | N* | 01001100 | 160 | 29 | NX | 01001100 | 161 | 54 | B* | 01001110 | 162 | 57 | D* | 01001110 | 163 | 60 | G* | 01001110 | 164 | 44 | J* | 01001100 | 165 | 38 | Z* | 01000100 | 166 | 39 | ZH | 01000100 | 167 | 40 | V* | 01000100 | 168 | 41 | DH | 01000100 | 169 | 170 | unvoiced CONSONANTS 171 | 32 | S* | 01000000 | 172 | 33 | SH | 01000000 | 173 | 34 | F* | 01000000 | 174 | 35 | TH | 01000000 | 175 | 66 | P* | 01001011 | 176 | 69 | T* | 01001011 | 177 | 72 | K* | 01001011 | 178 | 42 | CH | 01001000 | 179 | 36 | /H | 01000000 | 180 | 181 | 43 | ** | 01000000 | 182 | 45 | ** | 01000100 | 183 | 46 | ** | 00000000 | 184 | 47 | ** | 00000000 | 185 | 186 | 187 | 55 | ** | 01001110 | 188 | 56 | ** | 01001110 | 189 | 58 | ** | 01001110 | 190 | 59 | ** | 01001110 | 191 | 61 | ** | 01001110 | 192 | 62 | ** | 01001110 | 193 | 63 | GX | 01001110 | 194 | 64 | ** | 01001110 | 195 | 65 | ** | 01001110 | 196 | 67 | ** | 01001011 | 197 | 68 | ** | 01001011 | 198 | 70 | ** | 01001011 | 199 | 71 | ** | 01001011 | 200 | 73 | ** | 01001011 | 201 | 74 | ** | 01001011 | 202 | 75 | KX | 01001011 | 203 | 76 | ** | 01001011 | 204 | 77 | ** | 01001011 | 205 | 206 | 207 | SPECIAL 208 | 78 | UL | 10000000 | 209 | 79 | UM | 11000001 | 210 | 80 | UN | 11000001 | 211 | 31 | Q* | 01001100 | 212 | 213 | */ 214 | --------------------------------------------------------------------------------