001 Bool IsVowel(U8 l) {
002   return Bt(char_bmp_alpha,l)&&ToBool(StrOcc("AIEUOY",ToUpper(l)));
003 }
004 Bool IsConsonant(U8 l) {
005   return Bt(char_bmp_alpha,l)&&!IsVowel(l);
006 }
007 U64 GetPowerConsonant(U8 *buf) {
008   I64 len=StrLen(buf);
009   U64 fc=0,lc=0;
010   if(IsConsonant(*buf)) {
011     fc=*buf;
012   }
013   if(len>=2&&ToUpper(buf[len-1])=='H') {
014     if(IsConsonant(buf[len-2]))
015       lc=buf[len-2];
016   } else if(IsConsonant(buf[len-1]))
017       lc=buf[len-1];
018   U64 ret;
019   ret.u32[0]=fc;
020   ret.u32[1]=lc;
021   return ret;
022 }
023 U64 GetPowerVowel(U8 *buf) {
024   I64 len=StrLen(buf);
025   while(*buf&&IsConsonant(*buf))
026     ++buf;
027   if(IsVowel(*buf)) {
028     if(ToUpper(*buf)=='A')
029       return 'A';
030     if(ToUpper(*buf)=='O') {
031       return 'O';
032     }
033     if(ToUpper(*buf)=='I')
034       return 'I';
035     if(ToUpper(*buf)=='U')
036       return 'U';
037     if(ToUpper(*buf)=='E')
038       return 'E';
039     if(ToUpper(*buf)=='Y')
040       return 'Y';
041   }
042   return 0;
043 }
044 U8 *GetDigraph(U8 *t,U64 *power=NULL) {
045   if(!StrNICmp(t,"LL",2)) {
046     if(power) *power='L';
047     return "ll";
048   }
049   if(!StrNICmp(t,"TT",2)) {
050     if(power) *power='T';
051     return "TT";
052   }
053   if(!StrNICmp(t,"TW",2)) {
054     if(power) *power='T';
055     return "TW";
056   }
057   if(!StrNICmp(t,"ST",2)) {
058     if(power) *power='S';
059     return "ST";
060   }
061   if(!StrNICmp(t,"CH",2)) {
062     if(power) *power='CH';
063     return "ch";
064   }
065   if(!StrNICmp(t,"THR",3)) {
066     if(power) *power='F';
067     return "THR";
068   }
069   if(!StrNICmp(t,"CK",2)) {
070     if(power) *power='K';
071     return "CK";
072   }
073   if(!StrNICmp(t,"TH",2)) {
074     if(power) *power='TH';
075     return "TH";
076   }
077   if(!StrNICmp(t,"SH",2)) {
078     if(power) *power='H';
079     return "SH";
080   }
081   if(!StrNICmp(t,"PH",2)) {
082     if(power) *power='F';
083     return "PH";
084   }
085   if(!StrNICmp(t,"NG",2)) {
086     if(power) *power='G';
087     return "NG";
088   }
089   if(!StrNICmp(t,"WH",2)) {
090     if(power) *power='W';
091     return "WH";
092   }
093   if(!StrNICmp(t,"NK",2)) {
094     if(power) *power='N';
095     return "NK";
096   }
097   return NULL;
098 }
099 U8 *GetDiphong(U8 *t,U64 *power=NULL) {
100   if(!StrNICmp(t,"igh",3)) {
101     if(power) *power='Y';
102     return "igh";
103   } else if(!StrNICmp(t,"ough",4)) {
104     if(power) *power='O';
105     return "ough";
106   } else if(!StrNICmp(t,"owl",3)) {
107     if(power) *power='L';
108     return "owl";
109   } else if(!StrNICmp(t,"air",3)) {
110     if(power) *power='R';
111     return "air";
112   } else if(!StrNICmp(t,"are",3)) {
113     if(power) *power='R';
114     return "are";
115   } else if(!StrNICmp(t,"ore",3)) {
116     if(power) *power='R';
117     return "ore";
118   } else if(!StrNICmp(t,"re",2)) {
119     if(power) *power='R';
120     return "re";
121   } else if(!StrNICmp(t,"le",2)) {
122     if(power) *power='L';
123     return "le";
124   } else if(!StrNICmp(t,"eef",3)) {
125     if(power) *power='F';
126     return "eef";
127   } else if(!StrNICmp(t,"ief",3)) {
128     if(power) *power='F';
129     return "ief";
130   } else if(!StrNICmp(t,"est",3)) {
131     if(power) *power='T';
132     return "est";
133   } else if(!StrNICmp(t,"el",2)) {
134     if(power) *power='L';
135     return "el";
136   } else if(!StrNICmp(t,"ar",2)) {
137     if(power) *power='R';
138     return "ar";
139   } else if(!StrNICmp(t,"oal",3)) {
140     if(power) *power='L';
141     return "oal";
142   } else if(!StrNICmp(t,"ea",2)) {
143     if(power) *power='E';
144     return "ea";
145   } else if(!StrNICmp(t,"at",2)) {
146     if(power) *power='T';
147     return "at";
148   } else if(!StrNICmp(t,"ey",2)) {
149     if(power) *power='A';
150     return "ey";
151   } else if(!StrNICmp(t,"ay",2)) {
152     if(power) *power='A';
153     return "ay";
154   } else if(!StrNICmp(t,"ai",2)) {
155     if(power) *power='I';
156     return "ai";
157   } else if(!StrNICmp(t,"ew",2)) {
158     if(power) *power='U';
159     return "ew";
160   } else if(!StrNICmp(t,"oo",2)) {
161     if(power) *power='U';
162     return "oo";
163   } else if(!StrNICmp(t,"oa",2)) {
164     if(power) *power='O';
165     return "oa";
166   } else if(!StrNICmp(t,"ow",2)) {
167     if(power) *power='W';
168     return "ow";
169   } else if(!StrNICmp(t,"ie",2)) {
170     if(power) *power='E';
171     return "ie";
172   } else if(!StrNICmp(t,"oy",2)) {
173     if(power) *power='OY';
174     return "oy";
175   } else if(!StrNICmp(t,"oi",2)) {
176     if(power) *power='OY';
177     return "oi";
178   } else if(!StrNICmp(t,"ce",2)) {
179     if(power) *power='CE';
180     return "ce";
181   }  
182   return NULL;
183 }
184 U8 *NextSyllable(U8 *t,U8 *to=NULL\) {
185   U8 *o=t;
186   U8 *tmp;
187   Bool has_vowel=FALSE;
188 
189   while(*t&&!Bt(char_bmp_alpha,*t))
190     t++,o++;
191 
192   if(tmp=GetDigraph(t))
193     t+=StrLen(tmp);
194   else while(*t&&IsConsonant(*t))
195     t++;
196 
197   if(IsVowel(*t)) {
198     if(tmp=GetDiphong(t)) {
199       t+=StrLen(tmp);
200       goto fin0;
201     } else {
202       while(IsVowel(*t))
203         t++;
204     }
205   }
206   if(IsConsonant(*t)) {
207 fin0:
208     tmp=t;
209 //Check if word ends in all cosonants "sell"
210     if(GetDigraph(tmp)) {
211       tmp+=StrLen(GetDigraph(tmp));
212     } else while(IsConsonant(*tmp)) 
213       tmp++;
214     //Ends in e?
215     if(ToUpper(*tmp)=='E'&&(!Bt(char_bmp_alpha,tmp[1])||ToUpper(tmp[1])=='S')) {
216       tmp++;
217     } else if(ToUpper(*tmp)=='S'&&!Bt(char_bmp_alpha,tmp[1]))
218       tmp++;
219     t=tmp;
220   }
221 
222 fin:
223   if(to) {
224     MemCpy(to,o,t-o);
225     to[t-o]=0;
226   }
227   return t;
228 }
229 U64 Let2Note(U64 let) {
230   if(let>U8_MAX) {
231     if(let=='TH')
232       return 'A#';
233     if(let=='CH')
234       return 'B#';
235     return 'R';
236   }
237   if(!Bt(char_bmp_alpha,let))
238     return 'R';
239   U64 ret=0;
240   U8 *lets="A B C D E F G AbB BbCbDbD E F FbFbGbGbG A A AbB B B#";
241   ret.u16[0]=lets[(ToUpper(let)-'A')*2](U16);
242   if(ret.u8[1]==' ')
243     return ret.u8[0];
244   return ret;
245  
246 }
247 U8 *TextToMusic0(U8 *t) {
248   CDoc *tmp=DocNew;
249   tmp->flags|=DOCF_NO_CURSOR;
250   I64 l=StrLen(t);
251   U8 *ret;
252   while(*t) {
253     DocPrint(tmp,"q%c",Let2Note(*t));
254     t++; 
255   }  
256   ret=DocSave(tmp);
257   DocDel(tmp);
258   return ret;
259 }
260 U64 NoteForSyllable(U8 *s) {
261   U64 diphong=0;
262   U64 digraph=0;
263   I64 l=StrLen(s),ptr1,ptr2;
264   for(ptr1=0;ptr1!=l;ptr1++) {
265     if(GetDiphong(s+ptr1,&diphong))
266       break;
267   }
268   for(ptr2=0;ptr2!=l;ptr2++) {
269     if(GetDigraph(s+ptr2,&digraph))
270       break;
271   }
272   if(diphong&&digraph) {
273    //Favor last one
274    if(ptr1>ptr2)
275       return diphong;
276    else
277      return digraph;
278   }
279 
280   if(diphong) 
281     return diphong;
282   if(digraph) 
283     return digraph;
284 
285 //This returns .u32[0] for first,.u32[1] for second
286   U64 c=GetPowerConsonant(s);
287   U8 v=GetPowerVowel(s);
288   if(!c.u32[1]) {
289     return v;
290   }
291   if(!c.u32[0])
292     return v;
293   return c.u32[0];
294 }
295 U8 *TextToMusic(U8 *t) {
296   U8 buf[STR_LEN];
297   U8 *notes,*en;
298   CDoc *tmp=DocNew;
299   tmp->flags|=DOCF_NO_CURSOR;
300   DocPrint(tmp,"M4/4q");
301   while(TRUE) {
302     again:;
303     while(*t&&Bt(char_bmp_white_space,*t))
304       t++;
305     if(*t=='[') {
306       if(en=StrFirstOcc(t,"]")) {
307         MemCpy(buf,t+1,en-t-1);
308         buf[en-t-1]=0;
309         DocPrint(tmp,"%s",buf);
310         t=en+1;
311         goto again;
312       }
313     }
314     if(*t=='.'||*t=='-'||*t==',') {
315       DocPrint(tmp,"R");
316       t++;
317       goto next;
318     }
319     t=NextSyllable(t,buf);
320 "%s(%c):%c\n",buf,Let2Note(NoteForSyllable(buf)),NoteForSyllable(buf);
321     DocPrint(tmp,"%c",Let2Note(NoteForSyllable(buf)));
322 next:;
323     if(!*t)
324      break;
325   }
326   notes=DocSave(tmp);
327   DocDel(tmp);
328   "%s\n",notes;
329   Play(notes);
330   return notes;
331 }
332 //Ryhme test
333 TextToMusic("[4]cat hat star car sky high");
334 TextToMusic("Twinkle Twinkle little star,how i wonder what you are");
335 //21 Savage
336 TextToMusic("They dont ask for I D cuz they know im Tweenty one");