/* 录音 Recorder扩展,DTMF(电话拨号按键信号)编码生成器,生成按键对应的音频PCM信号 本扩展分两个功能: DTMF_Encode DTMF_EncodeMix 本扩展生成信号代码、原理简单粗暴,纯js实现易于移植,0依赖 使用场景:DTMF按键信号生成,软电话实时发送DTMF按键信号等 https://github.com/xiangyuecn/Recorder */ (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"; /** 本方法用来生成单个按键信号pcm数据,属于底层方法,要混合多个按键信号到别的pcm中请用封装好的DTMF_EncodeMix方法 参数: key: 单个按键0-9#* sampleRate:123 要生成的pcm采样率 duration:100 按键音持续时间 mute:50 按键音前后静音时长 返回: pcm:[Int16,...],生成单个按键信号 **/ Recorder.DTMF_Encode=function(key,sampleRate,duration,mute){ var durSize=Math.floor(sampleRate*(duration||100)/1000); var muteSize=Math.floor(sampleRate*(mute==null?50:mute)/1000); var pcm0=new Int16Array(durSize+muteSize*2); var pcm1=new Int16Array(durSize+muteSize*2); // https://github.com/watilde/node-dtfm/blob/master/encode.js var f0=DTMF_Freqs[key][0]; var f1=DTMF_Freqs[key][1]; var vol=0.3; for(var i=0;i=keyPcm.length){ state.keyIdx=-1; }; }; //新的key,生成信号 if(state.keyIdx!=This.idx){ keyPcm=Recorder.DTMF_Encode(key,sampleRate,set.duration,set.mute); state.keyIdx=This.idx; state.cur=0; state.keyPcm=keyPcm; newEncodes.push({ key:key ,data:keyPcm }); }; //将keyPcm混合到当前pcm中,实际是替换逻辑 var res=Mix(pcm,pcmPos,keyPcm,state.cur,true); state.cur=res.cur; pcmPos=res.last; //下一个按键 if(res.cur>=keyPcm.length){ This.idx++; key=This.keys.charAt(This.idx); state.skip=Math.floor(sampleRate*(set.interval-set.duration-set.mute*2)/1000); }; //当前pcm的位置已消耗完 if(res.last>=pcm.length){ pcmPos=0; continue loop;//下一个pcm }; }; }; return { newEncodes:newEncodes //本次混合新生成的按键信号列表 [{key:"*",data:[Int16,...]},...],如果没有产生新信号将为空数组 ,hasNext:This.idx=buffer.length || cur>=add.length){ return { last:j ,cur:cur }; }; if(mute){ buffer[j]=0;//置为0即为静音 }; var data_mix,data1=buffer[j],data2=add[cur]; //简单混音算法 https://blog.csdn.net/dancing_night/article/details/53080819 if(data1<0 && data2<0){ data_mix = data1+data2 - (data1 * data2 / -0x7FFF); }else{ data_mix = data1+data2 - (data1 * data2 / 0x7FFF); }; buffer[j]=data_mix; }; }; var DTMF_Freqs={ '1': [697, 1209] ,'2': [697, 1336] ,'3': [697, 1477] ,'A': [697, 1633] ,'4': [770, 1209] ,'5': [770, 1336] ,'6': [770, 1477] ,'B': [770, 1633] ,'7': [852, 1209] ,'8': [852, 1336] ,'9': [852, 1477] ,'C': [852, 1633] ,'*': [941, 1209] ,'0': [941, 1336] ,'#': [941, 1477] ,'D': [941, 1633] }; }));