UNPKG

recorder-core

Version:

Recorder库: html5 js 录音 mp3 wav ogg webm amr g711a g711u 格式,支持pc和Android、iOS部分浏览器、Hybrid App(提供Android iOS App源码)、微信,提供ASR语音识别转文字 H5版语音通话聊天示例 DTMF编码解码

236 lines (202 loc) 6.67 kB
/* g711x编码器+解码器 https://github.com/xiangyuecn/Recorder 可用type: g711a: G.711 A-law (pcma) g711u: G.711 μ-law (pcmu、mu-law) 编解码源码移植自:https://github.com/twstx1/codec-for-audio-in-G72X-G711-G723-G726-G729/blob/master/G711_G721_G723/g711.c 移植相关测试代码(FFmpeg转码、播放命令):assets/runtime-codes/test.g7xx.engine.js */ (function(factory){ var browser=typeof window=="object" && !!window.document; var win=browser?window:Object; //非浏览器环境,Recorder挂载在Object下面 var rec=win.Recorder,ni=rec.i18n; factory(rec,ni,ni.$T,browser); }(function(Recorder,i18n,$T,isBrowser){ "use strict"; var regEngine=function(key,desc,enc,dec){ Recorder.prototype["enc_"+key]={ stable:true,fast:true ,getTestMsg:function(){ return $T("d8YX::{1};{2}音频文件无法直接播放,可用Recorder.{2}2wav()转码成wav播放;采样率比特率设置无效,固定为8000hz采样率、16位,每个采样压缩成8位存储,音频文件大小为8000字节/秒;如需任意采样率支持,请使用Recorder.{2}_encode()方法",0,desc,key); } }; //*******标准UI线程转码支持函数************ Recorder.prototype[key]=function(res,True,False){ var This=this,set=This.set,srcSampleRate=set.sampleRate,sampleRate=8000; set.bitRate=16; set.sampleRate=sampleRate; if(srcSampleRate>sampleRate){ res=Recorder.SampleData([res],srcSampleRate,sampleRate).data; }else if(srcSampleRate<sampleRate){ False($T("29UK::数据采样率低于{1}",0,sampleRate)); return; }; var bytes=enc(res); True(bytes.buffer,"audio/"+key); }; /**编码任意采样率的pcm得到g711x数据 pcm: Int16Array,任意采样率pcm数据(标准采样率为8000) 返回Uint8Array,g711x二进制数据(采样率为pcm的采样率) **/ Recorder[key+"_encode"]=function(pcm){ return enc(pcm); }; /**解码g711x得到pcm bytes: Uint8Array,g711x二进制数据,采样率一般是8000 返回Int16Array,为g711x的采样率、16位的pcm数据 **/ Recorder[key+"_decode"]=function(bytes){ return dec(bytes); }; /**g711x直接转码成wav,可以直接用来播放;需同时引入src/engine/wav.js g711xBlob: g711x音频文件blob对象 或 ArrayBuffer(回调也将返回ArrayBuffer),采样率只支持8000 True(wavBlob,duration,mime) False(msg) **/ Recorder[key+"2wav"]=function(g711xBlob,True,False){ if(!Recorder.prototype.wav){ False($T.G("NeedImport-2",[key+"2wav","src/engine/wav.js"])); return; }; var loadOk=function(arrB,dArrB){ var bytes=new Uint8Array(arrB); var pcm=dec(bytes); var rec=Recorder({ type:"wav",sampleRate:8000,bitRate:16 }); if(dArrB)rec.dataType="arraybuffer"; rec.mock(pcm,8000).stop(function(wavBlob,duration,mime){ True(wavBlob,duration,mime); },False); }; if(g711xBlob instanceof ArrayBuffer){ loadOk(g711xBlob,1); }else{ var reader=new FileReader(); reader.onloadend=function(){ loadOk(reader.result); }; reader.readAsArrayBuffer(g711xBlob); }; }; //********边录边转码支持函数,g711转码超快,因此也是工作在UI线程(非Worker)********* Recorder.prototype[key+"_envCheck"]=function(envInfo,set){//检查环境下配置是否可用 return ""; //没有需要检查的内容 }; Recorder.prototype[key+"_start"]=function(set){//如果返回null代表不支持 set.bitRate=16; set.sampleRate=8000; return {set:set, memory:new Uint8Array(500000), mOffset:0}; }; var addBytes=function(cur,buf){ var bufLen=buf.length; if(cur.mOffset+bufLen>cur.memory.length){ var tmp=new Uint8Array(cur.memory.length+Math.max(500000,bufLen)); tmp.set(cur.memory.subarray(0, cur.mOffset)); cur.memory=tmp; } cur.memory.set(buf,cur.mOffset); cur.mOffset+=bufLen; }; Recorder.prototype[key+"_stop"]=function(startCtx){ if(startCtx&&startCtx.memory){ startCtx.memory=null; } }; Recorder.prototype[key+"_encode"]=function(startCtx,pcm){ if(startCtx&&startCtx.memory){ var set=startCtx.set; var bytes=enc(pcm); if(set.takeoffEncodeChunk){ set.takeoffEncodeChunk(bytes); }else{ addBytes(startCtx, bytes); }; }; }; Recorder.prototype[key+"_complete"]=function(startCtx,True,False,autoStop){ if(startCtx&&startCtx.memory){ if(autoStop){ this[key+"_stop"](startCtx); }; var buffer=startCtx.memory.buffer.slice(0,startCtx.mOffset); True(buffer,"audio/"+key); }else{ False($T("quVJ::{1}编码器未start",0,key)); }; }; }; var Tab=[1,2,3,3,4,4,4,4,5,5,5,5,5,5,5,5,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7]; regEngine("g711a","G.711 A-law (pcma)" ,function(pcm){//编码 var buffer=new Uint8Array(pcm.length); for(var i=0;i<pcm.length;i++){ var pcm_val=pcm[i],mask; if (pcm_val >= 0) { mask = 0xD5; /* sign (7th) bit = 1 */ } else { mask = 0x55; /* sign bit = 0 */ pcm_val = -pcm_val - 1; } /* Convert the scaled magnitude to segment number. */ var seg = (Tab[pcm_val>>8&0x7F]||8)-1; /* Combine the sign, segment, and quantization bits. */ var aval = seg << 4; if (seg < 2) aval |= (pcm_val >> 4) & 15; else aval |= (pcm_val >> (seg + 3)) & 15; buffer[i] = (aval ^ mask); } return buffer; } ,function(bytes){//解码 var buffer=new Int16Array(bytes.length); for(var i=0;i<bytes.length;i++){ var a_val=bytes[i]^0x55; var t = (a_val & 15) << 4; var seg = (a_val & 0x70) >> 4; switch (seg) { case 0: t += 8; break; case 1: t += 0x108; break; default: t += 0x108; t <<= seg - 1; } buffer[i] = ((a_val & 0x80) ? t : -t); } return buffer; }); regEngine("g711u","G.711 μ-law (pcmu、mu-law)" ,function(pcm){//编码 var buffer=new Uint8Array(pcm.length); for(var i=0;i<pcm.length;i++){ var pcm_val=pcm[i],mask; /* Get the sign and the magnitude of the value. */ if (pcm_val < 0) { pcm_val = 0x84 - pcm_val; mask = 0x7F; } else { pcm_val += 0x84; mask = 0xFF; } /* Convert the scaled magnitude to segment number. */ var seg = (Tab[pcm_val>>8&0x7F]||8)-1; var uval = (seg << 4) | ((pcm_val >> (seg + 3)) & 0xF); buffer[i] = (uval ^ mask); } return buffer; } ,function(bytes){//解码 var buffer=new Int16Array(bytes.length); for(var i=0;i<bytes.length;i++){ var u_val= ~bytes[i]; var t = ((u_val & 15) << 3) + 0x84; t <<= (u_val & 0x70) >> 4; buffer[i] = ((u_val & 0x80) ? (0x84 - t) : (t - 0x84)); } return buffer; }); }));