From d3ae48dd0940683c5d6b4dd45ba49459dd32ea36 Mon Sep 17 00:00:00 2001 From: Howard Mao Date: Sat, 11 Jan 2014 11:14:50 -0500 Subject: [PATCH] add basic support for file output --- .gitignore | 2 ++ src/sndfile.jl | 62 +++++++++++++++++++++++++++++++++++++++---- test/sinwave.flac | Bin 44358 -> 0 bytes test/test_AudioIO.jl | 32 ++++++++++++++-------- 4 files changed, 80 insertions(+), 16 deletions(-) delete mode 100644 test/sinwave.flac diff --git a/.gitignore b/.gitignore index c375723..eb5f126 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,5 @@ *.o deps/usr deps/deps.jl +*.wav +*.flac diff --git a/src/sndfile.jl b/src/sndfile.jl index bf557be..9149c8b 100644 --- a/src/sndfile.jl +++ b/src/sndfile.jl @@ -5,6 +5,20 @@ const sndfile = "libsndfile" const SFM_READ = int32(0x10) const SFM_WRITE = int32(0x20) +const SF_FORMAT_WAV = 0x010000 +const SF_FORMAT_FLAC = 0x170000 +const SF_FORMAT_OGG = 0x200060 + +const SF_FORMAT_PCM_S8 = 0x0001 # Signed 8 bit data +const SF_FORMAT_PCM_16 = 0x0002 # Signed 16 bit data +const SF_FORMAT_PCM_24 = 0x0003 # Signed 24 bit data +const SF_FORMAT_PCM_32 = 0x0004 # Signed 32 bit data + +const EXT_TO_FORMAT = [ + ".wav" => SF_FORMAT_WAV, + ".flac" => SF_FORMAT_FLAC +] + type SF_INFO frames::Int64 samplerate::Int32 @@ -25,12 +39,28 @@ type AudioFile sfinfo::SF_INFO end -function af_open(path::String, mode::String="r") - # TODO: handle write/append modes +function af_open(path::String, mode::String = "r", + sampleRate::Integer = 44100, channels::Integer = 1, + format::Integer = 0) sfinfo = SF_INFO(0, 0, 0, 0, 0, 0) + file_mode = SFM_READ + + if mode == "w" + file_mode = SFM_WRITE + sfinfo.samplerate = sampleRate + sfinfo.channels = channels + if format == 0 + _, ext = splitext(path) + sfinfo.format = EXT_TO_FORMAT[ext] | SF_FORMAT_PCM_16 + else + sfinfo.format = format + end + end + filePtr = ccall((:sf_open, sndfile), Ptr{Void}, (Ptr{Uint8}, Int32, Ptr{SF_INFO}), - path, SFM_READ, &sfinfo) + path, file_mode, &sfinfo) + if filePtr == C_NULL errmsg = ccall((:sf_strerror, sndfile), Ptr{Uint8}, (Ptr{Void},), filePtr) error(bytestring(errmsg)) @@ -46,8 +76,8 @@ function Base.close(file::AudioFile) end end -function af_open(f::Function, path::String) - file = af_open(path) +function af_open(f::Function, args...) + file = af_open(args...) f(file) close(file) end @@ -89,6 +119,28 @@ function Base.read(file::AudioFile, nframes::Integer = file.sfinfo.frames, return arr end +function Base.write{T}(file::AudioFile, frames::Array{T}) + nframes = int(length(frames) / file.sfinfo.channels) + + if T == Int16 + return ccall((:sf_writef_short, sndfile), Int64, + (Ptr{Void}, Ptr{Int16}, Int64), + file.filePtr, frames, nframes) + elseif T == Int32 + return ccall((:sf_writef_int, sndfile), Int64, + (Ptr{Void}, Ptr{Int32}, Int64), + file.filePtr, frames, nframes) + elseif T == Float32 + return ccall((:sf_writef_float, sndfile), Int64, + (Ptr{Void}, Ptr{Float32}, Int64), + file.filePtr, frames, nframes) + elseif T == Float64 + return ccall((:sf_writef_double, sndfile), Int64, + (Ptr{Void}, Ptr{Float64}, Int64), + file.filePtr, frames, nframes) + end +end + type FilePlayer <: AudioNode active::Bool file::AudioFile diff --git a/test/sinwave.flac b/test/sinwave.flac deleted file mode 100644 index 739a2479ea584cab960002b60ed14753f6b56072..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 44358 zcmeFZ`+F1R_C8!nz)1+0Oamss$DNr@LxNRvsI}d@XgitKOb8`SsT>p}X&69LK@jC6 z(mF{eCEYuj1jx`@n%V*uy@1O8q7hv(a z=w#-3)^o3W-RoXc7@O0al9Ga>DQHT{2qr~rlyv6*kTPNp_uhyT>%tlCQp>mRKFe)K zDnuzM4~>OOZO)gNM;>{|ko%B9pEUyhVmy2;dcJ&_d(nz%|DSJGrl{dtcYocDz}*Pk zjlkUq+>OB92;7ap-3Z)`z}*PkjlkUq+>OB92;7ap-3Z)`z}*PkjlkUq+>OB92;7ap z-3Z)`z}*PkjlkUq+>OB92>ky&0(X9$i=^Zgr=%dGWU2RE|69kDmmd~oyN1;N`SHCk z?mebY{o$RDUOKc@Hjc&+)Yi$k0)g%ksb=ZJqjzQe{!3Yz@H^h^i%WC9c(>( zC8cRonb9rQ6p@$;VKAf%SF#4gEKB&(jVUq~lZM|adEnIrt%q(M-2HDM>hV<6t$XRw z>4gL)N7R1A4A&}sj$kjQ>YTrvsqgA0fzD< zid-_EK^{m~Cd%OxLXebkTu8fn*Go4N75i(2=qH=Y=0Ef2Gq)Gy{qi>KgTmb|xwKOr zC^B#^OzBHEsZ^7UY8qQqLfH#4%F3=>X}x{sRDOX-E|*Vyi?4H25G=EtqyE~2OU4?M zRdNv~7Gw0>^1<3`(P4wIb=AvdWwXCKwQR(My=);j%R4K>M`qcRH+ug~ZjQnx!yl7Zxz9qNJQl6fq3dcVMaS*4c_W zQ@L@~s@Y{5T3dcuovPimz=`ojmq`xMmAYi`0S} zjdOoncK@`&iLEpeNlG$>h&gR_8-L7ckWp4xDJ{{$@u;hjJKnbw0J{IZ}mh2yx- zHOse9-3gX7AYBF|;8J#$%X}`_xjH15k8k>}{MP+UpCAN0MU2Tb$&@#6`ai`rLBCu^ z1v=C9ECy%D8VnpMm$EKAeTit?QzfG)+4Q}u%BJ32b-k=4+cRjocExtU-NOY~00~(x z>%=%x>4SygvI11bHckEP;r4zL1NYB(`TFhovv2;gTK%@e77VIsl`2q#DZ5MtI7B2} z8DLz-?0hVB&Hi27*0S4WXUfi;n*VXMPpBKXv$}a6fs+`5iEsm8N@@m-AS6;CBV`mt zMr!WA_G1GxAn?0yUf;9#+~Ge)j4H}HM$+jo%Y4IwA|MSZ2Q?UInHma*6Rrr2gFX7=5 zi9{Se<5E`1d?uCDjEOK2g`=U2FaLJ)s%HS6v3>LW>1WpcGVh&H$`ecI)O;4Q1dI9% zNC9F7q;sUqM;cA(BHzp>Ic>%le_n6Ba%InzuTLii-n;elfj65x-CQTb7-AAK$m%S! zb(4=l#8^l}ZnJj7_74+-*{ZFxS0xer%-M}xYv6cXNz0W06a#`O0V2r+ma*yC=_3$Q z6-EuzmOuBF{oeY)-WN=UhU~?MZuu@YQxuEKI5>9TssIBApA0ZlR77#Xvf?MMwVBE@ zHte}Q|5VwzUq;9ZOZ+o1$aMkM`jzoDVaYC04X;qVbj14K#yFaFRZ>N=j$3Ase0z%?$*|Wtp^WoRC85TQw>8; z5pGD-bU8$lGxp1Mi3ziruuZ(U6xIWB|zRM%QAVb+T} z$tBE^&*BJ%giycr{_hfl9){^jQsd19-_71wtK4EmNfegl!la}eHq&X~I@JL--Grr7 z62!%(H_+S9?Y(~G(EL+W!owtn2mf3B&U6eZTZXMJSbivShTnN*&(&@`fu{7PRhZ zL^uvlZ)Kjsjp^y~Xdp>kh9poRnh8QiS=c7))_)Cp2FoXv8~pncOc%4bZCT2bZE+bd z6B{w42y&`R7JwLZnM|?(mx!jKGs~!1q7Qz7@RrR#w<|hO_t>NV_@-%zFe%-jQbM){ z%m6J+RE~*cq?)r>{29BJ-EKcUAOJnQ|KtaI%U=Dxs5`)9@3&JbP+( z*`-ypOU6bMeL};HUzdGKV{)Kh3TgtCjIG(g0bwJZo^Jnv5jUD}362m~T3Z)fZ{73V zXCkO>HSJ+yK#&U@n=b3r0B4J^C~FV|5iVmx#Jp4SbL|zv{v98~;k+2EDk@x;R%TCc{Yd4nx1I_?rM)1=B8Hjt;BZRF9WE09m#7$~&TYZ^hl1I2#g#Gs~k;+I)s+ z6>J^YA%#Zl@5xK(*?Sj2J@{fX)zy_4*uMSwiB^bJfvidmKbiJkCsj|f)u0Rn4vr|z~=@e(YY{H6x8#McgpJ$ z18wD#Ov;Y~YifnMHP`mP{~5)jP-&PX|EV~r$dE;y<*@NEu2%isz*RL?P5s{4oF7qm8#lAZ`$n@0)0DPxrAAa@sBceI`>vfVqZvWo8_vPzfCr%%&>$`UL0h)**7FSRY`G!Y#h9REY)mRK+3>2gL6fIzKnNsk z6#-B@!z=G^^`j&v14)UgfNr=>LliPq#RWL-Q<Jj z)duTImnAygIA|p4&^skm!9#Z-uw}Csw5FG@5&k?gcf2iZOgEWS%FZre8#PGuPM3_7 zBP3y=r^ed9UtE`+82HEDRjbMteE+Kbo>A+g3oR(+DT3_+o3S|PPZ?BmlK}*%({!b= zS01elPbCP|BRMr$5uVpBQPf_)%D+txk*lQ zqRqs(AR|mBX3gb|t^52MRK~mAE~6|_^w<5N|1rZJRI-tX`^HCw4}Wp0Z1#rR&-@!! zHgM?HTT4+IR*TCpd6I>@3|ykzgpi^FnT04sBM?L51M z>FjhtsfVPHK~g}TCKBCojL1NHPqshv_JY0VK-iY3>P)Jk|E@cK&{`;#L30oV^sy!t z2ZAsSq6I5P{6C4~i|0`&T!vS$t+zS7#*h*v#=t`t{sH zv|`r#9ao2eZcNz*IKD~Q%pV(&a|BCNriwyR==Pv6c41KLfk?Q(pmCve%GaHC`}9Be z{Bo-7R_mYXCZ_+tU!Iz9GTRe?_DTtK2FL?|gNCNmK#OeiyX1G%uJ%O-RsLG2sfoUZ z!4XeeSCgcS$3WDY3>;%pa=?O#A|QfL3TvGImYmwU7czS7;Z-HTO~Su#{aU6C`Voj| z0i-}ONXc!09!$mz)7H%Cec|Y#w(PFy=MElhz4_g#S#o*pu-M2@WI7ZcMjoI*cPUxm znrL6zO-4)UJB=>Wx;Q~+3j1@y0=izt$?ZzfLuxNKmENq`8_ zba@79+Xpv1xX00?Wl7uxv{x=;)u5Q+*bJ&5*Ig?UpMSCj$BDhaC&ldUy~{y0lu#aK zo~9@fNI-^m7QqH!*YW^x0VS8?85vjpcCNvb0JW&;V3_Re?6a%!tYRCXUPyb*sF$@89jN{4x$ns=8Qi)_$ z1tONE@m84%z>Wgt)+CO&#tF+Sf8UFhN2 zWvj|oT|c~0y{qQ4#E~twKG*~X-82UpGuc(LE-VE>QBmCboV?-mjcnMmDNO}<8ut8m z^>8b}g&=0owkp|jWuRORx*!^0agBS%Mn3+CvPtcq`o)#oWw&lFXiUY`Rd3B*F&B4x z5^&U@vj@*mNks`e1=vW(na> z+IKEn_h{|@x(x6TuIw$F{q{wDQUawKi@&_*e8;!1|5*E5U_?l~Ssolp_kC?T$BA~{ z`Klnl{jf;(pbo|HqV5C`E6b$IlG=eZ8RaqolxV!JNdH9k>4A0z^i@g~QiIggysKJ7 za25i1Ax-udwU!&CJ``FDilFF1^@&!kR*NJ4THt_kkLN6+-9JO8XWzhalgSW-kgB-O za-%B97Imh|h+yJEiK^|#p+rR>@iAB#1HT>q@j6Y*f%T{aWXxa22PqGN`gRx12Szl#9{=EzWtKv_GO`+so>RtTa1+BYJ-TGzr2)V4}2{en} z+{7fbDFWC(o zoJ?bmb-Oj55#n)*3*!|}5m{wHrC@Ynz4? zp)}lRG|7Vr5+qol2xLZgcM1wgO!Tb%$L+Q}kUELEb%vpeL+|f2lm&x) z;gM5_7Mr;f8;_Q0@VF zF+wh)3KdW6YQZfW1??R)q5x(tS)g1%N+JtRac>qlrgBZthjOqaXunMr`$iRh&YHa24Y!PZvY~+vH#S z;Rch?2KH36ZPKLditXF?9g^6@sWMhrtbHGBxMgHc=a(olazZJo=+OcUC&kLAhV<7wa? za4VD1iL#iO1HA*M2AbC5{$*Da|L2|7)?a2{X-x$~wkl8|`xg$5AfOZR2a1v^6+T2l z+2mL@rf^jLy9U>)p_OM&_wBE3Slosfn$}Kc`D}*#iwoh}WK)8$?jm=ph~Q_|e55?< zNou-m1Dx5}8#isUDF^s>5KsW-Us4Uq5-^ZK-iA}BRkLc+N9C7HxqWNzss)E;|4=~9 zT3bzoaUA5VJeU+Z@F}n;4YG}>NQ~(-FFdhfc+J1cnLHa1L|?;&^VfT6IVuZMK>5K$ zXSqogg+p+;aMZ{&s;-tR3JN9DRmHxz90y9D0f_^9I3((j?b`8s=pvy9jHs2RL+$5{VVUZ z-Zik#C)?s?m}GYVItY%c(*>nOr5`~ML)&W7+bS*qn|PQ9g$7Um+3Vx4j0a?aSmF|Z zd?2gwo8Aq4CrIp>BxBB`A^8D=43 zA(hPhlHtCgHQ*6M0|RZ$x^;K{@5!2wSf0%9A`@T@s2>9|4|LboWuG1y`DglQ97z}I zpj%_kj@+3h6~e zIPZm;2e0-4CqPfowR&*zdn;pa7J@y1Kro^CF$ipu{bd{uf5UR2IisG}^uJ_=>gljsCzwas(k=Dkmb z6wuLND0Gyt&rVnmg~Qq*L5vG^-TSK=Iea>_u&ZV-IJ7#YX)1n2k(*sBgj7fZY{g`I z2}&;D##8b)lBC7_*c(r@0qRXAR~O?MXsh_}s|vv=s>H;QO@K>7QmMm-AQ?SH11Xvr z4@nD0J#_f+_h;7bKD8XYrILwXWRw#~> zp%;cSmY#m%TahIAP-@CL2};s(6^H|hG0K4NprAlr2uiim;%=GR`O?|MFx0`*?RkTb z-rBZggS8L=e}ScnT*3O9|CD@0FacR~0TH>5NfJho=OHf+S< z_GaM7PU!!k>>z;@Qp6I~-WMhf_Fb-H`usxMQQ_*%Uk|+aZyx#_Drw4sS}B)vwj$C1 z%bA3$EpuO*nm*z_;lfd2e|zF1QQ`QaTp9niiE_Km;DXs;*$C9lZnrZz9H15No*q1R zb)DgY#|Eom2JuoKtX!sahC)<%?XM}Gx*zt+lzUu*roQ*z zx#EhHpg0P?1_BG0CEV%IsySsAR2ISu$CEQ>o*ia}UBF6h_pcsajl8w!VpL^>j1<7= za~brIb^^5KebLnXMyJg`nR;oE8E9Wz9eAp|f7+pbTbaX;;&Ldc(6|S>m~N|*m} zcJ*+!=d^2Je+P5pr5pE0Z3N&BWgyew5k3aR)EPPbQH^GpS-rYH+jK-OvMa_J^vJJ{mrx3kd_uO#!wgP)Z{w~{v-I603WGK95n-z`H~{dDT}G2Jg+$5v7n=S# znAZj}v_m^4)*DGwgr)FC z74)kHsFg~th|#3G+%|tocyN4yTn?fJYE55VN`ZZ0*UlblAR9MgLDrQ9`Ckq;VggW! z$uXK}J$k!-O&#Mo9X)-+w772FYUxbUNx(4`xfvMoz;ZAHa1jPGoLap|Yj1f@PQ7q- zupByvzfKHQZN`P_B;#$5YcCvnOu%gbD?dhvCCH^?A-G7qs z$#~qDl>gA$CMTvKbdi96qZk{vs;M#Ev_@#pF3)CC5eaBz$-$bY?ih}#gQNx^MgiS{ zKL%q#@XT?F4^FalNj5fCAswEhfr0%WE=y6qfj;Kuiw2?s@ViT%;v4c*F+R(MX-B3 zt5d6{YMWP*bF(QbJw54ma15*oHegZ*xfohl@`#~$4OE%zM0sFMU3UMv4WhIaPE2h< zZEPnFO#{T9OqX?cYM3Hh-3aj~pO%b9+SipQx=vTLjSv-7Rqgp{Dh1(JV>nkop80YRAzTY$0zdZHmTr)P3=o6445KNseWe`*-G^C+AwWu=6 z5HPSEXn>@O4o>jgsJMJ5E1RY)9D#vXY6ce$WNs7~gap1MSemMuR;Zu~3gp>+`+jU^ z2Ck0aT2ETsVhYSKn3I7w1WF|VE*IB*nxr!1&prH2*ScksvKI%A`s+*;A6~fJF)!ry zBNk|RV8#uu9Gec6sgpD@6?N{78$Pb8N!|EQ57c7M>A{7_M};p5><(KrX~W`5HUVhs zG^eXn96(UDHOmE1xxrwFCf=Iee|8zr)BbiQ zF?j#7A4YB3LKB!csX+hNO#wK8yxndOm*Sq1F?AQ7+tvkDuXg{}rw2V3Y9HHAQy~=c z0{RmeRzk@RCN&uhs0mE#h=}*^(pFXBNL_Y0;DI@oQZ}hG$Kvj(gPx9~U}8go=q>{4 zmj@9UuloC}Sqp}zHJG|iC!R9(wQV@_!x?RJArd5U&|D@U7)1O(!_v#k~|~@o(EZwtR(3sBf?p@NXaVC;_N}-$!u3wpK$eD zU4y(u>tw}hKqX{$GBhw6k|W)e8^>|Ad2Hxodtq93;s>aj*$kqURDJw&$U#^rkW7^b z1=H&;C_M=ugCZ0~@Va>)|DUOSV5sY~&{ob={3~Y=$v8=LqtM=U1Iz#A0R=!62f97o zJsX3KFbpMT&0Tcz>YZr~p26&X z=Gd}V-Cq(IHW77$8Cf!36P)#AtbQ&XNld%mNuF0Z1!;_9bAo>?)s1hueL zxCjm-`CbB$DiCTFh`<`_y!X3rUwiML*{9F;=iR)1d6l&g#S5UlE>Lr7px(cFHxw1i zcm=MrtiZG!#nr1Le>Z2#&VdVqi|n5>E^LGNrslZ``r7t)?98oy1%PG z`)2$1&z<!$ zhH!9SN^MD|8LS)Hda}x|d-~vpq2a;ozV>7HuNfM;ym#KFLO%%Nq>rB57yOSz2zXtD z4dISA*RC8~eqpdYF>v*4&Yf4+UMl1%&QgWTEbwfIZt{!8WFaw1MBe=Se{WyA*4Eds zreQGe(>rHdnnMZ*y%^kc5<&}K5IPL8bHV1hS%=oIJiF$-eCwkFA>3%*DW1 z`zxyODhUE{gK;sGe6(;;S@BCZ4`&aWYTIfL=Y0R=wfhu>7{neLtfZXG=kh@wq*hV5 zy(GiB^^Nx~-|y)!KYio*?4hL}ylu_clypd|ARS-`1Fvbo0m698FGh6_JoNn^7y3Tz z&t8_@e{9|1J&`6_ff5jWu%*>ha`p+3C@4V1Scx_K%&nUr4l;0M#kKEO?r7yLJcdIH z2}^)4xSGRY%tfNOHADCE${QCduJ$wQvX3o0^X~6&LH=OCMO5_(Zl7WW!Kwlzx>Awhb~mKdu~i? z8+_r5Fa3Oo(2@noHWv1TfSU!{4Mz#wyXnEQSB@U880xEIZX|~OyK+X>`xH;X;vfQW zZ6%y>GS1LaaxvN(p8e;I!NqON(e3}7_TKiJpG?odf#oqZc*yX0QB`s=94r`BL>#|- zd+Y4kb%30~X$`mUeA3cX0#-IWHhE)Ah9_@Z1Vp;RNvXh7VJvaKZ6E~LSoW1$yTklv2f=G5$kP+|_z+XpEsRqXi zEuAOj~Bjw;pFb=G(n4#$1kda$HTQUNM_jED5PoX+*KQH*Y|q{h9E6I z9J;)!r%+3Z~?+Cjc2_ zWEEV8BCrBQWZs@TXP<}5+VTdcUAr?}X0c2h#)eBef56zf4bJ?B@BrXsxk53%c}x4@+rJ&EWBTtudjH_LZ@zFmsDQUks(=oXe22rI6v%G^ zg|WAF>zn_*c|WAY)iswJe!cnfiim}W1O}!B=q7pZuM;6rv7Bl;_1xvh2Y$U#(U9HO z*8l3ARhb8PfInQ2%w2FJf%$@@Tp~w_d9&UhzHxTAFWEVsUABJdcc0gAAsjp~xFcMf z{})Yz;Uu#Md73zQdCk#D{qQc{<%Wt|w@)pdWyMJxm&@QC87LGiWQB|)pdV9M-kchK z#_$f-o*Qr!4R^kMF%pcS>L46!a$osDcu7SrB1uB)pD_2iw|7pv zc6H!FUt3@M&HpUjbKnFm#~^+FmlIWBk^R-e7K#xz}&6pOK*;I7lBT>p&sNhJb{Y zgP^<;@ARi;wqI@^%p3Ilc=eAzt}kunyLpO$o&OJC6oi4JpjHM$XwCH5PycZNx~pNP zuYK#A$=W|^ignkTJ+Hp=#RqHSt{(r8=3=5dC91mbL_S@0Esepizg`qXWh2z2SuB;L@jvEtHhxuQm^G`&Ux**~>!MCY2nFi= zi(y!n0;L=qftjXEJGHAzT9i4WMsGPft4+|5Bnq$bu}M(^C6=nvQXvW1RJHQ?ccBp- zrL4&+`f};+r_07r5xAF~tdznEEkqSXSnPag(U$O>Xja4{0vG72tMb6$}pKmSOOH~Xl} z_SR09o>B(pv<9uAF&ejVG{GxK0$ed5OBj^+W=0rV8)I4wcI+pWQ1Q;HTzri&;w(F zln81`oJdjT$CWC{{qvtaRhC~^@Y-lRhp5Qh7Yp**5J_q=bxg)-@#OJ@$c;qs;=|MD zLBOYK*>d@_)UHzfS8f8UR2QnDHUVm79NZaHS|NEvcWcSVHE)bgAEgL9ee%$}=B7-0 z2#3-LYL)e|7|3=op7|mb^B8bZs;FpyLD&<4ghyeh}2HTqYAEXg;yg zDJ6J&FLf|Wx$9#tq|A`qCMb&#dR^sj^1idi2Fe*a)AOVUX+qN1_0v7k~{V zYGws>-_5ECOngo8WO~WOXFqSrz)N6>P&Z+b90(-94;fNyp3r)2;eKvERW`n+^#V8N zM1+S-C2^p91ZE{<{)kHPNVQYUFMe2gp#<@dP9Gh3;mM2@-f?n{2i*XxOUg32Tr8HO zDMxxF^tKoOnM8QiYvYSHS$bcbA|}M@LRl<{Yzq$l5V(0ns8AH{?QCs*ZT$EGE?Cf& z^Yb>PSxiVV>Bv-(r79`yL~IpFaZQDVx+R7$KT>~O)wFBhvl%6CKU+d8EL<=Kj}*ZH z!VSSQ^P>32Q_JQpeQQ+BRJbR_efmgSh_`BkO(dmF(hk&H%91JzN(sz3(_m1CKHAkd z6>n;Nqv*gNQM&;LqZnb~O@Db(SrCL@lIqktZk12eep=OZM7h7*k)d<)7E4liKu~ZD zItGp_!6@ExpmBS%^&@T8!Z$`un5tKv_%^RY?IgrVK0gA<_d^o}QRM7?MPa1%leY}6 zf?c};CDgM=XT8yq5wh?=CCMA2aNm3oNEX=9CypKgZoRA8#`TwqShiuBtrN^Aq4?lJ{%oMpz0996NQqLp2xO) zSu5f`s?oc~O!B;wm4O9=Kp(03{v@)~XI_#JPfC^AkL_i(6`AxF-qJ*iL9_mkwkdV0W%OtfpT_f= zpDnFgyonHP8vQ_8n)`=Xet;H3AqW1V;OJyA7~*e~vOV=Xt^Nu4M~$7MQw!dh@U?4^ zhODe)2@BLp67(aG3T3hI8H%9U`qYx3Yido+8{_jUERjFc2$rpcu(60d`Eweev{yub;%r!3_%&O?eX8u7 zRaW!Vi4wX{LL_S`&>WmIDo52~#7*Qdk(Tz|<7Gveg+*^XXJvr3wSIB3;R^7{))k^mwG1;sr1G)P|X;7ByJvw5mB4g9$S?A z^P#WHBZphYL^_NrDH}zVvbfSImO@cgNqMU(^RPAQ{h)bz)_=d%b5^=C7oq8C&h0_xW`4+oejJ#2NyDhb-qcD~D{BOFFI?!XjMGw+adoM-^w(`qy!d0*`^Oli zU2DU9qf%*v7K=xw2IEfNE$C*9X_@}P(lc9sGbhF=ZBl*k2rq**A~r(bLv-}GTMnE! zbI8&#Y>sH1nzU4llVxF8PCBJ*Fi}0uu@+v_-to>s3U^%A#pvph8gnXqA0CboKAH&M zo0}j{T3=r(``6NCG1(65WPJ~o??aVJaIvIGht;M}M6y1aDxd1wJl*xoV&RxVgTgc5 zHfFFv^{{1)P0+2eI$BPI4ES^S^J`*L#5pwU8;zp*jikk`k1B{Bjdj9W;IIMoYwA5m zzm5%=)+r;tAM0((Mj5+Al|T z>JE*W`gHM@=eH;lc$(22j9ZizGbE``C6)@}{5C#<%XNW&Hd}6A${fzI_eg`?HZcZg z4!;S_XqD03y9n7ro%!s{bbRfapGq+^=0iz~LQH66JZf3qp^w>`e}m0@?ZD=LyTU6` zkv76dnn#M&3*B(0nly}-D6;VJNHiMS^8L#@b>BE_-EMdQ%bVfYFu0b8MRMjwE`4JC z?4LU{8Dq3_C<$#Qg0M%zmzKKF0-+CfGb_Dg9()vk%H>*WmFLw*BxGgWrq=@XsX^E) zl?sA)pI@B$Us9uK_V^t;dWA@ChEy|J2|vC?W0gT)em5=E!vsb`ePDV_Hndn{acf9hGAH9OD^ekD!RVCT9`m8~DRfJBgXhvXXM8ddJQ9WDVTno~ zU{$4$6+2$P_0pjK6~wDuy~5rB3CokH1p=kD*m%_T7_;DM|MSu({Y+3Jr(ZA@WmX^#D?w()|VNAk<)f*LJEXdn@ixFR(us+qiXw?a$ zfR=_UX`%yOwctrOTk}Xlt7L3F^#>vcZmw$KsKbKUG?In)hwae&bi+EN7;98W1%X~V z{lO0o7?CGVHa9m51l*j^YhhBGM6t!j#=Vk>f6LktdJumyl+}_II}X^0+Vn;={|K)l z2&2lI%JTMZwq?r+3_a0ob!>TJn=R_FhY8pS5D~m3L<5+`q#Z{ik07k|nU>JTfji04 zagWX#d^d7Ic%|W$H@5c;5<@zS|B^77%-ci2D>ejV;b^-B22d#Ae=W3~Q|ljm4S&mEA|$ykh-% zo{rjMbg{!5*>UGGkJ%zQ?hXm+=G{SoFpV39(b~m%E%#==|7w5Vm|U7|?(j;zBclop zjm2r;13@^pXqv7?M@D|zCLhCBkI^_aDovW&&Ra*NvOPSd^Jau~i&(NPvSX{Z^mWPP z3~_!8^C|5;8r1BwFq3lyE%m5mQQq0o^DBfcX~#xkzR8ueRHMRz@nF4{u{G=ZvkpAX zQ6FBm?d0vTs6DJ9X%sWm~#}SRG-S| z6lCtdG-J{thx~rE|TH_s3qz%KV0U$U3=4 zYmYK%QX}bPdyF*ElOa+3{ck3#^_8n_rt?lGPaEklVVs;XG8oe*q&+?P&3Ts|EA6$s z{`lh=*4HeN}xQMZW@jxP6dRj?MHlGu|S-+*o|g! zwPZADuQ!*Dou{iM_lPwrsnKHB$9!ofiNk(u z&2g@@p>&HQG-k}0RQ2N2O42rNw9^Qj5_OW*lC*Hn+(lz0(|^7^RX!!RM*HYp(u3dTaLny1<}XI#QG26fvcyclYg9)Bu}>u#T|7!0mRRZa$2saDJA@0L zIJt-PIn9J1*6X!2+(j_b!f!Jq7Vp%hGqgo+(wmW$rPI(k#iMD$r-b&x$u`H?h%p>n zLOqcAExn=IYZ_;(hb#`pSkO(uMt4W9Mse}t32y{{aYrPw^QQ(?eXf-4klZs;s_&*X zlO?u`_yk2_XZQ9`rf<8?LRGwfzPKX2lk-&K4tkfU5ca!2)(I>Oa#MSZ#VQT3*+Kv< z7AAV=o@0x)O_&t3bJSx?k2xX4wx~NSxd-FZ#8}5TD;j3W`s4new^?7&;r9u;T(49o zQ4w*PS4e#-A|dEBFXD==aPr7e+@x!)`$ z6QJCJ7lR#@q_YF#ohIXo>d3>#N_FJUjbFDVc^(m2xpkYi{7Vy_vUN-S^Fveic0Hze z>dz@(A1Pco!l(d{#VdnCrCFl1H}{ea%y!x~^ApKTJ`5aKJyOaSqjv3NpDo883w!H_ zZI^V`_1d}J)!P*DD5G==5ZM)~45?rm=cooZ%BTARLJ z&|e0Y-l<(lZa?pwF(%g}0rnI0(9siG1yA#|cO>uC*kiI5WAB=orc9kyp2}C6c{;z@ zC{K0z+;N`nFcGv3S8!|Pd66t#v3!hJ4`n>& zHC=jqNG>6Lqz`uQ#o|7dRDWLUzO3`s=aQHD#^4iIYA2wTN4V9_YA8WO414SQFj~mg7E? zmCtFkMQsuwDTVjm42k>X&{9EmICGef)MtjJTI(oeg=$>$ z>-(fJItt}I>K33Ln2E#`ENm3&&zMd{n)@1Jpx@{yYg=h}zC4 zeu~EIp*KyU(8r?A{1_4J!NM5bW0Ih8pS=Z2$UxKc)p0yuzLU z;c9_WR3G+E5fZ>`y6rQ`48)svF(ylBZShK<4O~Bq6O479uFqM@hqr1S+wS`$S2yHt zj)jwTMa-MUCTUdB6N%dWd9mq_t>|4J>Gnz!7y0E;w+0$ILSJvR?-(`a*y4U;ucKiO zm3Mq-wXLIC8rDZ7qd^WRI*uuNdL8lDqJQ8k>$OzaxWZ{!9)ki+vT?>1?}##$^e5Zo zWB;zGKTp=jjwupG`!N;41H1E1A-}mpQaoXK^A5*cTK3`8QMnz)$y%pYL3~Ati4M#p z1~EXyE`D-vpQQAX5%h?!UovqN95>*r2eLEG=rs30No!#057hM&$74>X*$28;yFBjJ zC{_A|ws-~9qa81X9$RX4O)SmLZ<9EC^f9hZ8|>BU`8Af>H$xkSrtn=$ z(9_a;k9@UYW2$Aj7j&*qp;0o{VujG07;518>dTqAIS!jXX09G*Gf80wko>xf{w)($ z2-E9#hO419fs`kGX2J+Eg^#XSzGK4TNai0OevC?i9ESpvmO5QwO~1Da-c zIGlS-(V|`7X1-MaYf^ukd@A0lKTlV}S`t%Cxzi(&mih=sT|VZ%*l17av zZ>~3)>p^t3Y`v^Iu+82a(*kMMYss)QEY9!A5SvY7rI&S(&?h6u_i>Kpv3RxgJn0N$ zX8lEwa1b1KePoO@CL506isSwhrQy6t{du9=+0CGk3s79{;e9M@%KsRZdp>Q;Y6rA3 zJw0JDsLQYH9Yk2l%SXn8`wl=#!RFWZDt0Uyrx{Vn5<~$9^dOe`eXa;t4pSR4-&}HHi zC&*c{Z_HR@!(zz~URIoK%{}VV(^=%m%#;WLn&LJ4L zjYB7EChH`VGb8cHF>3o(VAnPOD3X{yqFLVD6P7HJFe_*7>|J_d#qxc} zpy(TyUxcbMN(y5xt1aP`*ftw6X1g~=Mly8>yN{bNnTPZ;(h}wJ^KnqJUd@WI7t}@D zAHQwq8=M^(VvvPlF*E>`7wdDNvswy+%433KO?^E2G!Svz31SJ#l9+{m973VBRFc(3 z@01)WWCZ<{tZyJ0>?Uw}Nl=#3YLot$)nQG$WNdKsWo3pW_MKxTD$pIk97?y3_KtI& zmqm2&8=q)-eXL{!7Ksdj+_Uj^tYI`@)fb*Y5TQTbFF5J^2gTi82hjIla1*&gOBXtYO+KqvJQXRmefmREG& z{)q~SSOh#9LJPIsE3Ov%6aw5VZ=0nOokN8(B#zgKA1*eQio+Ng>@g-6qL56^%~?Zg z* z^pU(CEwjctVNvdjCv7`?_GYM;Dgd9f1M|^RNH!DZEMD{N-|zdTl#FTZ30*Gq>A(}v zMuB@cMYD2>#FiVL@%LG}Z(bSaHUk62fmNkmaiuJYQiruzRgX_MLhCR+^Zn*n56NTN zC5jBVxly5kL|}kV@yYcUkN@P&+~wdki!&OW7wdU9c(-iSvK+RdGG~kf7&WZGtkyY{ z?iicDQvyzzl&`e7K_&qm5MkmxUA(xPjm?zUTORYRk3_O0?wC%JR!PHyFtY^Z7u}oN zpVyM<&x)Lv4U_z8AaUKe$prL^ir{&H6>=Oab^V#&F3$W3i(_PXN@``4tOR4p>{IEZ z%Xy!Zri&H7#nQ++m>iEQ-7-NHOoa6U8(p45=bz^pGS2SQL8GWGwNBUNUeeglli_jq z=m8D3xI3wIyg1++^@(phVH8)M_b6Foe5pfDW%Rs5i#@XBqb8LoESa>#R8`C}oRS6P;xZ@)ZGZpHMqBc=X`~sjQfz43a3Og&f9fVSgktz_sZ%vg>BE9fA4= zZn50d=b<9>66>j*roN40&BQ42Zqp&VRF)lZuJ}c3mrB(z^i&(PBpm@if*INxY#*21 z=BRnz&Mj_#9#tP>7zI|IltTh9q)+e5wvUyLk^1|DH7k_$L(;Jv4ewfe3`a#$G}R&( zjC9y+)b8aaHSxbYGy9BTzpPkI(Pim$nX3hgYz>DsJI-dywTkMG!ukM;09mA+=djWU za}c0K$4TNl<@4XpK9f4di(>NbJmhXhSsY;(6ST!uPZxWGG3P40l4nw{vmJt`>udrZ za#MIgCQbHxxYl-K*sDk-Ck9P>{JBwL6kHG=&?c27eK*3m^g}j__1qq5ry}dlS+mU= zQMAB|AaT_weKzB@p^ZbS#-aKl{2g)v`L3 zY#*1Wv8xLGJiJqjj678zQAfw8YOX8bY6n6S72c^T``BnW7!Sf~Hd;g~8$|V5d)#&V zK-!^+5|$>=j`10zheDGI30PPe_Iv!s-Puzk72f^;tS7r{r`Z||qtZ>{`w5RjSjP84 zs-scp@otkZ8VZEOdJ>gB4_AbEfR0zT6-SefwF}zgulxO8@09J_VzJeSYL?McMv7!v z2o^hrvP`g*6?KJiq2(7|}|HkkP~YnaA*(i>hDHE@?_dqZN2&E%bKil96a zq~no)i2N|~bWxs1s_-_99W(V@{q8(i*`$X7ryRy&d=8$JskZpEp^&4l+=+%Ukumk}mZB$wPYQ*-Q z9rA_iy@&?`aw~085TQaZzS=N~6AAd)Wg)ar(i#H4D#G$?wSQu?ac3b~1ZCtBvnV<~ zt>4scx}Fv!ubn$2CVgh3f+^LM8D&h_lt|;oaN|-vsotcs=0*K>wO0|Msd^9I42c$s z&P?3m=ZgG}jp6H4B?fJZX}9?!JOKp(%1=RCVWzNxERia3pWmP`9!=WD-l&%Ht_3xa zupBL1~vPKci4`uquz{FIQ85w7=U7*mP9cPP? z#rqJn%3>{QWK?07(;%up=UhHcN4-(SHH^uqK1{Ft$Z4IggcZkVv)^RjRMk<~x(^VXfh5hD*?Da`oS2oZtKO_T*9 zhw^%Kyh6%FCMTF$PX_Zy@h@h(^2_=bB{D7wg}3P<2U+HkQDj>g{}6HF<+ttL$WHBU zh@%O`MFfBHIOM*(REPCC+uxBKt#wbkHhZd~C3QMV;6ja97F(!P^W=JElPchT`j!Jl zc8S?RBZk91pasg5(0xXg9`T+5+q1_$_58$Kg<(a&6Afn};vvKqE9G%wHKC&Ff8U*d z(mMOzxN+;^!>C!j|VHJa^b@bavW%A z+!+5fO&=%V?Jf%2%+eZz>2UH`mBHu_WyOi95K?bfz1-;G8vAymyRlays4;cTmajkn z?q_PNRwWuxKDZcHU#MlOg04OjG|RMqS&$-m8Pka^42x-FnDhxYuqb%HV0Onp&^ zKow+nkr4$VD$Jv31X5J!6q*ldhZd|peBlDWA?=*A7?OrA0s2}Ngjq-u(Tzz;l4RD| z+jWnoUZ1Lg-7@hN~*=_ zhaBeI88Yufef*zYk^VShXEt{f2dN-!B-%`UDBNVfcD;Y0)kqTeCFA2{SOK*Ybz}!= zQAUUsqAu6pzR0^f-&9~QDVJtrdm6| zrVuMS;_=nAhzf}~6k>K)a3j57peFxNRnpPiF#&nD%rZTWhc2U4=^x2!Gy11%rw&Z% z;-5R@t69(&W9M3Y7Q*!}OS+eXa-2iN6;kzb(b;VKYp}v6XG6>V0l6vU(4!PhxO_0e zc20{&X7ab^ZoB^4o`>z@t)Y#|7VfAhlU!(oGub)c=(Y2ZIXV{|R(PFrXGpi(J-%!i z>}SYQhEW8iN-rbrsVaNqAsXwb88xVC1krKwLXT2~_B-sPGGq<=EQV2b#gwF@+Z36K zHj0e2qr0Y&#c&*Y7b@2xM;rq2c0(@PSKDx5w(3qOTV^B6s34(&Ek;m=!0Md5#G4v4 zRk+#qUvCe|mmAv(6;WtuqRSYs(plBKNVu*@o75XPT689@V~kpb^I{6lSfnLnM{$?l zR{b`W`BO!Ek!QLV0i>%BXC5Swe%jHbfh+Nz`{_can~k!icR(gm8L`u-hx>FW5qngo zb52qF>O1GtoZ6qq64=ZoBivr#@8(cKn!7V&{lm)>p#sJdxOe!hb zPD<-mM0Tg&eur@byja6OTxGX5oY^pO18c+5{)uI6MD*uRy?&Gb$_Q3Jx{leBapP9- z|1urQc38u50T#qVRU%ZTkH#QRBt%?jFR3=HKz}mgafp<=W4J=261598a{dxkF=aeg zU$4)adp$K63BXsOf1p&>`}E3G$hMEv0lh4Ofw!@|{H>$ezpY#Spft}ddzL2@JSR8XT9 zZ;XN!6Up@m2?O#KimYel3pBe|7{-r6@l6?Qi542AJcLjii7?YOH8s2}kiI6Ze!f`3 z(wU1<(h36Y049QKbdat{*cwo1(oUZty?;>}MIdl3j5r#dv_j}GsypOHS>XKkHb=Nx zbVlK6p*N!bCK8`QN7WDY8zmj%2^;r#s~4P+a&uF|dU7L7luU%qrk^WxSp8m)T~(9q zJy-FDJt;`aN>Wi0V~WU3pC=2YL2Dqe2cbjoTmyS!dwk?3t4HijO$|&{ zoL``r&CS0M^57_g8^tsvUyfYeFZOuGC{Vz8vDjdvva+Y9`SrfSJ`C~j!e|_tymTRQ z9GR)zT$71~@q<~`NEk)Fjl7W2CrU-4d&>C+n`%&Zs5%wiP84!EWHFov@&m6-&$R$a zVtSU*+bLCNwtsX+Y%#WH&F03*^ghxRq^&?}5_#x8{>u|A z;_Hb#I|0EA*$Vw0WrczaxsC>7t_RNe(Txw#1|i}Du@5~;oSa@G7jQEbUhgjpNc+_K z-3aQrmh}3N*@Vc8DTk>cM@qI zXUCY*WNv&P-yLNqcA81db*1mj=BdSKF{9Xzj!SC)J1M!fxwRZf}w0 zMH{lGR-?<&pIx_TkAfH=T2KOTpoi(R=uF{o02cSWKbtE~KoHY!@Y)gL}95fGX3T(XmE zJa2%HCmbmFx^^4TcvaUGSLe2WbnIDG35;}Kh&mONTj)5Mm9~UQk33tNdaglkI+|sy z86_`aMAL&KK%>xzl*w$A#H3>AVd~yrFI@Ll7Y4%2uj7Q;tjZv|kVV#D{cdEb=jpJa z`1hb5u}}I=B*{u|G-?QPOIROK>^U=o?e|`&Hmoh?=rtY$2w`NI^>}^X>@kW|V|~RW z!$-)qNsp8lQ5Ehi45627Dxu*unNu6XACqM(Ie@o0XCnE{Pti zO~B2o^#u38$o(F)7{eq}FofZ6v&9y3^}e;{wdU@Oa*6{_ksC;8t@`i=| z6FXXOjX51Vd@^BP`pAk2OIO730ellyB7DWrEe5T`WrR{TI*#XQUtl$?SuEs?|Gq+4 z?UC8yIT*wv$|x5>5d;r&Y96uQ`>WF|ePIR4;)+GHCGP~$auj3!2y>Fa)X~N2dFZc8ImWa0HM-xv zsL0MlD25owMW>%~VO;XbW5fhX49LyJtf}2bU3G(DTEiW`U(E~YjN&r<5Yztn!$P&l ztcT9b9_(J#DA9K1`7xbNVlXuULz!$0L}C~GcB0>1CCPcAeD3Coz5EJquwQ58QHV{` z9i!9bn7%~l!L(W~3|=WnEI7aC7xXd^Xwd-I!gQA$1GlbIXcnW;P*gon`170C;hPG( zU8ad1H6j!nGXnE;qgfc4)EQOr-YHWP&;M3nxS*p9Z%o7>lTtNm1ZF=m#>!(`I7&pj z7}cpbaiDvz_VCtv=&H@A(#2s6cF7Ve_Lv}KEHv&y9qgL7Dq@5wrz;k}hN_1c6MOg> zevW__@hT5dj7|Gz!w(1QGoNp3uX$dBXj!Rrxs>)1J`8!q>M$jR+H}ea=bL}*)8a|L z!ra+;KFqtxSW0I52xb#81W{LHsyO@=`_h?mn4j<`^Q zcG5dt!o!>2{w6W$kSTyD4Zka9B#Xn2CCOL>V4)h3_uC(TE;yE9et4aSwABKs;}K;_ z%&j8roidqrFJQC*341b)w5GxU+OOSd@ujl`iUG0 zQy!2f%2h`3xGa}SXx-@N-{}&5p{rk|cz&DL>z|Hpn2yvfv6f-xz6{?(8|Crsm=cx! z(Jg%G{GYq?h#=yB2v%Ec>}ZU)#$u$NiX_R+V%;{O`}=ais+W=)I;UG`5gYq2#_Q-v zO%z@TvyJ+8a|W<^f7AWEbm6-tI#Vc~nK;G+qOdvXA!g9gP6RX0|EK$inTT2K=9+VP zblgZz8Kva1l!S}Gg6J5Y>kciWGIba0-_!Mev_~#N+0DgV!67wld=o|(^~hOM75X>U z=-eM(dhd|;tjGbcg|ET@B>z;1 zj2S6bs=4~vA(?8*-(PHKa9>YFIY^9qD;6;inv#C%lpHpLwzNN|*iGoVb+?5L`R7pP zv^dCETvr03LV5_QxnzlLw4Q+P8%r3D&8>Lrt@U;(+s+G@xlSovR2grBg@Z5EVNBF? z*1AWsK&Y7i)w}b(lZvy9a*KoC0zuZZEj-u@2*|0RTAfu_Z~gn}(-m(?Rv6KULsP^e zX3PmbAQn@!MW&}TsLVPu&U0XPdVUp}O%eGxmM=CIhDQguN@f_@f+%Xt7|Dkef7c>I zedafL8noBsx+NAi{uU=J(P5N0!GaN6)18|4Pj?&KFJ!NtB=W-U#&N_DFQqua!hH&p zudz!^H1+T7AFJvMmcIURmR(iEq{@t8!yi~Of#L_p74Va)3m;tF%St?5@s8rG%`h5< zgjq3<$18)an;sAKSLCjeyly_wa4fq6qlGGLGfXYUvoVP2BSq1yFxOI&Rh3wMPN9VSqm)b5)$W*0&(2g+)4c0FU()pxZT(3G88F{4(18at|cUl zB%+8goja!HS$@6wr2~ZF&kL^>qHc@1Q(V9b3Hc5_GtO(|Ddcmfp5HKhiSb0y<8<`X zTVB|7Y~#1~wEl@3!tX}+{`}c1|9VR2u3!8g?HR={1`8$;X)-1Xg=lOurwna9*Du)$ zg+wreEfysvR^(T7VcMav&lAN+7!HCaNgbvNsQQ}m&vCuo-(30Wn6VChfCx_(Gm^)F zeCjc|aV@C7(D1;z=Aa=rNn#C7H)5J3l-?FIawKOYp~@0*Em=j|&(~+hz?&Va&gF$M z1c9;=-X<2e{FE4BB-({^P4*k5vlEYgYx+eLR$&ke@&rGoq*)=OhZj+ASDnA|&9@CN zZq%90dYq}U4b$il7K%VH7;+c{s%x3wpUkak|5GArabRXi4{1e>4Ju+(deMW=ociL5 z-QvX!YrQWDhzhAPXy>_HJ1t@g0Vi9JyN2qCFRu`8`*5-G-FHj!QfVtjo=$~?!qKEY zN~c$$64v6;TS@7Q-sY+)=L0B0T6{~asM_cu_s}A7S$c@ZZELlHg9h*OXnsYWu5=aX9}O{bG3{VmtnQB&<<4`b*{bS@aJ1s znE#mO=4MN|Mww2J#=%IoCP8OZwv3cz<%Pny_;UA!1p8WQ_C&Q`8N&UHGJFMgqYRc) zkA|MI&7QRFo6odYvS+{gQDnLveS8Qp#`EJKiz?(Wc2)Luck+wdGP63oQ|(+m2JX3| zG53tM!Y+sjg}CpHF^Y!MC%RX-C89qA5d=Qay^&%br3@|6muV)-3yepxm(flBD{w&-=rII7Pa%7=vo3f?|T8;PizUQ8k9`p6PRs z{z#eK-inx?oZ0}&KNiXd@hqcIS45Fe}$)p|Dv(*z>aJ z(J|1SEd^?4vD)Y~*M8tl1b$HFL>1kaw1A&4a0 zPhkw+!q#)12-c{mGJaA!+O~(?i7U+Yh8qG!ok)%5vzXS!;nohMSWJaccor!RA?9tI zwkC7WRF!zT1(Ud=bruMPl9^YDOfT_YkW84}e167_)i1|~m2}~MF9)EkE{sDrY25g~ zrN(ui@3Q^$XOaSAwLAx(q7h_4wnytx7DP$!SGPh}+ar}c+n|to9GERsQa-OUglZZAE zb{HHD%)Ju3p~P%V;V+A~e{=LX!}W*tZ75Y?7I-AS1EHT!QwE{%EqYP3yZt;tcDuKa z(da{Es0uRbgAGMYgN7*KFx!d(hQ$)W&4a<1EMp{8M#dxNMC2%EB0j7b{ZgMcsrsFU zo~m<)qzZ-Fg_bk!1-we;mtp_Tjomcy1j?;~g}t|;Pe{Y-Y*e_4AAB3wMTR^0j~q(GnHb>V3CLx8xnE?FtMHmEOP9 zuot(kNjwI-Gn3hR903Dot)m-a=AGTr-F5#+pkv_X;|E7`>*u?W_W;M4fil51CEzNi zfQ<{Z4KFOZ^!3eqg*~0NM}gtTy=J#5_}{C_xX_H_!4_zRxUi`psvEx8b8E(tt6i-n z-wm8CuDO)7$yvb%JOI1wzfd(40dNI=kkm`IEnf52qm$FFb_Lcw`p^3Z8kaZ9b$ACB z0|Al1JXI^<3M8|}NG?uZ)7e>CGT3~tIQ83C_MZ>yDu6P>F2_T0<2}KJeZ`$}nlNmt zJ}}r>Tyng-VBo~jTbn;>&;_xZ*hqjWV3Cj!?5I#6Ay3yEF1>Sh+L7AsX>~)TrE7*W zlNxb{9d|2%dBEVe0DDsaBn+n;N3{3g<7vl-Itz|858uB3{ntRf!M$b)&~EVRe0(>u zCH#*$v!oZ_nti+D{$Opv{S&vFx6dPJ=CZp^f?Z_bK(L=e4hwWD!WSlI-d_Lp!=bL$ z;%WW8&mEjHcNex(h&=?T5+2DscxD1EAlr7GznD6HRmX{@t!YDBONZCIugJyfab23l z;HyO8uBwo)(`o^6rZ<1_^7`hhogD*pJ%2Ch{N`6(BcRFLc$Ea|$!@Y{3fOiSU&Xkb zDQ~Sg@j%^G*Ku;%-(LL@Xb#vV373W4k#K+$fwR|Yg#_W%hI8&7UN>CVHF)B9X?NWZ zm*$$axM1wm;$0vjVz!nPjAH3bZmqlM#_g@Ej^FF)F73GgaK**z|4Yk}IBU!B89WW@ zE?{9t#e`Y<#m9Tbrw-H>T;15*UE2HVSM8hRfb~dlvvBj)iOpn$U(68@+J;&B?;i}; z_4MRDUD{dt?QI!t#v4%-j=WqPHIr4w0I|5{2qcC{RhNqI-DAE!uldp0$BP;WY$q;? zYb7{Hd`OGS;5Z}soLQ3>4*c!4X-x(F-FXAI*9u zL83J%%wMf}Ja{{eQO&;%_Fk#}M6TP!`Ttgd6ZHhYiA0_+avSsq-`KjNuB#vRqok|* zo%eu|QNaiFJ01yC73S>m-CC_~mm%{BXwXo8-~EAsTkEgnRvRQ*N;?zCD2&X(D9wZx zQ2^|5=URXJ`1s?r-mPgpuu9ukspw52Z5fFlV}}^Ar|@|lp%<7AA3M0`=-~aq=AqKR zrw*McYTrZvkDFjl5yqn&;4ipYFOU#=!zTv~?xmgq ztn=%kg25x-toc}BqP2G1`WG^IK4sV?d{zXkPZ3=;hDF8=hhJh`HQ#91x4Qnb z9n)(RRb_5Xzf|?ZmD|goeRj~5n$9ce|BeBGuLK##*1LZ!KLo?&#Iq8pCm>*q#EC(L z!mki7^&b1CV6Z8zqxN~Qj}%RPR zft054X7{SE2lt#YYb%&K3&3N__!2fgUC!Xh2msW;)qVA5-QexKro62nyzAOg*ZZom z3aB(D?Gs-FA&ue#W(+*(kY;w&%}Q)r$-2d+D%Eve*54a zgHv=Fn6U*XPV8B%AmxnhV=#??cE$pL7;G?uI-)b}s>&HM_7~Kqv;ut2)-&VC!;1#z zF5uKXQ5l#OY#>Vzh24ZMYIn^&`rL%>8I4W(YXRt-w(9oqD~lEaG70g6n9ulKyd+ja zG3U(&{<(SEr6WgbfdmMufR!mF_xD_EpeqpgFiHkz{$%ZlXz-e1iBMNnwfK(*d9?uK zEC7ws?d~h9chNe?EX)j^3r;UY6^z&ko`3;P*6#s}M@Ms71pEbgJ9dmO`gM|oLIl8i z@|JiwJ{k2y>B|9+(eUSwrCk6iOUwVR*4A~rw|DX!E9^YH5I~vmp3Lds3n+ji2*kRt zaz28HrsTI??owm9q($+2S-Ds@5J_RPZ$(j66)s!3kMb=j>6L^#!GP!=Pg|Ppssrc z-p>!-n5&(=AAj$4ixCdMlR+bJ?0oDbj3$GxMw@q^d~NN$m1(xl3ATdfdn?ZFS7=>x z*jgMR^CwGy4ae^=KAm!IlJ714w0YHut?FeRc+a8r%_pn$5J8A6)C=Mk?;Ih z3!47u{m|>x!W>f!92p}f3YeD&44<~a-+1zwZ+w1fq118@}y3k2+?UAG2K z3{1%Xqsf+5QrmGP@aK(vgh|JQ0XRs6)Crix!|O7UfkZE)7oFTZ2m{dwn7q8&>5tca zV*siM1Xc$mEbKVD49~`|!tIDjXJgTd3tPL6=XXD!lK)44N%P~EuFR^}>8K}e6f(=0 zA4KCgRIOH|tuW7Cz2?aA?i2ulcBgcg+}`r-+)Z+)7S>9OQ=ypEV^ImNa-f%p4T_@M zs{j!PPS0j_M{PmJPZzyj#0NTT!;{m&>Jy-6SPB9rgVa#7vKT;s-}!)dRdW3CD~}fB z3bh0QZ9#bU{}2Da;T%QH8MkoX{jcx!8Xeeh%|)(rxWtF0x+dvASXp1%vWLxS_e!=Vm%O*llIm@{e=chZ}Oe=8W=qR#J( zYqI6lc0BmCp+Q6fH;M5rEC>q;xnevGB*jG&RnOf0reu)e`vjTD<)PtMuJ2PYfNff+ z4_3hZMnW0jVW@KaU%hnl)cc*_z5+C1q@=ds$jSRfv;uTU5`H;kidnXRm4LH?J_xv4 zdhW^Fr3KBl?v%XE&7H4Jd-dpCfXTocLSC^au;5s|6OstYq83Q2ega-u=kqq0tFD3C zpN8iVyL2u@WQ-YvF=2iMjt>DmL|m9D-ILYR9T~DkF8|Tob!4FPAiW96k(P;{fV`N% zcps=dTPsYUF*5ni$0v5cJ9NiE?~iv67n{GYkjP>0VMFkK5L+P5K{;lEl}@;6Qq|-5 zPDa9Q0Ct`J_|*^JMIT?pga{CA7@sG*f^%n)$g&jA?0xA$>hZ4rwUFA@q5Oxvk5)_u zwhX{KAt%7+dy26@SUbrF_7Sbfz4&llM}O&r=b@biAe8!To3MhxuYoax0y93a41Y4( zL(!6I!@I@9btO%Jw{J=*{af>|ciU%)Ntje986#Bb`EZMc1}q7uC5^P_w_I3NI48B4~dUH zv6{^BFu%*!*@;gkzd3N?=GBxAA3R`l>D1J(?$Q4TydOy2e@zNwfgpt>xQmcankO$I zyO=;jkePM#a1-%)-|joXMFH8ix%6-Sg#5}|zm@)JnsoBkh)b_YU9a?{Tt0Jf-GQ$j z4F9%BltBo0TL^a?WCD20;35Mn96-=3BW)X41VQZBEGTB|!?IR&Jn)WNdmh`Xz)}oQ zA&CY|37}(O(3-6h0RB5W+_EUcpQa@{<&xI#HrK}0TKZ2R4qJGxk8lI-*9Tx>KEv#U zzalo9Y(zpjMTuPxGD>^$0nZy((Ug1@N7Ng2JU~zhB+Koq)GiZLw%UNaoFR#eV^eLL zN7z+gPX*4{=4M-~4a{yExCy&>%Nu<4PGry6X@-adAn29AG>1EK62PA_Tzk2=q`&j| z{L@{HVA$zS``0sD0Hf%~XpV#SS5zq=R z1)i@)z&_0|yfFOMPq8)8ALh&&0RK&1W&Y*OTT@zlx|{8(&meRX0?9h@34I9L6L zzW%TiI^EbLz^U0*zV_3|Oj#@`WQhS~?L57VA$yI*rXoJ-s*$D3;)I{iESJ0k602ML z&*c0Pl^~bz>b_Q?N;wTWXN1aNUtR|Ky9`?bLV7~yp7g`Cug|8G)TvLWwAfnm^Y5)2 zaZwTGC6I`#wGz5)e3h0|%Vbe3dR=9#>cbQBhHvcqt+%2!zqD)5dd|B9>P!+O ziP%Vo7*AIxWAQMO6{0sy9qVf=hisSqS5uPvQ&KvYa9@gvppPkAnuvvCD^F`cyO^N@ zcDHuKDLTHoHF-uLzw0U(-9BLiXva5&Kj2;%(v~uz8Zg^{Do?xM&4eN)Bl=TpE4 z+u=xpV)m>$=-8`uqk0BY%()^^4<)-FqdgznnBAgB<4`hpD&19G|zd`Q5#kHA%d z1jl>qyB)QET+P3H85Bfujs4y0xG$SENP8GMvo^3_;L%{5h1Xn~VsmcLKmFq_<*eoi zOunVBf5fJ!a`~`QB(fi=tJ=AM_nSGcwKYEy=~m|pM!zIP{T(D|fI??J3nKUg2CyGI zbR2ff$TGu^Q%d1nIzZ5O8QH|j;oy7KW(Kj3WsGRCI~fe?CAKO9bk!Y)o@&nkk2+Au z>n5n<0E~W0FiP-`cjxC$kXfw~XuxSuiD5mID%tJRib)}%&-DE50|p^Et}z)>-f^Vv z_X)xxbW15WSP5G3Zy0JLqiWW~#1t)Cv+d2XBICUd@YS_;`Jxc)|6}IopMADVOTuiT zCYJ%yUPer94Av>7!`%(Tge{$U&H4GKnH@#`)F1VK4Kh6^$^nee@&mUg}}M^Ij#Q10xi zjRU6swAv9%{`a~10LKbu3LC@C!f;Y8OZG#S+D4#^p^@qu;~!$e78Mbs z1b82LU`Fz_MM4RvXB!qS-r8{j(CW!P80uyDL-&3+t94*ABy})CfQ_$g1?`&+Y%zY0 zTd;HV8@k3=sGc@&dd_@MOEQURtal%8t;IlG2$sV@9sf3Oe%$_)a6*%Vs#hkk!9= z@wnhuOqcKp4)!Di>|qQ=F+)W}isLvH?hzi@SK1}ziyyDKedRw@Isf({-23iI+j2Kb zl1>t(3s9?8f){tGvhp;uKNOPns!c~yh7iw!68`oT5Z&(UiE{qn$2^V9$XMN(43)T6 z4AKgm1&V}Gtm!ss22XhRH;^hm>OEFb*|oW;bKtWNr4k8=BC6n1FZF_}LAdr3JOeBOs`qakxUuiRz7um%Mh`UU>C3Sr?B7JRVm_Y^(CdC zt<9Nt<6ltaL_wE^Fd8c(NSvu;wqw~7x@%RO4}~O_)}3^8?X8r8#?6iX%B8K#;vgRR z_gbFw0o#m^o*)}sw3V%Dwk9Ulp%L&Zp*rP0 z`$kX{5xBAIot_h=`}XGKEXrUQcY0F4nQ;D$7-~uiKqoGChTzX(U-=H3%}PqFx~IBk ziLk+fi8=G;<;=Ua@8ky1q`y>oO?n9L9tT2T#BAcq5GaqZ2^Q$0R#&}vck=z?moFC} z?prp&!kCW_*f(tCXnsOEjZ+85A>RT1R8W>`6G2jEOIL}SB}#3&;ozjZ@4tV2-6O57 ztEo5T@F63@em`4_kSY=K0-9}xtOrRbij9Qfhm;RiJ`dhPH7Gl8-M+N%KgUPEfO+(& zbOK}_Oc0N-2Sz*ss}IjT0ldrlW0l%t`|dK-^Ye0I)Du#MKDzBNyBYF5(RcSf{$}_F$n6nRG!+aSdv>y}f{)%rxl9~eo{R){DgKd|?99NG$Xadm`+84FZSqxEY>?Y; z_SdEL{IfxWv5W+ra4D=OCHU{(-2n6X-BamW!Khgi zvh<(YBHCqO8G))KP#}h1$_Jhx0tul=|7P(1eN?&f^TWNz_V2&@_Q{^8{f7X|7^TDh z!d)XWW@jve_AV8G?|lTE()fSICRDAzc=6Ky{da~DJLT2&zT9fA5WrBe#8EP_b1C?X zA^EY$!x>Rg2tOHit-! z9KMxkxN!rvu6O@u;6eFxb&`0pUjT>7sJjf`z%Xxuq83TtDVHbuk7rx|sI?{6#`*k? z*0ciu?Y}?&9u4>EBxP0zI;?dvD^UO;1HV&cmtaJw%{_MxYvz>~w?GP2xAsG;YK8Gt`G2@JhSC{?IJPAP~F<6bq38BPW122jyq2E!-Ua%Ps`iQBjM* zKs}tZ?(t_)68Wc}6$$ljH#^b>6Q2PdWBeAFdlJ#45EHX9vmR#IdQw1x3R4DV(EO5t zoA2Efxy2~^Wh}+gD=jeE(0qSotJYRflTf^GlcbzY9|Obsx(0|Ze-=x-{HO&w;*2mF zuE7>DvPI%#P<0Rr2=l^U)|^y7-{`~^asS%~8mRzYlqqIp)QfemCoei+u5y~3>1fzX z$W05MdvzrkmXiHbChgx>wf_D2`=WM!UPRF>f?~L~Vlk3}5=3hvJA!OkrR2K^)fuhH z@VIyQcKg2He#&Ug2P5s{s|wvN0--Qi67lZP5`M-qWVUKStbe?X=I-qT&$>Ep3S)uS z+}L;gsZso8i@aRcAyBX}$p~x}bBwS;pb;CviQD&ZK2Au}D>IT}PV7#2N7=Anyh7j|L`!S{CaI z!Jt|}7b?@8c>M1Yc1+a9Hsen<-w$`JZ+-cs@@re;wf-s2$~TYQxf*tSo81?6>e;6B zbJN#?S}$#7+VI!6uATm0G@L<1ftCOYm3&me2^1E~!Om);lZ;|Y^})lw;NX`3;T0m# z?iy&W)WmpYicxm7+Dv1j(y4Tmt(dYU6AqM@fs?|xIsQ>#+SW8|e*V9%mb5w&La{aN za-AKmJWdooNusBKq8n43cj@e#X1#FWaY^g%{{qij%gn2tY3FYHRk;#-!k2;#^9g*4 zq!R&-)i-|ebGZ%)V^*$3VI1(C(B+4sU$ITycx1u?HK0jm&+;ie_V e7|th2ftrt21>&b|tn6xDi`kD`w~WTQs- diff --git a/test/test_AudioIO.jl b/test/test_AudioIO.jl index 7d03f49..64de9d3 100644 --- a/test/test_AudioIO.jl +++ b/test/test_AudioIO.jl @@ -73,15 +73,25 @@ stop(node) process(test_stream) @test process(test_stream) == zeros(AudioIO.AudioSample, TEST_BUF_SIZE) -info("Testing libsndfile read") -samplerate = 44100 -freq = 440 -t = linspace(0, 2, 2 * samplerate) -phase = 2 * pi * freq * t -reference = int16((2 ^ 15 - 1) * sin(phase)) +for ext in ["wav", "flac"] + info("Testing $ext file write/read") -f = af_open("test/sinwave.flac") -@test f.sfinfo.channels == 1 -@test f.sfinfo.frames == 2 * samplerate -actual = read(f, 2 * samplerate) -@test_approx_eq(reference, actual) + fname = "test/sinwave.$ext" + + samplerate = 44100 + freq = 440 + t = [0 : 2 * samplerate - 1] / samplerate + phase = 2 * pi * freq * t + reference = int16((2 ^ 15 - 1) * sin(phase)) + + af_open(fname, "w") do f + write(f, reference) + end + + af_open(fname) do f + @test f.sfinfo.channels == 1 + @test f.sfinfo.frames == 2 * samplerate + actual = read(f, 2 * samplerate) + @test_approx_eq(reference, actual) + end +end