From 137ea65aa8acf6f685bbd5f9d0e0d357bd503278 Mon Sep 17 00:00:00 2001 From: Paul Guyot Date: Tue, 7 May 2024 18:19:31 +0200 Subject: [PATCH] Add mp3 example Also add channels and bits to i2s output configuration. Signed-off-by: Paul Guyot --- .github/workflows/build.yml | 19 +++++- README.md | 36 +++-------- examples/play_mp3_i2s/.gitignore | 20 ++++++ examples/play_mp3_i2s/README.md | 20 ++++++ examples/play_mp3_i2s/priv/adf_music.mp3 | Bin 0 -> 75531 bytes examples/play_mp3_i2s/rebar.config | 15 +++++ examples/play_mp3_i2s/rebar.lock | 1 + .../play_mp3_i2s/src/play_mp3_i2s.app.src | 14 +++++ examples/play_mp3_i2s/src/play_mp3_i2s.erl | 50 +++++++++++++++ nifs/atomvm_esp_adf_i2s_output.c | 58 +++++++++++++++--- rebar.config | 5 ++ src/atomvm_esp_adf.app.src | 2 +- src/esp_adf_i2s_output.erl | 4 ++ 13 files changed, 204 insertions(+), 40 deletions(-) create mode 100644 examples/play_mp3_i2s/.gitignore create mode 100644 examples/play_mp3_i2s/README.md create mode 100755 examples/play_mp3_i2s/priv/adf_music.mp3 create mode 100644 examples/play_mp3_i2s/rebar.config create mode 100644 examples/play_mp3_i2s/rebar.lock create mode 100644 examples/play_mp3_i2s/src/play_mp3_i2s.app.src create mode 100644 examples/play_mp3_i2s/src/play_mp3_i2s.erl diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 47e37fb..0ee8f76 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -2,6 +2,7 @@ name: Build on: push: + branches: ["main"] pull_request: workflow_dispatch: @@ -79,6 +80,22 @@ jobs: path: AtomVM/src/platforms/esp32/build/atomvm-esp-adf-${{ matrix.soc }}-${{ matrix.idf-version }}.img if-no-files-found: error + build-examples: + runs-on: ubuntu-latest + container: erlang:26 + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Build examples + run: | + cd examples + for conf in */rebar.config ; do + example_dir=`dirname ${conf}` + cd ${example_dir} + rebar3 atomvm packbeam + cd .. + done + build-doc: runs-on: ubuntu-latest container: erlang:26 @@ -120,7 +137,7 @@ jobs: - name: Checkout erlfmt run: | cd .. - git clone --depth 1 -b v1.1.0 https://github.com/WhatsApp/erlfmt.git + git clone --depth 1 -b v1.3.0 https://github.com/WhatsApp/erlfmt.git cd erlfmt rebar3 as release escriptize - name: Check format with erlfmt diff --git a/README.md b/README.md index 3aec3cf..4fd5285 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,12 @@ -# AtomVM driver for Espressif Audio Framework +# AtomVM driver for Espressif Audio Development Framework -This component ports [Espressif Audio Framework](https://github.com/espressif/esp-adf) +This component ports [Espressif Audio Development Framework](https://github.com/espressif/esp-adf) to AtomVM, thus enabling audio processing to esp32-based systems powered by AtomVM. [![Build](https://github.com/pguyot/atomvm_esp_adf/actions/workflows/build.yml/badge.svg?branch=main)](https://github.com/pguyot/atomvm_esp_adf/actions/workflows/build.yml) -## Usage: +## Installation 1. Clone this repository into atomvm/src/platforms/esp32/components with the required submodules. You can clone with recursive submodules but most @@ -23,7 +23,7 @@ git submodule update --init components/esp-adf-libs/ 2. Build and flash AtomVM -Espressif Audio Framework requires `CONFIG_FREERTOS_ENABLE_BACKWARD_COMPATIBILITY` +Espressif Audio Development Framework requires `CONFIG_FREERTOS_ENABLE_BACKWARD_COMPATIBILITY` which you can set using the configuration menu or editing sdkconfig file. You can use a command sequence such as: (port name depends on OS) @@ -40,30 +40,8 @@ You will also need to flash AtomVM core libraries. Alternatively, you can flash an image generated by the [CI of this project](https://github.com/pguyot/atomvm_esp_adf/actions/workflows/build.yml). -3. Use `esp_adf_*` modules in your code. +## Usage -You can refer to [API documentation](https://pguyot.github.io/atomvm_esp_adf/). +This project defines `esp_adf_*` modules. -```erlang -AudioPipeline = esp_adf_audio_pipeline:init([]), - -MP3File = atomvm:read_priv(?MODULE, "adf_music.mp3"), -MP3Decoder = esp_adf_mp3_decoder:init([]), -ok = esp_adf_audio_element:set_read_binary(MP3Decoder, MP3File), -ok = esp_adf_audio_pipeline:register(AudioPipeline, MP3Decoder, <<"mp3">>), - -I2SOutput = esp_adf_i2s_output:init([{gpio_bclk, ?MAX_BCLK_GPIO}, {gpio_lrclk, ?MAX_LRC_GPIO}, {gpio_dout, ?MAX_DIN_GPIO}]), -ok = esp_adf_audio_pipeline:register(AudioPipeline, I2SOutput, <<"i2s">>), - -ok = esp_adf_audio_pipeline:link(AudioPipeline, [<<"mp3">>, <<"i2s">>]), - -ok = esp_adf_audio_pipeline:run(AudioPipeline), - -... - -ok = esp_adf_audio_pipeline:stop(AudioPipeline), -ok = esp_adf_audio_pipeline:wait_for_stop(AudioPipeline), -ok = esp_adf_audio_pipeline:terminate(AudioPipeline), -ok = esp_adf_audio_pipeline:unregister(AudioPipeline, MP3Decoder), -ok = esp_adf_audio_pipeline:unregister(AudioPipeline, I2SOutput), -``` +You can refer to [examples](examples/) or [API documentation](https://pguyot.github.io/atomvm_esp_adf/). diff --git a/examples/play_mp3_i2s/.gitignore b/examples/play_mp3_i2s/.gitignore new file mode 100644 index 0000000..df53f7d --- /dev/null +++ b/examples/play_mp3_i2s/.gitignore @@ -0,0 +1,20 @@ +.rebar3 +_build +_checkouts +_vendor +.eunit +*.o +*.beam +*.plt +*.swp +*.swo +.erlang.cookie +ebin +log +erl_crash.dump +.rebar +logs +.idea +*.iml +rebar3.crashdump +*~ diff --git a/examples/play_mp3_i2s/README.md b/examples/play_mp3_i2s/README.md new file mode 100644 index 0000000..64733e3 --- /dev/null +++ b/examples/play_mp3_i2s/README.md @@ -0,0 +1,20 @@ +play_mp3_i2s +===== + +Sample code to plan an MP3 sound on an I2S card. + +It was tested with an esp32c3 card connected to a MAX98357A module. + +The MAX98357A module is connected to the following esp32c3 gpios: + +- LRCLK: gpio 7 +- BCLK: gpio 6 +- DIN: gpio 5 + +The MAX98357A module doesn't require any MCLK, so this example doesn't +configure a gpio for it. + +Build and flash +--------------- + + $ rebar3 atomvm esp32_flash -p /dev/cu.usbmodem* diff --git a/examples/play_mp3_i2s/priv/adf_music.mp3 b/examples/play_mp3_i2s/priv/adf_music.mp3 new file mode 100755 index 0000000000000000000000000000000000000000..40147bc124cee028e5f8dcba506b5b4d57699349 GIT binary patch literal 75531 zcmdqJg;!M3+ctb=sG%F_Zb7=cQ&J?A?k*{H06{{KEv*2@3xA3nX`SUA@qCpE>&ZyLx*8 z|MP?n{lwne)5kWz)y~85znb>{PuuABg}|F+O!N!?$IHys%NhLwF#tf&f1IxY2sSPO z5h*zpEj<$pJ0~|Uzo4+Vq>P-RvZ|)`Lw%!1rWRIDZ5*6j-M#$+f`Y?dMnpx&y-7?; zP0xClmtR;?R#{#5vFTG=XIIbHfp5cOKPIPt&Mz*nZfxx!4vtRFF0O7+=>DX1l^&{z zJdl#|gJ%8D_$X}HF$L5Cz~*io70>qw|L4K~wIz5%f(Z~G1Ar<3kiY-{77jq~J_9`f zC^7>8TQ~s21poKC4v6{R8xX84GWq}9UhkDE{P(T%U1+q4i;fv1_+oOk`O-u0u2 z7A1^Gk$M7MLWVGC|4Xv$=mOK95JX~D5#<{}KjFL2V**592N}ngR~c;d21vxg%jk^Q z9z{rl$V!WhN;=U{`>S-UaFaPBd~KIe%K|RNcIXb*z|dVkVoAsT0QxHe0HGqR=dJ`G zj1&OCjGj+qIDjcqI9k?pVa%r7QuQvK%{K$Tny}_sEH;(LND%ehnKtWA~;;;cgVW{@7 zJtiEQ##0p}0zlPTtHx{ZxOHv#!#dbP>T2%ju(DU z0(DQ4s@K67QT{c8PB{QS_?|+g_1ly2G8gktW7o-Qe$UHP;%1Dv7&JMuJ3DqisP?Z_ zv=&*jzWUeJ&uGOyWyBXLfT+#>y!|=>k-(^Vm)XC-WO5)K-@K6BehATVA3j z?D|s_t5@LNOv9R#KP2Q2T|JlAucFVu_RU2G97J|$V>|(CgeE4m7!q!9UoajM65gY+ z;Wqxtp3q^N`c#jHNNwfBfKtzx275}jaS4I(VxC~_izxmC4IaP&e@~(cPNP@xW~A_on`=5s&(h6tB3pGzXm{sg73P zK=-FV-mi!Rp6kWFs-adZ(TDxuO@B73bh-|7d9eQkZ^AL}hhsShw>`P+%R3MGO3;D*o=h!}!UsYn1_?~r%+?R7GYuWXG2LqbWEB)ktqxpd}&xHH1 zj5wbJYu}c$IbgGI;rtOJ1FuIzi~83AsDY%hD=X#$rBI15+(M2I7~u?#bSV0xJcXlWp0O7x8AGl zA5hOdMXlpU`^p-4^~bY{&0>7lZA7rIxU87Krs|{8p({QO)~n`p+@S~uyahAuP7T`o zOw7tG2g&h1c0FoyDPs-^FncHCY{T5SY!&n0Sxo`Llr=`hyzHe}h|ZGS(*XKGA9C*k z_J6#Ag>2EL|J*qnW(BI4cr-C1qTYVGCrhvk-V|VBL&#mF4Rr{F4ZLHt`DFVlh5lJ-b>?`tBS;82>P1QDh~*uJ!ZH?Fbx1F8n?@QY?LqA&?gWu^+EhY(Jh;9-z+9 zdmKSZ*_T2HglkfZ>X=1fY8N_gHLP>>RzLTW6dbC3c2((E*?#zA<3<0^$o)Mkty^dW z{*>EO{U+b;Jgk9bsqDkkE~a-s{?cJny)t|k;#FL^aHTD9ninJ+Ho;>XKDxuGXm-*u zgP%_rz-RE+B+!MF)GTDP2WAFc^D*JYFC2OeBg@g5bkdpaRG9fg6+)J*!3=j&4vf19 zb?_%o3K~DTLZTr%;sU4>YoA1V^=W6RoIjE=unmjZ z_pdB3HjHwO6(+CIZ<=Py&I|iuN5=%#62hO1b7@k%_CyU7+-}V*sP0DMlqotVoO~#h zM4kdrKN3Ud+jHKh%xf|y3ess~$p=K(Yv>?F%`!NJ8_N zhvf~3;Yq>W%?pN*COS#yFQ+QH@&|O|&$Fp2D}~b8n7!p=qwH+IMAACvtRu3HvjfHR zw|xmdt+zYmG(ZkYEb|P7X1h%I`1%G3qIYW(X&qp(%z0SjJhqw&B$3NeDm>iley}yd zC*t$06)z)opl+4fYBbr)*Bsem>?>7$$~ZyLxsnPB+6E(gc1~t*1zOTN=YrSy=+3}C z5o1@BGdX`--P4?gSM!>!Qk>GQRi)9T2{iaQ|9sh4aRDg%H(bCdhV&=L*Mt`yG>oaL z9~Cjaofvex)hvqY)aIL0?O4{^O#JK`?$R#&x~bJ(Wj|NDcNFm|ZOZj%B4_3P`F93l zi_;i$`Xbckb)fj%hgWv9a|`*4gRyU0%7)5b4vA?t$78|(@f6&TF8<=n+1$Rrwbu*d z>fRzU=8R6voyrqlb^dv__7#H zdBnpSmij)z1|FAFahup3B=6gL)L#e9 z{Xxfio$d=4&E_P~p<3HUfXeM`oEQQy{SGHVg1e-yWht!9y0syjZHzVUr&U!4E}tzY|dGd4ylHzkj> z3$KszuVfE}HGxKehD3(=yf}7Wel(4aHQ=+G>erAptbtK45l;F7&3jQ|hP%|v2rq;} z-C)FXj-<2d`F!DYXkpXLdu5k0Eep>2!Wa8A7#uNGxYX&xeY$DU*~&F1DS@i%whu9r zic3=6u~N>?g_}yXEn5(>cO&pvSz@(0S2=r}`La&oeJQaLuNQZ!Co?>Dx0EL5lMi$IY27`RA(my6`Z zbqUcT5Y$p)CFY^HAT-k=(06|x9XKXN=oBkKAR?o3LgFIu zzA?H}L%EzXv6-jo^TG7U;E;@?tSI-^d%o9kD-K*_i#AhC4| z@3Esyt7e+e-{{cqCDdJfnOLe$s`~*SrN0GC)pETqvZIquQj9Lkm_2X$-BtLCrR?2Q zjluvwUxD1Cjhn(m>2-g&Gx69Ak|BW(yUy`y-Q0Qx^QLv||JPF1T2sXt%)<4FwWZvs zaA=qdP1Iy!xHvTpbo-%j)MN0*2NM^7>@gbiAh?fZzmB-b4w&Km3wu&tQfzZe?3#X- z-hipj7~4^)Ok5mb6lljv$siJFg^5XeUC=|K_gA2}8LX_)I|n^P>u-0iV>d_)$>Uz7 zOfnGr=FRLptVwN&ns;-w5(=jF`Sk#=}}Z-sv>}39uP;h0afW zqZi-viY6F@9A2b+YxlCDlCVfVaW;tHNr_a>Qxt7-{eg>@v;DqW702DplwEV{%N0DE znlwzomrQA5FZzApAeQHtz;f96w@y%_l*AW^$J>n&Ov1xF40nq9;uB77nC~psLO?pZ zbojS)NavnvfHhADwYI{=t~~c0dhS6W>pWAH2$EH)ev2w0Hc6bQ=!blQg+1pa)d9V% z>4o3Pm@da;=k>uk5cTHla?({Y4MHX=%KXTKq?$mK;gnNRHELzcDyH7`O{)OXxzM4T zWdvSzsZ7o^sJZvnB?Wb{d~t6Vf&K6;y%`H*_~eulbAxPu1w1t;B3Z(Izo=U~E=i;z z4ht+v@|TR-@sug;>#>)a?IIp%@ZK#3&p_}@ovekuIG8zt=l*@}h5_wIQ<~d4HE`bA zEadv=bA@^s)k?u4%hvWBvuW3)!L;q1bYbS|CiT8u|L2 ztfwvXg)aGb9Ql!#54RK-GOt;lz_T8j3?&TT=!*{$J(74)zpimV8UE)S1n=*%(qPdl z;znMD_k@}&NxuqT$}l9Osf)u8ZK6+lR8jW1Oz8iu4Hpz%{4#gKmN9V&?pK3bFDM~m z)WWL8u7Gu4_MHl0g+mbhCa&9LigK*EPvkghVzOmS%NuON5jbw_r!3U%pAhQBrt)S$ z8OMEWcmkHFygoG}+_*(KM-SYasu}eAID`6Ndio+#=%r_WMq$vYs0@AJH#T1qMK$uC zTxAC=y!cmk##Yg*72A5|Z{!Qy5M(2a;L?u2asimi8$b&U??;({&f67E+vNqw1t4H( zKCvxcH=X$@298(k#uRzQ+XsE38{b2j>4;^L2R_=uqK-AmC8&r<2m0#8d7OY1-5P4W@Pk}L)Ny=rRf6jM#lPL~Yg8Fn zo83UHtIVKQ@_;g5oeMJtX6H!CA#VBfOX5qMR-w#;rO`h;vuC03Imb%IVg+QDb8c<7 z3<7LjmrqJ#k%Wp+782|-U1e7XCJxkl$w`@b%{O&myRx>u%#9npDtd=U ziVyPBoe_Z3lb%N4GS}pu+*UW@UmTX!;cMNE=!#$LiW|h0QgOs9T6Cpr-cteNX{P=7 z@Ha=fcS0ZqAcy30hy#*f@wIDLxovD5E4U$7fnLukV-@>ZYy+VMQdf@^)khOmj6 zyP7l5``!&UZN9%W(S$IQL7D&YtMw@-?24NZX|4-vYB7h^_;yIlKAA>6+(Xs`|dk-=jO$ zKg0AvupGA5zxMbA?^Qhd0iMH)QPZr7xZJh@4{FOc!oQpFN5GhzVj>!A`v3lLDSvWX zD)>?7XpL!?@@q*N3uS7w8u1x-xBWC0#fVwPZGYlO!Bupx62me+Lu zrtvJ$O6D|SWSjLJ%7u|>DKfML`2gJbDt$JI`Ub-GtIyJlGqv123m}yuSka}H3cpC} z^e8*xnY~0d8ZHv*MW4;7U|L_if^p`BwngX!7qPzeE)gCFS^dEq_%)1^`Nt~eKf@#{ z3Zu{2f^4yW#NQCioR=;aJ^NTR%PLi((53t}S`1q#GruWp1u+NuV!*Fc4=?p^LcC4Y zATSI8H1P*@?FyJ+G?YN*s70MADDeDVcvNNTG4anEeQ>O#hu2XVn3?l+Xa0 z7=4WpDI;dt*mn;vKk{~e*E?$p$E2mpz=B|8nnpd!87R7zv7_n)PjXS^;FVRBeXq*P zk6I8cn>YeKm@Kc7&A*pyixgRC9)m!EgD`J?n(OVWkIpx_;H-j^2m(ZT9HALhgqJ?p z3I05)v8}?TONhXNk`jHL4D8c&>h(-$c*VSJF_sn9u-{Z78EBy!yM?g(K5u7HyB^2%@EQ->&>H3iW6eD)r=c(f zAo0w2A^JDZ!j{fwmDHLW7acUIq{3M&$A5F-;)!PFtW6qyUi3+!7X6Rl!l68RmaeZT zbk&r3&23#NUe``ybz#9-x^5VeY4gS0WWEFRpsAog9@k3k@mI_m994K*vD5V3v=a7eR^+4~l zYc%c*J+Bl(>$j*N;^bcppy3jmV)0ioay8NOfRTG#h@AeSJNupB2*aVG`o=m0JQFH? zRjzVuvUof)w&e*Yq=sC3&1aOyV%e54StdHW%2hHqtS^T2SFWU6LA|8%Jim)G$r!Tb%nk+zm*r{k8?j9jyk)KR5%L)$Mjb~q*=@f z7mu~mCcxT2820InvoD)r8sx+)S!$lFqvK)3>nAlBzas6U(&B1X)hEjYa@?*Wx_Cm( zdLERK4PJa+{gb)wSqyqLo1$iK1|_d0_LN_)Aa8A>*AxDwHQsT+008yjp4-QL)vU*X z_gxMz81L7SZF!;@sr&=pv$OY7nB{z~!yFFLWIF2WZTv#PZlWU&69R?veqxcVM((R_ z3~y=__w!cw_2RKJgHG8QM>o<(S`o0=^!E(ujn&L{`DJ0Z9WRtRO27;(cm|f(r-&!5 zEHocQ70Y$(wTFMcY-J4#`&qUz>vX_`-9+QWBL0;9kn_oMj6z;r)>^>I8IEF2*+Hq6 z9;^2`eEf5y*t?du)?4{k{&h?G#K~kSC5I_dDzCNEg(&OX4vV%WcgHL^2|hcY|L{#1 zZJQs{JW8i&!8o?kE64tK{kq(+7Zxm8fn}tVS6##cbAj)pjbc^z^*ha=ks~RjQa$Rl z%zTd%@EYv%8&u@qEoHIE8@PW#(sR9 zZ8W3Sxs+*nNo6ks7dpYs;MSx{6EP#EzMbZY;KwUOse9d-`b);#d9ab;RO~|vu zraZs=hOs5cZ>g>yw(jRv&~)!m1D&4J*YH2xapqr6FnPh>`H$e>85{)n5;!CQiZpT^ zPDLesT!3(O(kS~4rK>aZjzL{Z{;gI^yldqXD`&|iEb-6Y@X*2(%*-V3mho}qRQP%` z>an+?0Mfu61lK)5q;jt{(wWDc7APz#6kz|?mSM#3Iu*#JJs}+oNEDr&DtirFjAZBV zW-Qqbj)&IY=i~rSE#auc%L{MC2j9A$6nfkyfp%U1$c!?bAL~KnumkA^$jic>RSy&RbOYEJe}^~ zLc2eovxu~hI5LJzzWT=t*Xlw7dJ+mxkOl7o{0kzknn*RnRhTIkTn?EP7y=g#=7d)z-=+ir}{*eox*KYdS1qyUtk z-H<3@tE0YHBNYspPTK_Oh92uGMeW^|f*1KDRREM0F;8w&W`oU5#k;$%v8Lej1zYx$ zWZ{{Bl!--PsaP^ieq8h3AIl7r?o$e7#^wCtJNru$4pq_niP$CcQ7wsIlKrL&8*q0n zgB_)ikX1ML)gFW9FVnzTvn4r`j2DC;YV)4y^-OO;=2I8i#aN2?k8<=QszQm3@6~vr z!7P;a)l%)xx47swV)e-*h+EAs&yBvT$T`!hMr4`H@2@MEvkh$~Z7OV-gP)W3fs(x1 zp+(h9D@;Jxs9p8L2}M;j+oa)uptL`w-6P5dMYcqqSK76p-9*n5cpjsnf;D(vJ`GMS z=cAK?s}J4aHMtGO1ytKxvBaMlmk$rq_g@9+`wW8N_`jp{{_h7F9+OGAh^fYC$BtDE zSl2xg3~8o3Yb;1<|8BEDvNBVD{&Ci2uU=mOJeyTy=bQTe0h4v@v!Y!?P@U1f&Js`X zkvcY(1481tla5f8lw?o?E`P;o$V}08UGbMY!BGQHRnDLLxY7o4QSnQH>d#@Ty|(2! zdXv--cuQYVa<3?9Vi6|T*BF%FaCdJF9nM}LYlP#Mt^h!N8%XX0*x8t=BhzX6ydJ8) zHEyW&WctCtxYbfb0w;l8F2C0L#A$B6u1nVBJGcu_Osi}D)=Yo& zijUvywNH6X*hiN7Y3Yo>pPjJ5x4Y24JyR4^m$s2!c9)1v{p{}8HJizzZijksc>GgR zpS8Z})x-SFSMES)cqc$%^~jxQt()KLA?cerW>qV8g`cvX8dsWw&6cK4@zr%Dyg_kZ zoCGVhu)392@ZcdF+|mc(BiHb2dP8fp!AVkVUQ8WzNG##O!}-$g5Nh!#w%F+X@m%@Y zk59Mp0`VYE{=4Jz%%$!TVWVN@e{mtNpZ*7N0F)UWDn(E|Qi$6-6zr44WAQcB9mp8?nViP~~hZUvE~Ab4zjiSlheM}3mxq9Dp7@@{Y%3qmt$fIz)NIBQg7%8Q-Uc3NDhh zJgp)U$8hB_W2t+wW}vV71oG;#q~)p z{I+zx53Zm(K-2x35fQ@1bG}6bNSZIlR#!+{<5%A0cPv7bwah?UMl2wnji^V(1_LJQOhJbqbB7*SIFwvv&K*~BLct}>Q;@YkmW9y04D&RFuJE8a<^8cX!LFV% zYi6haH{u+*iKfsGtUxc{rNTaVaZMYI{-S6i6}-atWs*Tga#oLr(K~W*&L+0ue)8KW%6oIz|i-cpUmYou_7ewWg6PBH;SJZFj zwv$>;QLp(1)h*sLd1u>@oPWDSB?YPvI3w$7zKoxzqN~sF>1S78i9yKu{W?7iAb{DO z5U>D9z0e|pRpv~NXHia&;~kEcjCV}-Ve*l70Q2nsYEYL-Bvj)#pd-N^wih5Vk>BCKbe(Ps8 zLHBG#ZQpA!Ik7B^U4OIHID~_Pk?6?sZeB>XZtom`VyRJzT`)cQfnLY!u^JUMqbDyT zx|W~*VdQ_R!SRu}-A|w#2`2`@+d;J3?E?2v-QX@Rcur>oXg&0Bn^yzUzVdC@t7trm zIbl^QFlghb<|YxI#jmhag+w>-QsEL4?RSR-cHipp_h-GM0+)~u-RC&7Xe9Vx0^v{s zy#?0|nPzn-9YR6=cQ`I;?&URO2Df$9C1Er1pv2g;X zUl?AI@p+wklMARcx+UL&<*=G>OWK$achqD$yU_@_+ zws&yn>RnqzsJ{PYd>2OW6@!%~HhnLQPF)i3SuZLfOAytGw9;12UaA&sjftjJ1D7>! zpR9o5cpMU?jzi(N4HfJ15j8ZR|3om*aJ3i5*m^``dT_ zT>MVpYMD1WvEfGUdng^WdEj2!TntfUKZ<1lLx;8bDJ|(yFBgE3rrOca>~0b3-Lnluv+%zF);Dr7F^d*(hSL zpm0shgz6@#ChIzF_7Y?PH9+ISzl+*(?wPX?EWz#4)%1YJlJ~M`*4{Iz{WZ&qb1bEs ziJg7uI<2o>Ube*43Zf!$_PWvNK`MYl)aFo%P2F}MMTpsFMmd()QnHU)u-pNK!eaeZ zw!c#EEob5doWn9K-ZW~pgc&OZ2eK1^u}st8Kkq9)Ya|}@ztMxGXMVLVW1uj+NGRwS zjC1fUuncx$a8~Yq)|2rIA}Ac|+C2_1C)wRDmaww&ggkw_NbrDn4dwtle)~`k&$fH< z3z9~mlcl>HM1^mry!W^hh&p(?5j6(CZ2*8g-(eO9tZ<*YXEo3H7}C?}es%n=Z~65^Q=TPCf`4{6M>D?|(J`M7v`# zfrQj7&w!qq7<=%3bopd0+*tWU3rCWLV$@!obJjx3qnV%S8Xqmuf3X7Sv4dmY;J@4( zg}Dck=QoytFvyS{8*9l)V?dnV1DWSLb_cKS&_fUo>1SVcjnuW0#f(SFMZ<8~WzYt= z96)lpt)5cG5`~(d`BiUN)>ZBAKd2nZ^`NIJKLlqw4t;?n5NSuE2uPKPl-HexA=ZGvLY?0TZ0yd{@&fZc0q8$ zWiK2Mj>Ym(zztDMU~IZQRV~09Vb5_#% zqpEM+;UFyuAzwGD1yBUL!%0>R@6dw@MBEt64ev@DsJbr9%Q}0&U@4wuFkj#g>3+!t zOb}CR>EkCgP6|F2O3c?2AuWX&rAwBDTw-GG?%9dprh-de7TWVBE-a6u4XNdoK6nuR zFc?HC0+d*quxlftSAhp(47uE znKC$dmF}&Mo+KOuFEB{)z#8nQL5GLPQVbTC%_!No+lOs&n|#I)oJZbFzA2<->U9ks zsPw=4FA*MMIk=HUy^|8hJX|yRXtq^!R}>2ien3lO3v@{}twHw8_ozRm$yPt@ zwW^zca`+`z{!)S^%M;C$q1|^lu`AOivvGYOgcXdV`pt|$b_4iFz3*^_>l0uk zRQxm-zok=lq4O6w+||%a`Vd|~=x7@QU#kbZQK@CgFbJz?+iOiJ+@9DVak41jc69Wr z6093OViB!+;@w7|i^{kuz0m`Ncd6~RC9Y=e!l{Cg)@Up+53tBSj*jP+@+5#xh9g4@ zjNV=?DsC3X#&pi|On<=34YR0NIJz-%J_Lm-Q6(n$yh(do)#vNW@!i(|$yu_Z3XJD< zFM4K9g5%$IaaBczO{E#)+TW~kO0F9SO53eht9=Z*a&mVb`UZ05&jrw~qkE-VaV{B8K95v!ByI~3~yh%j|ZYV`qhgjvJ$ z?inK=`k7@IRlesNTG*k$qS{a8J9F+v{Ncjcue#nVuN(V>pt&qY=@(tih^RPCt8IVk zVt`E3U;NI~ESrc)E}ZsrOBY7Sw(L-;sHF;MR zOZ>T1%knbH_YOV8=%q0wGp%j62H8y+emM>zn5VmE8J|7`lH$=YfY-wlPSU%zxc4w0 zysq(jQ-6aRH||Cg@{6rI-Dp=8uFca<&oh{;ex*uhYh%Spr99l8NbhseWSFW~6{PWz zx5g({;vmZ2^2*q3fJ~@dKx|okUFQh(76ie+tHQ=!6R<$ZU1EGfJnh7VkEzS>`5>{M zOFw^pbMIbz{VEtY(oyd8rG^~{W>b#~Tofi=-gIA})%#xgHHZMc!999_&P@X1Zy!gU ztaW_g{A{*ngPSVpy=hlY>(4J6B+k!1eNM)VbtA^B-(eWrr+FN)}MiAVes$akQPCR8-0a@ z*8D`d73ukI@Us!)pE2?~e&k?P$QUY)OtqkpdyY<_XhDF-bp6vybH>>hE65pB(67f6 zM{Ln78Ax=Pa=C#Gy&M-3Zs(N4Q?bG~t^8TtN#9iRE3=w~1iY3s`nnB|t^E7?+S z|K;6HS}#r{`J}a{W54Bd-E@5RU}ameeynHW^!f?-bX@OBHu^RdxW(YWAG#O*Ng_4yi$}voqiXEXa}H(<-Z4qGFxn2DndB70 z_2Kb5^pJ-`PVi={CAFC4dM$?KoK#`d-IiPp#o^~EwYR--zauW-Y@C7FQ}+v93)?mP zyMM9rQ@-2`3aIi@N#qfp}qhB{2`bm>qCTpse7rkBT`DVhr-cF2dK=c*NdHpq2_!Xv4YY1189 zmg**pXnkZ;?o^M?hAtW-B#QTD=T1vZy35L!3r;FCFsAb_7nA;sM;@y%{K^O4?mJQHj*OcoAK0c z=N)=*04R>qPQNBi3 zd!8QmYd|UMXY3I=`Z7GaQj*HJ@16&u6cA0?<(mO|hJpY=YxhU)SfQ~Ax;N6WIHlw1 znBRgf4P@tT1^?vmr0__R%>CmM1--gl2zmJYK+~aHbQCw;nC}QgLIkwmB}7g^gE8M| z*o6H3`&ERPQEH=HK3s%4xA@$>;77#Tp58#H7VzFLJL9i_1}Pl0K6ADh_Y^isCspm( z(-Owe&0?Vvc44Rbilv*)gb~~8z7{u-s=aXTOk27F7yHU%%WkqC9(=skg@*Uae*cG&94${SbqMVAP~P1%k{G8{;L^-X2E;oI6&IQJ?)tgG8R zID$Zx1s^BOBmiV=T`--NVwx?_;Cd~m)XiJO&i69B)^UE<)b$f)JFIAXgfvyIy~HGK za0jig<5M@zmhJ41g4b3nAPvQWiFpX z@8p%zCmuHa&mKJ#FI|B0isR z)Aodd4x9TGjE*N&*p;?x89eAjb|V?b;g$o6kiO7!33IHp6JUeGwXT{UBp2oGeQo)n5F7Cu6PNH(=cb>Hb$zq8%-Uju#!h3`_#+`He;Q5QQ+23!+&e11*jP6tj z3P5%!9`6%#+sH!02yLTzagtkXYuMF*i!8pgvveEPK1FERYoR(q;ak~B+{dCEbK&*@ zW1n0;QdSL&oxe~C)}YSxUQ1dryPV-g9ra6Gs4~rV=&OPg0A`laLB%9iLy>FxgS>XL zLAJPm&o+5*_GorGpEcE28*DP0Rljrg$SyK!9aur>eo$4I)HmI$%m=~W0A>U~o*W6k zCycD7ZpNJdRd}Io&nqmZD5`w|E$-3s6Kjn>-@P*6Yf<;P4pFPi6^H&SsB!N?tNg}9 zMX094b4wJKA@*uXapd}D5g|EaZ%mH}ySs&GCzTE-f7NN$-ONP6G|Y%e~%e0R&5nGU^Jfm46| zLVm&20Dzi|Yu4GQ`Lz)bvihWibP=c9oRcfQv{_40P^tahJIV1_TO{>Iz1{$PcOT3^ z(sL?Mqfae?LvU37bR{~hHsL03v{X4>j@-@N+y;7dy$95_x3 zGjFtc&A02!D_?!*-78$e{3W)ck$c9{DLljC9g=G-=_5t&9`!7xmBvVs#R>1$a(vOE zTo;VSv^N#Vjti@8d1Ru#G7X-j6kOELf_r|srYKbHP$d9SG=99rjboLu&dh&@9&B{> z&5vgO3>%b7JCL?q1~APz$MS@_2#kCDXZ@6RTFS3$Z|n-CoMXoPWqT)o$`3qY?D(J? ztjpkS@}b__vD&?6;0FjAomU9;z`-CB@S#5PPXYQk*f5Py1HBq6mIEI)uq-~h-hv@9 zF+#yA?I$uTzECqLXtmSwV|je<;y&`d!ZeciX|FF)!wdCucxN@L9CbWfz)b3W%RfzS z>bOe0H~s5U!&MkLQxkA7LGMqlZ#ItSUxdkYBW!MXJ!5Q5jSg!xZb-kGBv(^@0?#|^ z(JiDhnL|VqGRrnxRX36!JXGc=B<^j9y0#s>I75RsjL-m{vO3PIy_HfdA&wHcfY`m z4U*5=Q-Y(TnJIB7`9UZbQSUAGL2v6JxJCX{7No| z`bKKQrf=JC8Dh7VB3fftUU6lw7t_tvZN)#IrT&}h?_&eo*5OVI2?xit>`oS3a%W+2 z3?tXm;LeTt(P=C*1S<9@yYxpijkb>iALUmHEDzp?K;Bly`h9@bP)~GS+5r+_eG%lW zZp6ObM7dL;YBi_nyi!~udr%PsqTusK7c452BB~*F?3pq;?L?&it#*=vmRH-xifWi) za6z`OFj%X5dA5!sc#lu;0_HNu%{xpgIE(ioz9r`I3K!M8V8ssw%fG?_ZY*ftpxkZy zYhL$hxP5$*IeH({$-kfr6ju=V0qm?DC81z(3U+#58<~Zt<#J{hTlF+fH^T0#PGgfw z*W1wj-?__Sra6_+&F`P5%TkbvEWb#^3&Y?4Zfzp&EW}6J9)bLOU@B&|@dAV+r7nex z{FOJ!uhDs5%OSFCHi==JfzM95-68g|QIs0Hj_#nJ#NB4*dzoK33P=U7!N9R-kVBn^{sF~T1)kjGf{9UJVPUdNm&)qUMK6)AZi5X(!k*aZZ2hzqZ z0k1O9dZ%QoSEFtp5tVn{?`Z;hw(c$p;d9$pJjb12v9hG9lVBvCt+X?l3UR3>3tupDDCd48kgcAFRCS;k1cFrT*0*yR(?1EPG4d&pvUidP(A9o~NZsVx9JNd6o>sRgD4)1-GJV)A`8h?<;Q2tu ztX^?FI3kR51xLy$>=@rFgZtg!l@Yj&3f|D7qU#oKfY|?KAybJY&*Kx#jmY+Ah)s!L zmZttd=keoZ{`?53cmG}$VV>sU{V+qfSb5Hzm)Zp zQZs-6^R-jgGr`yT*s*_A?uq+k84X)(iCN(X)fSLOwe66qUwS{1nssElELUHg;>8@h zol_P6aufPdQD+vuj{tvoF$bkzSOhbwoaxl2YV(}g-aa~PKG4hcy7 zNnE*Z&9D_@?*dQd6joYKmAcNl(W?m7x7`Pq6m2KZW}0ERGIcJW77E7Dtmj5Tx^bPBI+0sT4n*oe1lTGmLF?yh1}Ol!gdn@5ASWaB7Ubb zP>2%dHI+~heTdh|!dA6;qj1g$UOAune7Qy+kmu@3wuiiFcTgB&nfie5mry~Dqn9W` z*8Lpgcca4_hre$Gzi#Wb8jq@1>grbga+My@j>2*dmSZPnTl)9r`b+ZB-$Q_fStvSb z(}3N04T615>&L{UWJG4TPeSu8tpC}?ofAS+H%OBC5QGr70xR#5?FK#0rpl8VK@H|V zu{8k~xb(;Unb+3_vVszFW`35+xb2s{P3I5ZYh?1_>}@W22`#VCgZ@KJfhH4 z))@98C>H&8-!RFZPpqK+JX3zAF|H#<1N%^b5?ZildzmxDz|k*f-Rhk#1fI(bp;svY zX#YAUD?SaW5*CFXt;K2OyrP}7u|A72{-U~c%djSI#jb7NY`WZx$;$kf(nNyT=w=Z> z#<)ur%|GYQ0GMJQ0-=3c%pQ5KHplIiNSMc`G3 z%dg`(1CWDrlBES#!YrVABKiFY000AMVUD{(GCjKu*b^Iq8cZOeAkknrpFQ(a*+_vP z$PV=biB{O}9)0GvlT+1_*qMqKtCMxWULYX#?4PCz*)cAblL_BAgHnO!rXMcNgWYjO z^JcmT(N}ekVLknaWu1@1Q~nbWXb~x&wDds~)*t(SZ8SB=x)=k9qF)9@iLD;$icZfr z8Dv3G42qTFrAW)Nnk0%5v8CZk{qp;5(5l0u^^kyqHV9_5xkWo)U=Hsf>1j}rIGyU^ zO2k(DUil>^xhKwv{`AqEKPi$(kK_(tLq?yZ30G zeCluX`zRF*>x`5)&K3Oj*WwoDKc}Du>Yo~JwzjL}o{?}O9m`4yWBZHQdb*pd)J0)c(hs?v|FnZ-p)cDam z574=V!*R^igisj@b2z?;KU0Jy&J&%37wVZ&90 zLb1&3$^9&p4bv`XGx^m)LH_7C{XQDA`q@eOTgdBz5%_<)9)&YeX?lu%fq4Ka1Zm}*Vm z7+EN0LdE)PVE=(~^6l-dRMSHMD+u+`g}_ko2%VlPJ|RpZ#G%AISOmi$NCziV6?BBN zkF0(=O$@gwG6<*OaJc#~_~PY*{@r&ROL^kAWq00z zGXS#74oiX&gVa#_xD9i8tmWeIClWDHdT`k#RAfsU#&nk#>jmu(b~3Fgq7tPEUU52H z?#a_xh!!YGb2S7R=L9YUQw zdn27LotJ=ztlGG#qkDP)Stpx7X5Aogl2DTQ;OQlvteRuIDvu3XJ;K6O`kbD_CQ5Mf z$Yl8Y-Sc?{yl6r+gp0>KaPRf}^^xtv(MT0=fdDz8YARtX$R_Iih;na4tO=mShO$?A z%Br;pUPfPeSYeR>H_rmEv%VE^`%Tdu7Nq$3IS2_gW+?)|El90AZ>*2HNrougE?f>$ zzs)$nV|p~G%rG=oZZ+l}85&%5WO4?onptX>5Ueh0-1#UO-A z#0ey6bs^u3>l({Htx>nJPhvlUfD;K`q|D-4_pPy$I zb39*m!#ZQFq^Hm-TPn5cV6g~VlBheZo(gL=ljQPZYV(DGu;MVN&1unLnV$g;&v^+c@{8-C6^O}I}{2<4?%i7%b4&Wgl$`N%D z%KX8$^#aPzp<4)1kT+W>FzB%Y=haQ^aK62bR~o-^I5g4v#BL&%b&qz~G|L|p;TH(7 zJS^%p49CtW;=_n2Vci`6r9zS5-*nR`+(d~ImdGv&r!a<9piVWP3gSF+k0qRffQ+$_ zH&{0le*k9p?U11SC$+g!Q|n^jWI4w|g*QuBeni~^iHX{_2vjZVY|YrK z6Lmer!jC_Bu9o$LB|A8oesRBq?KAJ-AG8Rs_T4)Nqn`9|o(+0D!5{Iz1UnCSW*F>gB^E z9dJ>1@6rMXq4D9$HOBbTCpoCss}otG4Uf{m_zMii!c<}HZQhW<{;z5nu}5f0fVtlm*MeLA;Z1e`Rd2M z!=G02`~wurEA0ULi1_A@U z>yQS#$_fH=RO_Vn5K8C}SrhhaS3;F7*P?B_S0xs9Ul|)N6r%G9&h{UEW1R?pRnnl+ z>k?y`Ir2RYOFR#mEdXxJ#Z$?8OLEMN>%kWoR|-X^yZiQ}un^l)!n5nh;Tw4GOigPB9ls85OhUpIkBJN8y%YuO!>X}cd_(t)E1F? zM8id0T?GPlgiRLu*?5`u)Sn1ut%5(pIDS6gel;70F%mLQ&$mfTR>Dy4 zO8ECF0Ho-!O)R%UP*b(!b_l0{)kj2-0Y%kmCveVQroPxr+RC1Q0=*liqNoi^pndyi z!sN6h{124jQ}fraJKMxji%v(UDoN=;B^iGDZ3=Q_Lo|fZ1R!Bo(OwHotd-y}>E^Az zW)?ZfcR!6VX$Lo%AKcf0(`A&*RWK%0^iip{OO^8gXeAqoA>yya{Y??HnOK>Ygu9(-@mgg@x2y55jR}ln zg?YW^O^NBQH@PCizlf_P`G3RW&8xt{bse&V8lhGnmWH1GA^$=(pR}CaO00lj|2+NH z^Zorp&x;M6@J4>R)q6XQSyjhrzFLz3V>(5}vMb5*z`DyoeWK10JnX~-6lP3|WB9>pT6Xmc6%Sz@2{~u9VH{#CrIslZ+Bta%s^p zgjfeOWo7-%!@b2p>Fe$&p(1s#VM(&P6mT~4{DumZ;MN4HX(`udAR&a}`dB{fDNC4;s63SS+5MgKQ& zTq{}Cj5e9oEfT6M6!8h^(bDy>A#xMh`gzj}Z7 zVl@@8y=S^dMUXhR7CI$n;YnAF@AxJE{FGH{E}(#o>PIqs zsK??A3=c-^4hQwcJOjTo_b%FdYr3$u@jeep0e05p<4uY|c&NOJaTt`0N;lpnaCu6G zY$ds(V#k7yD5hh$iR$G-u@=o4l`yW6)>Etj--Nn&4rJQU)6&7)e}!TF9HdECbOt7S z$?!M}neiAH;}kmH0BzD>XdqT;I>I6{;Q5&pm2nw#B2009cqe3xzgW#u{ z{2O0uN)^@eoj%gWs5tzniFp_HB^|Zz%_N z-5(c~0{{R>7b8HV$|QK*oQOyg5uVU+`wBcA!DGVQ5^6p2{KLRPR#31 zRU=(^3QFiKT%ygZL-y*W_tFF~0foqcY2|`N5dXPd zWU!p_^aob1d>I+eA!{2gjO`oivU+3yPN7M#ohgo;K1A28Y6#kbQ-Rd=R=A?Fogk>mLp4 zKCl5B4`WK7jAqvmzP0z$p~P@&)TvFXH;74nUPQ7z0l{jtS%X%Yp{*iW02T4tJd{Tg_*YE`Hh85~Dty0O&eqt(F z;`UZmF6k%F=e;WF*PP?!`ZMjNT)B5{2zU(f8PWMlk39Dp^dj)zb$NVEcb1A7iSg2d zc|RFbxk`|-B6C{tFhYY+iAAoo*aKA4xagJ-q;Fc-3oU;7F7tizHRX?-%P3Xq{wBr6 zP|umWI4IV=J^;^3IA{5`55J)USl+p4vI4hUpLMcz3SbtcpDAEORPkalR%GF#L=n$= zo&^aIH93$!!2#VlO<_Gbf6>HM%*)o0qZcq+5!75Z6B56Hh+pka*!3&13!M|ejAfg- zn_(9RrbmvlH|cJ@Jy!Q_9t@IEOPAdgQtfqa$R+cr5_HuE-fzJ2BMm~cbML9P9JUQ7 zb#E4#?xSOBwqxiP?9$4v;VGZ~EL<9mu}=|&_aIy`l{a?p1KaNL?mm}3f(?QOhjJiY zRc1}DL~O`x&=WIATW`O9xAOqMN;xBn0EB98aH+n7UCQa@TWNik!(HL0H!8hED(Xi1 zb2~f#!{K?v;$H~e!pFMYOIAJ(1()%MTEaPxl9%dUPoAtzAIhIgwEXo#fg$tud*i^~ zf;A8d3Js#3=!o)`g>S2D!8142Rd+`ay~iE1L^kf;fHgUXt6blT`N0pVQsyKeY8Rw? zr8YG4eKI`*ILk;rc{=?-P83Pc$kPA*HKZtRn*_dPJc$*~Zr~nDQa}-hs;2-%2()bk zD{;G}gj8^UINIp_q+Xl9c^_fIC93e(;tBzE zQhtAQB{P{VGXhel(3MLpa?Fq>gR;i78{j2}mriM?Du_&`S?|DEVPHFciD>--#6ZYX z+Wd!^J+X=m6@LH+LS)V4QMeQGJK2qYHqHEH%vf=^L=!IBeio4Z7#GQ)5J@^c@yEE> zEgs9yWEn9iucIc(2|G^M4NJis++V&yjHaL}Px(hVb=%9l!CvPnRbxXAm%ArOgMz0L zwq~(@cP`Umjs50IydM1O&OjZf_|fbQBKyl11Ni%-tva_U7Ls1b6)xU{bMkC_&CvRX zr`mMLsi;4=*YW3@IR0wOBK9$1cvxJ-ltOlZPc22Zv6S3DNgf-0@7dD71sln`XgkFw zTy1-AxBUXJw*#$dynP=MSA3wLzldWUa{k$Ml%Go zRL65Jwan>RG;JvW|08|)0>r(hW7fpV(UXpg=Z6|*r}10^M>)4fN5X+@3;Ax~Ogn2T{IwH|MVT zmK?_DqxG;Okh?0lI-l=ZX`@g%Ax&V?@Z$XHOF;O=Jvxwl3j%RDMNoq~u`;1n?tBy~ zf*R78&`3E>ED>ImDSd%S7hj+u{;u&Gd&6x0`uv3amtZRV(~3HvU1EfbpfYl*9z+s(M#(Fw)MU)7wXvxY!AKetzStR8rd^#5NK!cg z>-mYLWE9}i+N}u;iv4Ryek|cJ@iHHq_0uh4N|aXEomuBU3$hwi%~j#EpOY;Fm*434 zWnm7i{Z%s$D;JgQ6wLM+Y;GQ?u}swdio7|4AoqVNb~W;0xAN?_kl(OGyBXOhHrUhzwO%0uep zC2&sW~b~ajj2svI$xs^ zAr!dZvJ{By$i-y73lVK%2?Gs-vV6dd&x#$;>0h~|5Ej!}Vuj6?1T|m~uZkhUQE6ur z4f`#F()$CEQ70Za8pE*+YQeT4u#>TIvKsF)4+{yx%HMUMt&Awg#rD>Nm%4qzq75vC z)6Vvk2nq^hi98eV;>HQ=81{NUj_mwl>!eb4A<5Xt6Fn5XK&UsgFOVt5w3}p$f`?IU z3+Lu@foCV>^eQBpri^(*tzahkaa9FshGs)gWn-b?QPtBel$&IAkR<8S88 z2rP2ESkefVM|x0rNF(ibPN6!V`e+KJone7$25JuhfWc8wPv>eoQQ$GR!<-7WAYghcm#qUeHt;<=F3T{tivu|!Z3_ulw z=A({_g}Y(28>iw{V_V+`tu1f-Tu%ClQ!9V-2m%2Pc%Du-1(PaKVq>p{xhEt-N7ev& zI?q4CstgOKAhNB9EbYv8w}A&-Ma=7zng%Zv7m!bBIknO;fH>a5W}Q&U5LNZESTIRN8j?bZ zAWGrqViPz9g*L2ikNO7f)x>__xG%f=R_wxX=D7WOPwM10li}H`8wO&jj*g!XW9Ps_ zA`D!X*J#9!kH~(G&#-Jd8NyyAG5J-B1RgKqNyhEYk4fDgyl7|b0afatE6hK|($dA% zml9n`01SzFcR(Oa!oh>)AK808=bs77`kQyh~nL#pVsebJ+#+d-)#$;Cejlr-- zEuAdd>BaYsj+Ltkj5F+%XU>YvAs;r#e_q`S+t*xNon1WaIsBEPL&ndYR&IbKAT|Lw z@_6r+cXfrVl@C0iKV{spxP6#Io-Gr19YN5gr@!+kWpvgEhuvQGnX{8+Wb{5bh zJ@j2iB($`42JyJ(v;O)y~{33}F#T zzb>pMe$MPJKG+v%;SbIa(Ov#@762QC1T+bUSLA7+6G>N0d1NR{!?42znI1{k)H*E-u*`M| zxJp7Wbqbl(N6=m}5!{=jwxROWaSh*d7k^HT%f|>rR#5|$_?1J1a7r;jw!}fwnDk_! zpnMku3TowqNGl80{(2bM7KsV28Di`kVROH-GNS;^pvRlqd@7U*#UkL=j6;SFI|pJ` z>z0VqIM)~~ku)nw#2Zb`+WG?Rth&)4vSJZitg>zSy~5hpaZ-1&h6qS|4O>^ z&`2lxhys(~XodOr-`K}Po?f@8a9?H1(Sznch0L>tX?;$r^Dp!p)6*!aM8guxN>u#x zBSWyMXp*lz6zFp&r9u5m*aJ(^I}mx?Rxu)jfG0C4PYK~K{y3UQFl9i={jAlyC22$ zbS<8-Ikw4Uz&Dk((oCqOi8&||% zEnQrC?T_tee&Ls2Z`??eIULWFEFF`&ICWFk=R%=Si$Sqonk8Q33?Mt!TNdZCfeV%CiqE|EWeH$XH- z*L(Mol*|;BJ#kJjgNrxVs=mJdc=2`VM}p4^^Ud_WmgckAZ+E6w=YW5rK)sH(A&C>a z^6^GLnJa;T8J?1C7l&LIXnX%mzRu7o{XnT;5Qiw~U-`P|NLkB^fG5NpPp{s6uR~H~ zp99T7aMV-~rx8MIaFm_`Vk7ei0u&TVK4A`LB2 z>lq*qsx7lqfHD%KUzNCQR_>Qr=NZ#F2#A#=jrmnXmHT-2J>53FI@*sl1ulBRnF;s_ z2Fui1Ge6sSQ<7KVhCbb358zZASMBQqdmyG|Cw?{&idNKM(Fm&DyURE<-os>tvw??D z5O{>P`9Pi^rrOT?lo5$N+TPRrDFMyA}JnUdgu>o zn-l>pWE4FQbJZ5I!Fv}NtMZJ3w!7tNVhaIf#}=u%SGNM?o6(=2`6AxmTH&WvR{g%n zTQoC!g(DF!g|J!R*_Wq`dN@&`>{@2O1=v4M>8Fy94fo-p?%DV~ognWD{Srn- zt0x6KXalaGkY*%9XdczrP6zuERSUB>tMyYKI2fB5Jvfsi2H%di%nSFb`beG9>+7Y_ zPaz8G>oQv%qmH`nL3uzWs-5LO)D066xSE={|>ANM>AY+N&|G8`CX7WkPyrPmHdL;q}kIfPPP{au_jbNgX% z)5T?*j4pKQV~&E1eM4=NJg79`do3%H_T@--mMcr z1ji-_CN_1v`lL&F6^ezv{C6@X10^kz>cn7j_KFnTHant|WBBMhvK1@yZAUr`Rr4A6 z?ERp2NWTcJk~-Qv1pXixF*2F8ZH2pkihc^Ab7w*1l75+1_gYT71?p0mv5gu zjjd}@am^Hr!DHZ+r0tGw9fO*qengKV=n*O8D76awWC77;SB8@Ia4U^;`}kysN21uU zQG))UR5H=zOeUcd?nY!Ib&rs`l8CNxQX}OZif`gFUlDJZXfYynk-cww`aP`5p@=ww zFX5Vs!K^=f8Y2`^N!@W5S>Ap+3ph$6L_h~diQW(YK+Gi(u#v|U;ehEiJ3ZAVSJ*f+ zV`YDZ&Ntv24WV4@RlH|%+qNV^MG4DaYj}>NQ{BSA@1i(}AyjgmUox0Z!?mx+l4Pqe2Q20wsa) z5=V;O^~{6D*@HjE;Tb3yUO$3>jR5~4)fJ~u>XcmP`o+&AACaSLUskM~zYld(4vo{{ z_*ebCpt}dP-`KV`9Gks;et$lc<@;YdRE)5Y;@NN|PpKW?#1l*Ti*>Tf8ioa^#-ev? z{T;p4i-PWXHsx#!*IKUUzq?Ml5HKB$px^afax``g_qA=j8>pA}dOq=6Vfr;N5RsNC z^Wr$&lT+z;qnnyCZ}KCQ*94<-28M1wyuc!mVJMJ&crH9{Fi1rCF0-7GB(+tq{r>q; z{lrRmgorgb=mVTcn?W_2LEKv!!j`0-B5DiPf{XmVG}hjCiaXaq4`EdzM9I&vQm}7Y zKM0r!Om$x_!5ow)g@C)S|C_#tM0PFF%~Wx4c8dSO>a-g0#;_WBJxX4ge~{&fmP2jV z)ku{4j2?rTnE(y~LpsH4_}%6EWHmoo)X|}R$lg8LhIe953w0I2v3ZDm-C$?rBF%iq@dx(U-FmRwW?Z?fm$G>YZ0mLa(+RWY=mSi%(XNHo)mrBK!uqd@x^$ql@8(n**xvB` z{Y9}ue%D-8Tt|uSDTgH7K3WeMsB50ifD4CHO(GPlz&^qgBh+6TKMloiJc57+1@F)qXk&7Uh!@?p^9|@n*!jb8id7N2&>H4T3Op)9 zf~c|7b+y2rP{S2@Qo*+EX{-RN6~k(pjb&gPMp=?bsH`;Q*5An-S{#|9C&&@!CZYrp zEV;gq!N|2Hr4<8mt^~E=$=NO~`INomd0m-!e*0gnA%8>Gmkoo1TV9A_o6TY`<|;3y zYz!%2NMlLd+J{c064b{Q1dBeis^<}=2{hNvqH0vpG3b5!G6L`H7e%TRum?da)k~#~ z1=(UpxeLTGoe-;*QKp;CYAF-1zxFd}D~ng`18ECum~i zrB*9vNE0RcBIjR$y=%Sse2m~pYnK~&3SsRIN)QL3tX0EjpsNX~So%+s>=@GdfgW5! zg`-fZju|v+5}(pqsF~IPtQ<{s-4p~XDo<$wk2JL|Z zOs4mC7QRp{QIHaWn%Mw`5>{wVm8L=`MuqU#S!th_VP9W+V1L$Qu+SVdQ>a@=(DS`K z&mXIy;|4CV*(8=(kaKL0=MnsF2o&*{lM;hZUk|5v4|IyZtDF&MfF^_H z+RdJjs61zJ>=XL}<|aVa#r?G51m}j(Y>Ak=iU<&rEHZ9dqJqo34n0FNxE~bHt^1*4 z`HN02q2n$hhycYvZTSa2HPel(&OG_L9J7{j!v$Av^T4NtGWvHdG(RNNt@7Pvpo&_f zzZ8x2-(_IkJ>1>Ot0DrujlFeoVJJIV{P{_Qd3>F%^bA^HRy`6(G943sZVX+x0xbYtemjD!WjNFR%`9`Ht7I)1V^)ZgmkVPU@_QRN}&Cn<-`#?k9 zq{86t;DLn*lWH?3_ta`$oIq;=T+Ywx3mG8PdXiLbq}CN*@u1d5D5qZNJO$vu{mO2N zxrC5NDBi{>RJpa0(6otWsxS?ACOfh0O$qPU`5=6uk0hE`to@FVLbO)giIOe*Qp`86 zCNZI>%;!xc*eFI*%2(+<>VMDNshCk5eje$4%69gWFBVPo7%Q2_Vw3<#^jD3z-BIG{W`Ju`Ux1gxVYB)r?> z$Ip&VF^xJckSIfxmPFi)pg}zetDwXKr$BW*>OlMK6Q>OuH zG?v=94u8g7)l3s7h(DQ-cD~nIf{g?hW~HM0n4@9|N3k?ss%`Sbbh(Mw&7kUvVVy{f zO43CohWAG3!%e-ocq>X7jtNUB!k$}A4D*F+ZV*HhJ3!HxG&q>lC*icDxU#>qhgtq= zsNQG^1!JP7sS5sK^Q&!0fb!@Mq9`V$z9ZBUj*P~9Y5z%bTHAv>D^g+;_!z1B9&HpMBI%fNW{^}h2AaXp0z<1roy&JrqD4(n#Qag zAarLYR_f&KBe&=O&E0^Y5D=rm9y-yy^k(IxIioSusY%b7SydVueR$p#^%HsZoubgD z3ut7xjF82yDoa6F zp8bquwj%lLS4d}=8eypIJF@1WAZEeju7Yz&ahM?Fqy4)Y;Rn@}#G)QX z<3u&Js*XF`SsP7nEI#zfIQJ-E%mzENqhLIR#WSQZ8by62MlFXk`VYhJVUkdEr3x|W z+(t5r=0tOaCKn$?-5PKD-P_s0sfn80rLyK_rhD;R&O;&x7=7lF^B1b%C)Wg zd$pC)pZxpP3^F-(8=m1x$_QYnq7^7%ZV>Mt1}hY)WE`IgY@!sq`aGjAj`l!uCccn@ zp{tr0{2B+R>2|f>2nz*ft@K{D(bvC{>Xdctpv}{o3VI?Yo}nf zFmF&iWgQ`AHn54Q#W6~VlD?Q1u^Lbc82^ouNz&P=JT7f{bh~Pi5E`xtIo*Yw zq7QBMK`@5PFJ=5blGdiVxPb^nwkN+5sjnV}#HQM|4N6S_fvNbF*boSzNb#rz3^9%+ z3=Jk^ikd2FFn~V-haDSCMK^<@rnM$7|3OSb(GN<}q^E}5?SO>6oe<1aX1wI$`WkF= zV$Ia4`ntBW(lZ(cqrK)^M$zxP&eYJT+LDe=WOp1%8Vx+92a6T|acd5bAU6rs^rwmq z2dxUvC>ccsGu9mw)|NVc%qhYft76DIpt%3IYewpP=+K#2 zFa3+2S`n6m3~&!D{W0qfPyXsVd{@5<$Ss+n2jRd5glZ5j>1+I4Q8H6m{x4^&9)?*) z6$=NrofOAc|C5C#1O>Z_7}{@(`zXn0Uz)R+V)A{~;;!HCqD-$GD#qMytWw;yu4+@& zq*(c55p5rbgX zZ%lz(SmzcF`Iwz_G=dbTA{(M(RS`QO)6+L@Nf?S3=V)F&8`t;Vt2T#(lP7$X8GsIFuae2o+W~HH^uG(#Ac(0NrtL^z|HX?6k7jyHnQw5AjUG!ur zWc_$e!j;C4brLa43lNyHAyOf74PLVK=2ve=Bnl1DM^a2|G~Y&hcTF`{xge_s`;R)JG`Jtp z-{1R{94)i}>FjWNo}DRJ*%wzjWXIrpRO$B-LWmD}`FMw$k1Hl)YA0_iSje$`&_tWH z#NT6;h7@;7#r`hr<9o+f`~Q~j|LETb&b^Rk{N3rdQq|(M%P?IfyyY!Q1wv0#X4dlc zM-6f-V90EXFcRt>bz%vV`Iz%xPh8@)x4>w^$*1PwR|^F<1(q0^TowD25n zNUAf##><&Ge0Nv^;fDXj+`W~W`+NSu6^SzqQG zIX2N50}wAc2i!dRnztKapItHjM^B_|T1@KvYsgTf>=nH1*N%+9WSogU@Y4}v%*i|_ z3$W50sS5m(h;V+$54_$$<%Dr7YjtlJWI9Snq ziyCriUZEtZ{L9{NRm&$R`<4e11wu6idlv?W{I{rYr4B6O;J-igQhKoMHV8{DwO#WmWzb&EN$1}y@{buRA60I{wb0Nr^}hC3r{7v%7b&7M|Xy{ zx-uSonyr+4PB|^%L}Oz&`n6N>;P*R9Bmb*qAzzLv{#-ZCW}xWKZpN%oa;{+;V|c!5 z|HQQA-2CXxYt-<6-kn-#!{sw+aNhb7=p-4R0wf`&bE32f8>MyGoLi-3p&xD#`DPqz zn$EL%dUWJ<&AqAX9sb$ftNI{E|4$EEoE&rNHV$AY$l#;0FR}@kK^ntr`2@_$ZlFWN zh86X?f{FjpO7S9tjVbk-FlFEh7+728j0VteP3DT3j$lEusz!Hwddw{s_Ki+r}U_37?k6>3=|rljbe5`!_;iq zLl*ostA1+L&-}>!xs)-}P-3&tGHzB@gVlGwt6kPoasc)CcyQBkTybCbeN4zevnkCT z9wbemRo(sK#o+uKgJCkJ>0w_lUPK2$z|YJ~Ge>G$XfHDlOIC;c$}iJiby^UIeupw? zL}qG{AQ{~MN&YGtQ%WyXPzvUPpeD5(tb_U%rt^ z-8;0({Ue5pQv)!x9L1Me1TntT@Vx$O1DGT44V3gRy$%+DASLc&)?09`{Qop zVr|!&@@^SZWMg8NFuwehN$j=!*w{m|O6U5odCSSI&q3sTWqk)6x9w^%9g9e+rf~tP z3hpYh(t#X@K@>`h7$Gmk>y+FSCza?ng8pl=D$A_y!cDIRho-Sdf1+Jb8(>jXWgsqp zKFztcuF40ie*138$_y{BeD{+F+6*APnC53#Jh8ZX7PuB(k#~2Y2s^BLcBV&JbcqE9 zVcHQf{lF)4U6LL1>Xe>xOa@uWi(%R&qzPwaAFaeF8Sj2H%fi)4eU^JCP~s z!Tx(oAF@rg4WajyclyYr0Zwmbw#fYRLBUXy(g*E@ZDA70yB0aI1bDxw=DmTTDmg7B zI-}tB4zW&=-JCB^v=`NMO2yXj9$lGD&#(cJt^`dNPrqT6 zAam^I)Ct^mNyC&r@sD5}C7;gj?RBrU{+vzip)A&mLKxR4GW(Z1N4JuTyVmqjX$&*T zA1s)$vX8)_gCOF9hT!%0oPfl*|Fn(8UBZBzKDN6o(q`w`x?0fj&v`-|% zaTrIWbZnZed0$U1{o1A=smV?y$@c0QgF9&P%?b?44EM$Senp$@!}{uGcP21L**e-@is?=nAc> z>Gw5@P8khrN=e+;kJ@*>mK8}H19Wo5^vnNUxktx)xb&YTdg)tBIS3sP5Zof^Q}XQsO*U|H*|V?QwWoJ7(+h* zdf*{7)zW-0(U|!I`O2^$!XuYdE*ZOOE@B8thqAd`4Z;#wH2E`6=M|Gcl3}Oj2R)S)Vq)2Qy zc)!HoS@uG*Jrkk|-P>GSPH^NLuk)0O!D|9)yf*3?o}B{xPXRar@)7_BJLHiMf7bk~ zh_NK$H^2ik=Ex~|Ml{%t=-J^O7C3Y%{^f5|O^4Z17nVFbs%Z1rcm}`ooc1%?ijEHd zv?E)~3C)gsjBeYgj$1f4H~0AO{3avaJm5hCBn-CXP$$@A2q}344h;bzGF=$j(xDe; zr6M%54aYbLG{eC;MVw|j>4uU)UGo%^&;3SVBhQQrL^|dd*Pk!fZK-5^*F)Yb)L~*@ z`}Io46v%hE4ZK6Xao=C29Y_p;hp=odjBu8lpyju^UQD+-0t(^*)rb4$Z1+s)`Hj=# zc+!7S$6gz>J^b>z?Rbs6;-y?^3;=v;?2#)!m5s-kQJsfyurKNB^M2B*c_C_l^My0b zmq%k%|JS6G`7~1avby5}m_sr@fbsVjNE-ttk;;<)JrA{V>p9!*Hr1L8zj#n*#CE}BTV>^o zqD>Mrn);LU(w}uI)06ik@00?U=ZY?XHso?5_7#BzWH;zO^|Rm~GE#+o!$8DaX~9)Z{(;+T)s8P=Y9MtseI{9iK;=I#k4125DM?Y_b2bGI(* z0Azq4r)jl?mk^K3toPu8Vaz9)A0?iDarznQb!0zn)jP zW+j~fxwCz6E+3xR`J54@cMm}h$4bNSE^H;+QCBeS-j4=23dr%Hd>8}njYwvA_zUSt zMRYV1M5}BVZ`%LI(pASr^*!xnsbxWOX+*k2X{5WmQ%XueLQ+9kx};MOq`N@@36~bZ z0Hsqvq*=Pz`(D4l_x^wOvv=;yoS8Gvd7iY~@tvtn=2_n!6_=UGnhCZOJ@VXVJ`-xk z^Y5H$Mlkg|#V5DuvqqmhGyu#*QR3vw!xEUNETg0$)v0%|!`!oMBC4uZz1A9XcGF-` zs}8zH4TdLcxb|j_Pdt{oFJCO5V+t@0g<5!}f(5`9L<~!XEe*!@IFU!<5H%jXS@cVP zCP;5dlqc9zr9N~Z&Cxq?a-lS4F%#emL0twEBbSRoX8-*IILH9xR8Y?V;bBqN@s4X8 zl+vgK_=w&owKUC;bI@=xd1AE_x5z8N<8N_G!_N{Gi#wg)ZQscU+7=qVuD(CN zaCfSj8vVzq&q6eY8&=XC`&VV*r0}nsAK)wta;QgmqBntCSzt)klNatKsJJ`fLQJw| zQIVv>cE`+qHK2$t`}-0;Jtbp&u!f3)*yr3B6(}d>YgKdGEj`e7&6PsZInfA(z~gdA z0%q&oWiIEq+pb=~8{+r-+blw*4#(%gdP$%=2f5Bx-&sKJb zp2cxP0{^Dhnuz8|?&{40hr=u_C6VyG_o@z)$AL+Y>d;F&04AbSW)EqqxTL~3DK~*& z7S8v@N8MR7M~^-3z!K2@`;bfy)KE(=I)t$(iKMZVBi5J`TI^quy*i^5Ly zhu|CgTl72t5Jv2yPJk8#F5oJZFw|9!d=CEP;I~;O|FGDe%hOjwTfukZZ(<&$PKgVX z*%{JnaX;AU{IgBlR_?J3oWij`p{Fu{ts;akFlmq`PMP^HgrK2VJNz@)+`K8WLxhx$ zG2!@nC>LI-lAgmiZoTDHut%nmLM$)oo5+t(#0R%nAF+|eM~8|H%-fXaw1#W{I^|>c zCq{K1`A%q=0_bL0o9jeeS6Lh2R!uI@4RS#56|mlNaP>H75g`4P8n+ovIkji0w|1fluwK&X=;0fZ(Lb(;#A7D#o{{Am&P*vYd;+j^_!{Fi_sSO-GOFC%!xq&VoGNmabY z|NX<6m#tCmn#Qd+ol4HqyufcL+U?8+`44D-O922o8ulnqvjSP0rW5mp#N&|+`L_m7bKUSG+#I12OH51nrGz1Rx5PI0sHInC*}70-(z zopzH^n8d4D>_4MG$(W5Ds`O|6{n+dME2%QFwtq&z4?SGDXBr_Ub^un|5XW^je6KQ} ziqdta$v3=MF?k0}okHS7N8a8J3xU<;V_v&{@wMHasyJG=LOCCrU#m%d4yakFMgvFx zN}rRY`g<0c58uZ;9@A&l{20fn`>L4v1qHu6j(>PQJ-w?EK9(hq`I!D*L-vgrhiL!+ zRNTbl%>ozTS|H6lRRl|&D}n#j>$ESt#(Z)u3VOXq0#H_?c{v{D^YT3r{gskQm%2Ni z&)6R!fg@aTTI`{G&?tV~KbuBhzg%{NKbDIj`-F5!PoMN6(&8bB>-@U*cTFkX!2d)|D#-+et@@ zDF3YkU4vU2KoNm4tw(DxXycig=zN*c(t^Er@-%rf@0OXM7?-|HlUFzQ;w6poW|E0o z;a{}%r#2#A0F#LZm>PCKzJ57K7%3L@!QG}Cq3j1a#yK$4>R;Z<#wCo_L@%)tY4$W- zXFg;G<;~9p1qGoFlk0Rry>-j!9ilSX0T>f?nB`+ON(+9{HC<@rdjf@-g?q;ykxZ>( z(H{Nxy;_5PvSOd*T<6r$qY~U3fc@*~w}sT>SF(UYC6rp@FNI%UI%^ky5BI=(WA?1p zWvnFgH@TrLh*^0Tbcy-E+(yEEum30&5wX4d{ATz0xV>cl65={WX~7tJZM8td&A#Eq z&AQ9=(xlt}4=92R%wviHut4$zZYfJ)_Z)bz*Ny!<_7o9O4O)Y53bSjf{ay@S&3;;PEdx;y2a;rXR)WS$g_e;p>A{d@=l{$EbR;tSe=92JB&$(Zm7gV?ca- zh*|%@+Q^G3JA>gm#*Z!~E=2#GD-q%yS@6%kCX|>^cKYW%68H!GwzXaBJ-@*`5|h_{ zgu`cgrmgmVEp?Bu@@Iy)bE|)y{NZb%T<;&Z$Vp1Z&&|;cIF!zjndUhuu*%AW5l9Vd z;3$zUZb}JU`05voM#YR_@bjygR-+XmCAO&oNj^nu~sV1t1%Y zjEtQNCxQ=QHMqHq!Yg(TTJsurc^}hA7XPVKw3i4CVaI(U!#jFt?#J6HR@uY#;o(-4 zJV zwi)1eDSkWp!92lc|1OA<@6^)&aBRb~LTBRSd@lCk?T@d*Pq zqcgadr2P&qWBiO|_^zS4dn-8H@WLU3Ky_@UB6P*QaZ7LhMwN>>gaH1c`% z=0`s)vq;@sS=B$8O7<+~7eIYl3P8_)656|!1_0#k9$4WngRO$hV+bzVrxX z|N3)!)5XCm8%c{#w(;Pl5+`}7pE{?(wZop&B2Iht`RZJvxy147 zjB3cHTTu#IHuA~4=d3mLU;avdEv<}o{PeXun@>g8!BL*fBSCy5 z-RJu+p&j%uu;1ugW6xnz*kn@(;I644u0Jm~Cei&m&|oz2DL|m`f+xZNom9#~>*jx- zJP+gdctE*)_%3Sc@A=+|_t`owHvoK)Jsj$6%KMB0&tZU@(W~~@hqg>_NX4EuNJW|d zmLxIsFI@=Ow`0B$tdVtB1!sVEF^`1Uxy`Cfki$CXaz9QbQKsdIUp`e^h>YnaZdssi zU(?~SZAkv$I&uSR3-BMlBZqpxd~p&7ekoNd8BzS|S5s!sHf1Z86`ut3k9)(uW*gE`K(pCceLK*-xF7@xzBaJWieJrQ z1y!15#?oRd-`chUL9^hoF&6nrfaZ>dsK4MOuO5P6&8Yz|Cy0n){_}!c9&TOu@^saW}qG#kN*J9D3$#Bm2 z#4SmhEaa`iGH^)doT2|RG%b~&_l4lwL@9}q$-DE+wn+rs6-@2MtUe-UlUD`Z1Erf)9Q}Mb_I4;2V&4*dF%GS$3!FEeK$g$Ib!2YaI ziGJw0h#R6f>O7cicPo2%Dkcb^9au5bf$H?Lj^g8nLulGV|?*Ge+=f!t_ z#mb&~ViG6OA4zoS-Xk}Gc0})R9BVu&p2l#saF_VRK3A}GHk)LA`8oyH*1!?%Lk?%| z7LJd-1pbrNoB3k;C#V`^cR&*z<3dB-7^NEl>p1Z*`+s0bR<9wwYq>%~u*vQwKuz9lyc+ zW5j(F61Pm(IJnOKN6QO zIHPCZoB;}=y<0L-P~X$-QzAQ`y$u!WoQL*AJxk^1*n^&kAypA#f7X6=5=OkoyYfdD zl0s^~pN`Cq1#|#nw{5Z>LU+XzCw~E zRqQze$fZx})4+74#kHTB5p%6jhNt2g+JY)+JDl!fX-RS{fKSIIYTvp|GGOJ+ebMyz z_oOn_Z?9J6<_cO-8zDf-yFOIOqw%v#sF|xIL5z_(lcj_3gU$`gsBP?z%GIgrno`Y+ zlOC_!I~>Pml~WxoL+@e^FyF3mKnk#TAq7=%Sp`5Je-iWA7Z?Ehw1jOG>wWeQ0d%Ur z1DIjw`gzWt?;DPcHB^Q@*aGr+XvE|4o|o!Ckf#Bd=fXBupxdjg&%er=pg?~@)CvaV z1WWE@j==x(o@A`e|GZ~RqJM|X;d2`P8?eFc+L8n7J%MP%i;TN0$p$V?LL(wI-hv)Z znJAFxJjseg-~TD8P_cnR`@a(Ss zXiVZ+l-C~|R`&%APcf?FjsAK1LJ#HKQNwpImu_*kS2;D4zVKOv0Zb1J zN{aJ!n3XI2WQC&dYyi=xfuq&%ysJ4+n~kP+;WIuVr2ugo8;eKU?({{dXXN+hhNEr; zhhCT}bpj3{KYZsKGL`Mm zCC~MXLmGySAdo%?jv3Z4emK%h^CeXz^U+i8z7eIZUZ)g;P|FB|$RhU@JECN_aXA}9 ze?ZLh%x25T0ytb&VwIa00psB=&ob? z{y!s-LQ)SIXGZxX^dwp54qP^*@L%+TCyYmOI~2Q=+4)?7>QM!=LU!(MB0(4&`A4%2 zucXMQcuV&F?XbWoxssRt0mUp`RvI?f4-Q9}v;Z|ht#8a%H!_o=$&XKnd~-vF2TA;9 zE=MtxcZx?%Ar|k^A;rAp6WMRQUa-4(#|AyGC{tvbO@6i#na}lRVVWzo*UIt0)m6^q96B9Y zZz80-x01n!^W)qPD6AE}XF4mYx{F!1@`p#@e6n@xdtBh=`Mx9P({q}x*I&p<1^8ev zFUMQ1K@PPBikPS(z9$agKB=YS8Hv9LWNk3_9{^(wfajGY5~FxXe{jVlgAI21 z|D-ygB2O&Ucg1W~pJ_7Lacbbp1^bmVXv^L5J@h@vXx!`X`l8_^#U;!CfMmpt>=z3< zQ$MzD$Fj3R#uXd5rQhcE#323sd~2MMz&}k|VC%dMeReBrfZjxS#^KA_hBiH^EP3cv z`EWHR;pj5@xk%6SfC=T`^4KEBP^)sK6;8JeuubWS`Q#Y*;U2JjY6FzqPM=(N2HWgi z$xb}RNFh8U!gXh0REQ!USM{uRC|z^3NMGhL>vxl1Wj`y`I|zSQqKb>iF?;d!8R&)! z`A_;kNfwY5O*I+m|Gd@1G8Zd!C3a}k7GgACpX3wHl%qHV>lh(+W=mUmhWR$v_hkR| zKB=eaBoIps$`fLc|5p9?pszz79XdNzE8c??691fJ%2(oC6QYa0!~M^2uuv$zwS~a0 zxSSmJ{2u?Hf6M?_{FQFWon}4wbB5R~9wt9aH3~1G;_30re+Z7Wj4Z z13VEq2T!JM&wyW-1r3w3yt^7?4~%{$w$8Kj6c=r0GI&4Zulmxgzexhnm!7DFTz?w7 z>&$^EiJY$ML{j07mzzb07o;D5jrOj)>Z}J;J@=>BDlgKTOMh{l-p?41x-x6Mo483$ zpF^vdZ*ncQiTXaVIn(mhg{;qF-fHrdg6eJHJ2#*Pn7F%jg)%(D(9yhU5x#k&YH9KF zrR5Xhe9gZW!?h}1-x9cbRms&Ob4aHVj(!#&vUB&>99``ApOWn^vJHEU7sV=o$g^%w}tVGq<@A(B!{!yH^JtU zu$8Hx=eA?_g%#GB5jE9^5mW38Mu?J{S7uu7erw00_B1~Kd*|NA!HvMJfSOBuAmvI9 zO8S5U??q){=JucAJ(eI|zm+ZR_~haDoIbB0vSMx}30qS$ofJ&?OH($wP!fcb9H$9 zFm^JH!ZE*F$hPJ_b?eR;>sxo#CCLn+49QhGjJ|u0%?c}jrRV@z`)=WoL{bV*QWq=X zHY@^#v?ppMAwIc;MCOcS%&0ICUB9H$uX^gUC(hzMIq#CbpnrEIgT4YPxI@BC#bzYI zs#%Ra@X#(M8uq&&sGR1&>o&dCI5PjYC&jI`>GI`r&<352_b*qJbwHZUs(AiBdk?vK zLz@}djsa<}3F%Jg`tZ{#%Qqxr-CFJ`lf>V+q81&<$+>8eo~m6z-J%oX9Xi{PKQ@3z zII`aO(cojnA%eqGKU6^eCZfF9Mdha>m9>{I-iue4jiH*HRDBd@IH(4rxkA^|#ovwE z$#lmwT&jjM^A#S2N+>{bC~4!p#-|XbOR5!f`J`i+AVc77%+sWi)-0KsoNp3nJzQ4C z(AtqjGEwu{hp=>>Zx1BC(I+(=_vwpsO?6EnHw%>tz+Z_@&)-?B(GQeqSnr;M3d!t` z4Hxfpxl;~##utUHxgEZmE)AWf-n1d=X~|~SDyDZg>)Yd;nGpQ(@?WB-iVc_NH50;< zEL4c;QE)4GOSiI+iM-gcv-)XO|K6Gw-HiT=sZPuJf}v@VrN z`eTm)Ux)J-N=gMzreBZ&x+lQ!ZS2ID1fBEqtRaS)?XQa~IkU4;6IuelZrHg5o?VQ$ zBi`O?fSq%)9SJ`B++#ap*mTrUcNX%aXkU7E^`XijuSMky#SWa<5Bbk~aEatM?|~R6 z`bP0JNr-K~FO19HjF(NP7e8i~;h3_AxUf8dELo6?K3PxRuc0Q^Lb@Xiq2JCs#N9q< z=wC+Hb4T#_djxY*sRnw+@Cpe4lG{9YQ{R_^gmbfw-fe;U%GlEUupBn(udziVTJf&hTPA!q-gfvmT0NvaDCPvYnNn93K>7o95zL1LDs zs9qX#6gMUGFQM8Q%?50Enms-e!U|juOq3K=IPNTg2;I>2&3O|w@3}z-5|dyOPm$k|CuKdfcpRDe)bwex#)N|?|KDn^*g1LBwK0uL zTAgxk&)nOvs{HE{qG}uj?%kiHm7uRi2FOjWFaJ0-S{L~gFALoAaG5!B!r7YR?uRec zdA!;1tq&0R{85g$hj*>%3XfWBGa90Hlc2M_m}9I_aCLS7c{XhNFYIVT$+meP>#tKV zNJYgT*@gS#$F`X8mgi-e$X_-JMomQT@47jPJ);_^<%nJnx;5y5eyKVDfD|ODC|2A8Oq1;g2E5 zfe;s0?|Cxir_0Az+F=WLOytN_4k`bQ;%#RY$eMmyJuVForb|XP+{$7?_m_diTpq-X zhBB+t<-K=|l&2Jipj;w%hZH=jimA`qs&kdTgS&JVbgM4Pj3YW5#h*UAD zgBcEY?lZtt#9iEv$hzbEMU0{!QNp<%!ZY!F4biWAI=?1Hg*`6*X9O}x?>^a_Aqm%0 zi8YOJXFMYOT6wpM%4fEF3HRd?X!yVIJ{*iuFfHlU@_hPoZvHHAYDcG7iVSF*K$rI1 z%`}LB$QiTLFdtP7Ln~`5UfJXR4j~G!ijADG;w#%tvrd22F}gR~;w15NS$6`nY_pLz z$ek?Tv#CuEt?S-Nf~ZwajFcWGM5&Fmu9iO^AVqkH#`%`9lXAKBJiO044AD~NG`3&$ z-1b+DHF*8BDn4uxlbp+wqM%cF&0^zF?3FtK|643Ye4=v%rM`);7Q`+o;W*xE(LtHI zy_YuZb)GXi%R!diEV~^ovswn&fLj}cmJ=t{;U&vkP@H4r*bF3k0c)jLtTnP3LlS;l zDV7>-ss86MB|9VDuJ57y#1EbxG7l(H4s$d28W22SF6tM~DG^G5iMJ z5s_{A<5#)i`Tk@s^O3@cMV-g;I%alZU`CXSpRU+pIj%a^?wj9Gve=YO;jj74Z5bMd zQwhfP zTC1pz*2jcI3ojUx%U4Sej^espzl|cf?qGWadui=@QMUlsA!%y{?}ztKjd3Fpl;+YV zEVgBEVJIy2S=mMCN_)C8zu?=f{zZIu7Lm$-M*OGm_K12~(SEdv|C2GZ;SF4TLzOaoffOFeS_62`yedFIGBO;oVkNnU$npyG_EMhs0P zp1qWZk>Vn<=JX&3Jy}HUPnB|6!dBcWqs9EicP{un-srb)2YX#y195|2_Ab?`IeU>4)?GLWnptY=d)JlY}Bg zvSbHO>Pa~MoBYRGT^c>xMEA=g<4+C)e7AU#e1SN8kJa?pA)#^7PvhX&c!3-nbouvfLd6e zYjSMqtg}ePWB@mmnOt^J_Z+^8aHX#Zv7iury^9xCJ zzGjrx73_vH#BH@$+Vw{TL2N+lk=xUaRtOEJOa>my{NBjRTrIGM`3F%B`@=Z{syfU_ z_QQ{C`~C4FHLbKB5XtvJJ@@#Xi9H?&m*$f| zfr6qjF%*NeNLA~rQGLu!5e*sp%a1?2<2&6d4el)Ji?pr5M|WFkS5+fd8Z0L_X)T^n zzmf<6EBz%hL#!;Ni}r$z);tL&8=geZ!?pUi_mI!{E!Xv&m;a3SiWHrva;@0zxB zFBEM!X{F)T*o2Sq;o7^|oar6u6(On};1C!b$lmH{SQiQ^;{{XTbGQ&QcjUgl%h8;n zEz2A>X->^PUo+DPPz-j|*BKqbT?v#_6km-91&Rj0KJNBoX?=@VjipH#%x9(l=->^u zn#16oU@Ou2=~()-xt9+*t%U_&k`r?`l}T1z(>UMKQb3nhn*aZXW)ad}Bb z5E9t^6~$-BHzVTLkvomA!HT3EM#Xl&>pXUa5E-Ch@JR1cZT9?{Ng9OfjA=oZHrKcU zr}Xo_;F$UCBzQ-Zq{(+A=3}jf^_<(!;kGO3MG3}cVx7QFmE(vHME4H)VVqsg-2hMO267&0L+Et;|jeWlzV! zWtdO&vvXa;Z6r39k>@7L)Z94KEI2oRDmO&K^3ppHRg-Es{iHhA$CV6G`q9Xx9Kx1S z<_Z(oVdN25ntR0`nRlAAjSl7@s~dkopdv-vJ{NayZD$wx=bsS}klr0mv+=+8E2SbN z8f_gTVS1BhTBSN+SOm4OWA+qTiCLrIcN>#B&#$=M-cg+Wv{; zeuOn(^=vjv-bg1guHtIs_Gel+_n*-+b1n+gt{8ox5ou*-)Y+!vgaGu%Rw!}XPi$?) z#>TAXzbN=ZX+)^qCWX&o%C`~Ku9T@K4i}79nfI<i~AA4?T(O72yRy?DPEIL-W8EB@&NB=kU#NQ&pJ zr@}n~$w0VdmE5XEi!c&IwEmz9%{Ihd*>y4Tnav{auqs z(4b&Ou7gLbPvhjT{g%ger_oQ!u0y76(ux9{kppJ1T$>mMua!h7$gJp4E zFuN-~72PUgB;HehRO>hm=62=N{mVEKY=xY@20xA>6e~;QVMb?s+*o#HZb{Bh zcg_qE9*SNe`da))(ry#a<=#%P2F}xJ@0m_bKhUv2T@!MR*vwC%feCvB<#i~H;PlH2 zw>#_+a9U&LifpRmRzs6Bm3Bsp_Z6r?Qdyxs{J%cbtzgW8-a{FBc)(>!fhXB6*H71I z_g4k>BI>ycTgAb8f*V$3qHVW1dY6N?iE^AQE6WvTWPhak6z}4I}ekS#vcLKGwV_Z(B{Sbm>qxWILNUSLP zEKjYBI*W$%GpT>H15{DL=TYI(p=i;YMc2bq^5P$dlScRXNQ<}1T+^9{VubDQRTvS~ z+&ii&^qI4(y+UG&!VU;Wi>S0hVbi%?%yO_F3feM-2wp*~RR^mUsR*Ho^JExZUfM9{ zm4ifggPA?@HeRf3bKjm^y!t^D9rL|?OPC{^Evfd;5U#_2H4IT7G4mt^_x%(_Hl9Am za5I>m-D53jjujFbp582i-;_}@RVI$kWyG281Z>!P5}S5{p%Tf)dPY9yCKJtcD96NG z$(J++r{&d~AG8R;^QB5$oai9+Yn=#6$7f0k5_A=s)=x{AOJ5T3DSDc+_+#4MR=OEJ z4$u1jb!@2Yu6{wlt9#?)O+rJII?FDCL@zaSKy0cATzUOrUhu%nrS>ADu@SWj^1ls{ z0eWA4lK#}b8oFJ3dAp_3B-(YAn;?T{8(2O-;t|)7Rr{zw)@@pwrmO=A+zw%_GuP;c zH>TP}ik!}TO!4~@wt5u%Tg5N!(rTs*O^n@C;xM)_`2`6A>g0KDEuCr z6k}HEsSa1Ex(bZ#jo`I5j@ zM;32bO4PsHvw|B}vz0|likok0G1|T6@qUXp&W!d+j!S<~z(be0iEn=EBxh{)QC)p< zeBM70`+Q~4eG~w!L(5`mvE0fY2s0s+d={LQF~vyky{RYH?FLMH3?b))`kw{gSH9`c z=sj7z=W0ZJwtV6Bw7$Y6Dc=Iy4u1-S7EKI?vWnr8E-vB+(y50&kFSsVV1Wp%W0r5L z8gI9RSxwGtV1GX99`lL~KP%*UYlxYHRV*|-9HTI%(;Q}xpI!przuya+t=TNfEN|5D zTAqR|sabGex*ly-go_e1eQ`dlwXwKoi2IzO8*&-I2OuBX`D`?-l(*3Eg>C6 z0&^I&_*$r=PnyVgl3l9uls{bUCJO2{TqanpteovrL%fxA!K^r4&x`H*EB8yPlDIAd z8jN5mJpL0nn_+pQh~{sEiM)fEdD}V_53Sj~Ig7eJ z0dlfE&X6{a4~%pCll^M1WtUGmAT0{i-zc7pl#gZ1`lSfgp%<#@qh!WEB);Q=BvQEx zu_(il&t>z8jNO*%&I|)E+$i*Q(jN(TA1@tC68oYE zvcx>JphQOgQwa<6 zo9svv+@BsN=4G0zj^}*PEa*dP8>Q!t7r}KQ5R>vX+~#Y>)OdsAA~xN5k%bDu z{J4<#?(MBa2wTw*CBi)NA`FU4y~Xb0ubV*x`|0}B+sWf6PxpMVf|i9%T4t-3@a&ej z`VNfIeCVE0qlwn~ipt42js)FR&bVFm^p;@ziq&_qWPNs6S}NRT(#txI>#wm~dnWr^ zW=6&#*}2TPYgOBqTrt7V?2JR4O=@(I1yTRoA;a1D7wn=bYGooN{@Shb!qj5Sv}p9g z2uOFn-Vh99A+HemGV`!p`)<%;;dIc zx|nH<=bFpYi%FkSuGzGD^Im-NSHTd0(k4<>&5N;}Q)GDeJ^+*z0JmIU(EJXDR$rf1 z{*Dw@U@7VRp>*9-H%F*9>SgwR;|*GVyQZcwJj>5T2Yre(X!p!)chQwJeD5CEioV+Q zUj{HZ8Y#+Ik;D|27CMT!J`nhD7LG4&=A`P$mO#l|-UkuYv+{O6{@CjiXLtBeg~?-4 zAA7*6!K@{je{wIR4Alkzxx8gKrW*g{D{z#A#XK#rg@DN`-A|P2i-J9lF{owJ#iAsw zd!L#46^{Mol3p>ETa1ZlwJyrgNjz4oY>aNo__4yZ^)sgakzFEaIFGTIyJ66^*VFCR z$v?KElzijhlmb{d<-zggY;9A;@!fw6 zqQ5YZ;3@KA|GmsQ`^jQ|_2GL{=Dl|-x34O)CZV0<+>>(jAU+WQqDCQoIHHyYopA%< zR0DP{5IHwWkM8v> zG3>-V&WkQ%=CCE@%go#2fVQ#eKd1Q@cKEScoH)3Z#)zB`v46DRGrsny@9Z8p*ZE*!Y% zsa6ES8rySy;6rX$eN7l?z?0nF|HSIZAy9mJaF$PVAzwl-W%ri^|F?*}YM0##UP`_2 z=eUF<>xlki*9Y_aNtxbU z9?nwe7&(De)+kp`Qw1VsRkHukpj?NpF-q2kxLso*{O-?FJn!cjKugK&DdyzfR;}09 zW`zy1_Ve^4>rrFyb`sRhmxuD7_dpVQubGY0IS{0Bcyzt?>^%7Gng)05n0vP4K*Bzn z-&CyB{QZ{nm1^uNktwl5sO7474Rw~xc}?YRvez#{&tCnZ=_Pv>|G;$7bQ?I115T}x z(dNHYox%H3r3;J9+{t#CUeuvIHtnPX8DbX;Q9F^p%rguttHhr>Ukil`(Rj;+U-#?i zj^Cc3j8>0%YKE$PM?z(xSSc(NGX{*NU%y)hz~^%r3y)0&?S*Rb*WyqXHeV#Yna52o z$IZZaO1^RFG?DyUu)?w%s5&)cm;*;&{@k7n!Yz*PU`*-Qm^?eJZY~uXhtRERb zbD;e*tCFL-jiLPmLSxm#_7F zKgjN#Z=k@domk-zqbyo7rT3oHWpH*D#m5GkJj1Nz;kgvgvnAo;LKKiwYTCMDnq)_p z?DAY2&m$)5e=Wi>S=`OqlxTt%GHqc4rM_oiR9P-KZ*E z^IMw=u8rr-r@d=I_nX;RAon$9x#Q6?5Q3TjfaL`u(sNQOs7;D;<@<*6gn*V-nHFZ{XV?~AHUO|z*LkbkXNkcnH|OSz)cT6xAIEj*E>3S??m0A8}4|d^Z-IW>=ZL&TtLfEUSV?{TKb8K>i zR9NdEPo@_R4Wv(se{pMtQcF2De$}=w5;pu%kElqm=bD$S%HM{Dd(dD9W$BbB`lN z>FeXgt6nnXQ3G&cH_CojT2_(*xDs;)P#DuqVfuRyvLez%Vc3xVX>Q0j8M<`2F~`*> z1**I@MD`&RB`}BhU-2kPEQ7D=7dej>A8m%%YI7j3T6Qq}GLwE7G;j@UUC9*?OIByQ zW(q9&q8;4@TEqjKois?uqvECwz9Jw!{Yjaec1l#6ON$K0K{osXcY)c0oqc|p9qJuW zHV@bmDP1v8Wq3yAFG=fU8I~a@$lN=b&BB-0&Z>Q`-nABvMy&n*>83D;gN)Fy;Tn3$ z!SUi>zM>87J)p35*^*n3#*yg#FJIaH^SB}`BA&tUc-U}>8ya*CfP0xTNeQmWj%lM^ zb$-8PnUvEwPwKg9$X)f4cz4Ly|ApE#Gj{-7mu>?DaBBE!@mE~#oIVu4+YiQF1pwQE z@L~lNM!q<-7XB=MwIDcNUUEk5?yKL&xcZsyP7Q*4g=T~K^)&-&A8Uk#pXS-=)X908 zYlA2FW>Yk$j|<1NJF9BtjH91wk@+e5XnnFGi(s%|16e+Xr(|vLEe@3_y z+k1;JQ$L`ORan33w{;B1_cFHO%owvhrr`;Tgu^n`$9TP%EAT1gsXyM=-1T|NbzD`7 z_2FpAcg>U;yqwtp=<}H|l`0V@Wd3Ae`5oVe7SXORufP9l!pgj=2fccs0KZ>U3^K|kbr&^FG?*cu#s!N}RP`QkAC zx{)W%T8m$};vn}8x=edlhcnY$L)OVY+~wQd1yn%rIVOWDe75^t0p^D(Cb^pNzbzj` zt|5$G)6n+Fgj;F|I6aAhXu4OF+1Z|v)SjHh^*|9Os#4(^!g1MJtDQc z?PL3)2gT33$SL^MjmlD>v1~H@PwGe8tsCZdX@~b_f$dx1B(0v3{`vb9QF^HA=dkMt zvV~b%uiR*Z5FR{wiO&Kd0NcB2+cS{FRM+NXA64uk| zu58!4T%^V%`ken-VK3D}RpSwkOIO|#0UzG@GeoS8@Dq3;qua6UAt!^+Dwv55d;nV} z>QJJ+s3JN2@-jia_Y|f2w|Bw<3~zm&2|%I7c<)UX(A$RH_k9vO$hy@?$5K&08Xgu3 zieJkDn3jT5V;PA0J&M)PGgvvoRcxH0Z$^Rv7tW)ZV z*8~Vs$?*6>yVy_yN_(HO$n)nkybn(f;zKB@z7ReCaz-OX_Z;ufALHG&O5hb(>s`v; zY(+eo&ieF)r#=IrLOE0bkD7^+6ZY60`_gNbEf)~WdcT3~uPu{bbJdB&h2Zg&gSFuf z1`X~gS3iJ}$kYU?Uy1MEQa&VLq45x7WKiNIH@9O7mwgiln7hw^RKa|R<=oZd-PD}F zIi0?ADBHi}J_5rDpooS2Qhi@}d<}d*x_#TmEjSXUG7(oiv#VKbl(0jp6{|zC#xJFd z9?{;bpZm2QtpFM1@H`l;@jmF{1PVZs3RzydkyEf5;@1Lx_Xh)8Yumw$@(|TG-cg~0 zY58|@;Z+iRv&uAoqIVxUx~Tk?7p*9Mm%v(P7nmA-)H?mQjR!~KC-h&~(Lln^5k@t% z8vL?Q_!n6sV*J}j0p$!@Ubh_EVAzqa%xLt#MS%xfn8xW@fC~bXQ&x%-)LDrmaby@xg`F#er@1z z`YwL+?~nZVNL5qHS>C(7EQ8*kOo^X}d%{W_^Pr~S3RM$)jof$orK}+H&s^YRCWi*v zYGDMv<-9zRTiLi45DT$E`ZGT3U*;WRq26VWe95844g%Qbxl2!rWi@2a&jIlJj{k2l zH}W8C8KBysWFr$U4J|GjSBAJ`{UocvYnk2_f1Sw`ai{uhtOC5B_!$LC z&%lUH_I#mg9FyDrlcn9`X?8^~&76+JpB3Xe+WGuGzSLcdk^`KZ$nQM%Boj5{Cac8)#jRA4FDQE$Fu+Yl&9{fhIzp7>4T8kv_uFpHC}Nk z`U|~MEC_{V*NvVnla&gcL448@-FB12R$1Q*!Yb*URjr#9PVf;!25j{MO*CkCL`X7l z7F_7!iBrC)2aAUnjwr;CG1Up+c|MF)oq%^}q$Vv$78#VgkLxh1%=prK#3t($D1*@k ztV&yUlA*vU*5v6VM3^3bU+G`&!G?qrQcP-+JmHs7zRI*?0ms;mdS9i~<<8=^qhb=8 zJ#@~E6^)HOWx1}3D(NBXKF=~3CrCnV6ioGW1Haz}Dnuh$j$7CKwH8M$;nBxgmk(xb zN-*EimwdN9a>9JgfcIm)rxRGyd{10NhkyRyG1N4O_U93;nlT9*ZEkwC`HQj%hwqSk zE)h&hJHS{EP&4bdg~Dh8URa?ih;ifU+xztKGBs&7Y&^g9&axbSyUz9!c{@t-+`7YG zTomUoQes0Qov)ybta8Fv-2f=720pi(+kI6WNzr{1W})81&AVds{rmBzQQZkv&@ZhI z-sZl_v0wz`8wJpzQG9wIp6@SrOf6Q?l%x1#S{eWVEzqGR7p7u>%L6}*4mXD|4puV6 ztKT2W0PjMQ*b%(qM*Z_1(gdvE^uMrq5lm9yuU)t!NMf|?ba?r_Hr zx$M<~L6%Tgk#CK49s*bfF(CiOHEM_L*+WT*L_%{wY*9snx`VW+)>hCZnFOwdH!Pm%i+^F8`K6Ad2U> zmqCSn3m`l$d#sF#k{=h%!#;I0SP^KPXrfJC)E5U9G7? zsqW%$uZUfx4F;{`5>`hw73xyab@G=+V*1KTHl19Yw%vsO-KIZ-24L$#vbPIdB3)V4 zj><+$Y%lxXhmQQsr7uBdh5teb1O{#L8I4~_#E9?Td;JTcfI%&8W}UukT(_fJEN1R^ zN1$s))p=NCO7RszIRD8&Znc=sC?AOCK&L_tBH4&{Rv>ZDTy!ZlTbKKM`L--ON22v=uDwHKyF#FFI`nmwPxOq+uzqZ>1)D{S$E^dNL`=~>dkxj6c!05w+1qS9;2aT20l`%Ka|`Pk>G8+n^v)vCR>wZ zWf*-UdT3jF(x@==XNiC4AxY@pg6gAkkn)L#pLjWjg<;az>S$zp!LD&RKS$?pOWk0M z`Tv{@i=s>wqX>sq{cYu$W_5C~WGrV-Dwc(@2S%VK^Te~fs$k)5=QqkjspsqsNK`v| zq^+UxHu8zUUH+9z)8ym{uSNWsHr-ML$N}3S3|Vs)f)mzHws~ZzN%OgXuqe~bvQ79) z9lq3{Y^_oz5trcWlu7)_KcJx^=)d%o5m?(TDr98=2#=GxdF_BaQ;!e zBiW8#9Sc6m>OLB@(=V^Ta`*SA_wiqO?`t2Q4O)%(;=lU6UT6sV2~^t@*fwuA^y(wNG1eV~hV>%y>2rV=A?e1dBFSGQr>^oOE_usXnZ(%` zOM^7Y?zuuh0Q+22YKio~FJ>#-ATyL4ry&kOM&$AIZ}LMUZTZwv2!EINh(~4+CUaFH z99=aGRvsv0!NE|e5RgO`^O)kgTP&_tkMo(Vn>xMa{(~_@cnfjYlJ&TPZZN0iM-a6z zn1qH!1JamlpEmRj{1-y#38DKCgLh1%P>KEfDBDOC%xol?ZjTZoZTSEK>4ke4=}b?gz8Pd=JH}diPQPPamQ#$C*C2aL8~(>`RBJjJDbMO!cHH~ ziUb!84kiNuY&HOTLRN?A%}E!=+}Jo&sLa>v77(x)VCP0@T^ks0h&x%3A#x}9SH_U+ zv(;Ve{pv?ux!pX0BLC|Oxu2+1XdyvMWLTN(5d{SvtCP%0>*Kxoswq%MyzBLk<=%t~E zqF{0P_Zw(S^G#!GmB}E-)OtS8R9a=0lm38$fQ7pRp#0S>e)sbAva#O@-@~E6*vToT zo9kbPkhSg%pJA4hd}}qbpH@Qvgeojd1(?j4y&noCVKKSz;iA*Rz^ldyl4!d}!dz1`Y6*aD@|v>)gq{UD|2;%=Te~ zlYEuv!30HHr8_YS$Bk5Z_%{P)YO)G(f>?<$7?;!3;p;;nrjqX>2JTanlaazF@%f8= z1*ozwvwi;|0SmW(icdeDmy20~75kG^p%*5sUr&Qi1HK309FLBvPx$CeCoRpwF8^Wt z(RJ?YGc-An;tLMz^fq{kBCknv2l6qtex>v@;q84)J#W@~HPdOG>ngOkQ`wPv77pd_-4 z*;YQ%=|3Kc=s%^@e@h@wC{aY^ZO^WNY4gJD45|sez~xj;$kAcXPl};Md-6>q7mFln zFc-Q)O2Dt%NFi9Af45MsciMa4oK`=SPsj3Sr~G;Gr@LUOIr+k2VpDc3m5)3WeAfY>2jK7bF^jHZ#;Dmd+R|7o^}_^ShpYGz z>#t$`_|CV7GC@gLkFM~*Bu_>I{Nj7KIPvI6Ch+9w2aUU=T?oqrE%Zb5eoFYMo<$s) z+spj)*S{BAgCppMV>czpqB_|b#AjLs>4WoXJ zeY!Z(74Kgq4LT$<(mmsXiZKS>N>18FtGH=tbaTTl6S&r|u@Y|DZR^VF3O^$5OfQ%E z7K#C70#2M%fAz-q2j7WsRgzj4m4;9)j-h_3Rb>TtZ}U-E3cv-*kh`ld3 zzMB6*2f^6>#$D+eADS0`uhtvW?uzm-+VKxdHpikrELKS z@oN3AAS4DrYc#92J3`fxyK#@UJC2x=gE|_LYJE3E9_)kIZ$I!i+zO$&#}*9xg~lS?0ha7oe&uk{97tT{x9hriP76Z4seoW%Bd`bT%EZuILes^k%<(S*+^=gYd-dM@ z{Eq5XI^y&x121Ri1Hl6cqUZ^t%?unZA=#LP)6Q%=+0yFYgbWR^Lg@xqAN1DE#xHDOxI zf)^~o49&V^3jHU_P-gYug`}rmXQBJ<55c?>wdu~4W{7~v($Q1r)b5J#dVcvO`QJzWfI(8sZfQ?Vw*dDe`F*;W6`gucEZ)}k!_DN##7L^L6Zh?2&9L78lW zFOl+pAp{3qQGA_^B%zT-r7E+vcfw5X_eS1n5^p|?O>*8A$siEX8qS#j?aqRO_I=IeQy%KPKA$(eYcsWu}fd5 z2rS5SsjH^Kk$HZ4)7H-2cJp}|;%VXYR5SXIr2sbiUm(At@}Zm~m_lFJWB##i9Or^$ ze)m7&E-r2u8ASgr2MwWGROPvCB=Qj)H8hxKfP0*Z*o5LE)*p0i1}&rEBe>SVDkL-F zGtY3RYR4c0igstQmZcp*4Pa+Ehc~XZms~1H!}IJM<}i%yKl5D)EqSRuFKt&9N$7-S z(C4BUYP*`Wg?&#%wB@NwP-in_BqKPmxWkPR$bW-3kt>)i=dCk)qa|7|V&f(6Ej%4H z;WLfDq(zI?5QHo2Nvqe(U1-9@;$N(Ex)|~cE;O8j67jNGnG)4fLrgZcgT^}LEGX;eM?w7sAl&Xa}gO85F$p_4ZQJ>>pI-du%y z3xAiuZF`kU1zR`bNf)&DmENuk`8-$e#^q4_cUOsqNpH9q&gn7+JwM!V_ACfZ+{fhP z{^v|Z3?e$de=&e)J-$}{40GyQb#(z=Tt z#{V$%35)Wki%}L!bS||R6fH!iy17W$sp#VWCOvo0_jBmi7!K)kKSzp`8ePpOI$3G> z6X>5JK~C(#GN&j0jDE{4XEJ(6#(KUagv@oUDV{7xyH-3$fyX&C`9$EL*z}yOu3rP3 zzFtHs#ostPwQ!Q}%=P3ND#&aqSX5?iS^lu&BrcWav0LP-qSd|oynG|4&g!CdGyl|* zw4?9l8}k#Y=(j}|)B274D>sjmi6+tqssvG6>NQ%HTDz#N(8VMZm)T+nD)jp0G6x}xpukZuco!uwNC6opsxnEXbZ|tkwQ~CR0u+Mkrdt{zMp7A%4BqA6MU7>ks#SqQ@i*J5fRXEH3&bt%s;V|$^R*sxb_dHf4JppE=;JwbAa_d-)fkDf2 zSGLP#9e`R1;f#K@>B(D0B3VNG{rboq+v=2M7Hnkqqu#T#0~-68k*uR>%deXz=pm=X z?UO{;o_zWJ5jL*Rd8St2&+)}1uTYTg*WNXJISl?I74A?SY&l62PKvYS_hZ_0k;zR{ z&a#F?Rk4;d^cB~$bH8p_X^n+fhFikq zSLDhGlC_)YFhB+J8`r3bfa#qJbU;FD?#bQZSUqF~F5=~(f0RREdZJ>*;XQn0}mPI2yG6iuy za&=WXbyK6?T>g4}nyiFo{ob6RopSA`;pdrE%dRa32)zIzH zTuFZra`ATh{dJ)^USbeN10^!sy8xbz#P(f9I%6?UtW za(1g^y@*2u>Hu&Tb$gIF6JabQnZj5eyvcCQr^K}4K`a*Ga$nIh7~^G@j&g7y*s_`< zy3HVoHg7GaXI`75Q7A z!qlX7Uy=z<96zh${rahf^ob#e5$H@S^w!4VxVDP%@vD)M%SZpaHo*8}tp2uzRj^Z_ z{vUdX(2&{5B z?ST+CujfM^<-n}FS17jFaWc43YHxoK>WyflZUwZ1!*gDvS@5-H?b4*D;SyC?T6e2! zg$=dQy`W(N#NhYu%5-&~w*#E{C^j)IRKI{K5yquCPoJM@V&TnT`>TpldssItDOIWIg!1S@Rt{tA-s3oVPEb{(camH%D6Sz3XHt=0SoG?i|VHB|ErfA2(uAxe^A zpJSPgws{%z-K9A?Mrc(y_?QXpd9CHgTaV1RPujP$)z~}oC!|mhc!Qb{Oc57Voa2Gg z1CRc5yDLL4LjmAsmmfFs3 zWCqNnb=(L$zHQ9di{b_?yZ|=jl?^(YKa0mX9u+^YPcnBOS*m=T_SU`qsP{40|E&Kl zZsCwp^=FRYPjNyR00(KYEg&@Yg5N@$u$4iSg^iRi6aDj5;_Q{4(Njq%DkN?2TrMQ-WXWFng&D zxc|z)#e$^AoZ$eI#FZZDPyy)_)P)(|Y!r0C)v9M@TUVRy-fu#%dgv#+{PhuzNL`q# zpS}HG z{%{i0xw7f?`_mrQ)3MTvSbcPR;{Vkq%IZ3(y)iw7L+0rj#?)yz8H+11QzPln*t<)1 ze;yCF+k&N(^*!LHm=~^dtW)6)xZQ8T=*F zbzG~wS}#!=s+||d^`d*)bLW*Ri#6{OS`psjSPvWlsYt_F1rXHYJx6>{H^h?@Jld|w zYf^YdrkKQ!P2XYgs*pX-Sy!A<5_G?D&#A98r^WNmxbj&+#y zzmRcu=-r$kE)iS9uFS9;S{P1&u!wRF3lG0)gZr~2|5#<6q75kM?Q*v3*MByD|0LW4 zI8O}654hh;*yo1ZhB+#~S5|X(7=_*994BVe#zczQ+Kbl;%-@qferK~df#h;me@1+A zFWex1McZMd2yh_B;iNknP0jWpl{oVvyBvGZ1%{_ z)U_sbA~#;k^Osw`0+upIAVwQdQK}uC(axfHDiQhOdM)_``gmzV=T|Pi7o;s$uSLc= zGxFpNkDA#Zw)_9cNfCGzx{Eajb8OUoaz?Rkj1Jtw5OCf;jLrd?@Ku=1!3 z+u+0$$hN6`@=CCl%i{Y49i?SG)40#uc+5JKxcocJCU|2A)~Dwf9p1UkD^=EF_SvN>0;c+ZFKe+ND*aCx{4X zqIL>pcPS8HTFh+q^v_i|m0=B>)t;bVG}vb9GR?tq*HhKz{aLxo?bwsc^a;C$5=thc zJBge4#ih}QK4`-xb$%i1fcs+i2K^$Nefaw_i%Lg{3xEP(5Ld?lO$Oc9ZfE1u{cipo zPwY{rb0>I9D=|0Y^t=>q%oPR-6W+@~lJ{{U=-MG<38(t#7rN56pO31EBCC60QqPLi z#vejGA+?(0+wVT=`&|duP5YQ_Y;$|~J=X6F6y9p$%yejHQYol`vC-&W4@RoO5lgBS zX|IHfplGI62LWk9!Bb?MOS8_r%XMhYTi;7~$$G%9G4BU6BF-j5G8`5=-2b760w6kI z_^P{u^eillr;^<9jz06YRIb;lzap$Y8qKdwDi=*Ib=$Z7@xy2Qv6FG{1o5pH*EMa;v8^1(r@Htp``%u+qk}05 z?G*q%QVo`2lk5l;`X?&|GSD3Y3w-tl@y2|sv<*$du{!&}of_$d-_hcdGao_+4^gLx zDw0cP|CmG>Hn831g>P>_mqa5LwAlZ?WmOc!X(qwSKQq?t_M$;k5sLSxym^p#y-Z9f zxyO|hj^kLYGfL~T$XzN}qsJbRyVhL~aPXONiY*s4heF0rFcLsXD{=;4nT6TddmP^|F+$5qv?U;Q#7782+-txqwEp=dK?ePt>XK86hM?K9kfy%7C|!S z^GD0zq9qnnL&HgPXRTQilKP$hFYcuu@r@$MCC&K_F2_a2TUT9*5_-fD*Dm+n#@+F^ zNoVQ>U$lD?Z;3@7x z?1D3sf#S@*yr~+)bm{KE$sE1RZ?kv0XWoTV14LKM&u8hnCgQkVptqvZn|13~*}4Zh z;}{_iC}=3GDl33va5R*7r@H=mb}d)Q4CA@}gm}8b9mRO2Tlx}%xiJjymrdAOAeL!} z)muxGyN5SjTwSLxn=G(lxaJL|HDvlv7XCVocfecQz2c%dB#-3=&<9eEENiXCBWC+< zQkJ|d{JDur3(1WFxjOI3U@qp2iM_2Q1*@pVs6sla81DmdD+VkWRtVeK`7#q1j7Ou{Rp6}#y$oF6`b6ur1O{ByO|n5P_GOf_ z?wm_60)E;N6Q=Xn#fv83PJY));-H0(yw^>jMNv!N1GjO$W)#Lyl6)X*F+L@~_8wEC z;6oAaEQ$eLMT(}Vocu{{3iBwb7}&5>5~QGSY0i35!0uh3Jcjk*S4&Op^#9QFhk9{# zN2pv{K2G0}F$@fjHCHb8tUt|mgWSX##beU3Q8}nJ1evKNKa3gt{Txi!NE*RM*z`&y z;g4X+tX5XqvYa4H+0BK{PPB{TP^-kUBFL-^=CK7m!AlroGr-Z zs6QCNO_8-T{ATCGjW~6d_l4sRiOXL#wECP?^D|}uYUz{{sCQ<=QNA`ar#@g9&!sydYLq3U3h4+#wfRb5FS$FC)Ca@BizkS$x zAFG`Ih5)vs^$jek9xhUb!M9TS-T%q({NgIp&>NL)ft#VVQ-P(=gs zE~lkN)ZSh0@(glOqnL<1D_CF^NnUOw3TWh4*>Y66^U2^$UO(wp_pO-Q==hn?;2~_P z_p5c72sy%cE_=`{EO&?JssDozx*&(Jp zp@u6O&;|xI^LsQPoMUMWu)X@p@SIK8RE`eHA{aV{rQGC}$zkp8!Ku%gKWko_b&xdH zo44Jw5En}RaHp8nEI^)p0t1Qf0%WinE%~$5M0I<-r1bw*ZLwmAwn*kW35a1*Vc2rE z)n4GKkGjhF`p~ntr_4k6#`eX_x_tu9f#J1MQj8Si;^B)lxZybBg$snrlN=uFb(~_%`8I6W;_A2B)gT5al|Gm0k7JvC%-`XxMQ0w+8Ub zt{CDOkFQ~_jc?7SP+RsGm=rbqwNH~uLni-hS^1N=@;zX%KR)`DRUBN@cvush2v9VXDO6GImZJB zO!#vJ4O~50f+P++n>DVPFoT}Fb|EP$=>3my!_go7W-%yf{A4I!=5k_^ZH-gJmCYYUq9_OQtWABWT5VC)#oNMqRA*@cge z3SRtGN;7hw?Zb$uxJ1X6^5l-d!?HD_qYBHf8jOE=N!zz>TJUz-0jKwSBh#Cgq|5DJ z<-Q##)TbML=;Y8a_|1&;e6FDO7-dO8BYk+G%9dlI>A?C@dAmCe!e+)GA)ia%UP6BD z`sv_Ee3BdA=1Rf!e!;-zhVVt{(iW0&X0m25Xi|w3H%U1Lh|9*X$1?-q@|y1pLBcrj z@ETXUxOK&Keo|QPt1jaU_xgsnT-c3@pJ|;>L|nDC_5Kks03fUHd3^#(XQ>@=K_^r? z%ymm?-0Vi+KAY?4D$a@z0B2A`L4*rWq9$k27wjq7_<5dFDZhV4%)}MC-`dllp;j?W zINHspirB8=M>>bYs`3-ZL=Oq}9vAP&iCF>2qU3sJX^dv-Ic0gpNajKcDa!h0_N`G& z{P>$wxdO}R87(ca98-{oXG-Cyyr=eNu9R(G?kivS-U9TN`eEGJufLk<7lJ6fIU zcJ+l4-{H`Rh)=|4TB0QZCTEtR$?B1)dtEjgJdZ^W*B%JOA?NysDa7)nqwQ}tYG!m7 zt-e~7JCxrMfd$ngTMj?UzO{O&9E|&zCg2e=wobX+$fX+MF9c@~{hfbO>stGT{7v)P z`CoNQ7|}IY{>0gnny9AznDXQBF`oR8eO?CF*?M8bzYxL)KzG!$f>@*}l8*N;ZS4%f zqR%xoq-<@@(%hSFao;R%R&dt11zd(6uo_EFU0=y9Y$T!Fp7Q)!y*MM2c!~UW3n;|7 z0x)yzMGU2^QCIQLE-fj9=~&tMcj!z~?U7{1@69Q=h_V)B|K^*%_hFSI68o#{dx6lP zs=Dv(b;Sh~Jd|bt_@vI1E!qHG9nM{017wAPY|V@#=Hlf2s z+RQW*%4u}tQu9>)MkEv`!sL#LnBzTLxt)QO`Z5l*HYU=MN}|2x;v(Nrvhzpk^>DL` z)Oe`m6^g-J4D)JvzO)HVdWK4L8C#xnjP+VSQG=3b zv2_@vKqDK_)!+6$eah{!kJmieda>{{0I(*Jy|s%aZ2sUt1%i$65B?boZ0Bd=1O?pe z%?~)(F8$4~I9701qpP8Y`a|ER8F8?Q*XPJYSfAw>*kT@b($+%Ns5d0zd_Y zk264es#anvqPGy*nmgVUx-{K(r$Mfr64ST=`tSD*5N$#hT)xp{ONKv4@iWp!XIq;p z*E@M#;-3li<15uk*F^l0=1+KXHMjrtVOH8gvXiltmyj5*SGxAkAZ%DHKe3hec781sU+Hj4vg~q9JSBq~$ZE^zfSC}fsllv~ ze};dGO#WEkn+2qjdeRM#zZO@3e%fzIrT1fJTOfSuEf9@Yu7>-{B~Y@}PBk#7u%!aV z{=ArI$l}~_S@pM&c=RznQW>ubnP?;|S!!sLVjawjR&?~58;nOWPG*{uCcpPWc>k}L)D5&7U0NIS>%iq4Cl zj7`*>al8+*H(u#LEFz;A(R^d|W8WE$!`!gqk%pdINh~Za0JcQc3CL{C!lKt4*9qo^ zNHF~%XtW}H34t)rn2?E#8(QB6+}_oj3ZqRWiE-HgrkrFWl+fr1^vK9UsBJEmsf|ED zbC#FPCsvH9s05qmTxZC}NuIG&e+n{d{?EMe2x@{XJUu1D11BU09HV2jwaa3Bpyyae zs+nXdm5qn{XAt+zAX*5+tEa?J6cCo5A9Zb>=j`59OdWMe;`AUsuA$+W*q7GLy`0-; z#e9q^Cd`~xI^G!{xJfhh$WBKJ2y9_7a9V7=5f~V{;VCsP>9k!Yr;eKXUfkZ%Y0UfS zNKS^hfm?r1FdcY@f@O!Xn$O1cWhS|(3X48&=aXVrv>}bk3MDdhVc#;%#ZDE`e6Xow z;c63K?aX-E^T1nT!dDG^VxOD|hPRJ)akc(F`e&S;-K8Pl^GHap`zdkML=^oG|$PEN?+D18GUWKS@@F{QqN#ZQN z&dC!ZjmuMs${9>y!;V(qh>6p~0S>f2$UZp+P;5o#!9cspz?z^jwk0QQVOKk=8EYWO zO&>+~_jXl&8XEuN+7%T+Yj%uIpD67&+k7JD?S#|7+}Jr0Z|lF;RQd3zfCUvenCeba z4?_wk1AoR{85_$c`Z%kFZt7{t0Pk@v{gb~3la(l)8IX{}*REIsqiwaNZG~(lgd%n0 zXmPN*%M=um`cB@Grpbu37sZo}n!y+jUg~Ok%!DN;2BhK_^)G0X5Zy)QovktK5NXpP zjBX|x)o%Cs=7frdIR5mBT2-chA%u!NrAM;jk_>w-gJza1Ip7@4=V#1{tLKe|btZJn zY~&1=r7j{FSgjl9Qj(T~R`0g`Rth3Mz8^!&5#e+7-YEBbM@Yy$heE_}LX=CnDbd2; zSz>H;_|OY0C(~`EhN0up8CDwSTx6+?CIwY1uITHiDXa`>MtdCMUJulhv{V^}sBcw1 zWb0%XT2pH#z6Uq!aW*8CAyfx4tbGA=^u08~1aS-8oLv^#pI)uLLR9hz1!T{9UXsqn zNPHs7t9ndhF3%O}k@}Uo9x`#b zWtog}Ldk`dRB=Oo3K3=h+LSCzn&NAA$Z*p0RxLoh4zcxkV@QOpkvMK|1H86Dh-fe4 zGDe5{Ek`!ZQeE&=Tu97wQ$4GvY4koqLeuj(BvJHf*X(9eBVw?9ar@ z)`EZO8(zAFF=&o?vqWf;Gq?79CLk>n5x$~pUZ@6?>_I+OaR`Lm-&9RfEMLB7 zk6sRNpI-v|1NCwneM<^z445575jUzXP1%MF-b`W+rqKI^g*B7=@xhR)#}AVwI4?vV zLfkvW4f)XJ>dKb_T0A6p zRa=FBs2=8IZ#QP#Rw2Jwi%fcXRC#&!gDLxGbKkU2(X-q`(pG%RpeI3+1dlSbh?{#w zu8?k=H~CEUKlEO0+Sd5|v<%8&x+t^#l4XFkKCdn%*Gq3YRylCZNZaODz^?d0X*1Sz z;Fn7K%nipH@*g!(fg+TSGsn!;Orfs!N;Zrr+k%w!ds0W++D8_i?@^_@wd+$7xgCT? zz({TIBw!d%Ctil)iK-hk=G$`Ema70X`>4nc!48z-+HJf{7(ZewkGR_U>wPG}?Eu^Cun#?K|zTxiBUj5zX9MR}TmUm_G=MQNt3_&40HxFAc zz6E%LC*Pu=%du*(rp8yTNOxxMeyp)ZAk7&co&7XWNK`ieDAFtx731)$yr{)tP|f3* zH$kafU1wA9V=33b_S=2|s&C_&!A`Vbsr|`G=ih6HwbcEb9JdJZHy6ZATqtz{2rW1_ z%YyW-ifgNLVdT|AEH3Pf3O_zA9{{}~x1?g@?5v~|1gSbnu!AUUD7>h-{O(zkAua~U zTayX~kcaXN#Jw=zImqx&`1c6N-pwSL-tjlm7%6$qM1Ces%%??R zp7K7$cY@;2GVfaFU=8JB>;uVK4MA1j_HglWQ(W9FJY z40RXVU%r(#BYVeoDrCoyk2t2`RHMNBWNQAB11XoPsyZXMcM=ZH_}#{Y9{_^u$v)Tm zU3JYDE)Pp>ey0wFk)Uz-H^c$_F70}H$Nkb33~w$U{%>n7y8isKZzMT$2^k`TA` z04F!G%6C*;%(z5ok|Rx;L~?}v#MpM33{Q7y1Q_XtcRI)I0tk7qzEU$4;0e6;jUn-) zw9y5OKBP6lffP?umuE78Xl<;8)GTpV^e>B^j*>)KwBt=CMf+8 z1aGTvZJ8K3jYJM9Om>#V9l6baCR~cfWv|tqq5-HEYaS7RE=7i*L{P;9Q$Zsm6>{DTClA3R${u~@tYe}kXFn20zTUdD7+8*oNflU_UP4VZt zxMzklhf!Z4SwBPOnxOzTbFKnd0_;9)wG9j!7QK zq(FyNwDBoA{)HVy4AB+w%shb{pH$erxa}bhX0?mlnUoW7j?I3A47<0tc&{@qjJ}@g zuUrwJSm*tXV~{$hcq`JZW}y4Y#wNL;nwt$Q(SbdMV-qTp53oBQ^wz3Y(Xc= zv&b9tQ8n^E!3Q23^qtn^_>iVc$}UdIc83mgMO`LAiVb#+&DC^Wki~qpNsd@Aoad3G zxzNPt$*R*JhCd`$F#a7un%k-!Kc1@lqJV$^b59`vq8F~PujynE>dZ4fjPo=0(U7)2 zmBnPMrD-^(E@vwSChA2-9c(XGYGoIpELC`@x+N!Mk`D)feQ^N15KCIC{?bV=O?G`q zKqrEK041DBfpJ&%jO|FQI!}%XgDr%RofWHNej={>vV!%yxvTcwr^1H_7oqh=m05t5 zUB*zc5S!EFNR%dKJm8kMBs6YIQ%3j6K-iYQ$$U+^tV%SxpsT}aoe5gz(Wv$1BhtsA zl87+vzcW)vPcJgIIhRwCa@nvz6k8=PObc!MvT84W46GBOpV$hYxEuiU;Zw1Zc(oS{ zHS8Z<1?(NITVQMck*MN+LcGNL4JH!HZ!FG=pM2)E@V)!pr$Adph^4nZKSCmoY`bQ`O=-=t6{o#_jx z2b0sF=3fZmfO7Ak^R0^kmmpEk<(* zFIF?OUiU~yQ+dAOqIiP~Ms57iRCiPi1%P)UP_(MtKoIiaBYGSS-wV)HA(O5afxSU*Njyj6X3&Y>C3ZYfkh>BUSK#us$}fEy zg7wCi=wo>J`J2Q1Oq6eOh2n;oR-*PVNjO<;L`i9dZlAjp#L7Dt6aw1g$eyUE5LZH% zYKA9%w!G!kB~JO3x}UG{uBo-Uy_J|v=o>dzyyTCp6n2s0#Y*1-u|?v8jttGZt*g{d z&`ki6e*}zz)J###|2`uHOEBbO*&gG9`E1S0vKzgTBAcu4_)79@ehF}F^y(tT`VT1s zL=5}BanHr%s&goNR+iBbM~W*aXa@c>b`|V9x=NXSGXg3U8%NI&>i{5c2xABpTuu50 zb+p9v_5_#ci1z1C%2HNtlRmhAg1(k*t$M7$Y1q|>? zLpsGz_+;#*)F^F5kTaG)A0MdY7ysr4b=LL3Fd0HE6s>ra=)(K!e>r3K$~T|FZgxyi zx7_}rhaeQRO=_qbCzv2v6i8uf?|@lusb2Qp%jP?noiaK`RDb+?>)gVUI~Gu*$Sjm_wp@j&`djjbOTGTM;|gqz0_Hkyx1y$2!^?wCGm%PF zwn-dYvxct1KgMLLY<50-wq=dDFIR~{A<(&K+;-eStf92MP41TUvpy^D?LA`LHZg^DhHC*yH$YP&>WVY6n~%x|I%oaV3m6| zjMilYUT%5e&3&#&7M?%zMpWmw4OS}cs6As@cBxR9i-9wNMl#}hk*s)#SG~p=uC%?q zDf3_H07oHa(LX+=YEuaBz(!`km_zpFWifMJh&Ya>TT;n`xhKS~qijV_RnoE`ckP8J z(aoyr)0JP(WdYMJ3r3g`x%Dvfn0~q~&v7EjT`(fPvjK6R1ShHx8iUH~7K?f~y0;tJ zFi*vfl{jbcW)rRSQN1&GxAyBNrJ_EiKkvMLUWdAu`^;}!T9sV=by;3PE2N>vwdF%g zg;AlF(q1fbiY8lz&QBcR$HbX2PHxqzC`IgWFvFD<-CdWi-Hox;s`@8f9t^ooV`tG( znplXa;I>CLk7vXc8NW3u^+D+>3y5H6sqCz8lucymi0t)&#_lS`7JJ4jZs9N;qJ}dO zmjbqCbtd-Q(VBwP86}&m@hZ~g z&W3c5yGFrjyx+d`;uCmhp%Ih&8z_n zOJ}>nQm6#?nhV0jS^6RED;D6N{A2ZtXP%fG_1we)G-_brsXgAkuYX>KBJWO;)o!0? z|M6h_s~i)JA|26r?CO}DkJGI)k1IdHnFEOPG#_z`<_gPASbp(EQ5l`rC2jHj-CgfigPT<2q! zd%xqgv5RsHf5}d{rGi$#5U;K~=lN|ZZqV+V`}b}5)Eyu;R9WKSnft9Py85PB2ZlcJ zXMy?nCZ+tjY76gLskkV*Sc-a0q~fmuD74co1jIwPtK{{L ztRlIO{Udp)yf+(ldeIIVzO!SmZNpJ5Xqp62;yEEDSmIaWiHBHiL747uCc+;mOw~!ue_4fp6q_Zz(8uK$MgBA9|3+ zW*~|=mtz{R3?mh-?I{LkwYGe((bfB=W^;WtRv-AGj zA?H$)(J%@eh}-pG1|qSTAB;$fyCQV&BWzVTNR89+qk2g(8pb;>M|N}gWkr7|O=gAT zK(%HHNXBY#?JkD7RJ(t!qJiLq#3E?`83|rb?QBw53Wh>hsy>!*4B@LrnO#_GOx5-8 zuEYUC#{>d6dY)$CBvJL+siRr1R(`i%nH-8&gcNy%6pQhb=I_9&d$ac-3k3cG+&J89 z?;h5t(r2-=fXOaCI>tL97NYKXTV$U1WR?e!a2HsZ*3ODt`PW4GznZ?nugU)Z`hpGE zV8H0cQPN0D#|U9G(jknJE}}IG)p%+w!sc4cM*)n`4nU6tqsbQ?xF!K{+RHDj@FfooKaF=7)$0; z33SW0Ad4>!V+`5*^N51Z8)9a07L9WI>QzLwczd;9KgXW+KEpe-v!CyHdjQ@eI@)+S z>UW%BrZQlp-N{gai^{;*gPN!w@Q>e}c`)%X?}n7>jOgd0a47%NtgneLUi~eTwh%zc zi&SEu2o+vfp$L+;^0V9kXzS-IQ>s_bKMj^Qu)Okq1=R_R-^*xo6n9 zNB58=E8Y+-W-$pty|bpsB&%0{d*I|iMRO4XAng`d6y4dfLJH{ihXOCz?>DCDgV7n5 zv3{_>|3eQw!o*{j@a%{~MU?u{WEd%fG8r+%2|?ka7q(#p9I4@m?o@mvTQ;dtL2LA)gcO~1hD>Ej@oii7Ga7HPDKv{Sxl>A zug~)nSSODS97%QN7mW3b8J7{c&dKiOewD(nza4Q`wu@q=At2-?S&>Lw_)8kJ8K_<5 zi6ALe*%FdTLxb5ExDJc^%)6hsRu0xt(AuJkS^FmRMe*wI_kmJMQi#QzvkP&JIRAe_ zL8Jt2K-%%GX!cmS6^bVkZsxJf8n+1P8#o{rs5pf!sc3OOY@1{pILSPa(^z=-m<;V* zMJxJSGkWzov2T3kp6Lj)TY4%;DV6H@qx5;XFJVA);!bcCd*gRH9}Upu^MX2P281*6 zuS+9}MHYF}-8-viKCGnC62%OHp`c|baalYgBCn%QC;1AmZof+jhC~gx#9??n%8p-h zl@~tOl_ePr^;|8}u{#h;xHh>;zNy|zrd`wdDALOe!s7lJZQNx;a#I6jxUe&2Zz@u< z#Q2*{9}dUG-O%k0ddo?=PgR@F(@@7x9SH4Mhs=R!n_82^i;>)4Bo9kO(Qlr6omFg) zC3{_+wN!DbNtt2HZ8OrckdR-J5-JSP(MK|4Zk052Er_&H(vH3~&q(h~ z&TJK)-+#8#klWt+I)V$4_ClAKD49p1G{7vGXRwRLAi(XZVmk0VLG4;V;Mep6Eyhny zn%7-0zp?GBKb)Rj5yJ7+w(^w_uSi)*YUAVGpZq1+=J%vGjo!*|h|3ng17>J-+AiKI zTo0ND{Y*%>#aJ`?apcwfmN4VY^l~Ng&C<=qa+<8wDQ?4t;o_(%YIN;66@**8INdJnC!@()< zY>^2J%|D(f_Z?=`xGmvSHG`8wGhNg+V2Fa{CaSk(g*jj`=UyZ#zXAfpiTQl6J9#mN z9sQ2!{x#1G1YN|JS6{qKD6wDkU%6~i{jli+nbINRE?kd1DESoA8q=Vdyb_$l0Wu$} z@F5u>+EibUN5cHWkK7-0#9K8EO7rlpH{}M+6sZ~!=u=sh?IUpVzv(8tB!}--#SFfH z%rK_#iN$L(xQkXU!wJQp@p>nD6B`4ms<7CVvFk+_rFYQbUW%SQp6B+7KdO}{-+$j& zSrYF#bm_xFP;Fx-GR4BV#bYghdZnq;EKBCsZPkqTNJ?747qzw4`a&)Ft@i86NIAUkrQn42y z`euLD@;$vR4s2(W37TW03%!}6Yw|=0Kum5y2LsjLD9OsCWMhVyHcop}OWi%`mu!pY zy*2V3{eVO_Do>ma2&>T*cN`2Kky?*@t4vN)UcB(kW^%#H#hdieutVhN|Egw2TI;Pn z8$!wswO4iyAWKj-DiamLT_kwcpCsxa{$N3MoUla)434~=Z}*6gB2SVP zVMt`nSWt+`&tg#ctUSJ3>Bg*8_ML!qoPH{;E?*)XB!P<2S2D|yOP-WjHMQJI+F4qt zrk7Wh>)~Oob=~r6`P|7&>|0cQnP`yoAP*{7X^Zi#Ux9{}n6i6#l3AKiWudLNk`_Lm&Yc1wpF-~Y_oiV%D zq9}=JK0Dxu(_Y>K9pZ*Ax~OgtQF^^IC=BW%B+yME~hnpduZ;`1m4T!vmBFD0P(A7Z{PDWVaSFMm7IJL^~#!1Zw5NRBU zI>s28KJBgs5$ag34Qz*lxf4bbcZez zaR{Y!SmmSg0n(MJX8}3gCD`UM1Q=<3J%n=Xt;ArJdM)bBVb#msn|^#kdcpL3KrbYt z4uncOtW|}Kb_wU6o`@{H&dXeU;w%{#FE8Q)Kxu&oX4lF_vmGN%9MQi}xPGRidSi;X ztTeBoJmc{toQSv;JlCCfsB)rh8lIJAoI+#v!Algv|n7I|M!Fd3^5+#vC^>~AB7XXRHrmppSCZ38~; z0EusW9JK35twKzj+FK5N*Y5=pBLCa6WFGxnYt1{(?4R%B2!hzQ1r?Brg~!YA)vT0_ z+Ml1H5e#6SKt^4;E|-szTufDmtgR{~idM_*#etx|%9YYgnmHfOTlTKDLgn%ZV}D+N_9#{;Vb*mc27CU$%yq#qwYAG8qQ*_=xgw~@ zG_~}~Yx?nL3A@KfiM{4dG&jH5by+?7F5UVwriPS*b*|3JmmJH!K03qcVN%1YfGo8B z>2i7P>S=J48J)uBKdI^Bq6$?)MF+qHcz8o{sAc2y%E@MV{&YkW<9XU6gKUIp zZ`>j_u=Mwg{r<}_<0<*&chlhS4($y}-?zTaHO_x^b|-z`W0r=0@?}!_+|RX(-D*Nu z!=8jZX=637dW7-rjA1Jx7UKh;l6sP;IR`7ZWT+!+g8w+q6%?&9v{|NVaU zjL?OoUw6~eYO<}ZO`%?MqmDeBN}Seu#4}Mao%;_xFbvTTdb5WFmYzEI!{6xVxF~QPPQf- z>f)+te;&8%VWq>VhcT1~9%H-0Rhu!d!;C!zCoPK4Wr!)l;bPZz(AkP)x(!2;86;D- zz8vn+CjwYrh<|*$K8A^et z1_W^(XKS)|*J}LjMsiGxh{zA?Z>FY*9FF?WC6bYFrb1`z1%ofCL<&<%ta8K*>)Do< z3^xFzQZ^xOnM33Q=?~k}HjLIKxFCJO658Q3%l9mtqVT zV%IUY>&D8(k)h4JuU&$_{bHRoiGaMr>rmSkM80hMPW&!xRlwn%7W?;YaaY63({q_S z8D=+%xhcCNl6Bc!;P@tM({h@`_;}Z`h5z>D!q>)Pt2^PZh5`) z5*l#RUMS-vEOILtk~Q6k#3V9<}{&3a|PC>!HwY3wmasSgY#M zmHn`TPoKe=y3XzZd6b>x(lvxxfcCqwaIc|Ed(4Ghp?8?RPN z5aq0gq(o1roj6>q6&w4FLvQJ~D0SN_M_Q#dVC*noH3OTa{u*O`mW>F!`+gNmiCQP4co zN8Zi47C{rL_77cg4@HU(#0}OL<{tI%K28afD{VV{wqT>3p7gK22`P|d^}^<`EOpFR zwUK`{kzy_s8)rE3&biC1IyFbo!}zcGJ7b#i*kH?3LZ2s#ZAqE@$=++|EuuJaw?@q6T5p2vlztpD<4RxH@ewk;Xu}CNacM zMTJ2{j4}~LSen>rnDCBV346sDX{URCf}OhoX14XcQ&?XrbL@2c4~yqC*Pav_`Gpi; z+Po*H)@eKpK@djRc6*dfy|91iAryaS%*M-v$)Cz9^taY371^=Lt<8Fkj+1!8&?{jr zjjJ`MN4H6M%F@m$;O^67E_4)&~wt>0v4WQt;i81bcks_Fx)Z_ z2gdK+OxBp&n9{YTyuZ?%<<~qf@xf_fDp>9A{wCB$UwyyrRvCvnvMuLCrnN_lSMXf< zZ*-{Y=m#D1L~<$`d#tvaJ9kon1EZRn85i9sCUv2rjflruV`xefuN?)^M_Ok%=qhmc78L!Kh* zSj3W0hTST5OhSeO$@s;gO8Dn_$U~vg`}KqNSL3*QNE&OG3>}=#Bcdq_Wj(H#oD@P zdcg%C3JTv!7hc4GX+V|WmKCh%Y|8JemJsN{4+k1rsm+};8 z;cjy_1=DF=Z(Sgs;AlfY4}l?!hmCD*S&OT>&QmH!a6;g>w91(E)lQ?`#gB2~;t62> zFsHzXVxE?}GTM6Qk*Sjmy7#!rIQ5uu0|ht@7<^i=5%i6@l+kcRZ_qRjx-~WygYac0dvCd&2v-q>?TB3Kg`1WeeRlhQ( z^3vhF(4P1}X0U&11vA zr`29G2&{oRoRF)O|IkB=p;>{AZsBzSf@76~#Ogh=4jG3s!AS8P!qDqDi8LDC3vY%`_rr2chTRQ{#*&Gk$ujrzkY^g>*3HxX3%o?S4Jm7B^Wf#Jpo7#o zefMm~PH#o3*un4^^@&b8BHV1Y(8DhJ>Nqv38=3l#qw&Y_m$iwqKv@@br-3jO?e8ecTq;C z+wpG|KQ=go5SW^O<4#`d1!1KzM36vBYLsS4Ld-kCo(g`EXI6niqwjT z2#Cjis_~QZ#j^LnMc(71z7|c3z&^h8(v%hZf*jR7g1PT;GM=ij5G9xA1F$mFPUn#| zFc&fwaYdFb-8U9oq|7NrDZO4<*&sB$Zv}Ln(v)JWH0xcv_!ZlMPq95mP)CUg7qHE5e~tm!lcEhTU$w92}mgn zXWm{E653>a^=&ZRj$S>LVHOJz-xS=iCOK9tykW#8H+%CJTw9Y;LhlJfP5uL>wbtbh zE=%k^&8@cr^Tst7c9YE=h&0vnr{5=G{ce1uSe?Gt13@Up!r8fli5RWFMuv%}0#(+U z-J>&|DJiaS6m&2$kqjEGk?m&pcxpt~-T7+LygAKKm(3jzyvhF}5*>`8EjiI~K9S3f ziwH%>|3eR9RlLV`dn<}9Qe|cSy>f(n%%Zh=nTRvyhz5V$8IQmg;XGjUq9aohvs|}H z1-w9-PEl#JE|Q-%YJ`O3CO$fy_PG$E00OkB(Y@d;oE!B7EFptp=MSV{PbeHvLO2fA zRH=ONqwVO2m@VbGpFNb~>y3BEyC}HULTk5`!pB`ooD)mbh&uY`6qXJo<|O?_)T z7ZwQdzwfBWszFsZ(DCHjMT%vGOQgJ9RKD*=Is0Wg8P);~?Rl3UuY!V4hJ1protU#; zf2u>EN&gc=BU*!vqLWQiREcu^l%Mm*il{qm*58$&Bozqi&dLe|G7-z3FzJ@(2=)VK&6k6Rgy8{LRa>fh*J}JE>iQG!?)M+s^wDkZ*x|rTS&t4t4H3gY3J&Gor0PHWdjndaR0kM z#tle#u2GKSWAzdd*R2fj zBsY|pNClK~DT@3U82H@;Hom8Y9P4{eTwUl3nP{(38Hi&JDb>J`INmYv6G_hS(vDQw zs;dieFf8I=hTH(1po>sOXV>sWlLL*!bpQYe006TZkN}Qk&>Rh7Pz=XaI-23*_Ra9p zl*DaaYGb>4zcOjV2~HNWtS+*(8}4dWL}WAa68>pHhzuK1r?ou#^weygC?m~kh2XoI y>XmpAjz5Z3gP6`a#~o?wuUDdfj + io:format("Play MP3 using AtomVM ESP ADF\n"), + + AudioPipeline = esp_adf_audio_pipeline:init([]), + + MP3File = atomvm:read_priv(?MODULE, "adf_music.mp3"), + + io:format("MP3File: ~B bytes\n", [byte_size(MP3File)]), + + MP3Decoder = esp_adf_mp3_decoder:init([]), + ok = esp_adf_audio_element:set_read_binary(MP3Decoder, MP3File), + ok = esp_adf_audio_pipeline:register(AudioPipeline, MP3Decoder, <<"mp3">>), + + I2SOutput = esp_adf_i2s_output:init([ + {rate, 44100}, + {bits, 16}, + {gpio_bclk, ?I2S_BCLK_GPIO}, + {gpio_lrclk, ?I2S_LRC_GPIO}, + {gpio_dout, ?I2S_DIN_GPIO} + ]), + ok = esp_adf_audio_pipeline:register(AudioPipeline, I2SOutput, <<"i2s">>), + + ok = esp_adf_audio_pipeline:link(AudioPipeline, [<<"mp3">>, <<"i2s">>]), + + ok = esp_adf_audio_pipeline:run(AudioPipeline), + + timer:sleep(7000), + + ok = esp_adf_audio_pipeline:stop(AudioPipeline), + ok = esp_adf_audio_pipeline:wait_for_stop(AudioPipeline), + ok = esp_adf_audio_pipeline:terminate(AudioPipeline), + ok = esp_adf_audio_pipeline:unregister(AudioPipeline, MP3Decoder), + ok = esp_adf_audio_pipeline:unregister(AudioPipeline, I2SOutput), + + ok. diff --git a/nifs/atomvm_esp_adf_i2s_output.c b/nifs/atomvm_esp_adf_i2s_output.c index 3c4c520..ff0e739 100644 --- a/nifs/atomvm_esp_adf_i2s_output.c +++ b/nifs/atomvm_esp_adf_i2s_output.c @@ -42,6 +42,13 @@ struct I2SData i2s_std_config_t std_config; }; +struct MusicInfo +{ + int rate; + i2s_slot_mode_t channels; + i2s_data_bit_width_t bits; +}; + static esp_err_t i2s_open(audio_element_handle_t self) { TRACE("%s\n", __func__); @@ -108,7 +115,7 @@ static int i2s_write(audio_element_handle_t self, char *buffer, int len, TickTyp return bytes_written; } -static void i2s_data_init(struct I2SData *driver_data, int rate, int gpio_mclk, int gpio_bclk, int gpio_lrclk, int gpio_dout) +static void i2s_data_init(struct I2SData *driver_data, const struct MusicInfo *music_info, int gpio_mclk, int gpio_bclk, int gpio_lrclk, int gpio_dout) { TRACE("%s\n", __func__); @@ -116,8 +123,8 @@ static void i2s_data_init(struct I2SData *driver_data, int rate, int gpio_mclk, i2s_new_channel(&driver_data->chan_cfg, &driver_data->tx_handle, NULL); driver_data->std_config = (i2s_std_config_t){ - .clk_cfg = I2S_STD_CLK_DEFAULT_CONFIG(rate), - .slot_cfg = I2S_STD_MSB_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_32BIT, I2S_SLOT_MODE_STEREO), + .clk_cfg = I2S_STD_CLK_DEFAULT_CONFIG(music_info->rate), + .slot_cfg = I2S_STD_PHILIPS_SLOT_DEFAULT_CONFIG(music_info->bits, music_info->channels), .gpio_cfg = { .mclk = gpio_mclk, .bclk = gpio_bclk, @@ -134,7 +141,7 @@ static void i2s_data_init(struct I2SData *driver_data, int rate, int gpio_mclk, i2s_channel_init_std_mode(driver_data->tx_handle, &driver_data->std_config); } -static term i2s_output_new(Context *ctx, term argv[], int rate, int gpio_mclk, int gpio_bclk, int gpio_lrclk, int gpio_dout) +static term i2s_output_new(Context *ctx, term argv[], const struct MusicInfo *music_info, int gpio_mclk, int gpio_bclk, int gpio_lrclk, int gpio_dout) { TRACE("%s\n", __func__); @@ -165,7 +172,7 @@ static term i2s_output_new(Context *ctx, term argv[], int rate, int gpio_mclk, i RAISE_ERROR(OUT_OF_MEMORY_ATOM); } - i2s_data_init(driver_data, rate, gpio_mclk, gpio_bclk, gpio_lrclk, gpio_dout); + i2s_data_init(driver_data, music_info, gpio_mclk, gpio_bclk, gpio_lrclk, gpio_dout); rsrc_obj->audio_element = audio_element_init(&cfg); if (IS_NULL_PTR(rsrc_obj->audio_element)) { @@ -175,6 +182,7 @@ static term i2s_output_new(Context *ctx, term argv[], int rate, int gpio_mclk, i } audio_element_setdata(rsrc_obj->audio_element, driver_data); + audio_element_set_music_info(rsrc_obj->audio_element, music_info->rate, music_info->channels, music_info->bits); return obj; } @@ -188,19 +196,16 @@ static term nif_init(Context *ctx, int argc, term argv[]) VALIDATE_VALUE(cfg, term_is_list); - term rate_term = interop_kv_get_value_default(cfg, ATOM_STR("\x4", "rate"), term_from_int(48000), ctx->global); term gpio_mclk_term = interop_kv_get_value_default(cfg, ATOM_STR("\x9", "gpio_mclk"), term_from_int(I2S_GPIO_UNUSED), ctx->global); term gpio_bclk_term = interop_kv_get_value(cfg, ATOM_STR("\x9", "gpio_bclk"), ctx->global); term gpio_lrclk_term = interop_kv_get_value(cfg, ATOM_STR("\xA", "gpio_lrclk"), ctx->global); term gpio_dout_term = interop_kv_get_value(cfg, ATOM_STR("\x9", "gpio_dout"), ctx->global); - VALIDATE_VALUE(rate_term, term_is_integer); VALIDATE_VALUE(gpio_mclk_term, term_is_integer); VALIDATE_VALUE(gpio_bclk_term, term_is_integer); VALIDATE_VALUE(gpio_lrclk_term, term_is_integer); VALIDATE_VALUE(gpio_dout_term, term_is_integer); - avm_int_t rate = term_to_int(rate_term); avm_int_t gpio_mclk = term_to_int(gpio_mclk_term); avm_int_t gpio_bclk = term_to_int(gpio_bclk_term); avm_int_t gpio_lrclk = term_to_int(gpio_lrclk_term); @@ -219,7 +224,42 @@ static term nif_init(Context *ctx, int argc, term argv[]) RAISE_ERROR(BADARG_ATOM); } - return i2s_output_new(ctx, argv, rate, gpio_mclk, gpio_bclk, gpio_lrclk, gpio_dout); + term rate_term = interop_kv_get_value_default(cfg, ATOM_STR("\x4", "rate"), term_from_int(48000), ctx->global); + term bits_term = interop_kv_get_value_default(cfg, ATOM_STR("\x4", "bits"), term_from_int(32), ctx->global); + term channels_term = interop_kv_get_value_default(cfg, ATOM_STR("\x8", "channels"), term_from_int(2), ctx->global); + + VALIDATE_VALUE(rate_term, term_is_integer); + VALIDATE_VALUE(bits_term, term_is_integer); + VALIDATE_VALUE(channels_term, term_is_integer); + + avm_int_t rate = term_to_int(rate_term); + avm_int_t bits = term_to_int(bits_term); + avm_int_t channels = term_to_int(channels_term); + + // In standard mode, there are always 2 channels + if (UNLIKELY(channels != 2)) { + RAISE_ERROR(BADARG_ATOM); + } + // In standard mode, bits can be 8/16/24 or 32 + if (UNLIKELY(bits != 8 && bits != 16 && bits != 24 && bits != 32)) { + RAISE_ERROR(BADARG_ATOM); + } + +#if __STDC_VERSION__ >= 201112L + _Static_assert(I2S_SLOT_MODE_STEREO == 2, "expected I2S_SLOT_MODE_STEREO to be equal to 2"); + _Static_assert(I2S_DATA_BIT_WIDTH_8BIT == 8, "expected I2S_DATA_BIT_WIDTH_8BIT to be equal to 8"); + _Static_assert(I2S_DATA_BIT_WIDTH_16BIT == 16, "expected I2S_DATA_BIT_WIDTH_16BIT to be equal to 16"); + _Static_assert(I2S_DATA_BIT_WIDTH_24BIT == 24, "expected I2S_DATA_BIT_WIDTH_24BIT to be equal to 24"); + _Static_assert(I2S_DATA_BIT_WIDTH_32BIT == 32, "expected I2S_DATA_BIT_WIDTH_32BIT to be equal to 32"); +#endif + + struct MusicInfo music_info = { + .rate = rate, + .bits = bits, + .channels = channels + }; + + return i2s_output_new(ctx, argv, &music_info, gpio_mclk, gpio_bclk, gpio_lrclk, gpio_dout); } static const struct Nif init_nif = { diff --git a/rebar.config b/rebar.config index ccd0808..bc08a7a 100644 --- a/rebar.config +++ b/rebar.config @@ -1,3 +1,8 @@ {erl_opts, [debug_info]}. {deps, []}. {plugins, [atomvm_rebar3_plugin]}. +{profiles, [ + {check, [ + {plugins, [erlfmt]} + ]} +]}. diff --git a/src/atomvm_esp_adf.app.src b/src/atomvm_esp_adf.app.src index d33157a..2e4254e 100644 --- a/src/atomvm_esp_adf.app.src +++ b/src/atomvm_esp_adf.app.src @@ -4,7 +4,7 @@ {vsn, "0.1.0"}, {registered, []}, {applications, [kernel, stdlib]}, - {env,[]}, + {env, []}, {modules, []}, {licenses, ["MIT"]}, {links, []} diff --git a/src/esp_adf_i2s_output.erl b/src/esp_adf_i2s_output.erl index 080f523..f99cddf 100644 --- a/src/esp_adf_i2s_output.erl +++ b/src/esp_adf_i2s_output.erl @@ -5,6 +5,8 @@ -type i2s_output_option() :: {rate, pos_integer()} + | {bits, 8 | 16 | 24 | 32} + | {channels, 1 | 2} | {gpio_mclk, -1 | non_neg_integer()} | {gpio_bclk, non_neg_integer()} | {gpio_lrclk, non_neg_integer()} @@ -12,6 +14,8 @@ %% @doc Create a handle to an i2s output audio element. %% `gpio_bclk', `gpio_lrclk' and `gpio_dout' options are required. +%% I2S is configured in standard mode ("Philips"), which means that +%% channels should be 2 (this is the default) and bits can be 8, 16, 24 or 32. %% @param Cfg configuration -spec init([i2s_output_option()]) -> audio_element:audio_element(). init(_Cfg) ->