【前端】智能库房综合管理系统前端项目
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

134 lines
3.2 KiB

  1. import { Now } from '../../utils'
  2. import BitBuffer from '../buffer'
  3. import BaseDecoder from './decoder'
  4. export default class MP2WASM extends BaseDecoder {
  5. constructor(options) {
  6. super(options)
  7. this.onDecodeCallback = options.onAudioDecode
  8. this.module = options.wasmModule
  9. this.bufferSize = options.audioBufferSize || 128 * 1024
  10. this.bufferMode = options.streaming
  11. ? BitBuffer.MODE.EVICT
  12. : BitBuffer.MODE.EXPAND
  13. this.sampleRate = 0
  14. }
  15. initializeWasmDecoder() {
  16. if (!this.module.instance) {
  17. console.warn('JSMpeg: WASM module not compiled yet')
  18. return
  19. }
  20. this.instance = this.module.instance
  21. this.functions = this.module.instance.exports
  22. this.decoder = this.functions._mp2_decoder_create(
  23. this.bufferSize,
  24. this.bufferMode
  25. )
  26. }
  27. destroy() {
  28. if (!this.decoder) {
  29. return
  30. }
  31. this.functions._mp2_decoder_destroy(this.decoder)
  32. }
  33. bufferGetIndex() {
  34. if (!this.decoder) {
  35. return
  36. }
  37. return this.functions._mp2_decoder_get_index(this.decoder)
  38. }
  39. bufferSetIndex(index) {
  40. if (!this.decoder) {
  41. return
  42. }
  43. this.functions._mp2_decoder_set_index(this.decoder, index)
  44. }
  45. bufferWrite(buffers) {
  46. if (!this.decoder) {
  47. this.initializeWasmDecoder()
  48. }
  49. let totalLength = 0
  50. for (let i = 0; i < buffers.length; i++) {
  51. totalLength += buffers[i].length
  52. }
  53. let ptr = this.functions._mp2_decoder_get_write_ptr(
  54. this.decoder,
  55. totalLength
  56. )
  57. for (let i = 0; i < buffers.length; i++) {
  58. this.instance.heapU8.set(buffers[i], ptr)
  59. ptr += buffers[i].length
  60. }
  61. this.functions._mp2_decoder_did_write(this.decoder, totalLength)
  62. return totalLength
  63. }
  64. decode() {
  65. const startTime = Now()
  66. if (!this.decoder) {
  67. return false
  68. }
  69. const decodedBytes = this.functions._mp2_decoder_decode(this.decoder)
  70. if (decodedBytes === 0) {
  71. return false
  72. }
  73. if (!this.sampleRate) {
  74. this.sampleRate = this.functions._mp2_decoder_get_sample_rate(
  75. this.decoder
  76. )
  77. }
  78. if (this.destination) {
  79. // Create a Float32 View into the modules output channel data
  80. const leftPtr = this.functions._mp2_decoder_get_left_channel_ptr(
  81. this.decoder
  82. )
  83. const rightPtr = this.functions._mp2_decoder_get_right_channel_ptr(
  84. this.decoder
  85. )
  86. const leftOffset = leftPtr / Float32Array.BYTES_PER_ELEMENT
  87. const rightOffset = rightPtr / Float32Array.BYTES_PER_ELEMENT
  88. const left = this.instance.heapF32.subarray(
  89. leftOffset,
  90. leftOffset + MP2WASM.SAMPLES_PER_FRAME
  91. )
  92. const right = this.instance.heapF32.subarray(
  93. rightOffset,
  94. rightOffset + MP2WASM.SAMPLES_PER_FRAME
  95. )
  96. this.destination.play(this.sampleRate, left, right)
  97. }
  98. this.advanceDecodedTime(MP2WASM.SAMPLES_PER_FRAME / this.sampleRate)
  99. const elapsedTime = Now() - startTime
  100. if (this.onDecodeCallback) {
  101. this.onDecodeCallback(this, elapsedTime)
  102. }
  103. return true
  104. }
  105. getCurrentTime() {
  106. const enqueuedTime = this.destination ? this.destination.enqueuedTime : 0
  107. return this.decodedTime - enqueuedTime
  108. }
  109. static SAMPLES_PER_FRAME = 1152
  110. }