block by vlandham 9313904

spectrogram

Full Screen

Interactive Spectrogram in the browser!

Same as example in: https://github.com/vlandham/spectrogramJS - but in blocks.

Click ‘analyze’ to play the sound and create spectrogram.

Uses web audio api.

Also uses D3 with canvas to display the main visualization.

index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <title>SpectrogramJS</title>
    <style>
canvas, svg {
  position: absolute;
  top: 0;
  left: 0;
}

.spectrogram {
  position: relative;
}

.axis {
  font: 14px sans-serif;
}

.axis path,
.axis line {
  fill: none;
}

.axis line {
  shape-rendering: crispEdges;
  stroke: #444;
  stroke-width: 1.0px;
  stroke-dasharray: 2,4;
}

    </style>
  </head>
  <body>
    <h1>SpectrogramJS</h1>
    <p>Visualize sounds using a spectrogram - right in your browser!</p>

    <div id="vis" class="spectrogram"></div>

    <p><a href="https://github.com/vlandham/spectrogramJS">See how to use SpectrogramJS</a></p>
    
    <script src="//ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
    <script src="//d3js.org/d3.v3.min.js"></script>
    <script type="text/javascript" src="spectrogram.js"></script>
    <script>
      var sample = new Spectrogram('bird_short.ogg', "#vis", {width:500, height:200, maxFrequency:8000});
    </script>
  </body>
</html>

bird_short.ogg

OggS ��``ܖRvorbisD�w�OggS ��`�N4�-���������������vorbisXiph.Org libVorbis I 20070622vorbis)BCV1L ŀАU`$)�fI)���(y��HI)���0�����c�1�c�1�c� 4d�(	���Ij�9g'�r�9iN8� �Q�9	��&cn���kn�)%
Y@H!�RH!�b�!�b�!�r�!��r
*���
2� �L2餓N:騣�:�(��B-��JL1�Vc��]|s�9�s�9�s�	BCV BdB!�R�)��r
2ȀАU �G�I�˱��$O�,Q5�3ESTMUUUUu]Wve�vu�v}Y��[�}Y��[؅]��a�a�a�a�}��}��} 4d �#9��)�"��9����d 	�")��I�fj�i��h��m˲,˲����i��i��i��i��i��i��i�fY�eY�eY�eY�eY�eY�eY�eY�eY�eY�eY�eY�eY@h�*@@�q�q$ER$�r,
Y�@R,�r4Gs4�s<�s<GtDɔL��L
Y@1�q��$OR-�r5Ws=�sM�u]WUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU�АU!�f�j�3�a 4d��C
Y��� �К��9�堩����T�'����s�9�l��s�)ʙŠ�Кs�I����Кs�y���Қs���a�s�iҚ��X�s�YК樹�sΉ��'��T�s�9�s�9�sΩ^���9�sΉڛk�	]�s��d���	�s�9�s�9�s�	BCV@a�Ɲ� }�b!�!�t���1�)���FJ��PR'�t�АU �RH!�RH!�RH!�b�!��r
*����*�(��2�,��2ˬ��:��C1��J,5�Vc���s�9Hk���Z+��RJ)� 4d@ d�A�RH!��r�)���

Y�$�������Q%Q%�2-S3=UTUWvmY�u۷�]�u��}�׍_�eY�eY�eY�eY�eY�e	BCV B!�RH!��b�1ǜ�NB	�АU �GqǑɑ$K�$M�,��4O�4�EQ4MS]�u�eS6]�5e�Ue�veٶe[�}Y�}��}��}��}��}��u 4d �#9�")�"9��H����d�(��8�#I�$Y�&y�g�����驢
����h�������爎(��i�����lʮ뺮뺮뺮뺮뺮뺮뺮뺮뺮뺮뺮�@h�*@@Gr$Gr$ER$Er$
Y��1CR$Dz,M�4O�4�=�3=UtE
Y��K���$QR-�R5�R-UT=UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU�4M�4�А�#A��r�Bn=X1�$�9����39
"t�A'=��9���R(DL��%7� 
¦\I�8BCVQ�1�1�r�IɠD�1	���9'���I)-�3)%�c㜣�Iɤ�K���c�����А@bR
)��R�)�R�1�RJ9��S�9��1��)�S�)���A圃�A( � �B(4dE'�p$ϓ4K%KE�e�Mו4�45QTU�U�TU�MU�%MMM�TUEUUӖMU�m�4e�TU�Uնe�~W�u�3MYU��MU�uז}_�m]�4�45QTUMU�TU�6U׶5QtUQUeYTUYveY�UW�}KU�SM�UU�U��mU�}�tU]We��UY~[ׅ��}�U��M��uU�}a�ea�u�(i�ij����(�����m���[�誢�ʲg���ʲ���l�(�����,��,�����,붨���ʲ�������,�p��������,뺭��q�0|�)˦�꺩��n�q̶m���*�°ʲ��/�u!QUuݔ]�WeY�m_w�[���m;����q���9�o��m�n�����+?a8��g��m�������n+ì�BQU}]�e�7]Yn�7�[׍���*˾�ʲ1��o�0]�6�[ם��}c��	�k��q�:��u��	Ǐ���@�!+�8!�S*� tR� �T1!sNJ��PJj!��*� T�IȜ�Jh)��R��PJk���Rk���b� �Ji-��Zj���Z�c2�d�I	��Ji-sNJ砤BJ��KJ-V�Iɠ��AH��SI��PJk��KJ1�[n1�Ji-�[I)�Sm-ƚ#� d�Iɜ�Ji-��Z嘔BJ���JJ���R̜��AH���JI)��JL���JJ��RZl1֜Rl5��ZI)ƒJl-�Z[L�uZ��Ji��Vkj��PJk%�KJ��kn1�Ji��[I��[�-ƚSk5��jn1�[m=֚sJ���R�-ƚcm�՚{� �Ji-��bj-��b����J*���Zl1��Z�9��bI�ŒR�-ƚ[l���jl1�R����sl5��Z�-ƚSK��Zs���V��@�	e�А�@A�R�Iir�9*	B�9'�rLB))U�A%��9))��9%�K*-�Vk))�k-�� �M��

Y	D � ������c"�sNJ�c�I�sB*c�A()�PJ*)�JI%�
lДX�А@`b1� tT2*�LJ'��Z�u�Rk���Zj���@���2K%��Zf�ĘZ+����B(4d%�@�c�9gb�9�41��*Ɯ�Bc�A!��9!�B��B��B���A!�RJ� �B)�tB��R
*p�Qds���BCVy�1J9��F)� ��R�cJI�rB))�V9���Z� ��Zl5vJi-�ZCJ��Xk�!��b�5��Z���kJ-�Zk͹��E6'	*4d%�� �c�1�b�1�C)Řs�)�s�9�b�9�s�1�s�9Ƙs�9�s�9�s�9�s�9�s�9�s�9�s�	*p�Qds���BCV�Vb�1�1�c�1Fb�1�cl1�c�1Ƙb�1�c�1�c�1�c�1�c�1�c�1�c�1�c�1�c�1�c�1�c�1�[k���Zk���Zk���Zk�@�
�VG8),4d%Øs�9��)褄B�CJ9(%�PJ))sNJJ���ZJ�sRR*%��R� ��ZJ-��Z%��Rj���:���Zk���AH)��Z�-�PJJ���b�5�RRj���b�1��Rl-�c����Zk1�k-)��b���ZkI���b�5�Z�np�H�q�������BCV!B�9�sB!R�1砃B!DJ1�tB!��1砃B!��1�tB!�:��B��RJ�tB!�PB� �B��RJ)�B(��RJ)%�B	��RJ)��B��J)��B��RJ)��B!�RJ)��RB��PJ)��RJ!�RJ)��RJ	!�PJ)��RJ)!�J)��RJ)���#�$��"l4��Ph�J�q�j�)�� Ŝ��K��rb.R�9G�eH�Ք1�SRk�b�QO�cJ1ì�VJ(���r��v� 0!3�@���)����1\�2

DŽs�i����X���b:X\`�������2�]�u � !�����nx�
O��	:E��
 ""�9����������$���f����$Dd����%OggS�� ��`\�bHR` &'{b`UTgebcZ_"%$&)'((�(q"&$'+-lZTYY`_Z^ae\VX\v&,,,2/�8
�e|�˽T���6���-L�����E<���l�Y������h��,埂�5FK$�}c��[�6�ߴ.5����5�{
j�`��{�wx��������6h�_�r�d�_�?GyY�
�������o��YH�ȟ�v���s~��|�-��N�D���_��u�䷕�D�ϕa�+f��'d����8�W:���>�����p�K��3��0@������Up�B���nS��ۆs
�{�X ��R��yk}y`E���s��V�<�Zch���p����9�����:�d�$u�Z��^
�~�/��W����e%��4(���Ix��x�Z2�U�lj�����|��`�v���'}�Rp�9�B��AK���`0,)��f�{m�W����7�K���w0���<��D���;%��A����UJ�!h8��e�H����˟��h���>�],��v�N-:;��0g+�������o5����Ә��J�Tk`���!���Ƿ�gY�2a�(�/��:J�/�J�ۃp4p��fp"1e���#y��飫!~��W	�m�Ɵ���r�
`��"R�ɗ��0d\�u��|x��>�ף��
>R��s=˺!�O�v @��Չ҄���k>���_�4��?���D`\�\�q�Z�;�>��l{0�c8?Q?�r��g+Q�3������!�Y�w�
��w���~3]P���PQ~������_��L]�+MK֠o
F+�N��l�@C��y�߇
j���9��{��DZ�D�A`��Η��>��������Ȓ��1�,����Ì�
�7�?"Hm����¤��q	�POSL|�t�	�>�)QMt��=	��Ht0�>��r0��S�����gK;Դ�0[ީ�^:��}w��^x�_/	S8�?/��+�����<ỳ�xy6�؍���(ckY/�%%kgwB���;��k�'�j�t�`���tn%��n��g���Y�Qh^xe_��Ob��G����ub�4X� �"�u�u�L�0+R���[�e�
�5�����>���}�;	����E���_�>���=�
��d��瓉��3��n�	zG&��
��wŀ�{����3��T�9�*_�{L'�G�i�!�Fדg��~�J����7e��َ����C�MO��,A�O��F�/�����	B����*))��U�p.H-�����a�^
�`���V�.�������$-_�O�����#�l+@$ħҐ�ڏ��I�jB��$1�o�����;"��7�p?;?�r��������?Y�_�Oϊ���Df2p���pjaca��7\�����|}!����P�g�8ޔ����Ɇ���_��άR�\_�K���@�aON�χ�a#Mǩ�'����{?��Lw�9�>����*���ե�dz���%��@���C�*���e���gN�v�(��Dj�����,��õ��˵�ө�6P�k_{��-�i��v��_��v�c����̜�%���k.:��٩gՀ>Rm��Z�R��>Z��,�uj���ڢ��â�:
\�)V��)o���e��(_��L��C�'n�catl��m(j����e��.�B@޷}�<	�!A8t��%�B�g�sK���v��ZC�S�ׯ;�9�X�dCK�<7�����������}�dS`������s^��������:Pz��Ջ�}��������9�s�&�z���������3����x�����Hw���L:�����ݔ�)����	3��KN�.�G��s��w�xBD{�0F�Wv���p����E����2�×=��%/�ijAo��Y�����!�y�%"��*+��vs{U,&b�mW:	��D��e�w������`�jpU:�:l���)_tb���<��4���6�=1:�����񷧿�+�0y��
�GA�Tk�o=f��.߸���Q��T���Wc�|!|:dk�X�q�:���C����%�Y���o�������V��E�޸���������'����%=�z��'��])�-��^'������+N�hK�ޭ���4
6���Ȅ����_��M������A�H�4�����n�)>�fR�㛬_/Y��t�9^�[$��F����=]*L ^w�}��h�Gߔ�\�,��5���w����5p�0L�،t��C)@��(.�����w���iq��t~|h!Ԗ(���	v
��/S,�D�E{)7�eh����}��SÖ�%�w��h�8��%(d��a�FĆ#���lc����M���t�]���I��r9eǓN�c.�4�i�I+�Wݸ�E�f������a���8@�3PY�+��
���w�ݚ�#��ꉐ���z=_�J�"��{��(c19'�	&��_��D�<�h��"����|��Ue�%}}eYC>Ao�[���D8����.{J'�
�gyǠ���p���Ǜ����u�����/mh
#mf�K	��si|b���=)��U�D��,���pW$��X,�〜O�g&WQ�t�D�,�i%�^���@?�� ��Ӟ��P�}�ů���t@��vO.�m���~�_o��"�K����k�K� 8@AM}
��%f�U'���?�֔��E��nD��S#P	؊�_*��!<�1�o�:N�X;Ö���_~�ş_�?�����z��B�P����J˦���@�fPa��C^��q�`�1I��_����^��,�^�7�������
 	����ş��/3~�����!8}`Q�R���/�5�'g�ңV/��������,�Wu��I�ԁ��������
j�Z5W�E���,)Pxk���7U>��1)~�?�F?�@���S~�4�(4Ƙ��`�C������`6Bw�cN���$<�x��0���mb�)FUj�km��Q~'U����
;~��^�9�i�&df��>B>�RxI�
��g=^B/4`�XكJ�U��,��5-y��c^E�t����r��7�^�`�Ʒ6�L)�K�-�Cd
�g�g�	��&���F8���Q�t ZO&j����2Sk�\���V[ŘO��>���/
%�WuU�@	�,��,?�d%��تB������ֳ���ϋOtm��x}([�u@�%�="���W���"@��,6�����G|忋6�[�Y7p�p��޻���8u��h����@=������k����y#�4�j��E�V�=D�?�wxƦ<����g(X���O���2��)�/�=e�c��J�%�2�lb��o$P�O��d�L�+%��� �P�pH�W�&�8"�~� !�{0]���&)�ߜ���zbd�i�$d?˟H�D����ui��c�8{{��'!�o��=�tc+��	�4���*��nб��hD�2oꇝ�_�%�dI��^U�����(D��������I����V[g����O�=r#�_It(���m�G��&1==]�Dz4�}�]�_O4[�TU|ey���e��g���o�ϘUU�њ���Y�sh]�lj2}��$��
i-oQ��<A-�����Y�&_R[w����-���KJ���^���*!cs	S����u����D9^��&�%?o���
Q!y�~��'��@fղ�G�+��ddyv-��)���vN���ab'C����e��,_B!L6 `
0�]̼����&�ڝ�ؖ\��Sy��\��A����OggS�� ��`�6��Z"&$&"x_]daZaa\]UT�)***/-1�""#$'//.,q][Yb`X^V]u$*('+/20�-�e��,_J����EaL��`�틫I���=��5T�+R*{b��`7o��Klc,��
���F�)�����E��s:�L,�F����f�a���b��%�N�8���C��э��q����	��K���<Yy� x�c1S6�����C��[�s
��������-<P<_�Fp��v�-��XԦ|(����~d��~C���(
mt��S�1>��};���_��0�Sj/�������@Z4��Z��{�gKR���_�O�m��
�H|	P�nH�e���hS����N������ol;e�䈛���(�%&2Ԯ�c���$�8��.J���2�~����X���E�l8�5��A~20�u�
��S�m�"G��A(v�nrg���rxu��^xU���)5���i�b�D�W��3�*��^�j��,��r3��h� �o�Ϫt�&���rRΊ-���G�_n-��ܹ��xD�5�'�����u�xm�����A��BX: ϯ-��%��>�1�ۗ���$����}A��wHS!��O�!�('�������(`�S'+?�L��e�	���/�j÷��˽5&�d?@��q$/ߜW�ZtH�H�ڊfhq��ۣ���-Wr�*���K�1Pz�����]�X/䙒ؤ��p�LX%޸_��7�������[J
6䆠�g�qn�r�K���ύ]���ƾ�e��|��*MG+�P:J��@�}���A��V���v���^������=�����9<N).@��`5���tf��;�:��)ϟ>~/gռ	����h��j�ps&ؿ�֦	4��NGR�G�����o����w����OF��^��EU}���Tҹ��1ҿU�>�����m)j;�96��:zm��ey9Bn�"<���&^������^��PO�
0YX�&@�c��~6D��w�q�4X�
��_G�C��R�!�i��ӿ���R'���!Uː������L���p����Wݸ���_�b�����@:Ht�F�W��I��V80W�U�Cαw��3!	��z�iW�T�z��{ں�4�-���k",r�2^x����T\��/^P��<@O:`(�v)�q]C�h���zy�T�*h���[��[�=�K��0E�����DN$�$O��*?��G��-�vg�x�-�"�D/�	k9�E2e ��?����y��bl�
�u�MP����C��Ӟ��^�ދ�
���^��'����'��wo9(q�
��G��T? ��:��n�I3����.
�!��y��Љ�@j���l`  �)d[�X��`�6���gs�����?����-�r`�@�$��%��{�3��eP�����c��iLZk���v�/F��:��^ ����>H��R`��3�r�煯
G�"]/��$��g.���������~�%���%�߸Cd ��J�
־��bm�o��<��#�x?�)�?�?��D�ӼDd�z�k[�0����m�W����,-���#��"'vx��#��McfHqQ�o����`��_5,1����T��PcX5��� ��_��mq�aApf�;��$�g��&_��	r����܂���(5���ĉ�n��ۭ;ƺ�%,%���#�<�3�n��~K���ל0i����a[����pº��ֱb�w��'�u�����	�/�}&>;֖L��&��r:��c�E7O:�;�¯�h��4�5,����@�jT0��pvR��2Y!��_" ��dCw��nD9�����{s���E�������YaJ���(Z��̬O���4䳣�/���z�REO7)�n�=L�S�N��[���j�T�?�_-�j�x�y�p��ߒ���7�L��Z�]*�e��,_J���իW/iY���+����Jշ��Q�5o���.��������I�~��Z ���&.S1�K���~���>DӔ:�x$�n#W<oD[{��~z�h�m����-p�W@������J֎�x��w&Q�Mv
�& �H������*W����y�m-kV�I���r?�w5u�˽�PL�S�C������5'�7�[������!}Ў�5�_���[��ғ�=�L��S�Ų�{m��ɮ�4��?ʡ��0ɜ�����O��K�fh�l�֪ð�F�rS�Ǖ�ׁ���&��$���%!_���������9^�TPw�iUz�*����6��?��Eq\t�7�﻾?@�/~.��@0e@�-�_���������K��
�'����KQ�}+Y�T�VU�?07�/Y>/��袒_��D�Egfi��(��~8$�����`e�Ҙ�ȭ���`�'�����j� ��gϛ�P�������Ppg1�T��'C���-z��-��(�t�7���1�4�i��ݟ����m�U�D���?}ۚ>,%h
@�*K_���)Mn��ocꇍ>��#N@ެ	u�JĆU0�~⏍/6Zz#�.�{�@޸�ݓ�} �����o��,�z���(�)s�f�T�]�O����y�ͱ�(2��^i
� �b�/�A��[
��Ӓ��W�}�A�,3^��>{W4BE;�R:�����x`��Ӆ+��C�����1��ʮ������>~W�3�˥-
Ӥ�������XG���-|~ݴ�o.����k���`$�}]ڣ@"�LC�H���1��h_���x��֚�ֈ,��#��|���$@�.`?�d�]�������
�n��<�~������,'�}3����q
P����n���F��c����6�K#J�׺(�����׭fb!loe6���G�Z�)��8~���?�?�����O}XGV�,1!L�u�꯱�}��O5�V�cO8Y�����|��`˟�����8�173�e��Mk�y�N-��%?_����}��>��dA;H)���!>��Q�M���u�h	�EX�Ƣ��o�!Q6��g�_����{L�6�=��O�銿�<�7%?�"�*�z�v���H��0HX
C㨋�o���ϲI�`0?��x)�fFa�I���A�Y;�>�ks4��^S��9�@���j��V����^5�R��;{��%`2M(�,���Y�II�.�u�ܐ����C��BO:К�=����g��L��y[��
֙(0Z�>QB��j�u>`rNxVǴ/�q
��>�O,5_�'w}���%�n��	pp��`s�����m�v�&1�o�����芀}�����4�>a?R��w�S�@z}O-_���
މB��e@�0�"�C�|�	��E�V����$5���?��}W�MB���մ�h%Q��m���=<���8$)_���~�����~����[=�&�X��K���U6�p��*�%���W\g%���*@���cI���IL���֡�P(���7��D�l�VE>�ݙ�Ux�VO6�3�`<.�S�
�q�7��*_��Y'O��)y�K�����
\�Y/������L,�A�z���֬f�f+�e���}n|��<���KvZhH����Q~\m:	 Y���?q���|n����B��������"�ɛJ�}�8�q��̩���g�|]��@P��ſ�,���5�Y֍������n62����H%��a���f.g� N��ٖ��6J�/!{S�|���Ϯ��x
s��5�����ɮ�_í�e��Y� �
�,
(5ݱǷ��:�i-GX��r���eZ�sOggS� ��`�`[�N-~nkgb##$$%-,1�
 !$ #/0\ie]TVY]ZU^F^&(()&),+�#�e��,_J���;�R��[>	��	ht�,C`���+�e�ϧ>����[˿}��q:�,`�f�$6b��$�Չ���[�����u��)87�F�����!�zC����^߼9�#�Y�n��k8@ė��өk�E�N���p���^��e�O�o�8�'4�n��%��6�,��3w��
D���)a<
h���ۥQ���l>��)�lt�S�ҧ�������fn�]��sk@F}�@�����l�����	��������86�^!jK�������D��	H��`V� �����p&f�����`i���nX����CX��S��`�ѝz�D�M�{l�S#�M��님
�Ƭ/����z0����,U��@�!L�~u��@Z8
ύy *a���6��|��|�+�ZK��e�=��O���9��#�fw�����BkB�S���!�'-�������T9mӿ�Vai�����6�1�l#,�__�����D��v��WT[�hw�ٸw��{Y��j%��*���3��p%t�u��J�uŭ'__�b>j	�VM��Р÷|D��|mѹ'�u�~�t�`K0A�t�x^"��&��la����l^���|��O�5̦��6z�!/��LEusa�7���}8	��|VC
�����u
&�q�<I�׃濗H��^O b^�]>�f}��L�c�e~4E��GF����?v=�H������BX�J6����4E}s��q���_�V������ ��0ƥ�:0�)"DAu뿎���ъi\~|p�,�c���ʹ���Ɨ������w�v�\K��6{��O3@�]m�3\MDt�����
c��O���|c�Uz���*P�$O�Fk*8 ��X�ɸqv�Z����Gٴm�4C��dt/�e�^F�K���|�xK����2�e&ɂIς|������d �_-C��_O�=���Rn�}_�/&w�9tL�
��E��N���_i� �to�gڀ�z.��׆�)J6���/��M1��ik2�^I��e>y�#�'(����MP���*�o�M���Յ��E�-�!`�ү�sx��ҋ80���'��C_ȟ����x��w�
�`�$������-�5
�/��f�(��2�%[�P�����g��D\6� �i�*I�]�����"��P��q���]��	*
����[;h���7�l0�Z��Y�Z�\ƹ�45`0X��Oq�E�m��'����tT���܏vq���m���d2}����\,(O�۴�_t�{����B��R�v9E<��*sMw��䳕&'a�z�_�ٞ]�_����ݴ<!���:������?ﯧ�
�V��d
��e&���^ϸ�l
L�N����g3�w����˱�S{�H���?q�����$L��	W���;]�	'&�Wݸߛ��lUL�?�qĉ%L3`<[?���7K�0�5���v[l��i
���)B���go���r�-�3[��姛�QG���
��
C\`~^��l>h��?�ǩ��������Ĵ@'�>LJ]_I�	t`�%Pw�>���#�X�U	>�6m$%��<����0�rΥ#��PQ��h��˳B���*��~^"H5ˊK���|$@g��C�@��=���?|�Nz\�����M��)a>����b�c�m5�׍�
� k�y�ALyhL��BL����D	�
	֯������s���dA`��1�������|�	)���_���޲׃�<��׾S�9���l��������3�@����m���'�Y~�եl��a��(`��ʴa%�ֺ����ٖ#�M��|�5�=+�K���c�nU���{e�/ǫ�� q)��-��o
�O��j��HV��V�}ԏ�YXb�(�{�w�w����dS`~Qe|��^���:3�	�Z�x�)m������7���o���2S�H��ʡAZ�C'�k��aS&h	����_^�OȲ֘P���lt,6`h����3�e"�ځ–����&���7����2���W3=G8�`�>i �@����q��rbv�@X�r>�<������ g'�հ�ي���&(���ö�X�� ����C��E�7��*?��W����,$�t������3c��Yfk�������]�M���O.>�l'�M�	���	d���iT�s�7�����_���/*q��`�YR?��H�Z\�8=Qz�x!��bJˋ�*R���|m Q��PX(J�������S�e��y���[	��x��&_@Xp�2�AG��G��T�K��u�jz���*4΀�K�Wd�?�bR�֭��pJ����{�ԯ��#fg!P_�sʳ�Vs����0Z�'���Z�d�_����Յ�PH�s�@�~q�I�w
`�j�L�§���$��o�����hmU[ejz��H�۴���o�Hp� _�o��_��<d5����K�E������Zz\'����_��7�`��WfCF|�iW��� ÎOy���K� ������J�Q���eAdcn��R����6E&Yڛ�w����+ʿ
��t�)8�/����(�ʷ�&�U�_��߱��0�0MS
��~�D+<��/�g�>n�_�Wy�C��p���!{����[�剧Ţ��������N����0��hn*�S}upuHf��i~��ǚ�+\?�����-��*}�e�����!�����/9ܹQ.e��e�σ	ἉcZ.���,[&���b�s�[8'�^M���^5�c��Z��K�b�`V)݆�Ϙ��9���~Y�8��ˬP�i�zD3�Ɉߗ����U�6��Ms{p����GN����=���C�~Dn^�(�O���F�|$�e��,_J1@_H1t���C2 �����

spectrogram.js

// shim requestAnimFrame for animating playback
window.requestAnimFrame = (function(){
return  window.requestAnimationFrame       || 
  window.webkitRequestAnimationFrame || 
  window.mozRequestAnimationFrame    || 
  window.oRequestAnimationFrame      || 
  window.msRequestAnimationFrame     || 
  function( callback ){
  window.setTimeout(callback, 1000 / 60);
};
})();

window.AudioContext = window.AudioContext || window.webkitAudioContext;

// helper function for loading one or more sound files
function loadSounds(obj, context, soundMap, callback) {
  var names = [];
  var paths = [];
  for (var name in soundMap) {
    var path = soundMap[name];
    names.push(name);
    paths.push(path);
  }
  bufferLoader = new BufferLoader(context, paths, function(bufferList) {
    for (var i = 0; i < bufferList.length; i++) {
      var buffer = bufferList[i];
      var name = names[i];
      obj[name] = buffer;
    }
    if (callback) {
      callback();
    }
  });
  bufferLoader.load();
}

// class that performs most of the work to load
// a new sound file asynchronously
// originally from: http://chimera.labs.oreilly.com/books/1234000001552/ch02.html
function BufferLoader(context, urlList, callback) {
  this.context = context;
  this.urlList = urlList;
  this.onload = callback;
  this.bufferList = new Array();
  this.loadCount = 0;
}

BufferLoader.prototype.loadBuffer = function(url, index) {
  // Load buffer asynchronously
  var request = new XMLHttpRequest();
  request.open("GET", url, true);
  request.responseType = "arraybuffer";

  var loader = this;

  request.onload = function() {
    // Asynchronously decode the audio file data in request.response
    loader.context.decodeAudioData(
      request.response,
      function(buffer) {
        if (!buffer) {
          alert('error decoding file data: ' + url);
          return;
        }
        loader.bufferList[index] = buffer;
        if (++loader.loadCount == loader.urlList.length)
          loader.onload(loader.bufferList);
      },
      function(error) {
        console.error('decodeAudioData error', error);
      }
    );
  }

  request.onerror = function() {
    alert('BufferLoader: XHR error');
  }
  request.send();
};

BufferLoader.prototype.load = function() {
  for (var i = 0; i < this.urlList.length; ++i)
  this.loadBuffer(this.urlList[i], i);
};

// ---
// Spectrogram class 
// constructor takes a filename, selector id to use to figure 
// out where to display, and a big options hash.
// (not a great api - I know!)
// sets up most of the configuration for the sound analysis
// and then loads the sound using loadSounds.
// Once finished loading, the setupVisual callback
// is called.
// ---
function Spectrogram(filename, selector, options) {
  if (!options) {
    options = {};
  }
  this.options = options;

  var SMOOTHING = 0.0;
  var FFT_SIZE = 2048;

  // this.sampleRate = 256;
  this.sampleRate = options.sampleSize || 512;
  this.decRange = [-80.0, 80.0];

  this.width = options.width || 900;
  this.height = options.height || 440;
  this.margin = {top: 20, right: 20, bottom: 30, left: 50};

  this.selector = selector;
  this.filename = filename;
  this.context = context = new AudioContext();
  this.analyser = context.createAnalyser();
  this.javascriptNode = context.createScriptProcessor(this.sampleRate, 1, 1);

  this.analyser.minDecibels = this.decRange[0];
  this.analyser.maxDecibels = this.decRange[1];

  this.analyser.smoothingTimeConstant = SMOOTHING;
  this.analyser.fftSize = FFT_SIZE;


  this.freqs = new Uint8Array(this.analyser.frequencyBinCount);
  this.data = [];

  this.isPlaying = false;
  this.isLoaded = false;
  this.startTime = 0;
  this.startOffset = 0;
  this.count = 0;
  this.curSec = 0;
  this.maxCount = 0;

  loadSounds(this, this.context, {
    buffer: this.filename
  }, this.setupVisual.bind(this));
}

// ---
// process
// callback executed each onaudioprocess of the javascriptNode.
// performs the work of analyzing the sound and storing the results
// in a big array (not a great idea, but I haven't thought of something
// better.
// ---
Spectrogram.prototype.process = function(e) {
  if(this.isPlaying && !this.isLoaded) {
    this.count += 1;
    this.curSec =  (this.sampleRate * this.count) / this.buffer.sampleRate;
    this.analyser.getByteFrequencyData(this.freqs);

    var d = {'key':this.curSec, 'values':new Uint8Array(this.freqs)};
    this.data.push(d);
    if(this.count >= this.maxCount) {
      this.switchButtonText();
      this.togglePlayback();
      this.draw();
      this.isLoaded = true;
      console.log(this.data.length);
      console.log(this.data[0].values.length);
    }
  }
}

// ---
// setupVisual
// callback executed when the sound has been loaded. 
// sets up scales and other components needed to visualize.
// ---
Spectrogram.prototype.setupVisual = function() {

  console.log(this.context.sampleRate);

  // can configure these from the options
  this.timeRange = [0, this.buffer.duration];
  var maxFrequency = this.options.maxFrequency || this.getBinFrequency(this.analyser.frequencyBinCount / 2);
  var minFrequency = this.options.minFrequency || this.getBinFrequency(0);
  this.freqRange = [minFrequency, maxFrequency];

  this.svg = d3.select(this.selector).append("svg")
    .attr("width", this.width + this.margin.left + this.margin.right)
    .attr("height", this.height + this.margin.top + this.margin.bottom)
    .append("g")
    .attr("transform", "translate(" + this.margin.left + "," + this.margin.top + ")");

  this.canvas = d3.select(this.selector).append("canvas")
    .attr("class", "vis_canvas")
    .attr("width", this.width + this.margin.left)
    .attr("height", this.height + this.margin.top)
    .style("padding", d3.map(this.margin).values().join("px ") + "px");

  this.progressLine = this.svg.append("line");

  var that = this;
  var button_id = this.selector + "_button";
  this.button = d3.select(this.selector).append("button")
    .style("margin-top", this.height + this.margin.top + this.margin.bottom + 20 + "px")
    .attr("id", button_id)
    .text("analyze")
    .on("click", function() {
      that.togglePlayback();
    });

  var freqs = [];
  for(i = 64; i < this.analyser.frequencyBinCount; i += 64) {
    freqs.push(d3.round(this.getBinFrequency(i), 4));
  }

  this.freqSelect = d3.select(this.selector).append("select")
    .style("margin-top", this.height + this.margin.top + this.margin.bottom + 20 + "px")
    .style("margin-left", "20px")
    .on("change", function() {
      var newFreq = this.options[this.selectedIndex].value
      console.log(newFreq);
      that.yScale.domain([0, newFreq]);
      that.draw();
    });

  this.freqSelect.selectAll('option')
    .data(freqs).enter()
    .append("option")
    .attr("value", function(d) { return d;})
    .attr("selected", function(d,i) { return (d == 11047) ? "selected" : null;})
    .text(function(d) { return d3.round(d / 1000) + "k";});

  this.maxCount = (this.context.sampleRate / this.sampleRate) * this.buffer.duration;

  this.xScale = d3.scale.linear()
    .domain(this.timeRange)
    .range([0, this.width]);

  this.yScale = d3.scale.linear()
    .domain(this.freqRange)
    .range([this.height,0]);

  this.zScale = d3.scale.linear()
    .domain(this.decRange)
    .range(["white", "black"])
    .interpolate(d3.interpolateLab);

  var commasFormatter = d3.format(",.1f");
  this.xAxis = d3.svg.axis()
    .scale(this.xScale)
    .orient("bottom")
    .tickSize(-this.height - 15)
    .tickPadding(10)
    .tickFormat(function(d) {return commasFormatter(d) + "s";});

  this.yAxis = d3.svg.axis()
    .scale(this.yScale)
    .orient("left")
    .tickSize(-this.width - 10, 0, 0)
    .tickPadding(10)
    .tickFormat(function(d) {return d3.round(d / 1000, 0) + "k";});
  
  this.svg.append("g")
    .attr("class", "x axis")
    .attr("transform", "translate(0," + (this.height + 10)  + ")")
    .call(this.xAxis);

  this.svg.append("g")
    .attr("class", "y axis")
    .attr("transform", "translate(" + (-10) + ",0)")
    .call(this.yAxis)
}

// ---
// showProgress
// ---
Spectrogram.prototype.showProgress = function() {
  if(this.isPlaying && this.isLoaded) {
    this.curDuration = (this.context.currentTime - this.startTime);
    // this.count += 1;
    // this.curSec = (this.sampleRate * this.count) / this.buffer.sampleRate;
    var that = this;
    this.progressLine
      .attr("x1", function() {return that.xScale(that.curDuration);})
      .attr("x2", function() {return that.xScale(that.curDuration);})
      .attr("y1", 0)
      .attr("y2", this.height)
      .attr("stroke",'red')
      .attr("stroke-width", 2.0);

    requestAnimFrame(this.showProgress.bind(this));

    if(this.curDuration >= this.buffer.duration) {
      this.progressLine.attr("y2", 0);
      this.togglePlayback()
    }
  }
}

// ---
// Little helper function to change the text on the button
// after the sound has been analyzed.
// ---
Spectrogram.prototype.switchButtonText = function() {
  this.button.text("play");
}

// ---
// Toggle playback
// ---
Spectrogram.prototype.togglePlayback = function() {
  if (this.isPlaying) {
    this.source.stop(0);
    this.startOffset += this.context.currentTime - this.startTime;
    console.log('paused at', this.startOffset);
    this.button.attr("disabled", null);
  } else {
    this.button.attr("disabled", true);
    this.startTime = this.context.currentTime;
    this.count = 0;
    this.curSec = 0;
    this.curDuration = 0;
    this.source = this.context.createBufferSource();
    this.source.buffer = this.buffer;
    this.analyser.buffer = this.buffer;
    this.javascriptNode.onaudioprocess = this.process.bind(this);

    // Connect graph
    this.source.connect(this.analyser);
    this.analyser.connect(this.javascriptNode);

    this.source.connect(this.context.destination);
    this.javascriptNode.connect(this.context.destination);

    this.source.loop = false;
    this.source.start(0, this.startOffset % this.buffer.duration);

    console.log('started at', this.startOffset);
    
    if (this.isLoaded) {
      requestAnimFrame(this.showProgress.bind(this));
    }
  }
  this.isPlaying = !this.isPlaying;
}

// ---
// ---
Spectrogram.prototype.draw = function() {
  var that = this;

  var min = d3.min(this.data, function(d) { return d3.min(d.values)});
  var max = d3.max(this.data, function(d) { return d3.max(d.values)});
  this.zScale.domain([min + 20, max - 20]);

  this.dotWidth = this.width / this.maxCount;
  this.dotHeight = this.height / this.analyser.frequencyBinCount;

  var visContext = d3.select(this.selector).select(".vis_canvas")[0][0].getContext('2d');

  this.svg.select(".x.axis").call(this.xAxis);
  this.svg.select(".y.axis").call(this.yAxis);

  visContext.clearRect( 0, 0, this.width + this.margin.left, this.height );

  // display as canvas here.
  this.data.forEach(function(d) {
    for(var i = 0; i < d.values.length - 1; i++) {
      var v = d.values[i];
      var x = that.xScale(d.key);
      var y = that.yScale(that.getBinFrequency(i));
      visContext.fillStyle = that.zScale(v);
      visContext.fillRect(x,y,that.dotWidth, that.dotHeight);
    }
  });
}

// ---
// ---
Spectrogram.prototype.getFrequencyValue = function(freq) {
  var nyquist = this.context.sampleRate/2;
  var index = Math.round(freq/nyquist * this.freqs.length);
  return this.freqs[index];
}

// ---
// ---
Spectrogram.prototype.getBinFrequency = function(index) {
  var nyquist = this.context.sampleRate/2;
  var freq = index / this.freqs.length * nyquist;
  return freq;
}