Web 技术研究所

我一直坚信着,Web 将会成为未来应用程序的主流

AudioAPI录音,生成wav音频文件

  之前的例子只演示了录音与回放,这个实现是将录制的数据放入一个数组中储存。然而,这些数据也可用于生成WAV格式的音频文件,WAV文件的具体格式在之前的文章中介绍过。主要是碍于AudioAPI无法自定义采样频率,这个技术目前不太实用。
<input value="录音" type="button" id="record" />
<input value="播放" type="button" id="play" />
<input value="保存" type="button" id="save" />
<script>
var AudioContext=AudioContext||webkitAudioContext;
var context=new AudioContext;
//调整兼容
navigator.getUserMedia=
  navigator.getUserMedia||
  navigator.webkitGetUserMedia||
  navigator.mozGetUserMedia;
//请求麦克风
navigator.getUserMedia({audio:true},function(e){
  var data,p;
  //从麦克风的输入流创建源节点
  var stream=context.createMediaStreamSource(e);
  //用于录音的processor节点
  var recorder=context.createScriptProcessor(1024,1,0);
  recorder.onaudioprocess=function(e){
    if(record.value=="停止")data.push(e.inputBuffer.getChannelData(0));
  };
  //用于播放的processor节点
  var player=context.createScriptProcessor(1024,0,1);
  player.onaudioprocess=function(e){
    if(!data)return;
    var i,s=data[p++];
    if(!s)return play.value=="停止"&&play.click();
    var buffer=e.outputBuffer.getChannelData(0);
    for(i=0;i<s.length;i++)buffer[i]=s[i];
  };
  //录音/停止 按钮点击动作
  record.onclick=function(){
    if(record.value=="录音")
      return data=[],stream.connect(recorder),this.value="停止";
    if(record.value=="停止")
      return stream.disconnect(),this.value="录音";
  };
  //播放/停止 按钮点击动作
  play.onclick=function(){
    if(this.value=="播放")
      return p=0,player.connect(context.destination),this.value="停止";
    if(this.value=="停止")
      return player.disconnect(),this.value="播放";
  };
  //保存
  save.onclick=function(){
    var frequency=context.sampleRate; //采样频率
    var pointSize=16; //采样点大小
    var channelNumber=1; //声道数量
    var blockSize=channelNumber*pointSize/8; //采样块大小
    var wave=[]; //数据
    for(var i=0;i<data.length;i++)
      for(var j=0;j<data[i].length;j++)
        wave.push(data[i][j]*0x8000|0);
    var length=wave.length*pointSize/8; //数据长度
    var buffer=new Uint8Array(length+44); //wav文件数据
    var view=new DataView(buffer.buffer); //数据视图
    buffer.set(new Uint8Array([0x52,0x49,0x46,0x46])); //"RIFF"
    view.setUint32(4,data.length+44,true); //总长度
    buffer.set(new Uint8Array([0x57,0x41,0x56,0x45]),8); //"WAVE"
    buffer.set(new Uint8Array([0x66,0x6D,0x74,0x20]),12); //"fmt "
    view.setUint32(16,16,true); //WAV头大小
    view.setUint16(20,1,true); //编码方式
    view.setUint16(22,1,true); //声道数量
    view.setUint32(24,frequency,true); //采样频率
    view.setUint32(28,frequency*blockSize,true); //每秒字节数
    view.setUint16(32,blockSize,true); //采样块大小
    view.setUint16(34,pointSize,true); //采样点大小
    buffer.set(new Uint8Array([0x64,0x61,0x74,0x61]),36); //"data"
    view.setUint32(40,length,true); //数据长度
    buffer.set(new Uint8Array(new Int16Array(wave).buffer),44); //数据
    //打开文件
    var blob=new Blob([buffer],{type:"audio/wav"});
    open(URL.createObjectURL(blob));
  };
},function(e){
  console.log("请求麦克风失败");
});
</script>
网名:
54.196.182.*
电子邮箱:
仅用于接收通知
提交 悄悄的告诉你,Ctrl+Enter 可以提交哦
神奇海螺
[查看全部主题]
各类Web技术问题讨论区
发起新主题
本模块采用即时聊天邮件通知的模式
让钛合金F5成为历史吧!
次碳酸钴的技术博客,文章原创,转载请保留原文链接 ^_^