<template>
	<view>
		<u-toast ref="uToast" />
	</view>
</template>
<script>
import { videoStart,videoControl  } from "@/api/core/sendOrder";
//录音对象
var Recorder = function (stream) {
  var sampleBits = 16; //输出采样数位 8, 16
  var sampleRate = 8000; //输出采样率
  var context = new AudioContext();
  var audioInput = context.createMediaStreamSource(stream);
  var recorder = context.createScriptProcessor(4096, 1, 1);
  var audioData = {
    size: 0, //录音文件长度
    buffer: [], //录音缓存
    inputSampleRate: 48000, //输入采样率
    inputSampleBits: 16, //输入采样数位 8, 16
    outputSampleRate: sampleRate,
    oututSampleBits: sampleBits,
    clear: function () {
      this.buffer = [];
      this.size = 0;
    },
    input: function (data) {
      this.buffer.push(new Float32Array(data));
      this.size += data.length;
    },
    compress: function () {
      //合并压缩
      //合并
      var data = new Float32Array(this.size);
      var offset = 0;
      for (var i = 0; i < this.buffer.length; i++) {
        data.set(this.buffer[i], offset);
        offset += this.buffer[i].length;
      }
      //压缩
      var compression = parseInt(this.inputSampleRate / this.outputSampleRate);
      var length = data.length / compression;
      var result = new Float32Array(length);
      var index = 0,
        j = 0;
      while (index < length) {
        result[index] = data[j];
        j += compression;
        index++;
      }
      return result;
    },
    encodePCM: function () {
      //这里不对采集到的数据进行其他格式处理，如有需要均交给服务器端处理。
      var sampleRate = Math.min(this.inputSampleRate, this.outputSampleRate);
      var sampleBits = Math.min(this.inputSampleBits, this.oututSampleBits);
      var bytes = this.compress();
      var dataLength = bytes.length * (sampleBits / 8);
      var buffer = new ArrayBuffer(dataLength);
      var data = new DataView(buffer);
      var offset = 0;
      for (var i = 0; i < bytes.length; i++, offset += 2) {
        var s = Math.max(-1, Math.min(1, bytes[i]));
        data.setInt16(offset, s < 0 ? s * 0x8000 : s * 0x7fff, true);
      }
      return new Blob([data]);
    },
  };
  this.start = function () {
    audioInput.connect(recorder);
    recorder.connect(context.destination);
  };

  this.stop = function () {
    recorder.disconnect();
  };

  this.getBlob = function () {
    return audioData.encodePCM();
  };

  this.clear = function () {
    audioData.clear();
  };

  recorder.onaudioprocess = function (e) {
    audioData.input(e.inputBuffer.getChannelData(0));
  };
};
export default {
	data() {
	  return {
	    ws: null,
		deviceId:'',
		wsUrl: "wss://80.5000v.com/websocket", // websocket地址
		record: null, //多媒体对象，用来处理音频
		sendingTimes: 0, // 发送设备号的次数
		timeInte: null, // 定时任务 定时发送
		audo: new Audio(),
		openIntercom:false
	  };
	},
	created() {
		
	},
	methods: {
		init () {
           navigator.mediaDevices
            .getUserMedia({	audio: true})
            .then( (mediaStream)=> {
                /* 使用这个 stream stream */
                console.log('使用这个',mediaStream)
                this.record = new Recorder(mediaStream);
            })
            .catch(function (err) {
                /* 处理 error */
                console.log('处理 error',err)
                            uni.showToast({
                                title: '浏览器不支持音频输入'+err,
                                duration: 2000,
                                icon: 'none'
                            });
			});

            			// navigator.getUserMedia(
						//   {
						// 	audio: true,
						//   },
						//   (mediaStream) => {
                        //     console.log('2使用这个',mediaStream)
						// 	this.record = new Recorder(mediaStream);
							
						//   },
						//   (error) => {
						//   });

            // console.log('方法',getUserMedia)
            // let getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia || navigator.oGetUserMedia;
            // navigator.getUserMedia = getUserMedia
			// if (!navigator.getUserMedia) {
            //                 uni.showToast({
            //                     title: '浏览器不支持音频输入'+getUserMedia,
            //                     duration: 2000,
            //                     icon: 'none'
            //                 });
			// 			   console.log('浏览器不支持音频输入')
			// } else {
			// 			navigator.getUserMedia(
			// 			  {
			// 				audio: true,
			// 			  },
			// 			  (mediaStream) => {
			// 				this.record = new Recorder(mediaStream);
			// 				console.log('2121',this.record)
			// 			  },
			// 			  (error) => {
			// 			  }
			// 			);
			// }
		},
		async toIntercom(deviceId) {
			console.log(deviceId,'itemdeviceId')
			if(this.isNull(deviceId)) {
				uni.showToast({
                    title: 'deviceId为空',
                    duration: 2000,
                    icon: 'none'
                });
				return false
			}
			this.init()
		   this.deviceId = deviceId;
		   // #ifdef H5
		   if(this.openIntercom){
		     //打开中 执行关闭
		     let obj = {
		       audioVideoType: 0,
		       channel: 1,
		       controll: 4,
		       dataRate: 0,
		       deviceId: deviceId, //设备号
		     };
             let res = await videoControl(obj);
		   if(res.code == '0'){
				 uni.closeSocket();
			
				 this.openIntercom = false;
				 this.ws.close();
				 this.record.stop();
				 clearInterval(this.timeInte);
				 this.ws = null;
				 this.timeInte = null;
			 
			 }else{
				 uni.showToast({
                    title:res.desc,
                    duration: 2000,
                    icon: 'none'
                });
			 }
		   }else {
		     // 关闭中 执行打开
		   let obj = {
		       channel: 1,
		       dataRate: 1,
		       dataType: 2, // 对讲
		       deviceId: deviceId, // 设备号
		     };
             let res = await videoStart(obj);
		    if(res.code == '0'){
		       // 成功以后连接socket
		        // 命令下发成功
                let wsUrl;
                if (window.location.hostname != "localhost") {
                        wsUrl = "wss://" + window.location.host + "/websocket";
                    } else {
                        wsUrl = "wss://tq.5000v.cn:443/websocket"
                    }
		        this.ws = new WebSocket(wsUrl); // 连接websocket
		        this.ws.binaryType = "arraybuffer"; //传输的是 ArrayBuffer 类型的数据
		        this.ws.onopen = (event) => {
		          // 连接成功后
		          console.log("websocket连接成功");
		          // 连接成功后发送设备号
		          this.websocketSend();
		        };
		
		        this.ws.onclose = (event) => {
		          // 监听websocket断开
		          console.log("websocket连接关闭");
                  this.$emit('oNstate',false)//回传状态
		        };
		
		        this.ws.onmessage = (evt) => {
		          // 收到websocket传来的信息
		          console.log('websocket传来的信息',evt.data)
                  this.$emit('oNstate',true)//回传状态
		          if(typeof evt.data == 'string'){
		            if(evt.data.indexOf(':1') > -1){
		              // :1 代表接通 :0代表未接通
		              this.record.start(); //开始录音
		              this.receive();
		            }else {
		              if(this.sendingTimes < 3) {
		                // 重发次数小于3 继续发
		                // 间隔一秒发
		                setTimeout(()=>{
		                  this.websocketSend();
		                  this.sendingTimes++
		                }, 1000);
		              }else{
		                // 重发3次 提升无法连接 并且下发关闭指令 关闭连接
		                // this.$message.error('设备无法链接');
						// this.$refs.uToast.show({
						//   title: '设备无法链接',
						//   type: "error",
						// });
                        uni.showToast({
                            title:'设备无法链接',
                            duration: 2000,
                            icon: 'none'
                        });
		                // this.closeIntercom();
                        this.toIntercom(this.deviceId);
		                this.sendingTimes = 0;
		              }
		            }
		          } else {
		            this.playAudio(evt.data);
		          }
		
		        };
				
				this.openIntercom = true;
		     }else{
				//  this.$refs.uToast.show({
				//    title: res.desc,
				//    type: "error",
				//  });
                uni.showToast({
                    title:res.desc,
                    duration: 2000,
                    icon: 'none'
                });
			 }
		    
		   }
           this.$emit('oNstate',this.openIntercom)
		   // #endif
		},
		websocketSend() {
		  this.ws.send(this.deviceId);
		},
		receive() {
			  // 对讲
			this.timeInte = setInterval(()=>{
				if(this.ws.readyState==1){ // ws进入连接状态，则每隔500毫秒发送一包数据
					console.log(this.record.getBlob());
					this.ws.send(this.record.getBlob()); //发送音频数据
					this.record.clear();//每次发送完成则清理掉旧数据
				}
			},200);  //每隔200ms发送一次，定时器
		},
		
		
		
		playAudio(data) {
		  // 收听
		  let _this = this;
		  var buffer = (new Response(data)).arrayBuffer();
		  buffer.then(function(buf){
			var audioContext = new ( window.AudioContext || window.webkitAudioContext )();
			var fileResult = _this.addWavHeader(buf, '8000', '16', '1'); // 解析数据转码wav
			audioContext.decodeAudioData(fileResult, function(buffer) {
				_this.visualize(audioContext, buffer); // 播放
			});
		  });
		},
	
		visualize(audioContext, buffer) {
		  var audioBufferSouceNode = audioContext.createBufferSource();
		  var analyser = audioContext.createAnalyser();
		  //将信号源连接到分析仪
		  audioBufferSouceNode.connect(analyser);
		  //将分析仪连接到目的地（扬声器），否则我们将听不到声音
		  analyser.connect(audioContext.destination);
		  //然后将缓冲区分配给缓冲区源节点
		  audioBufferSouceNode.buffer = buffer;
		  //发挥作用
		  if (!audioBufferSouceNode.start) {
			  audioBufferSouceNode.start = audioBufferSouceNode.noteOn //在旧浏览器中使用noteOn方法
			  audioBufferSouceNode.stop = audioBufferSouceNode.noteOff //在旧浏览器中使用noteOff方法
		  };
		  //如果有的话，停止前一个声音
		  if (this.animationId !== null) {
			  cancelAnimationFrame(this.animationId);
		  }
		  audioBufferSouceNode.start(0);
		  this.audo.source = audioBufferSouceNode;
		  this.audo.audioContext = audioContext;
		},
	
	
		//处理音频流，转码wav
		addWavHeader(samples, sampleRateTmp, sampleBits, channelCount) {
			var dataLength = samples.byteLength;
			var buffer = new ArrayBuffer(44 + dataLength);
			var view = new DataView(buffer);
			function writeString(view, offset, string){
				for (var i = 0; i < string.length; i++){
					view.setUint8(offset + i, string.charCodeAt(i));
				}
			}
			var offset = 0;
			/* 资源交换文件标识符 */
			writeString(view, offset, 'RIFF'); offset += 4;
			/* 下个地址开始到文件尾总字节数,即文件大小-8 */
			view.setUint32(offset, /*32*/ 36 + dataLength, true); offset += 4;
			/* WAV文件标志 */
			writeString(view, offset, 'WAVE'); offset += 4;
			/* 波形格式标志 */
			writeString(view, offset, 'fmt '); offset += 4;
			/* 过滤字节,一般为 0x10 = 16 */
			view.setUint32(offset, 16, true); offset += 4;
			/* 格式类别 (PCM形式采样数据) */
			view.setUint16(offset, 1, true); offset += 2;
			/* 通道数 */
			view.setUint16(offset, channelCount, true); offset += 2;
			/* 采样率,每秒样本数,表示每个通道的播放速度 */
			view.setUint32(offset, sampleRateTmp, true); offset += 4;
			/* 波形数据传输率 (每秒平均字节数) 通道数×每秒数据位数×每样本数据位/8 */
			view.setUint32(offset, sampleRateTmp * channelCount * (sampleBits / 8), true); offset +=4;
			/* 快数据调整数 采样一次占用字节数 通道数×每样本的数据位数/8 */
			view.setUint16(offset, channelCount * (sampleBits / 8), true); offset += 2;
			/* 每样本数据位数 */
			view.setUint16(offset, sampleBits, true); offset += 2;
			/* 数据标识符 */
			writeString(view, offset, 'data'); offset += 4;
			/* 采样数据总数,即数据总大小-44 */
			view.setUint32(offset, dataLength, true); offset += 4;
			function floatTo32BitPCM(output, offset, input){
				input = new Int32Array(input);
				for (var i = 0; i < input.length; i++, offset+=4){
					output.setInt32(offset,input[i],true);
				}
			}
			function floatTo16BitPCM(output, offset, input){
				input = new Int16Array(input);
				for (var i = 0; i < input.length; i++, offset+=2){
					output.setInt16(offset,input[i],true);
				}
			}
			function floatTo8BitPCM(output, offset, input){
				input = new Int8Array(input);
				for (var i = 0; i < input.length; i++, offset++){
					output.setInt8(offset,input[i],true);
				}
			}
			if(sampleBits == 16){
				floatTo16BitPCM(view, 44, samples);
			}else if(sampleBits == 8){
				floatTo8BitPCM(view, 44, samples);
			}else{
				floatTo32BitPCM(view, 44, samples);
			}
			return view.buffer;
		}
	}
}

</script>