From 8a4b9c8fc35c83e96a0330afd79b4f1482af389e Mon Sep 17 00:00:00 2001 From: Len Shustek Date: Fri, 30 Sep 2016 18:52:18 -0700 Subject: [PATCH] Suppress unnecessary "stop note" commands so the byestream file is smaller --- miditones.c | 44 +++++++++++++++++++++++++++++++++----------- miditones.exe | Bin 201320 -> 201832 bytes 2 files changed, 33 insertions(+), 11 deletions(-) diff --git a/miditones.c b/miditones.c index 952a307..c805129 100644 --- a/miditones.c +++ b/miditones.c @@ -253,8 +253,13 @@ * 30 September 2016, Scott Allen, V1.13 * - Allow -c channel numbers to be specified as hex or octal * - Add -r to end the file with "repeat" instead of "score end" +* 30 September 2016, Len Shustek, V1.14 +* - Prevent unnecessary "note off" commands from being generated by delaying +* them until we see if a "note on" is generated before the next wait. +* Thanks to Scott Allen for inspiring me to do this. In the best case we've +* seen, this makes the bytestream 21% smaller! */ -#define VERSION "1.13" +#define VERSION "1.14" /*-------------------------------------------------------------------------------------------- @@ -381,6 +386,7 @@ unsigned long tempo; /* current tempo in usec/qnote */ struct tonegen_status { /* current status of a tone generator */ bool playing; /* is it playing? */ + bool stopnote_pending; /* do we need to stop this generator before the next wait? */ int track; /* if so, which track is the note from? */ int note; /* what note is playing? */ int instrument; /* what instrument? */ @@ -394,11 +400,11 @@ struct track_status { /* current processing point of a MIDI track */ uint8_t *trkend; /* ptr past the end of the track */ unsigned long time; /* what time we're at in the score */ unsigned long tempo; /* the tempo last set, in usec per qnote */ - unsigned int preferred_tonegen; /* for strategy2, try to use this generator */ - unsigned char cmd; /* CMD_xxxx next to do */ + unsigned int preferred_tonegen; /* for strategy2, try to use this generator */ + unsigned char cmd; /* CMD_xxxx next to do */ unsigned char note; /* for which note */ unsigned char chan; /* from which channel it was */ - unsigned char velocity; + unsigned char velocity; /* the current volume */ unsigned char last_event; /* the last event, for MIDI's "running status" */ bool tonegens[MAX_TONEGENS]; /* which tone generators our notes are playing on */ } track[MAX_TRACKS] = { @@ -1003,6 +1009,25 @@ void find_note (int tracknum) { } +/* generate "stop note" commands for any channels that have them pending */ + +void gen_stopnotes(void) { + struct tonegen_status *tg; + for (int tgnum = 0; tgnum < num_tonegens; ++tgnum) { + tg = &tonegen[tgnum]; + if (tg->stopnote_pending) { + if (binaryoutput) { + putc (CMD_STOPNOTE | tgnum, outfile); + outfile_bytecount += 1; + } else { + fprintf (outfile, "0x%02X, ", CMD_STOPNOTE | tgnum); + outfile_items (1); + } + tg->stopnote_pending = false; + } + } +} + /********************* main ****************************/ int main (int argc, char *argv[]) { @@ -1196,6 +1221,7 @@ This is not unlike multiway merging used for tape sorting algoritms in the 50's! delta_time = earliest_time - timenow; if (delta_time) { + gen_stopnotes(); /* first check if any tone generators have "stop note" commands pending */ /* Convert ticks to milliseconds based on the current tempo */ unsigned long long temp; temp = ((unsigned long long) delta_time * tempo) / ticks_per_beat; @@ -1240,13 +1266,7 @@ This is not unlike multiway merging used for tape sorting algoritms in the 50's! fprintf (logfile, "->Stop note %d, generator %d, track %d\n", tg->note, tgnum, tracknum); - if (binaryoutput) { - putc (CMD_STOPNOTE | tgnum, outfile); - outfile_bytecount += 1; - } else { - fprintf (outfile, "0x%02X, ", CMD_STOPNOTE | tgnum); - outfile_items (1); - } + tg->stopnote_pending = true; /* must stop the current note if another doesn't start first */ tg->playing = false; trk->tonegens[tgnum] = false; } @@ -1294,6 +1314,7 @@ This is not unlike multiway merging used for tape sorting algoritms in the 50's! tg->playing = true; tg->track = tracknum; tg->note = trk->note; + tg->stopnote_pending = false; trk->tonegens[tgnum] = true; trk->preferred_tonegen = tgnum; ++note_on_commands; @@ -1359,6 +1380,7 @@ This is not unlike multiway merging used for tape sorting algoritms in the 50's! while (tracks_done < num_tracks); // generate the end-of-score command and some commentary + gen_stopnotes(); /* flush out any pending "stop note" commands */ outfile_bytecount++; if (binaryoutput) putc (gen_restart ? CMD_RESTART : CMD_STOP, outfile); diff --git a/miditones.exe b/miditones.exe index 51c0fc854d051938c5f7a6f55699e6e3ef02dfa4..b5902de5df968dfd6707bee692a55f6928d11006 100644 GIT binary patch delta 24302 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 bas3Uhd*XU%pQvv8x*o!_Iz3!pm?8cz3aK-# delta 23558 zcmc(n2~<_p+yD38=Nttmu7V5-avg94LIvmHs;Ho-*D;(JL{t>vGCFrL=a9s%dNfmU zp86FINm&}2Hrg-zm1bo{S%yPOlUbR(-+hM5IrRUp_y4Z-U+cYVJy!?5 zwG;=_CtL~QGPZk&>q~LCU)6AwN|}B)u5hCNn8Lu%2YHBkNXan13Z%szP5^_FKx zw)qopT=OUe&RIC#E-kma^UJPW;#; zgwn+>Z_5*{My#dil^9a-a1eReHI%!!>co4^Mp2sY^7F}~#8u>z%yzDDRr^@! zQdiUFIm}~)>sg zYirZQ=DO-7NkviD#-&T9R*}xv`QJZ2%6Ylgh%+hlPr;S=c<1C$VCADtX zB1fxSSq~p9s2#Fo*Ur{kXI^d3SI8oZ7@J=L zl*3W$J~Pg7XJg5Ve3aA|>c_6<+gPI>1Zq>qBX36j3Ty_J!Gz=n@qL0H@&;5G-7;MF z+XOhvjc7QJ48Q$G*iC~wjW9@qMMmhM!Bs~13-%HobE*-31sLshHZa7srfr8&1B_X_ zxj#R}cvogVr_Q&M7=B1uV-93Qdz}(PUh!3X)yi0WhU>4kG4z%zy4_&kVK@t7QqXN> zn`{&!!LjNm*9+|e2L9F(huKv%HSY|)j%7{m#No8RURBOd4t~(#UQLbCKnrRc^!r5;{12MIJE|<)7C9IYoC=|ssp#I*uc_XM8C&Sh_pg(@y%%q~(%QEZ zqtF=FmiB4gwiqK!%%)`dnT{w@<0K?ssjasBB3_=|#CZ|QCRDf*I|Q+)3fEH|A_iw_ zL6jjrkcGj2=Nv!NtDeUe7+pC1TJ$=#S#>)37(RJ+rBBrz!knXxZRyFw@L~Kn&YWBE z^|4`@N2maWy;i-6jwpj%Y8d2Zn(Lr~C9OQYR!)P@JF6nm6BHr0dLfCum8WCR-4I6= zZI8f+#jP8&qZbg0ax>KHY)fspc>&$ zH?7G-*IgU5{9W$CLk1Z~{%WQ&@@OondjETOR|dT;=>6plb&c#~ZGYmizDRHVW9jkO zd4YTgT^l?33>gO3TLqHRS>p;VhMU)_*~s|s#=noNs#CDC$cGkA^*4>VX~>^xIq1P# zG%rA@I;!)Kw#NC;GCSAKLnEa(+dC(D=zcDtOMkl0HK`_@DV(ZQ$7j>))VNl|`UY-xVDIo+$=8%2s;fb0 zB<;zB-4h_tc<4%irP?8@+Ca z73j_&9?7*aY)P%iVYtTkUO`wjdLooD%Poe zx4B*n@6jYg%@x3^0xDhA;X&A>nmiHEp)!qslI{A&g!*( z^KU1{KM~`@3P!tj4B5xckmx*aPDihVIbj?6HKU_eSYyhpF;pH+9rCMN=zW+&GEIhQ zu$4XyQ?!*%gSowx?x2pcwcDr}# zKf*_OMj=GcAhOI=TM`6TS9gX zSHUUGO0jDCLoJHSVV(MT{p2gHV13PgSSOGk@UJ=} zab2sxK2Po0i<-@JnA5*%Bd7c6_DJR++ymkB>)f($L)mDt`&%!lCB+@8ZKtId?^M$- zX!e|DpW8KPV{7lS{H|;+>(lU>>eT;p)&BW~YCC+U+Sk5RZGDY*`btf&|E#P^=;mY% zv@dZ%`;)`af#gHzAo2rrE5bSx5=>e_TS+K%YZ3$9hD?BNN3x(hkwWOs}UBmue?Spwagtby)JjzIS#WzhY}d(Z>O zkI;ij4fGHa5Q-}(=>k2J41*pP9$Qs9+CV3eNa#co3!Ov~pp!`s z^bE2#oH$7e*?~kVISxIGybC>>+=re+9zmxO3tlPACE?KXNFV6=WHfXJnF5_j7AVKh zKs(4b=q$1yI!Dn9$SXKrNKQj9A|F97CZ9nsA@`u2)O@Mz%wrA;+N4l5^1K$X)33 zq+T~d-Xi|c7f4^|i)1+T+av+{UE+X#kF1A&pB#n$fV>8MNzosY+c^F=aXx^lAY5N2 ztUDoBi68W*q%-t2(hvGGG8y`FG8?**6hPk~`=GxgC!oJ4m!NMF-$+7!ARVErNIdi% zG8g(TSp)qe*#v!0(f7$|99NUKp?@ZqoiM+U@1cKF^mlxzlLy2T`XLzz{Wpn+eoU4^ z*N_#^lx~J*^f&_VQX=vLGN_b|cK z586t@p7!e^zWr{d_eJU^B#qG#nFVp$aZRt_4$hSTrm)DcJ}%G-G= zS-!zjv*m!1NX?g%MqlnJtI$#Lu!}o;;Fsz7d&-DZaNC7m*mN# zkUA}I;Hk6nr#y8|Zaf;Pi}J+LEJ|)Pnl+KPj%Iy4-_u$eB2OR9g5^JvK`+UkW8iyP z9ybm?9PyHfGcBCH4qwGj|$SZiNvHSr~1SvdFc=`ujA1EproR7g}UnSqlM zpU-PcC8u`B9R&8BTBqbxrM5shXabu@ZSuMaEVxqwnrPE}aEQ+wm^p5uud=V@%M;i# zRy;tqPh@TABc2SCOC~Z8p?Cn1H|}DsoK}v@iOML@UIm}Qewa7J-Slg+V;oOZ7+=Agl5wV$@B&Vlm zreJ8hYJ`zQ4b_sFnQ6Jaq{CfG@4Y0qp2nKXk@3u5j#$h*T#_`tZbPT@dVJ;71dN#8T2J}&>CDc` z$E!`5<91oZS!Dui<@X`Nm;WP}L++Z4CDS>PP4X&@=T-6jp#Y|_{7pROVF3@-Tt1!1 ztg)&CUo(lR3zbD!sTAQv1H>{}Z*MZjhdUL!i9Xa%t1%xZp$GOPmP;e#i%FR5)oyO} zj+mmy(MuiVO&t<)5B+d-W`w^=QKyCBFxN!<F5E5#Pu~JS%VY*RXF$2^6g8bSHwx3l_m6K91m*eE+S(uz{DXgXQ z2oE+@?*_t<3m~>>DnU2!xdvjLY4rIHq{8I$5F}~3u~Z{$@6{#}0#cD+^y%&dDo8Y< zp&-^Iouub>?Z!9c2<$iNW|xtwk^(p3O`L#IB^ps1JqM)JM3#V5n8*eRH z8G7|R^huBi6L|;3rV({^D?y4)KEHtAfk|n!+Ms&aORXm2Uk^8xHWTUsC%cIZ1t~X? zL=c;4Iu?QyYee8}Cj8kMPioqjaq>J!go*3}aTaSxE%queHp^J-LlDPoV?VwIDV}2_ zKY^5|8A~;)k2v#;q%%lFx{(Y9DR!Dr3Xo;K(P=q|4R7kZKc|!F}?LKDi(T3ykDB z?z6~9PJq}KVg75Ye;cS+b5a}hACPhrxygN&7y}VcG-#>XG&x-biP&Ha^fQRV zM7$fKA12ZjgcKV~Jqcnrk%b^7DsiIs8Oa&5_?}j2a@qkW>qb3LPF8jfJG4M;?Z>f=<0x>Y0eOhYQ^15#=t(?P0DWGRSkx3RMAAjKw9 z22yDvAA>~f(Mn+n;`2L@W3Mq#Kx0&IBE3K=_8EQbAeQ|`;sCLmNFhkEi5%x~+(fDW z3Xt`HG0<-y4ijnF1PwBg0U&szWLU5XAa)a34N`0(FM?Fm5?=p#pprwzK%an+BSvx) z#CFt3m={8uNNbP^6B!C(dC^!Z4a9CBsDBkui2)I^52VsW&Voez%NXbyNP&s`22yS! zein4&C1a^b5Sx)W$t0ixBO=)#gshgnRq=h%uhlxaiSWg+_ z3h+;5>PDZH6xkBL!UO1Jnmy6PLK){ zc?QJty0O$YkPam#w2v1%V{|$PVn3@rA=`8DR9<{mj>u$fdKRDMe*FHPj}q>_h?%5= z?05U<4+vA$d+%MDY&I)BD|}sU;L3geiXiOIK+p-#uh$Y!*Z$-K6n}u33+?g%?9`b&c>;2T*wt#yq!&7Zd7M>lJ z@Kl&=&t@LpwsUoTSE|w4=IGDVye^s~-^xbOweHMd@1%be-Kgd^&NUWo7;#=5PJu3! zvsU4ezQpYoEFe>TFQUvq>3RA2T-GMGR4alRNYBj7o`tW@%mg#=shcD!PHE(OH_`k3 zl1%gUr(txXfsDTk*vhKU%U|VT+)ne{D4|+!!jya#BUD}@^1OX4Kt7v~;Xz7U3VO)5 z)W+Y>XR|4hpIpG&%GdH)IHq?L^FgydRL4_24=f;-f9qscrXw{2F7}U9g5G7PDy*bJ zCwes>tJQcdRH|995Y;?fz{1C(I0@wST-Kv<(gCDEBa8zQ1yW)nLqKf*sawwtwVo#y zp`IjJUW7UR!HxV{&T{1CrXXC>KMGc>Uav1!=i1(|T5;je?+@kOi!jZCZFmFKW5ZIl{${f8 zQZ@iDxh5_}7n-;;gS{K66mxy#@?a2b39c`8gUUdB8^ELZhWot2ZCI*)f;Bee|= zQDf&lr7!a9PvQKq%YC0huuksGU~l`Ubt~?s<|aB(^zMGgb{4HKz!D~35PAD<7JxPBmw`w~*IC39 zqpLP~!%Dn@v3;qJO!~~!g$_R7W`bIZ-9)dYkk3?e zxnvbyASp|?)hfK`e0C-F7so2R=-lAW5A<7z@h?{*7#IImw}&KeSk1h#r`sFyzuMuK z9f8hNPoRBfFTeUL5DZ@GhROTU)BcrSCK@HppY+VxUHOB#?o+#jkEwy<)~av7JY;mB zfxLbVTkTci4p@RMtcUs*?iIJc)mwEicIJYbyJ;=^1ml{v4pa8E8~HaxGn9uQ+qYW7 zGuE?qa_KbG=<^Ko^(#WB?9~)Y3|%MsYfZa6=o!{_zWt`YN>Y?J(YSuPNp`A+e$aig zQ&lgALI^@)gT?g}`-j_SeooqAj;vMc$T2cMb$-g6)RcL4`SLS(=kJjF7qYhA4kh2% z&nmT3o!4X3N(z}>D&a2jk3(57_Bv%rAkQiQt22a-#>mx$=xF(R*23F*OK+#XkZROY z?-r>Mo5`U?YzDUB4MiBk2>G%Ls|=Y|A?cP9vW>jsSuEaLTb^VsaB?@?#ut|omB`0d zvmm+AvuvDv?^)(s{~)q#x3yAX8(6US`+V_qH@-^5-xoBHqO!?^$}4| zFO0RDBqoAkEuD4~HEkq{4@UNVqYu(XqWEBksP*Cbzo2Q?d$@~n^cd)#i8N@AZ=+4b z7lg`L#h5g!{ADq|sA&UYy{8W|j}r#sa1(vtqxsnSmG#@mLh*-r_vE?HVYi4?pbY36 z=EzJ>%}-A!saQOzF3jB|H)`I}k-0!w|BinYOypk6 zP-e^~lu6+!d|R{$w;hh3>Q>^AU*E(o;*MkaX80~wXycj=g_-8oC8zwRVrLbQ`gB*90oUFX$?9_Zx1%m$T zUrT-prz8)(GBhWjSNN)%@KhCiLh<#qS}HMdW?DWLcDzP#!@>!=QEebusi-gg-G*u@ ze#Yc3PR-6F)<~vY`5Nl)INnh#j@)g}&zP%kMd(yvf_tt$oTjo`)`3cmg zH6hQa7fgH+thrj9ssmsAd=00~$|ZJR9$F=Q^wSqx{cA~9+N|v4lu{)u_u-%4&{yK6 z`($Cka$3^FO|Ymrsc@6T#4OydrDY^J19T@Kj0n7%83@J}_iNr}l16OJb&{3A8;IK= zcN|`kqQ&A6i9Ana!!h^#k^XCbZ%x=W!qW;r_>&imd>>VN%%yB z>V#M3kIG8A=p->Q4IbDV!gQif&<*#f`}14hcD&d>obbm7d}=CousN(WT<)_IJAbvC z`M1nYPUDZ@q%^#4_&-#yX}d80%1!gX&`PwUBDOHc#+tUhWk zpT@il>;%|Ts-KXHcd@zH`u^I5@3p(5k(P+MRatn5MeSpd>A^<;AKbm^-}rXdYi#6? zKSQIkBZ2wQzPw17Y|Uk&e>}?BBlV!XbP7m8cV2T_`O7_QI4d40Kfjx`>0dlj4aP`L z+U$%O_{Q`fWR_glCw+%X)SC|bZvGbyBjuz$tX2Q{sHoiS&#PW$BH?iMi&T4i8!Z>@ z!%*M}%g&19kc^50rd_MF=GgeMMfC=5OA5*5xs&yZWX;`WS6=<}axD*ew z6Wwk>-fE^XNCMB*9$k2OT&MdVP_F6VQ6c!lEbWBP$<0nvP8B!N+mWtTkay774pur! z?sE{$U*gUU;>>;t!tA9b&z4NBY+xbgIzp6Vx+8iNJ>f)#hem6Dl_oJV22#dhhjGHmMPY z9ziYGN$q%g_B?{fFSvO?;3?#hBos1N3r}1 zCTuyxTFBuq;^wVDbFE!tuPfoV{7b!XU{Owx-+d9)zNvHkLCil2y{oqAwq6QTee7Qt zq|e>l>a@i=49iN z;54BeM+T`d632|}c_bp!r|K@*yUmz)jFqzQBofN>klQ zpVlgMY{Fk==dq@KdKtrY$BhEy`|+$k9@UiXIjNM*fzNxT@cF}y_=Tg>r+n#6QDfuc zHVhA%{OUTjZf#8NdK|a7HOKTfK?SAQlvW?Zdnh7bJchuy6lfm7-eg+c@*zBTV$bh* zb(7TxGj+lJ0+M7R%nws*B8}uT$8pc>i;QAZMmvzLCejONKMv#f3&T;Sc)C9A zyySS0B>97r_-mT*xX4Jpjrz~y4*W)ulkPZbZ6f?>BiBTtK$e+E50KAIq$kJ?6X^x= zWxBgACo1a=bh8%4MMm-K=&<>2Cy=fnV@!lMC^Ez7!yDA!M0kUCmH|zlrchzhxxO9=z3;jHm~1btnAN zw>A)ObvF~?jh<{GywNj^q$l_JAjc4=C-?cpO%fCB$KX z5X({{S<4thow_4*v72Zv`F3qQ z)W@g+@Ua|LOR0NG97u(UOadt{*L`v_)E3RRoHJII1gB~fnG51LZ}iFKJ|vmEZDRq+^tys02)p)OZkVOII@Ro0j;Dl5CnE=tbE7%o3ZD5M*NFVhi_>5y5F zC6F}`7vwPHL&y&hhE}(NghFB<6ChcTLdXHgc}NB1F61GkNlW|?1`-LeLlPiMTH@SV zgM%ZGGRS+7A0ai6fIu`DG7K_P6DRC;$YIDu$Yn^sAUw}O5+HLSt0Co(46$aUi9hz2$ugsv=nkmlQ&_xT!BE66BUa9^lv)`$bzw1f(0}Ed82(Lo4aG^m}@X z-lad%d-NyzGyRqRMjz1M=^yk@`WJmfAJZD#3o|A#kx8sR^I)E=0c*q>vnI@oHD%41 zH}he>%#ZoA0M^o<1+pO4idk7})`qoZA*=)I$U3pka@TK|pR*V1!}_uQ_({b;W@Cfd z5Ejjb;SEwO8^K1hI5wJ%VPn}uHisl35Cy$x&_!^!qW>2vKwwyi9R_6;d_6fVfuCi9Jn6(ZWz+xDX@63L}L$VYDzt7%PkuCJK{; zCxv+EDNbRUkRT)q$-)d_rjRPk7Se>d!aN~em=B#PWC=M!u8=1z5EcrHgeAgKVVUrh z;1mjkr-c>5Dq)SVR(M8OFBA#S3dO=k!6j@Kwg|GY6|zluLD(tm7WN4Hg#E$+;h=Cx zI4m3$UKCyuUKUD)W5RL4c~UqflnJj2uL-Ax*M&EPGs0QnP2rsImT*D1D7-DaBfKZP zFMJ?e5@G%%QDP6Vr`SvEE%p`riT%Za;$U%zI8+=a4i{s^ z5#mTOP8=nU7RQKoajZB_94}53Cy7sr@#180ia1rAE+&YHkR&l#Oc7^`&N*V5I9Hq} zW{M6mOUxDX#XNBVQcJ~U;K#4F-e z@l)}d_=R}gDSjz_C4Mbdir+qy6z_@m#h=8V#b3l<#oxr=#XrP9#lOTy z;@{$9kw|~y%oik4lB9Z4eaREY4Wvd=W2uScC0V4VQZvb0@{yWLzLKBhFSU?bN`X?4 z)Jh7LtWq1Pt<+8mkvdA9q|TDFixet_N#W8HQiRl1>LzuUBBdy)htyN*E%lN5O8un% z(g4XO4VH#T(b7;UMj9cFltxQqq;b-CX@WFSnj}q;rb^SK=~AMUB&A3*rBrFQG)GF4 z=1TLVbSXp1lpIo)lq=;)`O*Sup~Szf8(zt}G9gT4B7>!6OXXGeW-1dki!#SdD|UypG}`sm}^ z@rYah@BLdgA?{y)eBJOm%CEBIOE16Cxf`KXU9EjfGAOgS&TMZk*EpGs< z1?gh=mcu3?&6i^Xj0>MFbqQ~)!3$9*pXUknl}?c+go?jEacj^c#6Vq2n$MUIV(975 z`V{W&YDi!BzUJjIhBTk)IfgV}Ppb`SzRLI4rkx^R$LDK-$d}9)hBROAymNX3_)2Jk z&gf~r)H)f{Sc3hHX)NrqhBROBDeknBidbU}R=NQd`C5L-kmhUgGeer6h<6O>c1^on zV0@F&MvSlF=7uysS2`Nf{Cw}Lr}4eJ$WO&FIzXDAqA7+nKXvmBX?_wuYe@4QVxJ++ zPo|58G~Y>X7}9*>;b#bMu#?X@-y@VwQ|kfWJ9=miJfH6=V~lC+HK~R)KZ})FQp+h`BUHG=iPaobz3%BSxf#pL|g5rGai(&bk6u|Pi z;u`^9MU}98+f0Jx%bdU}+onwvtWJK?@s5|G6rZsqSiTf&itTd20?U_L1&@L?Th1-k zaxpAF2kfx?WU|8YlhBTF;@hSTaruB(pgf;xJ1k#vR#?7N2`pdI4N6gvpDYpbEm3#^ zyJmnSY{2st`QO?x`G)EIU)(YIhKc_FPj*Z`S~jlmiGj?4EQSom*v^3DLsmoZ?h!W& zcq0P|hxC99hKzvl|8bB6;n(!YVAgdwIL3TopKu$sU5BV=au0g(q+=K9osfZcp z7gv9X6%q>Jmu|iiN+FjZ{Nni?6n8$jxaQ)Y`*`qM zrHo{JFIo>vuK}SJ)jC8ELNO+}q_?F3ZisRbi;+H9_9F8osD$*BX=A~!ML!F#hJVCi zv2jCx`58Yv<$?NJ>pRO6Y!__s#55a2&illAhbCW7CH>s}a1NC(PD z5(0$cxC^bRseS?@g`K7oj>|h@%5i}U!?6Wl8|;H$cO0L@aX%c79vsnoea{nP*)V#_ IBFqv03;Pay00000