volume

buttonB 停止 播放g711 播放声音
//播放队列
var play_queue= new Array(20);
var index_play = 0;
var index_insert = 0;
$(function(){
    //setTimeout("timedCount()",50);
});

function test() {
    setInterval("timedCount()",200);
}

function timedCount(){
    if(index_play==20)
        index_play=0;
    console.log("播放第:"+index_play+"包");
    //audio.src = window.URL.createObjectURL(play_queue[index_play]);
    //play(play_queue[index_play++]);
    console.log(play_queue[index_play]);
    audioContext.decodeAudioData(play_queue[index_play], function(buffer) {//解码成pcm流
        var audioBufferSouceNode = audioContext.createBufferSource();
        audioBufferSouceNode.buffer = buffer;
        audioBufferSouceNode.connect(audioContext.destination);
        audioBufferSouceNode.start(0);
    }, function(e) {
        console.log("failed to decode the file");
    });
    //播放后清空
    //var buffer = new ArrayBuffer(0);
    play_queue[index_play] = new ArrayBuffer(0);
    index_play++;

}


var audioContext = new AudioContext();    //被移除下面函数体

var a = document.getElementById('a');
var b = document.getElementById('b');
var c = document.getElementById('c');

navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia;

var gRecorder = null;
var audio = document.querySelector('audio');

var door = false;
var ws = null;

//audio标签的回调
audio.addEventListener('ended', function () {
    console.log("ended");
    //todo
    timedCount();
}, false);

b.onclick = function() {

    if(a.value === '') {
        alert('请输入用户名');
        return false;
    }
    if(!navigator.getUserMedia) {
        alert('抱歉您的设备无法语音聊天');
        return false;
    }

    SRecorder.get(function (rec) {
        gRecorder = rec;
    });

    ws = new WebSocket("ws://localhost:8080/volume/websocket/volume.html");

    ws.onopen = function() {
        console.log('握手成功');
        ws.send(a.value);
    };

    ws.onmessage = function(e) {
        console.log("后台返回数据"+e.data);
        var reader = new FileReader();
        reader.readAsArrayBuffer(e.data);
        //receive(e.data.encodeWAV());     //给g711编码后播放

        reader.onload = function(evt)
        {
            if(evt.target.readyState == FileReader.DONE)
            {
                var data = new Uint8Array(evt.target.result);
                //方式2 ok
                if(index_insert==20){
                    index_insert=0;
                }
                play_queue[index_insert] = pcm2wav(data);
                console.log("第"+index_insert+"包:");
                index_insert++;
            }
        }
        //pcm2wav
        //receive(e.data);       //直接播放wav
    };

    ws.onclose = function () {
        console.log("断开连接");
    }

    ws.onerror = function (evt){
        console.log(evt);
    }
    document.onkeydown = function(e) {
        if(e.keyCode === 65) {
            if(!door) {
                gRecorder.start();
                door = true;
            }
        }
    };
    //发送二进制语音包
    document.onkeyup = function(e) {
        if(e.keyCode === 65) {
            if(door) {
                console.log(gRecorder);
              ws.binaryData = "blob";
             ws.send(gRecorder.getBlob());
             gRecorder.clear();
                gRecorder.stop();
                door = false;
            }
        }
    }
}

c.onclick = function() {
    if(ws) {
        //ws.close();
    }
}

function pcm2wav(pcm_byte) {
    var sampleRate = 8000;    //采样率
    var sampleBits = 16;      //采样位数
    var dataLength = pcm_byte.length;
    var buffer = new ArrayBuffer(44 + dataLength);
    var data = new DataView(buffer);    //可使用 DataView 对象在 ArrayBuffer 中的任何位置读取和写入不同类型的二进制数据。

    var channelCount = 1;//单声道
    var offset = 0;

    var writeString = function (str) {
        for (var i = 0; i < str.length; i++) {
            data.setUint8(offset + i, str.charCodeAt(i));
        }
    };

    // 资源交换文件标识符
    writeString('RIFF'); offset += 4;
    // 下个地址开始到文件尾总字节数,即文件大小-8
    data.setUint32(offset, 36 + dataLength, true); offset += 4;
    // WAV文件标志
    writeString('WAVE'); offset += 4;
    // 波形格式标志
    writeString('fmt '); offset += 4;
    // 过滤字节,一般为 0x10 = 16
    data.setUint32(offset, 16, true); offset += 4;
    // 格式类别 (PCM形式采样数据)
    data.setUint16(offset, 1, true); offset += 2;
    // 通道数
    data.setUint16(offset, channelCount, true); offset += 2;
    // 采样率,每秒样本数,表示每个通道的播放速度
    data.setUint32(offset, sampleRate, true); offset += 4;
    // 波形数据传输率 (每秒平均字节数) 单声道×每秒数据位数×每样本数据位/8
    data.setUint32(offset, channelCount * sampleRate * (sampleBits / 8), true); offset += 4;
    // 快数据调整数 采样一次占用字节数 单声道×每样本的数据位数/8
    data.setUint16(offset, channelCount * (sampleBits / 8), true); offset += 2;
    // 每样本数据位数
    data.setUint16(offset, sampleBits, true); offset += 2;
    // 数据标识符
    writeString('data'); offset += 4;
    // 采样数据总数,即数据总大小-44
    data.setUint32(offset, dataLength, true); offset += 4;
    //数据位
    for(var i=0;i<pcm_byte.length;i++,offset++){
        data.setUint8(offset,pcm_byte[i]);
    }

    // 写入采样数据
  if (sampleBits === 8) {
       for (var i = 0; i < bytes.length; i++, offset++) {
          var s = Math.max(-1, Math.min(1, bytes[i]));
           var val = s < 0 ? s * 0x8000 : s * 0x7FFF;
           val = parseInt(255 / (65535 / (val + 32768)));     
                     data.setInt8(offset, val, true);
       }
 } else {
       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 buffer;
    //return new Blob([data], { type: 'audio/wav' });
}



var SRecorder = function(stream) {
    config = {};

    config.sampleBits = config.smapleBits || 16;    //输出量化位数
    config.sampleRate = config.sampleRate || (44100 / 6);       //输出采样频率

    console.log("输出量化位数:"+config.sampleBits);
    var context = new AudioContext();    //被移除下面函数体

    console.log("输入采样频率:"+context.sampleRate);
    var audioInput = context.createMediaStreamSource(stream);
    var recorder = context.createScriptProcessor(4096, 1, 1);    //buffer size input channel output channel

    var audioData = {
        size: 0          //录音文件长度
        , buffer: []    //录音缓存
        , inputSampleRate: context.sampleRate    //输入采样率
        , inputSampleBits: 16      //输入采样数位 8, 16
        , outputSampleRate: config.sampleRate    //输出采样率
        , oututSampleBits: config.sampleBits      //输出采样数位 8, 16
        , clear: function() {
            this.buffer = [];    //buffer里是一段一段的Float32数组
            this.size = 0;
        }
        , input: function (data) {
            this.buffer.push(new Float32Array(data));   //buffer存储float32,size为字节大小,buffer大小为float大小
            this.size += data.length;
            //console.log("当前大小:"+this.size);
            console.log("**************");
            console.log(this.buffer.length);
            if(this.buffer.length==4) {
                ws.binaryData = "blob";
                ws.send(gRecorder.getBlob());
                gRecorder.clear();
            }
            gRecorder.stop();
        }
        , 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);       //把buffer中的各个Float32数组合并成一个
                offset += this.buffer[i].length;
            }
            //压缩
            var compression = parseInt(this.inputSampleRate / this.outputSampleRate);   //6
            var length = data.length / compression;    //600/6 = 10
            var result = new Float32Array(length);    // 32 位浮点值的类型化数组
            var index = 0, j = 0;
            while (index < length) {
                result[index] = data[j];
                j += compression;     //j+=6
                index++;
            }
            return result;
        }
        , encodeWAV: 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);    //一个Float32转成一个u8  或 u16;所以长度没问题
            var buffer = new ArrayBuffer(44 + dataLength);
            var data = new DataView(buffer);

            var channelCount = 1;//单声道
            var offset = 0;

            var writeString = function (str) {
                for (var i = 0; i < str.length; i++) {
                    data.setUint8(offset + i, str.charCodeAt(i));
                }
            };

            // 资源交换文件标识符
            writeString('RIFF'); offset += 4;
            // 下个地址开始到文件尾总字节数,即文件大小-8
            data.setUint32(offset, 36 + dataLength, true); offset += 4;
            // WAV文件标志
            writeString('WAVE'); offset += 4;
            // 波形格式标志
            writeString('fmt '); offset += 4;
            // 过滤字节,一般为 0x10 = 16
            data.setUint32(offset, 16, true); offset += 4;
            // 格式类别 (PCM形式采样数据)
            data.setUint16(offset, 1, true); offset += 2;
            // 通道数
            data.setUint16(offset, channelCount, true); offset += 2;
            // 采样率,每秒样本数,表示每个通道的播放速度
            data.setUint32(offset, sampleRate, true); offset += 4;
            // 波形数据传输率 (每秒平均字节数) 单声道×每秒数据位数×每样本数据位/8
            data.setUint32(offset, channelCount * sampleRate * (sampleBits / 8), true); offset += 4;
            // 快数据调整数 采样一次占用字节数 单声道×每样本的数据位数/8
            data.setUint16(offset, channelCount * (sampleBits / 8), true); offset += 2;
            // 每样本数据位数
            data.setUint16(offset, sampleBits, true); offset += 2;
            // 数据标识符
            writeString('data'); offset += 4;
            // 采样数据总数,即数据总大小-44
            data.setUint32(offset, dataLength, true); offset += 4;
            // 写入采样数据
            if (sampleBits === 8) {
                for (var i = 0; i < bytes.length; i++, offset++) {
                    var s = Math.max(-1, Math.min(1, bytes[i]));
                    var val = s < 0 ? s * 0x8000 : s * 0x7FFF;
                    val = parseInt(255 / (65535 / (val + 32768)));
                    data.setInt8(offset, val, true);
                }
            } else {
                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], { type: 'audio/wav' });
        }
    };

    this.start = function () {
        audioInput.connect(recorder);
        recorder.connect(context.destination);  //把麦克风的输入和音频采集相连起来 context.destination返回代表在环境中的音频的最终目的地。
    }

    this.stop = function () {
        recorder.disconnect();       //断开连接
    }

    this.getBlob = function () {
        return audioData.encodeWAV();
        //return audioData.buffer;
    }

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

    recorder.onaudioprocess = function (e) {
        audioData.input(e.inputBuffer.getChannelData(0));
    }
};

SRecorder.get = function (callback) {
    if (callback) {
        if (navigator.getUserMedia) {
            navigator.getUserMedia(
                { audio: true },
                function (stream) {            //获取流成功后的回调,执行一次
                    var rec = new SRecorder(stream);
                    callback(rec);
                },
                function (){
                    console.log("接口调用失败后的回调");
                })
        }
    }
}

function receive(e) {
    //播放缓冲队列中的内容,播放后清空
    audio.src = window.URL.createObjectURL(e);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值