From bb62616b05401f1d63df74ac1676cc1ae95c5b92 Mon Sep 17 00:00:00 2001 From: Lucas Theis Date: Sun, 26 Jan 2025 18:21:47 +0000 Subject: [PATCH] Fix(Spectrogram): alignment between ticks and spectrogram (#4011) --- cypress/e2e/spectrogram.cy.js | 31 ++++++++++ examples/audio/1khz.mp3 | Bin 0 -> 80666 bytes src/plugins/spectrogram.ts | 104 ++++++++++++++++++++++------------ 3 files changed, 100 insertions(+), 35 deletions(-) create mode 100644 examples/audio/1khz.mp3 diff --git a/cypress/e2e/spectrogram.cy.js b/cypress/e2e/spectrogram.cy.js index fcaa80f96..89938c72e 100644 --- a/cypress/e2e/spectrogram.cy.js +++ b/cypress/e2e/spectrogram.cy.js @@ -1,4 +1,5 @@ const id = '#waveform' +const scales = ['linear', 'mel', 'log', 'bark', 'erb'] xdescribe('WaveSurfer Spectrogram plugin tests', () => { it('should render a spectrogram', () => { @@ -81,4 +82,34 @@ xdescribe('WaveSurfer Spectrogram plugin tests', () => { }) }) }) + + scales.forEach(scale => { + it(`should display correct frequency labels with 1kHz tone (${scale})`, () => { + cy.visit('cypress/e2e/index.html') + cy.window().then((win) => { + return new Promise((resolve) => { + win.wavesurfer = win.WaveSurfer.create({ + container: id, + height: 200, + url: '../../examples/audio/1khz.mp3', + plugins: [ + win.Spectrogram.create({ + height: 200, + labels: true, + scale: scale, + frequencyMin: 0, + frequencyMax: 4000, + splitChannels: false + }), + ], + }) + + win.wavesurfer.once('ready', () => { + cy.get(id).matchImageSnapshot(`spectrogram-1khz-${scale}`) + resolve() + }) + }) + }) + }) + }) }) diff --git a/examples/audio/1khz.mp3 b/examples/audio/1khz.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..6269ad50851958606ee6b19be9be3e59f0cdb5c8 GIT binary patch literal 80666 zcmeIb2~<;A*7tqx%|H?Y1PBmD!zdz1m=qktC?IMWR8-V3h$vd(jF!U8{}2r8CSKtxc=LPbSO%ixHX17&L!4kh2diP-h7@9UOcE35l?zWdT^^{S<(ZY|H> zefHVs{LgQ9zu(yGv<4xgm{(ptTL|3C;@O}fJUl6Q{Hz0Ol!xs5>)-5nWRRCXv%ZrZ z@&kiwWod`FN%Z3wp;s51W0fOQq*!wXE>-pAa~kOFdw&|LQ`B!{?y`0126oGbMpnHn z>bFxlq3UJvjV0LB?uB~~|1e_J57GA)uIjUJ-|A|F1IGvLda^n+T)PYE`fO;}o&3dbGOQ4Egcd<0s~|zguI! zEJu#GOJ&mb)gjmhapk3v<~d^7kB{Dof6;9TzTkW~yTY_~L{XOS-O9m+ScBhc?nb{m zHDikc+E?_A8vCnNUAviG4&$xMo>fj<-ACtgk~yO$d~Dw;JLko)X06(6%E`^nDDSQh zsEy=Rc*ef?{^+U-dL^PwiMeX9Na7(y2z4K*PTWPXgp5&}eB8qG)F14I$dzkc>j(7pA5a1qKsQ0e50^bCO>HO_{~RSjiQH0*T+g z)8*z$gB9@Qm))Sy6MYYYQR6oH?j0noWR$&&NH3Nel$~MbZbcD`GXzTZ!ieBZUokC7 z$lCo9TgE1=CrP{ifAaI&cK`lCFcB9042Teu*31L5C+)>;BQvZ1*!GZZC@VB2#DY}Y>dp{*k<)f7pp)G?hOQTF+LV(S6wlkbw?!5zO~-8!zcwj!83WNH=bhEo z41q$AZ(Kw+61T9Xv-OIjjIu>T(>H7D>;DVBQ+KP7wU{Y7)O&P*+^ z&nx|zWhhg=_kKKtmK_!DI4-A}GhJc}L4abA;RJ7CTS;||z! z2V!jjk-9;NB^x(%eRD_OiH%qS{Ap}`GZOR977X{$O;7X6htVCJG`&+N7~3aiDsUA; z$**mXT)QIUp|XX6E<`Y$63rJ2hDJ}*(w`j^@_q*jmAQ>*0ELca?|Wy~Rjj3t|Ih!- zCv%>1rT`)A2ij1^{u1GD*Rz5KDhDs1ITm=?alMdAKqp+LieBF=u^&`uubVFQE(C?% z)EyXW81I-OI@negInGKHt?S7%az(nV#Vs~#I4kwF`sW6PY`+7APPqp*eW0tVvdd0D z9@6T6;(zqVxJxA73YhfP+z<3`#%y@u#1hVNmOR!u(2@K};Dk$Exo9B6F~mcv7qV{) znTNht4?c@0L3sA8N6+$dlDP)LtduA>bO&5(q*sOycJh6js zh4YMSkcSM(JoGEGFeS43yYRxONrs*Qw65)@7qL@vOmMQ3i|EH^^G9e&9Q9{Fp;8A> zXd%SVw{+EM#*=pj6v{)NOq-QSDp=*pnni?@PSk5$sL~=YZshLd(f)WKJL0`DYw1FQiy^x({RK~$F7$cXh)o$7&2Q4 z3bnZflB--rcG)}Xta9Dmofj6-!XYa3HrQja`{yl=W*IpJxFpgXi@Z#^fk@ z&>>I?Z3E*>Pd)U^f*36+rgQeXZNxZ*wNGP4FU#nFot(dtUO&AliisS2v|0~+vIK=H zH1*IiO64K=J6d-uTl$h%%*oA6x6o}e#a-Jd$Jfi95@*G0=Jd|v;w z=fUbQG7S+h^v13MSW%Wpx4jXaI)lc<^W-^KWZ`h8fD{H$4oR74x+-D*Pg)Y`eNl69 z04UVyKB573+xxRAmWQ~xX+dPk+My?PuPzT-v`sXKNOIy7IHbI>bfP2QiEq&isZhr~ z;E#O!o;374$)Ki{y(=CM`dw!!fp-XsnJKZ%9I?qbi#A`ZfiRp0?vHMF#aG3!Q79Riab&#FJ13TCcBAw$qrYVO7{Ozt5($ydTWrrQ z9xCq$<$OMt`_)1}|bWg0lyV8tj&rb*s~IM;1H7nWlsCFK2O(I2Ma~ z_h(NUx-0EZ=x)9^q+ed@MA3$b{=w<@-sl8p367mwqU4a~otMjH_ z=_!Yv=B04%4^tG0FNHqZtf(7i^J7(=w3be*Z65i%Fu^drE$gh-1R`T7_X#LeuP%qm zsu)kYsC01J-Cm^6+DIT|?XisBDNm6c&lO`2_=v`M`^5W!9t}^kbS;rp5r(>ZPuqQf zoE5A9IbS9il-vvFAL4BNEpQjH?1B7Fj?{r!FJ>KhuHa+1QvZ8fttzx(Jt)+yIZ`;1 z-SKV&m5vlFdCE1D;7H-19pN51i`KCK4H)8IEcHE}94srABAT6u9`9aaXN-*QW;^IE zkpz(nK{*t0fE!nwkIPDPgQRb+>^+OMN>k`UAwK2E9ycy>n78Px7FW3ik3gYQkcY@) zx$OOZgD7>R&~GccD2AOvSu{%C6ZuWF;K-$Fjy>n$Pritg$UuhrC^^;M78yNp*8P(+ zU2IE$LN}81kY)dV=F#%%2);*%N#L2eZA?ryI0F6X|A9&P36V&?MT-g*{{jlNxdned zQt-2)QXcBg|Cz3&lX1Z!23(t`|Ma=lJ`Y;6LyqL<7WTOeUJC8{gJ~iRZFubI7u-`1 zJu?)Vq!HL5d%|QJa+HVLM%G9|DLO>)p zT@nmK(OtveSzVS2PF5>^^&_n*jM8V)>xK!}R@Ti{ex%{Z@!PO`g3dzx z@k^39$zogb61>}Jbvm!8I3(yagON$w5FZtu^Iny&&n^)%W_1cBSfSmS61TD1Q)n6) zL&b1`2QhRayKJdd`X()X{C~k`vIm#(PQ#?H%JYAQ-Tzr!`j(5vAM(bSCMDbEexe2V zhXe(GdWqB5zNni!i?bxnGYtm+s^7t=U0RRFdPsdkEs+s-lgBfCklMa*#}ut zfqEh==Mv?(au{K=#3eu(24uQJ7j#!B;5%dy4#BIiZ3I8GbvZ8PncZp+oVA`=_Q#Mt}`8|!`X4UZmc zQK8ZMy9rmJCJ*g}3p`30NxFM3<(}#)`$qcmd?F@0S?C#N1tf0|VA#r3tSl7GD6;L~ zBg5bZ-DI)dHqf%$(?BZPQ;~~e8jm$sA8jzKzd9$2rBto3SYR!y+wW*};M^o_2}JJY zTo*tLsXo_35JS|ehq}MG6cs7>&XGo&yfe71VVmRQOjl!wIh0Qq>z}pm48=+lm&iHE zQakbj??ze>F|0I!b)(Mlh?0lN$6B_ZO!JjHAmQ|@m3i{;X$^gxZ)!^-P^h^MVhFkW zUx4eOa>l+c3Z0xnIV9TwdpR9(G%@E!CMkB!Rmmx6y_=>&oqHk73v3=C1KudGT@`q;$Zdep|iyw4wQ_3~g=Y$QWY8 zl6yJ#5sjb_xtAMCrM(>aH@)+C4lN8OUcV_j<~zH(@Rs<=m6DPJzS6y>NkWHMWXgM? z7-q`|VYi@yxjXuj7Gvnt zUWg%yTQJl^WxFV5BK z?Dj~C3_B0?kR4eMJqe1SJ@nTl>;edak%$O>UBN}YhqcAEu848qxWXS5-dFDWo0g&o zV(8FAh@p>~JX8)b2NM$c+Egky8G=nMOu>x zVkj&EVo2`pPZ~*1P_G`!2@=`e0F{;m_4h9~w5!K{dq(R#@Jv25C#^%T5ZTq%V2Cvo zJ-ec_2kwWwzlVdlr-np%OwGxDS!`ol6A#&j#;t3ZwuDqSTg*zp$;#Ir)qk+zUW{Vk~mTok%93qe9o^i!`9(-2pNvu(YS=IS& zSz9UN^9?eTHsyNozN=q)`&DfP5XcO6x#upRP_tVg`F!Xgwd$enuIQ7pjV(|RN%GLQ zm%8G7TH=1MV54aEqqITkx__q=rl>rE-G)i;445q^(-0X#y|C74Paz1QwzVKotDAoV z*ySp-JN!maDTKP>0^H@cpO|o5^on6FQgd zC({tA(DQ$4tsB>4t<%y@n+&0i%~4{tLh9E;6<{P8OQECfZcQSBS=R|ll`RX7YI2Ec zs}NQ;Tip=eh!ZvIDr2i%!#8=z#2n)BHaM2^B#-5;28~iqXQt@X8DXrqh#@)}@*uNw zizph^3K_{)F#ucAt6UYNp^sE5SU;J*LNiQ3qWvCj zSlq~JBWLrOR!3R|BX{3AmL4Gx66t=qpX#{*?v}hQFM9IOEz(;jkXD;37Y|XUi>6Io zFhWdw@=xpf=&%5xaheOY5OCnIn>>4O^M`I*8Om5|TN#Zj}}lDk05SZ=f847&-{$ z5S5H1IYXW8egS=E7q;TBjf8km8-D*iBaxYX+Gj9#H?A-jF_7aZm++P}9otc}d#;k6 znGpkb6^c^1aeL=ae83L!8HBSQ(1p5O^ypW6Ya}Vd9QvQuqC&G;L7`HOu^z5i-}R-E zq45*{A`!@kRqirP%)EFpB<8W3F@qbKEqS&5cZ`sZ*@(O(D{B?{p@{3`0C`CBz6(>( z<~Xv&deSU{UB*U!*^&;+Kd^M^7z68NLsXHwG8f3Tc|Bw{SiQ;xHo_%%1;xstztlrZ zh@sM1Xk~w5<~BrY?r+Re3HwFxkywOXKR3;Fn~Tr8WRnJVu^80+ffmc&0kSF#;v5KO zGp@3bRwzO?$|gyJ@ZjSy1QZ|L0A!T;s2!s}f)R;wO zY%#YJXU+_;llvYsEDv2OH!`dQBdp7Vo0FyT_u~S}_y(*_RbyMsN7Y zRbYiVnK+cqJ;YL|w%PTcAj5OS`R{XIau#XwP`6QLEA9L-S=ciHIvAINbNdH--}}hS z$|%TP^XDBp+w$kEU$mr;TA{M7ppZhtT{=#!>!I$ttvfW_rTQR-zvZQltqGyiA7g^i z-<|k@H9}xdgo;^?-||EV1<|TsM;!TTp-Yqv4lA9$9PPPWWT;PCG$`@?9E?(mA>~zOY*>H zK%pYi6#N(71(otpPZ~=7ibXLLFWU2XG?|A;BS~+pbz0jifI`m1W*;PWr zP?+;oTXiY~0j)IWjcCUxv8QOA)5h7t5FJ`ai;hQ|l?&#epdYBX-jj!Jq%oxQMONW4 zS6L{zBmzq|sZB}ap~PBo(4wwa86ib$e@Ps-N=sn`3MJa86;kv6Kq22hs8q3Ld)1he z4~-Wwh1k{=bSd)yI2iAn?x<6B>)T}TYh!WR<~?hdbNE@Q3%8N{zcn!UE;a@`zC~D- zDq4u*Pz^30>f&*@B2I3B6oRKjeRJY~b2|B{+EeK6dQhldT@Q6sQH;`+xUl=K4hNYg zCrvmmyK^}4$pLsUfyL|Jrd^32Tid85anzrI80wILLLD0Z9{?|?#Q!s|<|sIDNN~lz zHnM+lRCHA95nCQZZobz;o*pG<5(MwrLFPuQ@ZAA(R=pdvrza0}tm$+L-NwN8xUJFW z@ayz~^wtN|D<9HjN>1&*NcjXdqP${Bl&-%ZTpFTsi1gK z-wmaF%#9_-zYqWmrgSkex1SkWg=m68CrLvixtD`;xk^Td_dO~pRCi0xC10laSaXGJ z*(ZYxPXl9D8tpG8MRYzfl@O!Q#g$`pbBRC#2LEcvGugH3Qek<5?eIqrMO)&G=Swb% zg0YG;)bFIPYev5#O{=u_cM}x)jyySS)SSy5p&ECo3$BM8VAgdaX317M{lM#I8#OEu ziNX>$id%jWSz?`1)Ni{l4cRWcS-QUGq0yUwBEEAlnkTPF5HL|q z4BAq_8;WRRt3tOwdd}sZ>WQ7o!f^)h(249&>6-&ir~Ma7Q*ea}Pw;%WA0Ccd)ZEjS zN}$kP5_qA|Jn%Y3G4N7*L?bf_)-7v)0wtI$opUAhAP2NtH;e7Nn3c$ovQ5$6{$_@R za~bNl<_ma9T@Q`32^;s#fNMTB=r86vOa98bT@g8#{IzrQK&lK1EnW-?m45**QHpZ< z+hnPn#9dhXE3mzGGF>yNpB1u~k2L!2n8+?e))`B?E;}s8h_Ez))$ShN#S?lBGlZvf zUoFI6cVT{60ST5NjDGN34=09werzPmyEH;eK?H`z(+p6kLX(G}>x1{rE(-M&IA>>N z=%mz?LofOpS|=Cism$3KyV(}Qm`yUIZ@NNk-p0Z%wVb}6+jBj1w?OuXh0NPk82X*^ zl?Y9t84*9~qLxPd!0yR9$hQS|=^CjedDI~^>_-p?S_)8-|CfET%wjYF*F&M5pR-b0G3khTM&W(Z4w>v^2lSLft+_YxH~D)u01aL0pD6b$_b;!B zmzxolDY2Ve5^=%=`|*IbB8Xh%^j$%r&(}joD2Ab}yVb(&fJM%)Yd$}Stkc$F28^Q+Nq9e)JHSq&(NqM2kR~^6Y$wMUn zPZd}zvX$~Iq^5td*7?#5|0LN9Y6PH`G=dm%KL-k_GOJYPa|O3$2nydz#A9YdR5EEx!t^8oND)}YV)zrTOoS*Im=;4`4mQOV~#1k9L& z@QRgEbh+-%#vJ-2P)Pp~np)DT)AAU_EzWdS&ikf$4b54Jm_brj-L#+}C*(Mp)5BeY za>(7*4mpe_2DmH614ipwwBjOQv^F9M9&@Dhpbm=SAG@a|kw78)-$0>G4gc>DgJS%@ z_SuchXfZ;T&Kmw-4C|ls|2}@<|0zSi>rHISEDrL?xX!FJz z5w^Vktd;~KW2k^+IX7##OR!U*6#uVoYcXqT8Jx=PU=n)O#g51)!w5Mk9MEHvK*iiU zjCPst&_x}uWFa|vmlJ>O;m|(D9q>bIb9JK#f;L|_C*C+!LaHuM=yQ80su@Yz=W?0zq)@P8%jqxU#PiyoSx+Xi9_#7Oo|S9v#1M-nde_fL zMpAqV(}2H`tcS=`R`AvpT@#h}j}eC26A# z5oxU>xUtCOt>JbpX#@)0e+&wxyN@K>L!E>eq84|lZf6WD4&uVcm63)er~!ceCs_Dr zr|jL{O|%q779qRtB^Xiz0RLP3zr}n|s6)d;KSVKOeeW%b!2g><=AlAR^Z)Yyw6s3- z>N8*Jp~vX`8dXYOA^k#%Z2{U6R3Gb=g$4$o{NXAcgo$Y1NA&68|J^9;!e5LjxnC;b zk9G(NWQP3Rhi9-GCmeACf3&`DZW_b!(vQ9RulHgQta4j!LJW0k@(}sJi&7Qq7wl52 zJK7nf5?=@2MT&QbA$!{#7C%Rau;XD7ra`NrX=JdOfaL#?G4vR&DoRWh=0S2=$t37Q zG|zi`JTCI>6GHf{Q?^Ukwg{T*p6$i#_htwvq(2B0x}&*bh0ZAy%|m_!056{T7Vj_R zfk&~5qpJ30ArFzXetPe?Y}^4sc* zS_6`hd$}a?zV+?+O@G18>UoFxAosTBBbH!~cUzaEkHJ0jQ984l7lGmn7*ceToA~Qv+$NCwb@(cRJpV;E8Wbb~PJ}Yx(h` zD1xqx6`<7c@PY)T#oE!&?)7H+doczSngYxiS8p}{Pf-fbSgG{T_}}CIk-!Tw4|S)7 zwsHO6O zkPy#;0e-1}X{{TU-*6KVp-b?;t?I?p_i_j*w0o{PhWszUWBpP}9?0#xw&p%t&dUDi7sIBqs`+j{4^8qYBpAxL))SL)@Dh?iibNzvpOn_!VcEs#Zm zGp}+ntw@RcWzBQ9OvIg?`!I-Mu@>(L0ewrP?Ba;8&U|kNfL-oSlK*!{!~dfg4;^~3 zDx1LTLtB6up+B~C)}$&4VXi|&+*Zn06B??zGC`RkDjQUm#X+~z^dWBbj(%TaqD7#Us)b~dDXAFDz ze|K~LmACFEwYRRf5%Se>u*f<2fS0sHtJzjNt=B1->?&nV!0h5N@JCGh!u1OVdB2?Z(p7J z-VFeSBxayci{@Ak7@8Dgmv!!o!OdWQrZ)zvQI zaF0+Juc(Z8++(fl;s2p67n#)}C0(@NVdIKIF@xT<+33Y)jGnQ$sQkR_4KJ~pE0SYN!gF-K=d`4bV=7=taVB1*1GKRb*Ja{a{j+Q3>32TQ?GJr{$C}O zLzFs}>pZ@Q9uAYPzpIRXQE|R0RN-t9niXO&+9I{n8p@#nXjJ&KOH>PihnY?O^1e$~ zX(?$G_~ZeJ#L*7Ski0p-vM zYALig1{Z)rdb7YUx2d>bfAb_Kj$k)u*S$f{X-K)#2_-B3%oJM@NDwiqhyQmY%>oU) zDk)B-JAk!r0cTgspqF^3a)%8ft#x8OuH_D`8XC7bs$)pa|Er{yO+kGw2l`+K1Hhul zLq7Fsc$Ju5#SU^A#9>{d3pp&z8}8(gkTaFpS3sH?NZv(>9S1w%O(JDj9 z7R6HhXb{4?c!askKFEBe&O}1QV~k(BW(VJ!o6xy_RL=vi=g9^Y)fsJmV$+?0%e(EvGu0knhi1tNge%o?XG#V3{gn5aFpyfGbPcLdqBv43#K%qhn z{|{Q*P>MtQiT|7kHi7Gh8>}?+Iw_yPO0gu?_5$HCt%g8M_aP!}xfvnKK%t4(L7`Lb z{!L3CcEG8R?>*|!wmHdZ>epRQb8|TvgSK4ptS`LOjElApTdr(0wQYS4o|R@I25DvyI%(_G%6L`XEqYW^Q}T27N@xrwmM>20+44`u(pMmIJD8B9cf1pwNzk}C*>aM{P~S3P;?U-17> z8Zt(Mt82eL^SvDb3QbP|g(@_8=qQ6)eK|gvzEtFmht1s8K4{AR*0`8DJg+pjQQG)R zatZcEDxrfWcQl zj6oh|RfYrh+<{nIK%{O^Vt=tH3h<|~_034kKU*+dMDqV&H0t1_>76>k*gi3HR~r6E zlpd2fO?pD)jfq9Hy)fy+p}vEf|K~6ycHb}mE&iV# zntnqxhU3&7+4d^EI zEKBh(y>)Bdd#S+JhJiwkJW%LMf2fWVBdD~>0TA7MH0%^oeFccwuT+Rka5pbQ*P`q? z`i>!VkBkcXntu7`>!+LG^0T)|@X|5`G&BYtI_-K7|1UB-Eolc0i8>{l2$KJ&z_;pc zmQDNG%=h;9L80rjL7{qe9x9_6ZTpjHvoc5pX9}N^Y?O(H;_NjQR_l;qvwdFr&jLe# zahEIhOnI|bh;LbERie8j&65NL-$)B0hCTW?z@lTox3P4hU)Jjy%TtVZ8Dd>D-iiJk zReWPMFk)4275LgXFf{6}28B-b^eLnmvHlB(R-B5h*ppyienobQW-E$`w;!pvB@$wF zKb6sjV90No*{Mj=5Dp;$H6N)KRae+VjnCA-lE0sBzbi)-kxPh@uyK(GxBMuy*s=Zk z*Jl0S_fYJm! zy%pkw3pV-wgU&Sdq@j+lTI;mSyLd>p`Yd+~K9E>n0SBj$hIalN692Cr`lT9*vYSeC z_7V^06|zPGaW?zFAgexECo<$rHtIjHkb`&xifQ_Sq5VJjf1!9p|KRj{Z*+n)auv{9 zmxB%ZnSWV((*iLhBah|CD^}oLz>$Ilhr84({@&={F*NfeC{(WD|3Q1GrCbWNZU4k?Rs_6(2r5^3qdBF! zoUsEHg_sW})B)}yZKcYc%dUNJc;s@9x9FP%7CqdhXZoEw1$ttG^J#isVze|nA>NA4 z=$ApTm}qcK>Z6UpA!l8+sgPngD0E75ELTk>V?8;EJ>aFgUj+a%4)gz=-nxd`k_hsU z0m-{iy7`klbhrdxN-0xtcXxXcmsJf*mvuqy@1}*5b)4~QHReuu|H8y5b48&*fW}#@ zxb*vY#QDLfheO+%`+>e(uZ0mX3!AwTdsw^TTfKpS5z1m_0U}HyN}OAH*q--uR%u5g zQ0OVN%XQ_tgVel60N_qD)o9yXhw$PPuD$|e)|-rh7uZ#_PA&^=dg0`P zctR98@vgt_VzC_oVs`Ta<8a}5tRqZ3+EFQ#hZg!D>$1wC^E#RP|4_N2P}Al;BebKB zdM`I+0>qG9lZTFjDcFiac?gIk{O5{bn03<9s6%|vQPkowKhtDcWrf=bLQxU89wnTe zhY)w_;`l+NyACYG=t)p7n(N-vl0*RzCC0x^I%#LxnK@X_2Co{vkNK+@5wr zY)>;?;AO6#h&pZQD8Rg2=!|&7Rt9KEA9W0EX$OTCx{V-Ptes|b_)w||o~EO51zdxl zAcmK8S=c3E9=BPE$nlDYDYqTz6%uyqYZx6)Xwl5fYb5`Vx<#ui1W|24$R%lV@}x-*SodcR ztfNcQhOZ_0e=!^K#>F38r6qyLGX>sQQ0O!NuLAaR)XGCZU6Sb%q+^a~VGLg9=rWUT zUbfM-uEtFtN8EI07Gb?|h^mkl+VIMspo5qBV!_ZT$V1)*F#Il7&e&ff{Ox*H&_Lzj1vJM3FFURmQVHmU%T&?p zn6$hPgkLl1fQbih?<2J>pRzI554oVo28QYT!gq)DS<5=~L-tfi4! zROsC?sE4f7{J%2FahJ%0xkXYqm<#=Slj0Kcffu=#`&CbfrH>Ft@e1`rCA4e0f8XJ| zM`r<}kZyrCyWtE%kcL_hm}^NQSmiS45JSy9zzd3TmtYz@_m0EV$cvHwrJsF@o3kPc ziBC@Fj}UX6P{@FfG(`3(=0YCwB=gX(J*{>1H~zEMx?{DZk9xO#q(8)vNb`J%g8V;I zs8;uTxM5%C|6M167i8M{2mcSPk5wXpLuHd9Wv)Pv=n`>~FQa<*NpIG?(w0OJL*LGV z7+S7T=oIzN<<8j&3{zp+hm@EoZm^0HP}f_mYuus;n?T=%%tmA=y@LokJi|}PyhehT z$UM|5{$F1$NdyY%jZ|AsM*>bkb%0{`L)~9a=1P6g4(~?Y z1+4p12R6_plHs~&S%pt$DBAO2wbu69kcWzzQ>{UvMh$q0YJEA{$Gl{Yg-cfJ00-=q zdwbeV{{^>|4u8S_@zAW4%a@$;^;S+C+mnXKa_IL>x$CMzn4R3L+Q_W6HknCELPvMF zg8Q6~9(7FpEo_7qL+DzJdMl?sIE4`Mqf|MhCSH)Ia+QU{A4r_Cv)IOM){l{{B0*xl zOKM?`#>J#cRXP?Zc$$taSq_n#?T#W<`KGKhVHsTT*7?c8Tg{_${0LvTsxVn0p7~u6 z>Oa_6TLP&Uxj)p49LfJHtDx5P5ZpZoE)z4vu$wFWdXwVAq@htkD)bfpA1LL%^PZM8 zf;6;tIVjZAmIJnOu9UhS>i#WJyfp}>-8$YBmoAri5Aq*8mB^2Gacoct2e|UiBa7pA z#Zuhk7$zw@&9nvIndaPFTuu-B~10hwN{&`P}Mt6K8SluRQ;Gs1uhb9%@y;DuHQhwl;Uv?>%|w zmd7%Br#wY+JXef8;3FF2?Gx_@dNe%E(zQfZmC4iHd)n@Uwj_cW^1BBy)T!~+AEX{b zlLP=NL7`p%0DIndJ>_G|)=2sU%CUL3xx2CRCp}%cyAd)sB<$HM40&?2`MFkO=R zY)8#`)?=){QFsbF%9Rn!it`s|IDRK84vbC{t`h~IiVN-&1y2J?LMMDXO^Y$~pb`}7 z((o=00+Ga>O7FY6+at>89%48-y-X7`FJ26ZdF*D);36OZwtpr7dP!E+?t>JQH;d%| zk$LC_G&KG>EFiL+SGbKRYIa#IzE`7r4o^$RZtgzAK;EL63;JkFAaXBfM_vy-cMog? zWBox&+2w#3qe>#}j0e#xl&)+=A19z|-bhD2-pNoYj*>egLQ4BS=M0AUF*D{jxc6|E z{?q)w7vyexxh4-mt4~Tb!TabLUuz2c1ezjH7XGWpz~~s)3AOrZN=oo&M^_pu5Ts`$)Zq7?6OV~BhlQ2Y-7qA;q=-V8u8)&Ftr{>@084FBWZ9gx{kA6${cHXo zU+et8jBi1q7EK;HLNWedcl)|$tYX+eTYuG~7_w#CU+N)zk+F;xbN)!Y;))>1X=b%B zN??O>fk`{j$VMi{_;E?v+HON0V(b8gnl*W-l2UmHh%r?{LlSqfN*>t8wVj0(hY^Dv z73PAG#$m^J_B7d>6q@|Gz6sjE!^g#@{o~9rJ6hh%~*Z^pp0!B6!H=o`hr3W z>7lf?FwD{%-E<`I=Duq?@77pF7$KgBakVl}j);D%1j`lwE&kv8JW?SI|L+)ZXesp+ zygMgIWFaOsVy5dx2l+qvo|QX?SooMZN{}2RNXC>RHi|hF|LAZ~$Xp>8_ zpphixA$12YYW3y#*l#P!cZL%Md9GZiF~bZ6Wn+lbfC2Hsyx6iSvtLFm(j7NfoPpV% zmjw<9{y+GCbNX&5z#*>16hkcLvls zIsG`k%?Z&-f@VC5Fz8%vSeU+5Di8#3YC7uM50iZirJ1ZfB*2h=+D(VK-C)Kd)O|Ss zc)=~QZ7JM#A2HMF2zore%c(IwPC6f#mO5GTJXj}FOSH*DuO|Bx$~6y-!M5#vlS(&u z|KMF*$3KocAb(Aq^XoBdSDt81-v~RW<}OR2O$r={Ac{XG#v5L zvFjxU+H;(ec_`Eh6#85b0p;`^h3BUUyjr&HE#rzz!6Cc@CT5hP7LSNS z>$SAhfkF*WL7^;7J@f+*8i%G+rl&wpE0h}wCGy~^_(9INoe_%s3;Yj7o2-j6&UHBEn$KbtEZhX09UOe4GAA z#CmL4e`-zvOQBe9irz|7A0w&Jln@hw6=LiCCDkXoEBe&u%K1iaGGLAJ(LS;t86pn z{Dc0Rd=up~LP?;TtxQ++KxtPv`sqKehi>9;^7m|r*;6U?Pn7$W`=c*HZ^Wx`=RA@73GfQ6y`0kZq15ah3sv;U4pX*j2i5gmvyVtaz_?B z!+d+r_QVwxcfwdxADbGS`Dj2!@*0J;mfsjb|r5XO23+0nxdRx}%Y1$EqJoGsN z3O#opp?+tay|0T(3XvAYLM8AKdSOxQzOD=95c$6AWhA4d?^Y4opB9IE0Wk#pKeA0BmGV$G`MN8`8(w!6f5oG?X?FjE z@V-mUyLe_nL>%D873br!(%c~Fn=56twBn?Ohg_=4IqK*Oe{#@dHwd`i2qaWh105Iu3|wY@{uL$Qb%%Dk$`Y zchTY3hdRe{@&l18AAO)4nV^0^$Ml%Wyk zu*Vzn*`v7bg5=p9dS6k>XuoI&Ah|ih?z8c?B}+Ga=FN5?eIq*`Xj~^_6Cyw zcM4WH;9ZPV-bFD^3eznrn+UU;71xryo7v(NB@2tWXt&lMSxnn|W3F~I0)K^ENP z5j6tDw)YYSA&v7Nprm-(R-0I zE^$T!Vqd4PMp1D;G-*+xj%DyjlB?nW?S}_mgD7Oig3a9L$HPx`m35?xRJ8To*tLsWiL`>hb@&+s9m_OJM1;QkkOET%m1HI@3PJ@E=Wz(OdZg znb_(~!Ke5y{6DFk*rhI%)z-*7;fhS-htAD;p}a3Ggf|ZZHWfrD>DZ{Qa}WAxMQaBw+O3JMGFU@xV;9Pg4E|`PE5j?i54mo zl97}-CC7jddB}SWjP4Ep&t5zFsP}U1B)hC!!~Y}qaul*Dz$~hX7gcaWbR>SVTkEU| zwo+_aK7rd$No4YVvc*bj#|P#JJnfvDtzS+fxl0OAs5kt-Ra#W&Cb^gEQuF^5-)BGd zqtwYMv~6$UcEGIr*tsjW+NJP0#m8KIougSkyn(}XjcJ8OI;cN$XGlV$qAI_K|Mw(N zfTkL>@Ut9f8~D(G`r{M*e*SlAlQ1UXxJE3KGOdu0OOBQ_f>q9!?BLa*$wP-AhA8zo z1^%YjZH=K%B{VIfQX*Tw3u%$itL>z0mcjkmlbxBb6Fimxzx4QQ{t#W@|9uN;wk{MA zPC8w~S&c&@D!5$tF+=ZHTXRjtR%&}4Y|U+NpC78l7@CmAFXulhgKZ zI+^ptkcSc`(Hue-Iylu3*bb2b6Nt;gjtC|QtO$8Oc1}GvV8HE;HLv~wyg0z<+SVa1 z%}V;G-Z~2{g%EkBF#9`o9wK)NWk&&cL9JCzeM6KAB7L3zceOYCzY979N}+9FoYB^~ z4=8kd0K^bWW80=2|1Y~rV^l~DorNt5mj25g#RXsZf4d~uTXtfz;!ldFxb#*r*HoTDxI|-F8v)Fg7UE z(!>9wR2~8|ma++UaHeLgbd z$atf7PAn0+Rj8!>)m@kRj27`)Sl%(VQd@s^NJD!`n!+1R8X~z%)H;^?(w75>7gLL3 zj)X%w#ByDr;SQ5!C=Nr)e~ocY8S zm*%5drCrr7oZy+Fm@`YX6-A)XyVIc1NB3a3V(oyI(-bR*zHn$=8EM%3TO+4?xTQK7 zg=ME4w){kNR7CPo|2`{mLhVxg8voDrGygAVj@<-pg%G*fPW%xR>gY*Bl(NfxGJS<+ zz_Nv1GiotWuFjAKD23iiSJC>BRkJ(gB7fAG#t)O-oUE``nh zZzewt*i;)m+5NbzwMTH9-r3jNRk3O$EB1V`JHTzpwQM#P^jhKKZgUV_#^ zg0wz@EIWbRS)gzg)kt=?VG{Q>#Tc%o0i^^m<9q8XaH1+ROTB z3$hA)5^QWUTLN@51m#IfM_+k>SNi7I=Eg5@d-#0k#v_ksZksW&CCAyMV7*=R{X(0e z>E+`+`(JBvhbL4W8M@S{_~x5E@aw-lxbW)U*_D5O_~Q*S>;}0Icj(Ze!|ru| zf`7EJu^C=LSMSW`e@}nebnI9oBYvFA`P9SDbuIGx&%z=+qfZxq+w`{}=DeAO^rVUM zWVCs@$2gZ4Gx~Eb?z(!Zz)bX z`F7L3zCpX3!*Ova8xu0=;#@X~3(M4xcCmo!0V&0V^^-oj&_3y_YoIH8?3;5-k^B-N> zG9d26tn1%TIhZ;*0)FiXAAXEDoVnfiIb8Ceb+z?3>%Z|GQn3H{52+C6XgA?8Wy09e V@oUQva#SMnZS?>B`5!U^{|^C8lT-iz literal 0 HcmV?d00001 diff --git a/src/plugins/spectrogram.ts b/src/plugins/spectrogram.ts index 8d234c975..46658fb35 100644 --- a/src/plugins/spectrogram.ts +++ b/src/plugins/spectrogram.ts @@ -255,7 +255,7 @@ export type SpectrogramPluginOptions = { alpha?: number /** Min frequency to scale spectrogram. */ frequencyMin?: number - /** Max frequency to scale spectrogram. Set this to samplerate/4 to draw whole range of spectrogram. */ + /** Max frequency to scale spectrogram. Set this to samplerate/2 to draw whole range of spectrogram. */ frequencyMax?: number /** * Based on: https://manual.audacityteam.org/man/spectrogram_settings.html @@ -384,10 +384,12 @@ class SpectrogramPlugin extends BasePlugin freqFrom) { + // Draw background since spectrogram will not fill the entire canvas + const bgColor = this.colorMap[this.colorMap.length - 1] + spectrCc.fillStyle = `rgba(${bgColor[0]}, ${bgColor[1]}, ${bgColor[2]}, ${bgColor[3]})` + spectrCc.fillRect(0, 0, width, height * frequenciesData.length) + } + for (let c = 0; c < frequenciesData.length; c++) { // for each channel const pixels = this.resample(frequenciesData[c]) @@ -521,7 +534,7 @@ class SpectrogramPlugin extends BasePlugin freqFrom` + const rMax1 = Math.min(1, rMax) + + // Crop, scale and stack spectrograms createImageBitmap( imageData, 0, - Math.round(bitmapHeight - bitmapHeight * (freqMax / freqFrom)) / 2, + Math.round(bitmapHeight * (1 - rMax1)), width, - Math.round(bitmapHeight * ((freqMax - freqMin) / freqFrom)), + Math.round(bitmapHeight * (rMax1 - rMin)), ).then((bitmap) => { - spectrCc.drawImage(bitmap, 0, height * c, width, height * 2) + spectrCc.drawImage( + bitmap, + 0, + height * (c + 1 - rMax1 / rMax), + width, + height * rMax1 / rMax, + ) }) } @@ -637,6 +663,34 @@ class SpectrogramPlugin extends BasePlugin 0) @@ -656,7 +710,7 @@ class SpectrogramPlugin extends BasePlugin number, - scaleToHz: (scale: number) => number, ) { - const scaleMin = hzToScale(0) - const scaleMax = hzToScale(this.frequencyMax) - return scaleToHz(scaleMin + (index / labelIndex) * (scaleMax - scaleMin)) + const scaleMin = this.hzToScale(this.frequencyMin) + const scaleMax = this.hzToScale(this.frequencyMax) + return this.scaleToHz(scaleMin + (index / labelIndex) * (scaleMax - scaleMin)) } private loadLabels( @@ -796,25 +848,7 @@ class SpectrogramPlugin extends BasePlugin