pcm.js 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. /*
  2. pcm编码器+编码引擎
  3. https://github.com/xiangyuecn/Recorder
  4. 编码原理:本编码器输出的pcm格式数据其实就是Recorder中的buffers原始数据(经过了重新采样),16位时为LE小端模式(Little Endian),并未经过任何编码处理
  5. 编码的代码和wav.js区别不大,pcm加上一个44字节wav头即成wav文件;所以要播放pcm就很简单了,直接转成wav文件来播放,已提供转换函数 Recorder.pcm2wav
  6. */
  7. (function(){
  8. "use strict";
  9. Recorder.prototype.enc_pcm={
  10. stable:true
  11. ,testmsg:"pcm为未封装的原始音频数据,pcm数据文件无法直接播放;支持位数8位、16位(填在比特率里面),采样率取值无限制"
  12. };
  13. Recorder.prototype.pcm=function(res,True,False){
  14. var This=this,set=This.set
  15. ,size=res.length
  16. ,bitRate=set.bitRate==8?8:16;
  17. var buffer=new ArrayBuffer(size*(bitRate/8));
  18. var data=new DataView(buffer);
  19. var offset=0;
  20. // 写入采样数据
  21. if(bitRate==8) {
  22. for(var i=0;i<size;i++,offset++) {
  23. //16转8据说是雷霄骅的 https://blog.csdn.net/sevennight1989/article/details/85376149 细节比blqw的按比例的算法清晰点,虽然都有明显杂音
  24. var val=(res[i]>>8)+128;
  25. data.setInt8(offset,val,true);
  26. };
  27. }else{
  28. for (var i=0;i<size;i++,offset+=2){
  29. data.setInt16(offset,res[i],true);
  30. };
  31. };
  32. True(new Blob([data.buffer],{type:"audio/pcm"}));
  33. };
  34. /**pcm直接转码成wav,可以直接用来播放;需同时引入wav.js
  35. data: {
  36. sampleRate:16000 pcm的采样率
  37. bitRate:16 pcm的位数 取值:8 或 16
  38. blob:blob对象
  39. }
  40. data如果直接提供的blob将默认使用16位16khz的配置,仅用于测试
  41. True(wavBlob,duration)
  42. False(msg)
  43. **/
  44. Recorder.pcm2wav=function(data,True,False){
  45. if(data.slice && data.type!=null){//Blob 测试用
  46. data={blob:data};
  47. };
  48. var sampleRate=data.sampleRate||16000,bitRate=data.bitRate||16;
  49. if(!data.sampleRate || !data.bitRate){
  50. console.warn("pcm2wav必须提供sampleRate和bitRate");
  51. };
  52. if(!Recorder.prototype.wav){
  53. False("pcm2wav必须先加载wav编码器wav.js");
  54. return;
  55. };
  56. var reader=new FileReader();
  57. reader.onloadend=function(){
  58. var pcm;
  59. if(bitRate==8){
  60. //8位转成16位
  61. var u8arr=new Uint8Array(reader.result);
  62. pcm=new Int16Array(u8arr.length);
  63. for(var j=0;j<u8arr.length;j++){
  64. pcm[j]=(u8arr[j]-128)<<8;
  65. };
  66. }else{
  67. pcm=new Int16Array(reader.result);
  68. };
  69. Recorder({
  70. type:"wav"
  71. ,sampleRate:sampleRate
  72. ,bitRate:bitRate
  73. }).mock(pcm,sampleRate).stop(function(wavBlob,duration){
  74. True(wavBlob,duration);
  75. },False);
  76. };
  77. reader.readAsArrayBuffer(data.blob);
  78. };
  79. })();