记录一下使用 audionContext 进行录音的方法

记录一下使用 audionContext 进行录音的方法

        //判断浏览器是否支持
        navigator.getUserMedia = navigator.getUserMedia ||
                                    navigator.webkitGetUserMedia ||
                                    navigator.mozGetUserMedia;        


        var SRecorder = function(stream) {
            config = {};
         
            config.sampleBits = config.smapleBits || 16;
            config.sampleRate = config.sampleRate || 16000;
         
            var context = new AudioContext();
            var audioInput = context.createMediaStreamSource(stream);
            var recorder = context.createScriptProcessor(4096, 1, 1);
         
            var audioData = {
                size: 0          //录音文件长度
                , buffer: []    //录音缓存
                , inputSampleRate: context.sampleRate    //输入采样率
                , inputSampleBits: 16      //输入采样数位 8, 16
                , outputSampleRate: config.sampleRate    //输出采样率
                , oututSampleBits: config.sampleBits      //输出采样数位 8, 16
                , 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);
                    console.log(compression);
                    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;
                }
                , encodeWAV: function () {
                    console.log(this.inputSampleRate +" " + this.inputSampleBits)
                    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(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]);
                }
            };
     
            this.start = function () {
                audioInput.connect(recorder);
                recorder.connect(context.destination);
            }
         
            this.stop = function () {
                recorder.disconnect();
            }
         
            this.getBlob = function () {
                return audioData.encodeWAV();
            }
         
            this.clear = function() {
                audioData.clear();
            }
         
            recorder.onaudioprocess = function (e) {
                audioData.input(e.inputBuffer.getChannelData(0));
                // 播放
                // var input = e.inputBuffer.getChannelData(0);
                // var output = e.outputBuffer.getChannelData(0);

                // for (var i = 0; i < e.inputBuffer.length; i++) {
                //     output[i] = input[i]
                // }
            }
        };
    
        // 用于分段传输版本
        //var SRecorder = function(stream) {
        //     config = {};
         
        //     config.sampleBits = config.smapleBits || 16;
        //     config.sampleRate = config.sampleRate || 16000;
         
        //     var context = new AudioContext();
        //     var audioInput = context.createMediaStreamSource(stream);
        //     var recorder = context.createScriptProcessor(8192, 1, 1);
         
        //     var audioEncode = {
        //          inputSampleRate: context.sampleRate    //输入采样率
        //         , inputSampleBits: 16      //输入采样数位 8, 16
        //         , outputSampleRate: config.sampleRate    //输出采样率
        //         , oututSampleBits: config.sampleBits      //输出采样数位 8, 16
        //         , encodeWAV: function (bytes) {
        //             var sampleRate = Math.min(this.inputSampleRate, this.outputSampleRate);
        //             var sampleBits = Math.min(this.inputSampleBits, this.oututSampleBits);
                    
        //             var compression = parseInt(this.inputSampleRate / this.outputSampleRate);
        //             var length = bytes.length / compression;
        //             var result = new Float32Array(length);
        //             var index = 0, j = 0;
        //             while (index < length) {
        //                 result[index] = bytes[j];
        //                 j += compression;
        //                 index++;
        //             }
        //             var dataLength = result.length * (sampleBits / 8);
        //             var buffer = new ArrayBuffer(dataLength);
        //             var data = new DataView(buffer);
        //             var offset = 0;
         
        //             if (sampleBits === 8) {
        //                 for (var i = 0; i < result.length; i++, offset++) {
        //                     var s = Math.max(-1, Math.min(1, result[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 < result.length; i++, offset += 2) {
        //                     var s = Math.max(-1, Math.min(1, result[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();
        //     }
         
        //     recorder.onaudioprocess = function (e) {
        //         var input = e.inputBuffer.getChannelData(0);
        //         var output = e.outputBuffer.getChannelData(0);

        //         for (var i = 0; i < e.inputBuffer.length; i++) {
        //             output[i] = input[i]
        //         }

        //         sendBuffer(audioEncode.encodeWAV(input), 0);
        //     }
        // };




        // 初始化
        SRecorder.get = function (callback) {
            if (callback) {
                if (navigator.getUserMedia) {
                    navigator.getUserMedia(
                        { audio: true },
                        function (stream) {
                            var rec = new SRecorder(stream);
                            callback(rec);
                        },
                        function (error) {
                            alert("浏览器不支持");
                        })
                }
            }
        }

        //生成实例
        SRecorder.get(function (rec) {
                gRecorder = rec;
        });

        //启动
        gRecorder.start();

        //结束
        gRecorder.clear();
        gRecorder.stop();
        

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值