From c38f6072cc43f7abcba5b3476f1496dcf822be99 Mon Sep 17 00:00:00 2001 From: Alexander Levin Date: Sat, 12 Sep 2009 21:19:17 +0000 Subject: [PATCH] UI improvements for the pitch detector (ongoing work by David Johnston from FS#8768) git-svn-id: svn://svn.rockbox.org/rockbox/trunk@22685 a1c6a512-1295-4272-9138-f99709370657 --- apps/plugins/bitmaps/native/SOURCES | 21 + .../bitmaps/native/pitch_notes.128x128x16.bmp | Bin 0 -> 64856 bytes .../bitmaps/native/pitch_notes.128x96x2.bmp | Bin 0 -> 14472 bytes .../bitmaps/native/pitch_notes.132x80x16.bmp | Bin 0 -> 26552 bytes .../bitmaps/native/pitch_notes.160x128x16.bmp | Bin 0 -> 64856 bytes .../bitmaps/native/pitch_notes.160x128x2.bmp | Bin 0 -> 21672 bytes .../bitmaps/native/pitch_notes.176x132x16.bmp | Bin 0 -> 64856 bytes .../bitmaps/native/pitch_notes.176x220x16.bmp | Bin 0 -> 204176 bytes .../bitmaps/native/pitch_notes.220x176x16.bmp | Bin 0 -> 121016 bytes .../bitmaps/native/pitch_notes.320x240x16.bmp | Bin 0 -> 248456 bytes apps/plugins/pitch_detector.c | 581 ++++++++++-------- 11 files changed, 340 insertions(+), 262 deletions(-) create mode 100644 apps/plugins/bitmaps/native/pitch_notes.128x128x16.bmp create mode 100644 apps/plugins/bitmaps/native/pitch_notes.128x96x2.bmp create mode 100644 apps/plugins/bitmaps/native/pitch_notes.132x80x16.bmp create mode 100644 apps/plugins/bitmaps/native/pitch_notes.160x128x16.bmp create mode 100644 apps/plugins/bitmaps/native/pitch_notes.160x128x2.bmp create mode 100644 apps/plugins/bitmaps/native/pitch_notes.176x132x16.bmp create mode 100644 apps/plugins/bitmaps/native/pitch_notes.176x220x16.bmp create mode 100644 apps/plugins/bitmaps/native/pitch_notes.220x176x16.bmp create mode 100644 apps/plugins/bitmaps/native/pitch_notes.320x240x16.bmp diff --git a/apps/plugins/bitmaps/native/SOURCES b/apps/plugins/bitmaps/native/SOURCES index 4d4cee074a..9f0897d48a 100644 --- a/apps/plugins/bitmaps/native/SOURCES +++ b/apps/plugins/bitmaps/native/SOURCES @@ -826,5 +826,26 @@ rockboxlogo.91x32x1.bmp #endif #endif +/* Pitch detector */ +#if (LCD_WIDTH >= 320) && (LCD_HEIGHT >= 240) && (LCD_DEPTH >= 16) +pitch_notes.320x240x16.bmp +#elif (LCD_WIDTH >= 220) && (LCD_HEIGHT >= 176) && (LCD_DEPTH >= 16) +pitch_notes.220x176x16.bmp +#elif (LCD_WIDTH >= 176) && (LCD_HEIGHT >= 132) && (LCD_DEPTH >= 16) +pitch_notes.176x132x16.bmp +#elif (LCD_WIDTH >= 160) && (LCD_HEIGHT >= 128) && (LCD_DEPTH >= 16) +pitch_notes.160x128x16.bmp +#elif (LCD_WIDTH >= 128) && (LCD_HEIGHT >= 128) && (LCD_DEPTH >= 16) +pitch_notes.128x128x16.bmp +#elif (LCD_WIDTH >= 160) && (LCD_HEIGHT >= 128) && (LCD_DEPTH >= 2) +pitch_notes.160x128x2.bmp +#elif (LCD_WIDTH >= 138) && (LCD_HEIGHT >= 110) && (LCD_DEPTH >= 2) +pitch_notes.160x128x2.bmp +#elif (LCD_WIDTH >= 132) && (LCD_HEIGHT >= 80) && (LCD_DEPTH >= 16) +pitch_notes.132x80x16.bmp +#elif (LCD_WIDTH >= 112) && (LCD_HEIGHT >= 64) && (LCD_DEPTH >= 1) +/* There isn't a target currently with this screen and recording ability */ +#endif + #endif /* HAVE_LCD_BITMAP */ diff --git a/apps/plugins/bitmaps/native/pitch_notes.128x128x16.bmp b/apps/plugins/bitmaps/native/pitch_notes.128x128x16.bmp new file mode 100644 index 0000000000000000000000000000000000000000..af59728cb79f7096038191d26df13e24857f2cbd GIT binary patch literal 64856 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 literal 0 HcmV?d00001 diff --git a/apps/plugins/bitmaps/native/pitch_notes.128x96x2.bmp b/apps/plugins/bitmaps/native/pitch_notes.128x96x2.bmp new file mode 100644 index 0000000000000000000000000000000000000000..da5845610cc864441afaee5c277e14dc1b2000fe GIT binary patch literal 14472 zcmeI3Npjpq5JkI5FC5{W58?0;yw<`yFL?(Y#b@Cq>70H}H2_U_Q<6~=YfL))q+V6%-8&4%|# zv4TD#VDvf|BMhb<1(OxiNabiwj(W|pV5Dcwv0x-EHJe@Gd|^5lmW1a{S~@tXa-=5psi!(hg&dEhLwY7fs7Fy&O7-acq*luVFwsl;(Y!Zz9peaN zxpimm-f?{IdO4N7D)QL-;>ZfMUG?hNy0@NHM`|zY)sfme#nB7mkzCd;>#?#+_pkY> zUvsio_`}^ex0`kg66Uv8iPt;9scz#uvri4=ZOEM{5z3oV#L~(ADh*P%%?c=n-LBj~ z58EmF&2Gydd+d5>6g}!lyicBvf;GK77Rr1#^;Y?l$sfnLujJ1?>dHNjGN6|mSy{y! zoGdM^T*{$3@yPF`e3(V(9XksCAz*;VX z(~Q`M%_>Gi!Kq!7Yia{$as$@&RBo_3=xO2(IWy~v9E}=>MG?c^nsF1eDGr{x3?p%@ zGH_O?eSL>;^#;!35UCjz#T&H3n`WS>rI*!%bDg8!Gu{Bwg?v#hn~Sx;r+fdLtHk>du7FTdw!Xl^lKM zrKH0<@5~D--mlmnnw~w1alyXwV9xzQW8t6Yp*Na;ec1b-oTs8R9-J2}Yg}!Co82fp zw5$NXIajhZcHF;lsNA`gv-df&5!aTNZ_CB9daJFk`iI@5q(nN%%O_WJ^JC>D$`dWD zc#Q+2as3$1tJ53(J@bF5KUCRKyjYhbuC6a;!Ae{o%SAnT%Ur2;eKZ;m<{|_07W|u! z-hNlY(M3ayRP(6z&=b3r6CU56K(07~i|U3ezu`)pKa0r?cQkYGh5s^%pa9M}ngP_n;n?t=3y1E>@$W~@=pA#m zB!_xuIV+k&z1z6^bVF zyri0ME=CR2Q|~s|ZJb4s?ew@!#S!f5&;bjnl&I3ugUXFYD?#`C-dZFpSW|5rd-VM){R_pTbk|{1Wm7V+{bn<=!Rny za<>0j{f(+v!pg-r5UWR;Xvryd-3m8=>diHWN>d*<927-x$K|JM%c+ZE_Aw zrl+{2+2*b}E7Mv2vR&T~_2x#;%K5`N%gmu&TkQi5Rl3OwZ!=yxDp%Ln2ct1vw-~n8 zq7E7tRI97Rk&EV8iMQOFb!>fSL*?FiPE%FA2`MZd>8bZIR9ZSH|8j9B=*3TZ+MXMB z4UR*#u|gBGG{l@wDhPKFg{{Xjl2Bkhn>HG@D0m=osydz}Lg6fu5s^EIGk@nG2c&lK z%A0bUShb7P@RJdTPSfxzCnj);M)DG;H**TT1Y{C4#$qUP7Ox05!{P`& zMg&)tZgPpECLiX-hSMQSVVNZ9h*)GyBk6M4t`&pK zQ@OM}?hp-!NL@3YnK_Mw4aW>-_$ZtX%Uw1sfSpPY#W2cMJw&2hilW&yZj7RH8i^() nN`hT1{vl8Si`mYZNdl`}=fdy-r=hmwk$?67?O0N07n=GHBDZ@y literal 0 HcmV?d00001 diff --git a/apps/plugins/bitmaps/native/pitch_notes.132x80x16.bmp b/apps/plugins/bitmaps/native/pitch_notes.132x80x16.bmp new file mode 100644 index 0000000000000000000000000000000000000000..d77d25efe277fd21d6019a580c8797a25ce5ea3a GIT binary patch literal 26552 zcmeI4JC7Yj6ol7ANF;~^M1Y)FB6UJ)iHAr)LL>x42qO~Sf&daE0zx8U68-=Z0nW^i zK!TKzKR}2n&tYn7>hx=7?yND~k@os@_v!CcSNF`l-u3$VSMR)gF)yh4CjIi?68zFZT|+n(Qy9Yjf?lTDpP8!fxHVb@%Sw4HbI2gB`DH@dIoi zp&NKys}}I%#|<^%2@_xr@aSYuI~dbVM&R+vo<^{e4br$j>)GS@Py1)Exau&cy}O%q zN45LsX1a>S(Yb>irwH`g$=Si4l(nP}up9TwKjfA7)Z`&oUBi=Iv}Hhd0P<`e6(r=* zvAyKY5)5E)QE>#tg$?M20>v8@&DtYij2(D2ffcX@j25q9HfK+k{PV)jVz8cF#1uQ< z+xR>w!mRU1-AA%-{9y~xW}IW~Srs3t`^?T;@xVO6BML_)3mWWsq;+2oGHPi}Pj>45 zpr!jic<+oX>HC*!JAwWNpfN;Xb1xf!#!!&SU7{mwkD`?p$ffO zVP!X##G&SU8nYtc?E^#NvIJ{3&k1saQM?zmvskLmM!L=(jB&qGeTj{=+bul^jP{_(@g0G zJ+>J#E*h14?Amx&bb~$rTPW ziajLM*+|iq7BRUKipJQ?3KME8L4PDLKZ1{{k337<&}@3Lfu~av8>>?n(bV)+@x#i# z?t6Lm_K~_DBwL?b?KnTxdb-;@9nI{|I(w9`9+p{XZLU#IhGgqj4)oEGjiKVYi7`c$If6|t^98OpeIlUh9*a>ZiIoA zy+k4adS#gQATxOST4C$Fb_^Bjv9dpSgRM3rk3wsW8cflx4zy#+X$Qh?CvF&B$%YBK zq;|m`J7D=JoBeUF%>FtXiCv^sKohItVk&H;FAUImV9i$Q?m4NBtiAJ;t!JW>i?D)X-J;gtl!C zj%2@hTV>ISU**$ZmENLJL4ZKOGbw{#UWD05umRa7a&DyQo{6-y?mJoe41x&XfpA(c~ z&JK1~tcL^@nrzH2USQY?qp63x$1Vbjosd8)7&LVkG1?icBFuv2{|}+_24nbRR)8XYRehBtF|=tea&2Thf*j}4M8)oeK_8+A^n z`!G+ib7~0U6Zvh5qlg+ZZH0DZ9bo8X3ED)OqIztd+K%mHM-kuIHli?^5Ut;_Gm zWYmHsyOy=B|KjIu^G0S(hf-~9_}AuPqH!iqw9lRiZJv%Q1TluD7kgCdjKSDMhrsFo zhp>?iwwSsg%;zMpXi#ya6{pW^lU}^fYSnBmmp!xXp@uagW$-f5)HSoA$vm?egH1rV zJoz0ms2l_|(f}b_bfd2^X>f?(iKZ=+u0zGx^3@RJKmE8)vK`e0Y8qqPBJN@&EImP= zt(}-+&`wTlTc%0T3YM7{nb;;h&mg`n8fm5P`1%Nc!UUP7B&)^Rt-HQ<)Fz%y6&jP;Y{Xf wPmgUv)octYDaSoFW++eN46~jAc2RnJ7o*4kJGKxN^lIcBT z0&$*;L;V$a}I#ND_wLdNmnx~c)rc%h)D z^`EvnP*@2qfeJU_b3^!68H2K@OR@?;+}p* ze>Yww?&(*QyZBtdr-NLHSBZPd{JsqsN{d(6{1%2Eh~3>h3Bf6uF+_ z8QJLD$QyVh+YTNYTI$GHE51VWw&Pn|oWb&(-k2!|szUdBO}A9Jsk7vf&h+HG{C-uH zNJg#O7LUwKY$^;ErRTaG;h`$zNs}yfTW63NvOF|tl!0`U+1Bk9p7rWuhQl*zB3F(+ zQjO7mRv+B00HDtWVtWG*G00c>R2enQl3N+Zb<#(YNL%VQ#*$}*e2leLd>+X*e#3c| zXJp&K<9||12Fo6GvwD$Tr)jb3M%IZfTi5rex|BJ>F#7oUv%8dE-Zk-Wh7_Bv==+a6 z(m%o`{nu@uN9HHb@m2b)+gTp!tki9tL1w7&$PB&q;qmo+n?CfE#(etN*o~7bX{?cN!lTC0VoDRqrsj0jzQU0lRNjjb!RytDYh(+H9T+QX&Iiv{8;*=n&LQj^~)(Cw{RT)%JNt@ zyDaM1YPsnmj$q}qVlDs6x)tuPJ3MdG2dL^5o!2hLM8-p*daFjD7BZ-^Vagot4KGPzM#m@D$kL@s&UN z9DRHR{M|D@M;~7SfA`GK(Z^T7-#znl^zjw&cYlfbq2Ffkk5mPt{8N~!&-!BdCxZ3T zYKFt3%EF6ZTc7gj{AWvKmlc-A;bG~dENmZrjy|k_Z}7}WCS_s!=yUX81$={N zMjB^+STre1uU!+lmqBJbJW`F({u=t=6q~N{kEndF9pn89jQ2&?3dXW<{I2R_p2IV0 zB3Hh!J}pnk+VfB<%y!|v=n7#5X>=toVNc6W#Pq|J}qCB)g-mwhx>Qm*?ofoJaTb^ zCuGM|#4#*S`Ul%xY*v-pdhNcJb5g78N3Br#nOAme9aJm&|AycCZ`5Ndc*@f*e zf`Y?s%9cf1;ovhcbZ7&!=MPz~#jn`Yj`14uRVR3bHMdJ0vO%c3>d7q`pXeLS_6?c>40 z3&{&17loa-YH}=QLt5s?(&s@QYlNQC=kPenW9#U1^zjw&chB>%pbtLxohVgO+^0@R zaLc;c{p9!a_&;du<54qX(U(_^@+I{X(yrAke|QkPiAPO~MZZ~_c&u;EQ*n0iK!LJ2 z?L5}lfG{FXBM)S;+C*}pR^(E(P2FEp5|o&ZF{9Ra0F28QgfqusK*doz3;?HKw(>wg z?n2zyAqz;dvM_KX54uy+gkfMT@&JG?nRCVd%oqK8rPhgkN&&yS<(n&h9Fzb<@PW+t z2;FhLc);NNE5`cMpo>JFBHj_{358{nMq5@1+SwsV(FPgVEeL~F(#3&n(BxxRO~q~z zL(L$M4~Oi{LU^1xf`a7^{{>uo%M+|-e2TI>7I8EKYI9ibPt z?5U}Ce*SuDima)|I=A&s!;$DIBKY-f&r;zAagacTgas;uu=s@`^pQxb z=}C!!F%U&pfd?T|q|fx}ziT{*8jqH)tp${M5D3lNg<9dE*hVUxZk>lSpo2BJ5QvNO zv>SZypvq-N0Q~>jpI3Y7lklAiT*e^&_H$CcW2hRB76X`a`?{3?ZA=(eI*p<*Ni zR5h(4$;&tL)Wt&;EurFq_wqm` zH6a#*5~<xf1(J=<~MuvF@)&=Eo8T zQ=v9@Tx^^lOBs|1inDkx@ab@mJ22Q{&#AGZ4^E9s%^(+pPi8`uf$cVwNx=ZAoq-cV zx@mVt2M%vEY9z$gh*9Xy4f?Ez13Xn9oD^xD3l3@^FJ{M>h2jj-00}!d28zN{21*;u zPOP;hGq4@x;hdIS1teyWMwSO)7E-ox5`*mm50E%q8d-^CEZa36L~#abq$HAoY}a@! ziBj2^K^mzHJk^IsN}<|PWVTakbCfhv85j&vG6~zMY#b$xR0ig;9zm&W5`*nj2I8?` zkn`sI9pxMtY_Wh5gEf)HR39+F2bYXe?UXnGR+Drs0yv_H^yw-+<|)8z(g!n>Z4*m0 zo@-@gg@lk+s#7c&&>CEP#ubB7rC!UuSm8XeZ%{y;-s~eieh`eMT9Jp}a@aJYIH}4b z%c%|w96$Ti6GhcpSd_6Av-D}PtzKNtZedFeTX-VkP$AW`cdD&Zt5qx|TV$am)>Non zu;4G9UBOdZaG7M8U*%WDlu<$3(%(6+6{6}H#9%k|un@;jZb`aneJZ{s(Iy_JStP7A z)th*@n~q^Mx*cgM4nf}5GJle#VyYC-4XA}n&4xu;(YMu>P45LYC-_w!tgHU&qBYfV zg*mNyw3IlMYW+}7o`Tet&V2BQVI?W(jB=_(sZ?r)LbK@XYU|@tTSJ(dWZ4BPq4aU= z-eyrDRq)^e)!4Ya>PgizMsliwAPk;Gg~4LEW$NseCt2dDnWx88n>CG+buHUc-txz~ z6#})LsQ8w8SSPva-_k5%R?mw?^+eXlS^jDgf6*$TMyc?P;!x4}RIAO3JR;Q7S&Qna z$118D2%TZGDo)qcgI}Ul8QYshMb)!oQ6j0#7a!@rVo#@91>V#wI*59Fo(;8Gw`)sQ_7o;1S p#b>;fR^PJo4Td!^47T;LGahi-vOAkac&O-H;}OnEivk}X{{xs?2TA|{ literal 0 HcmV?d00001 diff --git a/apps/plugins/bitmaps/native/pitch_notes.160x128x2.bmp b/apps/plugins/bitmaps/native/pitch_notes.160x128x2.bmp new file mode 100644 index 0000000000000000000000000000000000000000..ee400902fafab914e6d6bc3f8ce2a333e730ca5d GIT binary patch literal 21672 zcmeI3OL8Pd42HYgEQnyoDOhp_7VOwD7vOY+kHN);eEmwjOEt!xa?l-NS3W*Tzm!>z z?zVsXuwV`$8O*Ndm_PlJ7;z%PRSyC_Se#&~EAj8}GjOiu3yH9cOFE3O5 zJ*Qtbzf($ENAb1slh+lI{bzk-J#_DC^|_bt)H;**>0hlrZ_{&ZEeYB4Dl7@vdmH~4 zmsaUf_N4!DA8Nn&6D_?cf;zrlOq`V8diw?nx*zj1h?Bc* zT+=|$(8i%@(?CTY!pLAW0KO0Or|9{jY182RxVw%x2BQJPx0$)K2oVjB7l7*gfB1Xb zS^9ZKW-m*F#pFA;Gc%^xw^ z-V5S&6pnA>wLO#b%Q?5Ek^7h#(%ptGN>J!uAeJV}%QvNjQA7FXT3T&(P)yL!m}1^_ zYAb@^H!g;UD~~6Y?6U+&a(HOuA3XraMTG?>HI8?>2r(Y+*${d6c&K;XTRpk^nD^aV z9&(sw-qiI(b^L5?z6bJ+9`J$ukms6tTkD5^&a`JrdX;$8Y#*r{7!v+5xR1oUdNzmF z_vJ-0vIG4jP)?iP(f%<8sDPOW1|TTfK-vs^H396ve5lE4}Pff`WwL06tvGBgnUDQb7Mf;l!{ajx zRUcY*_cpKZu|&^CzqTz!trdAzM&Gv!xm6WUKCjfXKF|8_3VhUlpvNlSaIQd0kAHBk zojw?6by42QjIYve$C+)0x1Kz&hHXFVV{5`kzOg>bOdsqv*M#g}pXZk|+jcH+yto%= z%X;hH_3N({%YLZeF4Y*Z>$UuqSL(^o8zttwsC*Aur{MmeMV!_CBKL>?b z!_WG>OMUc-xccG!?$h$YiMxjF{W`Dq$IhCfH`SS9!;gX3#^?K}-3LAMnD;F*Ui|s) zD(m9ek_it+6nMTW^Z{j?)CL~kZ1It%F$j3}fv$`Y@hpT`zL?*dcy0+#23%3b(_*p! zDUT|#04eVT$aw_Vf@=I0l=BdDmfv5`)cluulkkE6CqE0c7jSQt-dg1=*Z&*&9X?+# zEZ13nUm|kP= ze&dE7p!yr-oocwrgnx2h!^wROr-vw0G$CSlut4wR9@!S%nONIE+&ytWHvGOyNSt- z9f>mVdA9vj4iUc}V5LFK)0IX@jd?ohLskFd=Mbyg8-j~N4{zWLj5Os;K3(MDr&rg ztR6g8&6!|7EHiUZacRF9a1Iz8tM2mNDd~b^(4!+g?X2V{18egWceHgu7<;Yes!WvF z6pL-tC^XXqIaCOMTjaPW!8R!qkRckzi6E^0ba^NU9#>5eEffS`DNyFtOv<5>MoR$q zG>?HGV>^w2>5<%%pcLnC{E%^K!0P~si2;*S5+sYU9GlZ}-&VOC3Lt_G0!q~kGL})B z1$gP6E-1=PJRbPLu!)N+qMAT~wHy*E1tBdtI*c(TJjHVS%&;uN$?7a$JT%<%F*0=o zfhR^ZY=BG-RcJpb!@a681zGNBIxhY+QG$?=n{BrMumVEP>N*D*AkVg&3m)z%9VftY zIcC5+7!C0N$8to*aG%McP1hhEisG9FQK)TL{AG%aA;)-B0|-#bwwo>;aGz(}4VGi* n>O<)Zo`=Cvw%rpCka}K|EI`FQ7OICS@$6rtD{}s0=63rRo?gBQ literal 0 HcmV?d00001 diff --git a/apps/plugins/bitmaps/native/pitch_notes.176x132x16.bmp b/apps/plugins/bitmaps/native/pitch_notes.176x132x16.bmp new file mode 100644 index 0000000000000000000000000000000000000000..af59728cb79f7096038191d26df13e24857f2cbd GIT binary patch literal 64856 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 literal 0 HcmV?d00001 diff --git a/apps/plugins/bitmaps/native/pitch_notes.176x220x16.bmp b/apps/plugins/bitmaps/native/pitch_notes.176x220x16.bmp new file mode 100644 index 0000000000000000000000000000000000000000..a95ef0d6cb4e6198b34341a2bf8f0663fc460670 GIT binary patch literal 204176 zcmeHQP15B!5p04bJ63Gi6C8l;M6hSaipy{XZZt=OoUWikA=^@_RQj=8j_8MMmr9vg zS+d{vbq|04$AA9(`yam@f5V@@;Lktt=dZZ*yB~kT=*N$L;r<{0@Z;y7pBM1)-#9{n zP#_dADe&)~hiU5TCxN+8uh5>W0?;Fn*1`IG`FcQF92H0t-(@GJN47~qz> z7yvEs){1ht3*1G4gLi<8J5IAJ(gK{2FN?~U;uHi>YZzYYuAk=_;Fi18FS~V~0WyM8 zclGYs1}JkE5w89};}O7cmmNSGUk7jB0Z8sb|7w7&N3>a9G2poioh$wK`oEPs6u8ny z7rfE`2JWB_rrPy7cpZHk_b2-A^1qq;0rY#gzny+3_b2+V*!}vsgMOCeExTU^8>ir6 zIBp+&n^)h9JLJ-Gr-Pk$en;-N4}IvcEqzDsD1DYq4X`Ku3@uI#&7MwCzS&^Iw?237 zS;AC-RH7Zm8Pxu|gH*~l9lIoV6m10eEN4pJ5qW>A45v$Jo;G}l;F7v@X~S!s`NA+GYT-ok<;L%0tNG}EBA7@A|6M!9H!u6DpYx#O<#4IVHRFx z`ek0#yRyV8zUjKR+z~K{zWLdaV)hz8ahLpL|5j_Q0g%)Sd4HZVcjR}ZzZG#%t8zz- zi~n~cPI5=sHBxO{9ca_ z>?LM!*V0Gby-c-vp74Bl9tuRiZ{DX~@S@+N-=p8Xx@rGB(eKgk(eL~BsTacN_vrWN zcdu^RKTq^~^n3LC{(b6&F#0|EJ^J0NoA%EW{T}`PwSLFn4S?ib$$xFH3+`HaNU^z59pOdYqwcZSIX2YhseJogdq)PreOm>h?&{Uf=ey35W}@RO*sJ+HO6{g*5s;jSXc0IcOmuj7i@@R*pU!nh}u%iIi4 z`Si=&MH%sfLHSHrLk8a|8J^Zt*(D0QWr{XSp59tA&hYe{R&~gdFX5Xmn&ELgy|zY{ zJcY4joZ%UCDmrAzm+(y&&G5`TO<^nj|?VrX)2q)i6A-n(R4_=<}S*Ze}k3@JG7=u@(fSwX_F3Fat7Yem<&(nscaEXfV1RJVbiW>cpOi! zI%LVGaeP`R!!zhqS|dyT1Zmp!4A0EdX&j#xf-_N+nUu4&ns&=47M<7ScLb0k!#4T! zx=VEOGE5f?3oQWv2H1{M7TRDp?tkt9dkDH4M+ICVLK|-_@(p?`DgthOg*% z{fdf;ZXiMWezZ}h%QNG+UG_wbK`BXI7Qw_4LWrE~g2#e*G>i_`m zB_y`d> zdx&FhirH&Cjk}@IP=bEV3qsA|ZXk{+gUYRHOyF*CJBTa7af1omue(S2${ga5bToG| zzp62f_yq1siW$r#KAL+|(I*oh&7G;W#*E(8K{h+c(jY9GSUn{(3wJ~QDu8MLiO_&e z3(5?tI7b8w;@{pG!<@W&_8kDI>Ty8Giouu2PKP zPUc)|cql;PM3~A|9pEj6^n6p=>bk7~Be;{q5%y*7t(EePcdt8{aCx&sMiMH*NX^NF z;6DG$OGbf&I)Xc&GsEn48r-WpGhd@>Dh=RsdKEg$<6d{ARvj#SqZ1Jpa?h$@J0Q(p7i>8%&T^St1O$nZR4NM2YbTQw#;&kJsd z|&Tm~AZEp7ORouk`$G50#?y+j`gl?8~KZdeFo926=a$ z(p38MHa&jBN91Ajn@WEkeN^+y)oHu}?A0F*O?3@JV)OD@IbKLO9z2FP}$tax}{WMn6O0S3T0$Q83NnajY) zCc2zrb=B5o03yQZ>C?7~3)yQDn9YV~=Bz7h$19BSW|Ga;a%6g&YG(u70(QUXz5`?x zw4J)sEF|1bfdbS)xAswB5W#9%dF!xwwR4s{F{=nC1e9OBI%(>3;fu8VA>};rZ} zE?mO%<%-8XAD%x+f#~<>_p$;fxjmk7(eGuq$MZe<{UimV-=p8l3Y_Hjc)mx!m)#!E z_vrVN6o`J0elIIL8Xtn zFYz<8Xm~z6@2)`fJJWhgVm9e_z?gpw{TEW8Ll)G%-IgZ|?o8>Im&qMK)II86R>0kI z%M*s@%N3Wq%gf{rAnG1%l%IN7jz-f!ei*)IC3;nqzVN>flwe6*h&HZ#d2XJ9>%WYj(C?x?^*C-X~(=N&69sd(`hMy{=U_5b}4@Wvg3zQ2>z1TS~XEl(KSs|rNj zm%G##K(*o$5Ow#JeR;O1dsTt({BoE20;pCz_PX%AujQ6!3(r>-2+uEfsV{(P#bcij z&-+?#dA9I;Re|vQa+mr7s8&4o`S852<(6j)&sP-)&o6hWFMw*rW1nC6yGY+!r`gE5 zFAPi3`i>WpBA52%n`R>cEDTH0`i>WpBA52%n`R>cEDTH0`i>WpBA52%n`R>cEDTH0 z`i>WpBA52%n`R>cEDTH0`i@Cb@m(>TzN$cYez{A10aPm< z`+Rub*K*6Vh382HR)r1fxK(tT)(!6N`$LodtAeBMQFliLR@t~|-SE6)#U)jf{;Prq z)g5W~KL-7GjoghC2}6NUAQT7%Rw*#z>6|?uS5d33JA(UDPWiV*`#hJQa89@md#u%A z0>|nS@WT=js=#IjOm@OdYUEneY(V0fA2vaO`J|dwL>E*aRpx*uB&&i4?S!l7w5~hC z03?Rir4cU&+Lm0R8irJ6d*4p1t|$Q@ayy;BC{mEiJ%#zwe_AEG-p^fCLh~Y9mY+X$ zq)#sD$X!J+E8sX4ViiU3z0)hzd84&(zot-`*Y`?cdh2!pZhr5 z@6Wx-_JytEdh0OmO}2jpci#5F{c7*qE3c?KkdrtOc1!d2BAK(vOScPkULiOJTKkl$*WBBSn1rK0YPsTd{0^Nf}A8=ph-qf3< zmzr|A8=n86O%u*na3?_`tm)U0WZEV@ee2%z7ciQZ-k&>UCqcIU%@Z>1!n%_P5!MQl z%-ou`$$N!hzUUxQ$a8yZbME{O-)eZMu`~CkUC!Xlow@TxHyD2Bx;J&Yq3GLkZ*se> z=-YB9J5j=HMc{19?DW37ve*?OJ#+up`D*h=tZ38{)A-a zbqMH4{6*Y5A7@~CJ!Tfpyq0gdRRlAhITNv6C{*{s914b2hO!nJ4X8#>nZSBC?w~xV zub-M_bP>z>!57C9w$azi*xc_5*@b*lJr&HLLAq9qLxE5r6bJ6hwz?(c4JdMKkfCtTQgD z2-z+3DU6z_N}i6Zb(xFTy2wK^O~X*`GQ3yZHMkuw=y!DwbJ#xlpli^P)I?AUz7&ADd+{%KX zEHNi-@1Wmg_>;ExR_{8k?=e?YlY z3jEvMc~82qJ^8RZZ@1@df8LJAzu>_h=aruHJi^W^J-_3D{&^cdUwT9y=KQA8pXYpj z!#}U_n>PIO=r=k4Jo-(}Ka75>^FbfSs-53`T^s$$n?Kr9ESi2Tbs5{}!vLe-d;l!l zlw9~`NwOt=TATeqMF28O*mDXnPk4IL7Ur6(uNpxFU^eK0DVT^uQ#}m|_&aa)(@!yr z6hi9yDgB$qGviKz<>|ik89GfdW$-R{ZAEEfVGDL)S53lnpACP{tSW5BfZYt>NR3H_ z9bg{?7{Kl^J1Bq>xbtdCIDa1iWh~kRa%eDY06gP*LHJ^op)C57iw=;YX9E|qNU}fQ zs$yVKJ*r6}AQT7%LV-}gra;fbs5)1lR%A?;e>HLo@Tben=osF0uxx6ml)jzW?<7Mjx)eC3Ox(K0BN6kjY&w^TZ%lG z$WL;Ka@Yv^-%lLA$Q*PRT;|x8*=A&yfU@w-3_?|^Bh!jR;iXC3z&my&MFzT>ggO* zb5^O6%>w42nzKqqt$I2K)tptTWYYlt8Q1y7^=j^^VutaC+(}3XGw@BPkPCIXD_yZX zCSPa)`>=Of{*4aY`^&LU-J6I5cG*A7-A%Z+67MfM#Myy6h>$QOtiRL67388WI$wR* z%39FEB-d1iD@(Woyp1)`dJ%_K)3^&?GiAZ)<#sU%$sLOVw&5W2Ghx2O`MNXMhQ>Hr zU3Z3|fL)TK+#`tZU-v<*oBG|Qf_##3wN}ILR(IJ^Q+Pwid@Y7X4)ykvfI}HIC7SR5m2&VobyVKa&fkVVE_p=*XO|RTu+*KMawgu*&VN zaogbSa@UJ4+*LhfyDm|?_-92a zy&K$Hg>8x_Js)*%QuQfVU0ohb@I1NCA6fUZ`03rJI<{U%Qa*U4d_UYczM> z@Qz4Qf`zf;idSdyMF&DhBn7_dEyooz?oGr2DVyGNni4FG2XRN*!lKt(XpJ7S+1zXX z+bizeQEtA+6%uA;_XLT zgvnYUMNa9&HhMZwMC*u`3X(g79gV*yKgj}N>3bA8OXcc8IB2fH@PdS&m?}1ig)J>v zK7?J}OU}Jcv_bWq#kVbJUYF)KitF6vS9ssvwk5kX4%c)Sj?RCny0l)wB8(vtD zD|#(gkdE({LXxIiyzQIPwg&Sse5*hT-t#=IN&Ln)?c#s=;qNF1ws<>2#Lk zm=qsHAE7^K`w>e+LvnS5ISQ_+Nafuv2LKBVuk=arHQsBmYL`p#lNj7>Pij8M@S*_e zJzv|Cy$0g$nx}Qgm@ENQ$|jmmNwWc%N%0(rzKuv3rcEZvIM>QcS2a`CP3PkF;YL`m|VW9Fj-(q-CfP4_A zauvp8HV9rwGVK;wDbn_gix9&bX|xU`;3^Dq_rP*%ce#`ZiMa~+U4~Z$n9`SRPxcNL zD(6v1(*|V83V2BKfO{dyl3OJ5Ldh8CAZDLkF4dU<|AhR#h8G3M(x-Cin4G(z;e`TO zyIb2cok(WOBAZuX?ZyLP$Mmi@L* yv%PNoR8Z#ndkrsT>M8x}3Y`HqKj`21SkJiQ6s0#D@7?9D3dEIAU=sy?{P-Uz?X_nB literal 0 HcmV?d00001 diff --git a/apps/plugins/bitmaps/native/pitch_notes.220x176x16.bmp b/apps/plugins/bitmaps/native/pitch_notes.220x176x16.bmp new file mode 100644 index 0000000000000000000000000000000000000000..087235380b74cf5b71edbd99acc889f7a94ed578 GIT binary patch literal 121016 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 literal 0 HcmV?d00001 diff --git a/apps/plugins/pitch_detector.c b/apps/plugins/pitch_detector.c index 8d0b3b7957..857d74afc4 100644 --- a/apps/plugins/pitch_detector.c +++ b/apps/plugins/pitch_detector.c @@ -5,7 +5,7 @@ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ * \/ \/ \/ \/ \/ - * $Id:$ + * $Id$ * * Copyright (C) 2008 Lechner Michael / smoking gnu * @@ -29,7 +29,6 @@ * recording code to use proper, gapless recording with a callback function * that provides new buffer, instead of stopping and restarting recording * everytime the buffer is full - * - Convert all floating point operations to fixed-point * - Adapt the Yin FFT algorithm, which would reduce complexity from O(n^2) * to O(nlogn), theoretically reducing latency by a factor of ~10. -David * @@ -68,6 +67,8 @@ #include "plugin.h" #include "lib/pluginlib_actions.h" +#include "lib/picture.h" +#include "pluginbitmaps/pitch_notes.h" PLUGIN_HEADER @@ -120,9 +121,10 @@ typedef struct _fixed fixed; #define FP_LOW ((fixed){1}) /* Some defines for converting between period and frequency */ + /* I introduce some divisors in this because the fixed point */ /* variables aren't big enough to hold higher than a certain */ -/* vallue. This loses a bit of precision but it means we */ +/* value. This loses a bit of precision but it means we */ /* don't have to use 32.32 variables (yikes). */ /* With an 18-bit decimal precision, the max value in the */ /* integer part is 8192. Divide 44100 by 7 and it'll fit in */ @@ -157,7 +159,24 @@ typedef struct _fixed fixed; #define LCD_FACTOR (fp_div(int2fixed(LCD_WIDTH), int2fixed(100))) /* The threshold for the YIN algorithm */ -#define YIN_THRESHOLD float2fixed(0.05f) +#define DEFAULT_YIN_THRESHOLD 5 /* 0.10 */ +const fixed yin_threshold_table[] = +{ + float2fixed(0.01), + float2fixed(0.02), + float2fixed(0.03), + float2fixed(0.04), + float2fixed(0.05), + float2fixed(0.10), + float2fixed(0.15), + float2fixed(0.20), + float2fixed(0.25), + float2fixed(0.30), + float2fixed(0.35), + float2fixed(0.40), + float2fixed(0.45), + float2fixed(0.50), +}; /* How loud the audio has to be to start displaying pitch */ /* Must be between 0 and 100 */ @@ -168,6 +187,40 @@ typedef struct _fixed fixed; /* How many decimal places to display for the Hz value */ #define DISPLAY_HZ_PRECISION 100 +/* Where to put the various GUI elements */ +int note_y; +int bar_grad_y; +#define LCD_RES_MIN (LCD_HEIGHT < LCD_WIDTH ? LCD_HEIGHT : LCD_WIDTH) +#define BAR_PADDING (LCD_RES_MIN / 32) +#define BAR_Y (LCD_HEIGHT * 3 / 4) +#define BAR_HEIGHT (LCD_RES_MIN / 4 - BAR_PADDING) +#define BAR_HLINE_Y (BAR_Y - BAR_PADDING) +#define BAR_HLINE_Y2 (BAR_Y + BAR_HEIGHT + BAR_PADDING - 1) +#define HZ_Y 0 +#define GRADUATION 10 /* Subdivisions of the whole 100-cent scale */ + +/* Bitmaps for drawing the note names. These need to have height + <= (bar_grad_y - note_y), or 15/32 * LCD_HEIGHT + */ +#define NUM_NOTE_IMAGES 9 +#define NOTE_INDEX_A 0 +#define NOTE_INDEX_B 1 +#define NOTE_INDEX_C 2 +#define NOTE_INDEX_D 3 +#define NOTE_INDEX_E 4 +#define NOTE_INDEX_F 5 +#define NOTE_INDEX_G 6 +#define NOTE_INDEX_SHARP 7 +#define NOTE_INDEX_FLAT 8 +const struct picture note_bitmaps = +{ + pitch_notes, + BMPWIDTH_pitch_notes, + BMPHEIGHT_pitch_notes, + BMPHEIGHT_pitch_notes/NUM_NOTE_IMAGES +}; + + typedef signed short audio_sample_type; /* It's stereo, so make the buffer twice as big */ audio_sample_type audio_data[BUFFER_SIZE]; @@ -209,21 +262,12 @@ static const fixed lfreqs[12] = /* GUI */ static unsigned back_color, front_color; -static int font_w, font_h; -static int bar_x_minus_50, bar_x_minus_20, bar_x_0, bar_x_20, bar_x_50; -static int letter_y; /* y of the notes letters */ -static int note_bar_y; /* y of the yellow bars (under the notes) */ -static int bar_h; /* height of the yellow (note) and red (error) bars */ -static int freq_y; /* y of the line with the frequency */ -static int error_ticks_y; /* y of the error values (-50, -20, ...) */ -static int error_hline_y; /* y of the top line for error bar */ -static int error_hline_y2;/* y of the bottom line for error bar */ -static int error_bar_y; /* y of the error bar */ -static int error_bar_margin; /* distance between the error bar and the hline */ +static int font_w,font_h; +static int bar_x_0; +static int lbl_x_minus_50, lbl_x_minus_20, lbl_x_0, lbl_x_20, lbl_x_50; -static const char *english_notes[12] = {"A","A#","B","C","C#","D","D#","E", - "F","F#", "G", "G#"}; -static const char gui_letters[8] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', '#'}; +static const char *english_notes[] = {"A","A#","B","C","C#","D","D#","E", + "F","F#","G","G#"}; static const char **notes = english_notes; /*Settings for the plugin */ @@ -235,137 +279,10 @@ struct tuner_settings unsigned sample_size; unsigned lowest_freq; unsigned yin_threshold; + bool use_sharps; + bool display_hz; } tuner_settings; -/*=================================================================*/ -/* MENU */ -/*=================================================================*/ - -/* Keymaps */ -const struct button_mapping* plugin_contexts[]={ - generic_actions, - generic_increase_decrease, - generic_directions, -#if NB_SCREENS == 2 - remote_directions -#endif -}; -#define PLA_ARRAY_COUNT sizeof(plugin_contexts)/sizeof(plugin_contexts[0]) - -fixed yin_threshold_table[] = -{ - float2fixed(0.01), - float2fixed(0.02), - float2fixed(0.03), - float2fixed(0.04), - float2fixed(0.05), - float2fixed(0.10), - float2fixed(0.15), - float2fixed(0.20), - float2fixed(0.25), - float2fixed(0.30), - float2fixed(0.35), - float2fixed(0.40), - float2fixed(0.45), - float2fixed(0.50), -}; - -#define DEFAULT_YIN_THRESHOLD 5 /* 0.10 */ - -/* Option strings */ -static const struct opt_items yin_threshold_text[] = -{ - { "0.01", -1 }, - { "0.02", -1 }, - { "0.03", -1 }, - { "0.04", -1 }, - { "0.05", -1 }, - { "0.10", -1 }, - { "0.15", -1 }, - { "0.20", -1 }, - { "0.25", -1 }, - { "0.30", -1 }, - { "0.35", -1 }, - { "0.40", -1 }, - { "0.45", -1 }, - { "0.50", -1 }, -}; - -void set_min_freq(int new_freq) -{ - tuner_settings.sample_size = freq2period(new_freq) * 4; - - /* clamp the sample size between min and max */ - if(tuner_settings.sample_size <= SAMPLE_SIZE_MIN) - tuner_settings.sample_size = SAMPLE_SIZE_MIN; - else if(tuner_settings.sample_size >= BUFFER_SIZE) - tuner_settings.sample_size = BUFFER_SIZE; - /* sample size must be divisible by 4 */ - else if(tuner_settings.sample_size % 4 != 0) - tuner_settings.sample_size += 4 - (tuner_settings.sample_size % 4); -} - -bool main_menu(void) -{ - int selection=0; - bool done = false; - bool exit_tuner=false; - int choice; - - MENUITEM_STRINGLIST(menu,"Tuner Settings",NULL, - "Return to Tuner", - "Volume Threshold", - "Listening Volume", - "Lowest Frequency", - "Algorithm Pickiness", - "Quit"); - - while(!done) - { - choice = rb->do_menu(&menu, &selection, NULL, false); - switch(choice) - { - case 1: - rb->set_int("Volume Threshold", "%", UNIT_INT, - &tuner_settings.volume_threshold, - NULL, 5, 5, 95, NULL); - break; - case 2: - rb->set_int("Listening Volume", "%", UNIT_INT, - &tuner_settings.record_gain, - NULL, 1, rb->sound_min(SOUND_MIC_GAIN), - rb->sound_max(SOUND_MIC_GAIN), NULL); - break; - case 3: - rb->set_int("Lowest Frequency", "Hz", UNIT_INT, - &tuner_settings.lowest_freq, set_min_freq, 1, - /* Range depends on the size of the buffer */ - SAMPLE_RATE / (BUFFER_SIZE / 4), - SAMPLE_RATE / (SAMPLE_SIZE_MIN / 4), NULL); - break; - case 4: - rb->set_option( - "Algorithm Pickiness (Lower -> more discriminating)", - &tuner_settings.yin_threshold, - INT, yin_threshold_text, - sizeof(yin_threshold_text) / - sizeof(yin_threshold_text[0]), - NULL); - break; - case 5: - exit_tuner = true; - done = true; - break; - case 0: - default: /* Return to the tuner */ - done = true; - break; - - } - } - return(exit_tuner); -} - /*=================================================================*/ /* Settings loading and saving(adapted from the clock plugin) */ /*=================================================================*/ @@ -408,6 +325,16 @@ void tuner_settings_reset(struct tuner_settings* settings) settings->sample_size = BUFFER_SIZE; settings->lowest_freq = period2freq(BUFFER_SIZE / 4); settings->yin_threshold = DEFAULT_YIN_THRESHOLD; + settings->use_sharps = true; + settings->display_hz = false; +} + +/*---------------------------------------------------------------------*/ + +void tuner_settings_reset_query(int yes) +{ + if(yes) + tuner_settings_reset(&tuner_settings); } /*---------------------------------------------------------------------*/ @@ -463,6 +390,147 @@ void save_settings(void) tuner_settings_save(&tuner_settings, SETTINGS_FILENAME); } +/*=================================================================*/ +/* MENU */ +/*=================================================================*/ + +/* Keymaps */ +const struct button_mapping* plugin_contexts[]={ + generic_actions, + generic_increase_decrease, + generic_directions, +#if NB_SCREENS == 2 + remote_directions +#endif +}; +#define PLA_ARRAY_COUNT sizeof(plugin_contexts)/sizeof(plugin_contexts[0]) + +/* Option strings */ + +/* This has to match yin_threshold_table */ +static const struct opt_items yin_threshold_text[] = +{ + { "0.01", -1 }, + { "0.02", -1 }, + { "0.03", -1 }, + { "0.04", -1 }, + { "0.05", -1 }, + { "0.10", -1 }, + { "0.15", -1 }, + { "0.20", -1 }, + { "0.25", -1 }, + { "0.30", -1 }, + { "0.35", -1 }, + { "0.40", -1 }, + { "0.45", -1 }, + { "0.50", -1 }, +}; + +static const struct opt_items accidental_text[] = +{ + { "Flat", -1 }, + { "Sharp", -1 }, +}; + +static const struct opt_items noyes_text[] = +{ + { "No", -1 }, + { "Yes", -1 } +}; + +void set_min_freq(int new_freq) +{ + tuner_settings.sample_size = freq2period(new_freq) * 4; + + /* clamp the sample size between min and max */ + if(tuner_settings.sample_size <= SAMPLE_SIZE_MIN) + tuner_settings.sample_size = SAMPLE_SIZE_MIN; + else if(tuner_settings.sample_size >= BUFFER_SIZE) + tuner_settings.sample_size = BUFFER_SIZE; + /* sample size must be divisible by 4 */ + else if(tuner_settings.sample_size % 4 != 0) + tuner_settings.sample_size += 4 - (tuner_settings.sample_size % 4); +} + +bool main_menu(void) +{ + int selection=0; + bool done = false; + bool exit_tuner=false; + int choice; + bool reset = false; + + MENUITEM_STRINGLIST(menu,"Tuner Settings",NULL, + "Return to Tuner", + "Volume Threshold", + "Listening Volume", + "Lowest Frequency", + "Algorithm Pickiness", + "Accidentals", + "Display Frequency (Hz)", + "Reset Settings", + "Quit"); + + while(!done) + { + choice = rb->do_menu(&menu, &selection, NULL, false); + switch(choice) + { + case 1: + rb->set_int("Volume Threshold", "%", UNIT_INT, + &tuner_settings.volume_threshold, + NULL, 5, 5, 95, NULL); + break; + case 2: + rb->set_int("Listening Volume", "%", UNIT_INT, + &tuner_settings.record_gain, + NULL, 1, rb->sound_min(SOUND_MIC_GAIN), + rb->sound_max(SOUND_MIC_GAIN), NULL); + break; + case 3: + rb->set_int("Lowest Frequency", "Hz", UNIT_INT, + &tuner_settings.lowest_freq, set_min_freq, 1, + /* Range depends on the size of the buffer */ + SAMPLE_RATE / (BUFFER_SIZE / 4), + SAMPLE_RATE / (SAMPLE_SIZE_MIN / 4), NULL); + break; + case 4: + rb->set_option( + "Algorithm Pickiness (Lower -> more discriminating)", + &tuner_settings.yin_threshold, + INT, yin_threshold_text, + sizeof(yin_threshold_text) / + sizeof(yin_threshold_text[0]), + NULL); + break; + case 5: + rb->set_option("Display Accidentals As", + &tuner_settings.use_sharps, + BOOL, accidental_text, 2, NULL); + break; + case 6: + rb->set_option("Display Frequency (Hz)", + &tuner_settings.display_hz, + BOOL, noyes_text, 2, NULL); + break; + case 7: + rb->set_option("Reset Tuner Settings?", + &reset, + BOOL, noyes_text, 2, tuner_settings_reset_query); + break; + case 8: + exit_tuner = true; + case 0: + default: + /* Return to the tuner */ + done = true; + break; + + } + } + return(exit_tuner); +} + /*=================================================================*/ /* Binary Log */ /*=================================================================*/ @@ -525,15 +593,13 @@ void print_int_xy(int x, int y, int v) rb->lcd_set_foreground(front_color); rb->snprintf(temp,20,"%d",v); rb->lcd_putsxy(x,y,temp); - rb->lcd_update(); } -/* Print out the frequency etc - will be removed later on */ +/* Print out the frequency etc */ void print_str(char* s) { rb->lcd_set_foreground(front_color); - rb->lcd_putsxy(0, freq_y, s); - rb->lcd_update(); + rb->lcd_putsxy(0, HZ_Y, s); } /* What can I say? Read the function name... */ @@ -548,9 +614,67 @@ void print_char_xy(int x, int y, char c) rb->lcd_putsxy(x, y, temp); } +/* Draw the note bitmap */ +void draw_note(const char *note) +{ + int i; + int note_x = (LCD_WIDTH - BMPWIDTH_pitch_notes) / 2; + int accidental_index = NOTE_INDEX_SHARP; + + i = note[0]-'A'; + + if(note[1] == '#') + { + if(!(tuner_settings.use_sharps)) + { + i = (i + 1) % 7; + accidental_index = NOTE_INDEX_FLAT; + } + + vertical_picture_draw_sprite(rb->screens[0], + ¬e_bitmaps, + accidental_index, + LCD_WIDTH / 2, + note_y); + note_x = LCD_WIDTH / 2 - BMPWIDTH_pitch_notes; + } + + vertical_picture_draw_sprite(rb->screens[0], ¬e_bitmaps, i, + note_x, + note_y); +} /* Draw the red bar and the white lines */ void draw_bar(fixed wrong_by_cents) { + unsigned n; + int x; + +#ifdef HAVE_LCD_COLOR + rb->lcd_set_foreground(LCD_RGBPACK(255,255,255)); /* Color screens */ +#elif LCD_DEPTH > 1 + rb->lcd_set_foreground(LCD_BLACK); /* Greyscale screens */ +#else + rb->lcd_set_foreground(LCD_BLACK); /* Black and white screens */ +#endif + + rb->lcd_hline(0,LCD_WIDTH-1, BAR_HLINE_Y); + rb->lcd_hline(0,LCD_WIDTH-1, BAR_HLINE_Y2); + + /* Draw graduation lines on the off-by readout */ + for(n = 0; n <= GRADUATION; n++) + { + x = (LCD_WIDTH * n + GRADUATION / 2) / GRADUATION; + if (x >= LCD_WIDTH) + x = LCD_WIDTH - 1; + rb->lcd_vline(x, BAR_HLINE_Y, BAR_HLINE_Y2); + } + + print_int_xy(lbl_x_minus_50 ,bar_grad_y, -50); + print_int_xy(lbl_x_minus_20 ,bar_grad_y, -20); + print_int_xy(lbl_x_0 ,bar_grad_y, 0); + print_int_xy(lbl_x_20 ,bar_grad_y, 20); + print_int_xy(lbl_x_50 ,bar_grad_y, 50); + #ifdef HAVE_LCD_COLOR rb->lcd_set_foreground(LCD_RGBPACK(255,0,0)); /* Color screens */ #elif LCD_DEPTH > 1 @@ -561,66 +685,16 @@ void draw_bar(fixed wrong_by_cents) if (fp_gt(wrong_by_cents, FP_ZERO)) { - rb->lcd_fillrect(bar_x_0, error_bar_y, - fixed2int(fp_mul(wrong_by_cents, LCD_FACTOR)), bar_h); + rb->lcd_fillrect(bar_x_0, BAR_Y, + fixed2int(fp_mul(wrong_by_cents, LCD_FACTOR)), BAR_HEIGHT); } else { rb->lcd_fillrect(bar_x_0 + fixed2int(fp_mul(wrong_by_cents,LCD_FACTOR)), - error_bar_y, + BAR_Y, fixed2int(fp_mul(wrong_by_cents, LCD_FACTOR)) * -1, - bar_h); + BAR_HEIGHT); } -#ifdef HAVE_LCD_COLOR - rb->lcd_set_foreground(LCD_RGBPACK(255,255,255)); /* Color screens */ -#elif LCD_DEPTH > 1 - rb->lcd_set_foreground(LCD_BLACK); /* Greyscale screens */ -#else - rb->lcd_set_foreground(LCD_BLACK); /* Black and white screens */ -#endif - - rb->lcd_hline(0,LCD_WIDTH-1, error_hline_y); - rb->lcd_hline(0,LCD_WIDTH-1, error_hline_y2); - rb->lcd_vline(LCD_WIDTH / 2, error_hline_y, error_hline_y2); - - print_int_xy(bar_x_minus_50 , error_ticks_y, -50); - print_int_xy(bar_x_minus_20 , error_ticks_y, -20); - print_int_xy(bar_x_0 , error_ticks_y, 0); - print_int_xy(bar_x_20 , error_ticks_y, 20); - print_int_xy(bar_x_50 , error_ticks_y, 50); -} - -/* Print the letters A-G and the # on the screen */ -void draw_letters(void) -{ - int i; - - rb->lcd_set_foreground(front_color); - - for (i=0; i<8; i++) - { - print_char_xy(i*(LCD_WIDTH / 8 ) + font_w, letter_y, gui_letters[i]); - } -} - -/* Draw the yellow point(s) below the letters and the '#' */ -void draw_points(const char *s) -{ - int i; - - i = s[0]-'A'; -#ifdef HAVE_LCD_COLOR - rb->lcd_set_foreground(LCD_RGBPACK(255,255,0)); /* Color screens */ -#elif LCD_DEPTH > 1 - rb->lcd_set_foreground(LCD_DARKGRAY); /* Grey screens */ -#else - rb->lcd_set_foreground(LCD_BLACK); /* Black and White screens */ -#endif - - rb->lcd_fillrect(i*(LCD_WIDTH / 8 ) + font_w, note_bar_y, font_w, font_h); - - if (s[1] == '#') - rb->lcd_fillrect(7*(LCD_WIDTH / 8 ) + font_w, note_bar_y, font_w, font_h); } /* Calculate how wrong the note is and draw the GUI */ @@ -629,7 +703,6 @@ void display_frequency (fixed freq) fixed ldf, mldf; fixed lfreq, nfreq; int i, note = 0; - bool draw_freq; char str_buf[30]; if (fp_lt(freq, FP_LOW)) @@ -663,26 +736,19 @@ void display_frequency (fixed freq) ldf=fp_mul(int2fixed(1200), log(fp_div(freq,nfreq))); - draw_freq = (fp_round(freq) != 0); - if (draw_freq) - { - rb->snprintf(str_buf,30, "%s : %d cents (%d.%dHz)", - notes[note], fp_round(ldf) ,fixed2int(freq), - fp_round(fp_mul(fp_frac(freq), - int2fixed(DISPLAY_HZ_PRECISION)))); - } - else - { - ldf = FP_ZERO; /* prevents red bar at -32 cents when freq= 0*/ - } - rb->lcd_clear_display(); draw_bar(ldf); /* The red bar */ - draw_letters(); /* The A-G letters and the # */ - if (draw_freq) + if(fp_round(freq) != 0) { - draw_points(notes[note]); /* The yellow point(s) */ - print_str(str_buf); + draw_note(notes[note]); + if(tuner_settings.display_hz) + { + rb->snprintf(str_buf,30, "%s : %d cents (%d.%02dHz)", + notes[note], fp_round(ldf) ,fixed2int(freq), + fp_round(fp_mul(fp_frac(freq), + int2fixed(DISPLAY_HZ_PRECISION)))); + print_str(str_buf); + } } rb->lcd_update(); } @@ -796,7 +862,7 @@ fixed vec_quadint_min(fixed *x, unsigned bufsize, unsigned pos, unsigned span) resold = res; } else - { + { /* exactpos += (frac-QUADINT_STEP)*span - span/2.0f; */ exactpos = fp_add(exactpos, fp_sub( @@ -898,20 +964,28 @@ void record_and_get_pitch(void) long timer; char debug_string[20]; */ +#ifndef SIMULATOR fixed period; bool waiting = false; +#endif while(!quit) { +#ifndef SIMULATOR /* Start recording */ rb->pcm_record_data(recording_callback, (void *) audio_data, (size_t) tuner_settings.sample_size * sizeof(audio_sample_type)); +#endif recording=1; while (recording && !quit) /* wait for the buffer to be filled */ { rb->yield(); +#ifdef SIMULATOR + /* Only do this loop once if this is the simulator */ + recording = 0; +#endif button=pluginlib_getaction(0, plugin_contexts, PLA_ARRAY_COUNT); switch(button) { @@ -923,8 +997,8 @@ void record_and_get_pitch(void) case PLA_MENU: if(main_menu()) quit=true; + else redraw = true; rb->yield(); - redraw = true; break; default: @@ -934,11 +1008,9 @@ void record_and_get_pitch(void) } } - /* Let's keep track of how long this takes */ - /* timer = *(rb->current_tick); */ - if(!quit) { +#ifndef SIMULATOR /* Only do the heavy lifting if the volume is high enough */ if(buffer_magnitude(audio_data) > sqr(tuner_settings.volume_threshold * @@ -946,9 +1018,9 @@ void record_and_get_pitch(void) { if(waiting) { - #ifdef HAVE_ADJUSTABLE_CPU_FREQ +#ifdef HAVE_ADJUSTABLE_CPU_FREQ rb->cpu_boost(true); - #endif +#endif waiting = false; } @@ -971,26 +1043,16 @@ void record_and_get_pitch(void) { waiting = true; redraw = false; - #ifdef HAVE_ADJUSTABLE_CPU_FREQ +#ifdef HAVE_ADJUSTABLE_CPU_FREQ rb->cpu_boost(false); - #endif +#endif /*rb->backlight_off();*/ display_frequency(FP_ZERO); } - - /*rb->snprintf(debug_string, 20, "%x,%x", - audio_data[50], audio_data[52]); - rb->lcd_putsxy(0, 40, debug_string); - rb->lcd_update(); - */ - - /* Print out how long it took to find the pitch */ - /* - rb->snprintf(debug_string, 20, "latency: %ld", - *(rb->current_tick) - timer); - rb->lcd_putsxy(0, 40, debug_string); - rb->lcd_update(); - */ +#else /* SIMULATOR */ + /* Display a preselected frequency */ + display_frequency(int2fixed(445)); +#endif } } rb->pcm_close_recording(); @@ -1023,23 +1085,18 @@ void init_everything(void) front_color = rb->lcd_get_foreground(); rb->lcd_getstringsize("X", &font_w, &font_h); - bar_x_minus_50 = 0; - bar_x_minus_20 = (LCD_WIDTH / 2) - + bar_x_0 = LCD_WIDTH / 2; + lbl_x_minus_50 = 0; + lbl_x_minus_20 = (LCD_WIDTH / 2) - fixed2int(fp_mul(LCD_FACTOR, int2fixed(20))) - font_w; - bar_x_0 = LCD_WIDTH / 2; - bar_x_20 = (LCD_WIDTH / 2) + - fixed2int(fp_mul(LCD_FACTOR, int2fixed(20))) - font_w; - bar_x_50 = LCD_WIDTH - 2 * font_w; - - letter_y = 10; - note_bar_y = letter_y + font_h; - bar_h = font_h; - freq_y = note_bar_y + bar_h + 3; - error_ticks_y = freq_y + font_h + 8; - error_hline_y = error_ticks_y + font_h + 2; - error_bar_margin = 2; - error_bar_y = error_hline_y + error_bar_margin; - error_hline_y2 = error_bar_y + bar_h + error_bar_margin; + lbl_x_0 = (LCD_WIDTH - font_w) / 2; + lbl_x_20 = (LCD_WIDTH / 2) + + fixed2int(fp_mul(LCD_FACTOR, int2fixed(20))) - font_w; + lbl_x_50 = LCD_WIDTH - 2 * font_w; + + bar_grad_y = BAR_Y - BAR_PADDING - font_h; + /* Put the note right between the top and bottom text elements */ + note_y = ((font_h + bar_grad_y - note_bitmaps.slide_height) / 2); }