index.html 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <!-- <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> -->
  5. <meta http-equiv="pragma" content="no-cache">
  6. <title>节点实时播放</title>
  7. <link rel="stylesheet" type="text/css" href="./css/index.css" />
  8. </head>
  9. <body>
  10. <table>
  11. <tbody>
  12. <tr>
  13. <input id="ws_url" type="text" value="ws://10.138.6.221:28001">
  14. </tr>
  15. <tr>
  16. <input id="ws_msg" type="text" value="53" onchange="changeNum(value)">
  17. </tr>
  18. </tbody>
  19. </table>
  20. <div class="container">
  21. <button onclick="connectWS()" id="conn_btn">连接</button>
  22. <button onclick="startPlay()" id="play_btn">播放</button>
  23. <button onclick="stopPlay()" id="stop_btn">停止</button>
  24. <!-- <button onclick="startPlay2()" id="play_btn">播放2</button> -->
  25. <!-- <button id="btn">获取数据</button>
  26. <button id="playAudio">播放</button> -->
  27. <div class="pcmGraph_wrapper">
  28. <span class="wrapper_span">时域波纹图</span>
  29. <div id="pcmGraph"></div>
  30. </div>
  31. <div class="wrapper">
  32. <!-- <span class="wrapper_span">时频域声纹图</span> -->
  33. <!-- <div id="stftGraph"></div> -->
  34. <span class="wrapper_span">时频域声纹图</span>
  35. <div id="wrapper_map_pcmGraph"></div>
  36. <div id="wrapper_map_stftGraph"></div>
  37. <span class="wrapper_span">频域频谱图</span>
  38. <div id="fftGraph"></div>
  39. </div>
  40. <div class="wrapper">
  41. </div>
  42. </div>
  43. <script src="./js/pcm_player.js"></script>
  44. <script src="https://gw.alipayobjects.com/os/lib/antv/g2/4.2.0/dist/g2.min.js"></script>
  45. <!-- <script src="https://cdn.jsdelivr.net/npm/js-base64@3.7.2/base64.min.js"></script>
  46. <script src="./pcm_to_wav.js"></script> -->
  47. <script src="./js/wavesurfer.js"></script>
  48. <script src="./js/wavesurfer.spectrogram.min.js"></script>
  49. <script type="text/javascript" src="./js/addWavHeader.js"></script>
  50. <script type="text/javascript" src="./js/colors.js"></script>
  51. <script type="text/javascript" src="./js/init.js"></script>
  52. <script type="text/javascript" src="./js/processing.js"></script>
  53. <script type="text/javascript" src="./js/dsp.js"></script>
  54. <script>
  55. //xieqian js
  56. let samples = 125000;
  57. // 频域频谱图
  58. const chart = new G2.Chart({
  59. container: "fftGraph",
  60. autoFit: true,
  61. padding: [30, 10, 30, 40],
  62. defaultInteractions: []
  63. });
  64. //New pcm player
  65. var player = new PCMPlayer({
  66. // inputCodec: 'Int16',
  67. inputCodec: 'Float32',
  68. channels: 1,
  69. sampleRate: samples,
  70. flushTime: 3000
  71. });
  72. const offlineCtx = new OfflineAudioContext(1, 125000 * 40, 125000);
  73. let wavesurfer = WaveSurfer.create({
  74. container: '#pcmGraph',//容器
  75. waveColor: '#FF55C5',
  76. progressColor: '#00BFBF',
  77. split: false,
  78. minPxPerSec: 8,
  79. drawingContextAttributes: {
  80. desynchronized: false
  81. },
  82. height: 128,
  83. barHeight: 0.7,
  84. splitChannels: false,
  85. audioRate: '1',
  86. });
  87. let wavesurfer_map = WaveSurfer.create({
  88. container: '#wrapper_map_pcmGraph',
  89. waveColor: "#FF55C5",
  90. audioContext: offlineCtx,
  91. progressColor: "#00BFBF",
  92. height: 0,
  93. plugins: [
  94. WaveSurfer.spectrogram.create({
  95. container: '#wrapper_map_stftGraph',
  96. colorMap: colors,
  97. height: 512,
  98. frequencyMax: 125000 / 2,
  99. labels: true,
  100. }),
  101. ],
  102. })
  103. wavesurfer.on("finish", () => {
  104. objSocket.send(play_cmd);
  105. });
  106. wavesurfer.on("ready", () => {
  107. wavesurfer.play()
  108. });
  109. function drawFFTGraph(data) {
  110. // return
  111. let newFFT = [];
  112. // 找最大值
  113. let max = 0;
  114. for (let i = 0; i < 1024; i++) {//data.length
  115. if (i < 10) {
  116. data[i] = 0
  117. }
  118. if (data[i] > max) {
  119. max = data[i];
  120. }
  121. }
  122. // 归一
  123. for (let i = 0; i < 1024; i++) {//data.length
  124. newFFT.push({
  125. index: i,
  126. freq: data[i] / max,
  127. })
  128. }
  129. chart.data(newFFT);
  130. chart.scale({
  131. index: {
  132. tickCount: 48,
  133. nice: true,
  134. },
  135. freq: {
  136. tickCount: 7,
  137. nice: true,
  138. }
  139. });
  140. chart.axis('index', {
  141. title: {
  142. text: '(kHz)',
  143. position: 'center',
  144. offset: 25,
  145. style: {
  146. fill: '#9BB7EF',
  147. fontSize: '13'
  148. }
  149. }
  150. })
  151. chart.interval().position("index*freq");
  152. chart.legend(false);
  153. chart.tooltip(false);
  154. chart.render();
  155. }
  156. // jiangkai js
  157. // play command value
  158. let play_cmd = document.getElementById("ws_msg").value;
  159. var stop_cmd = "stop";
  160. // var isPlay = false
  161. var connBtn = document.getElementById("conn_btn");
  162. var playBtn = document.getElementById("play_btn");
  163. var stopBtn = document.getElementById("stop_btn");
  164. playBtn.setAttribute('disabled', 'disabled');
  165. stopBtn.setAttribute('disabled', 'disabled');
  166. var objSocket;
  167. function connectWS() {
  168. //测试
  169. var wsServer = document.getElementById("ws_url").value;
  170. /**
  171. WebSocket服务连接
  172. */
  173. objSocket = new WebSocket(wsServer)
  174. objSocket.onopen = function (evt) {
  175. onOpen(evt)
  176. }
  177. objSocket.onclose = function (evt) {
  178. onClose(evt)
  179. }
  180. objSocket.onmessage = function (evt) {
  181. onMessage(evt)
  182. }
  183. objSocket.onerror = function (evt) {
  184. onError(evt)
  185. }
  186. connBtn.setAttribute('disabled', 'disabled');
  187. }
  188. function onOpen(evt) {
  189. console.log('Connected to WebSocket server.');
  190. playBtn.removeAttribute('disabled');
  191. stopBtn.removeAttribute('disabled');
  192. }
  193. function onClose(evt) {
  194. console.log('Disconnected')
  195. playBtn.setAttribute('disabled', 'disabled');
  196. stopBtn.setAttribute('disabled', 'disabled');
  197. connBtn.removeAttribute('disabled');
  198. }
  199. function onError(evt) {
  200. alert('Error occured: ' + evt.data);
  201. playBtn.setAttribute('disabled', 'disabled');
  202. stopBtn.setAttribute('disabled', 'disabled');
  203. connBtn.removeAttribute('disabled');
  204. }
  205. function onMessage(evt) {
  206. // console.log(wavesurfer, "@xq");
  207. //websocket返回数据信息处理
  208. // console.log('Retrieved data from server: ' + evt.data.size)
  209. if (evt.data.size > 10) {
  210. var reader = new FileReader(); //文件阅读器
  211. reader.readAsArrayBuffer(evt.data); //读取成ArrayBuffer对象
  212. reader.onload = function () {
  213. //读取完毕
  214. // Now feed PCM data into player getting from websocket or ajax whatever the transport you are using.Accept ArrayBuffer or TypedArray
  215. // 接收PCM格式的原始数据,ArrayBuffer 类型或者 TypedArray 类型
  216. // player.feed(this.result);
  217. let input = new Float32Array(this.result);
  218. // 数据全部左移,使得小数点前有足够的整数部分, 然后取整
  219. // let buf = new Int32Array(input.length);
  220. let y = 0;
  221. let buf = new Int32Array(125000);
  222. const aisle = 1;
  223. const maxAisle = 2;
  224. let multiple = 60000000000;
  225. for (var i = 0; i < input.length; i++) {
  226. if (i % maxAisle === aisle) {
  227. buf[y] = input[i] * multiple;
  228. buf[y] = parseInt(buf[y]);
  229. y++;
  230. }
  231. }
  232. let uintBuf = new Uint32Array(buf);
  233. const audioDate = new Blob([addWavHeader(uintBuf, samples, 32, 1)]);
  234. wavesurfer_map.loadBlob(audioDate);
  235. wavesurfer.loadBlob(audioDate);
  236. drawFFTGraph(uintBuf);
  237. }
  238. // setTimeout('objSocket.send(play_cmd)', 1000);
  239. }
  240. else {
  241. setTimeout('objSocket.send(play_cmd)', 1000);
  242. }
  243. }
  244. //发送消息
  245. function startPlay() {
  246. objSocket.send(play_cmd);
  247. playBtn.setAttribute('disabled', 'disabled');
  248. wavesurfer.play();
  249. }
  250. //发送消息
  251. function startPlay2() {
  252. }
  253. //关闭连接
  254. function stopPlay() {
  255. // isPlay = false;
  256. player.destroy();
  257. player = new PCMPlayer({
  258. // inputCodec: 'Int16',
  259. inputCodec: 'Float32',
  260. channels: 1,
  261. sampleRate: samples,
  262. flushTime: 3000
  263. });
  264. if (objSocket.readyState === WebSocket.OPEN) {
  265. objSocket.send("close");
  266. objSocket.close(1000, "Disconnect");
  267. }
  268. playBtn.removeAttribute('disabled');
  269. }
  270. function changeNum(data){
  271. play_cmd = data
  272. }
  273. </script>
  274. </body>
  275. </html>