pcm_to_wav.js 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
  1. // import { Base64 } from 'js-base64'
  2. function pcmtoWav(pcmsrt, sampleRate, numChannels, bitsPerSample) {
  3. //参数->(base64编码的pcm流,采样频率,声道数,采样位数)
  4. let header = {
  5. // OFFS SIZE NOTES
  6. chunkId: [0x52, 0x49, 0x46, 0x46], // 0 4 "RIFF" = 0x52494646
  7. chunkSize: 0, // 4 4 36+SubChunk2Size = 4+(8+SubChunk1Size)+(8+SubChunk2Size)
  8. format: [0x57, 0x41, 0x56, 0x45], // 8 4 "WAVE" = 0x57415645
  9. subChunk1Id: [0x66, 0x6d, 0x74, 0x20], // 12 4 "fmt " = 0x666d7420
  10. subChunk1Size: 16, // 16 4 16 for PCM
  11. audioFormat: 1, // 20 2 PCM = 1
  12. numChannels: numChannels || 1, // 22 2 Mono = 1, Stereo = 2...
  13. sampleRate: sampleRate || 16000, // 24 4 8000, 44100...
  14. byteRate: 0, // 28 4 SampleRate*NumChannels*BitsPerSample/8
  15. blockAlign: 0, // 32 2 NumChannels*BitsPerSample/8
  16. bitsPerSample: bitsPerSample || 16, // 34 2 8 bits = 8, 16 bits = 16
  17. subChunk2Id: [0x64, 0x61, 0x74, 0x61], // 36 4 "data" = 0x64617461
  18. subChunk2Size: 0, // 40 4 data size = NumSamples*NumChannels*BitsPerSample/8
  19. }
  20. function u32ToArray(i) {
  21. return [i & 0xff, (i >> 8) & 0xff, (i >> 16) & 0xff, (i >> 24) & 0xff]
  22. }
  23. function u16ToArray(i) {
  24. return [i & 0xff, (i >> 8) & 0xff]
  25. }
  26. let pcm = Base64.toUint8Array(pcmsrt)
  27. header.blockAlign = (header.numChannels * header.bitsPerSample) >> 3
  28. header.byteRate = header.blockAlign * header.sampleRate
  29. header.subChunk2Size = pcm.length * (header.bitsPerSample >> 3)
  30. header.chunkSize = 36 + header.subChunk2Size
  31. let wavHeader = header.chunkId.concat(
  32. u32ToArray(header.chunkSize),
  33. header.format,
  34. header.subChunk1Id,
  35. u32ToArray(header.subChunk1Size),
  36. u16ToArray(header.audioFormat),
  37. u16ToArray(header.numChannels),
  38. u32ToArray(header.sampleRate),
  39. u32ToArray(header.byteRate),
  40. u16ToArray(header.blockAlign),
  41. u16ToArray(header.bitsPerSample),
  42. header.subChunk2Id,
  43. u32ToArray(header.subChunk2Size)
  44. )
  45. let wavHeaderUnit8 = new Uint8Array(wavHeader)
  46. let mergedArray = new Uint8Array(wavHeaderUnit8.length + pcm.length)
  47. mergedArray.set(wavHeaderUnit8)
  48. mergedArray.set(pcm, wavHeaderUnit8.length)
  49. let blob = new Blob([mergedArray], { type: 'audio/wav' })
  50. let blobUrl = window.URL.createObjectURL(blob)
  51. return blobUrl
  52. }