javascript - 是否可以合并两个音频 'base64data' 字符串来创建一个独特的音频文件?

标签 javascript audio web-audio-api

是否可以合并两个音频“base64data”字符串来创建一个唯一的音频文件?

我在字符串中有两个循环音频 Base64 wav,如下所示:

data:audio/x-wav;base64,UklGRuIfQVZFZm1R7SH$WP90AhICLwKT...

我想我正在做一些非常愚蠢的事情,但我想知道这是否可能。

我正在尝试将两个 wav 合并为一个可以在音频 HTML 元素中播放的 wav。 我想提取第二个的base64数据以合并到第一个,然后播放它,但导航器返回错误。

这是我的 JavaScript 代码:

var audio_Data1 = base64_audio1;
var audio_Data2 = base64_audio1.split(',')[1];
var audio_final = audio_Data1 + audio_Data2;

audioControl.src = audio_final;
audioControl.play();

非常感谢您的建议 谢谢!


编辑:

我正在尝试解码 Base64 block 以缓冲数据并连接缓冲区以再次编码为 Base64。

问题:返回的base64是“AA==”

我认为“AA==”是0字节。然后当我连接缓冲区时我做了一些坏事:

var myB64Data  = myB64WavString.split(',');
var myB64Chunk = myB64Data[1];
var myBuffer1 =  base64ToArrayBuffer(myB64Chunk);
var myBuffer2 = ""; //Same process

var myFinalBuffer = [];
myFinalBuffer.push.apply(myFinalBuffer, myBuffer1);
myFinalBuffer.push.apply(myFinalBuffer, myBuffer2); 

var myFinalB64 = 'data:audio/x-wav;base64,' + arrayBufferToBase64(myFinalBuffer); 

console.log( myFinalB64 );

控制台返回下一个:“data:audio/x-wav;base64,AA==”

我的编码/解码工作函数:

function base64ToArrayBuffer(base64) {
   var binary_string =  window.atob(base64);
   var len = binary_string.length;
   var bytes = new Uint8Array( len );
   for (var i = 0; i < len; i++)        {
       bytes[i] = binary_string.charCodeAt(i);
   }
   return bytes.buffer;
}

function arrayBufferToBase64( buffer ) {
   var binary = '';
   var bytes = new Uint8Array( buffer );
   var len = bytes.byteLength;
   for (var i = 0; i < len; i++) {
       binary += String.fromCharCode( bytes[ i ] );
   }
   return window.btoa( binary );
}

最佳答案

我解决了它!(经过艰苦和疯狂的工作并复制 Convert AudioBuffer to ArrayBuffer / Blob for WAV Download 的答案两天后) 我希望它可以帮助您节省我为此开发的所有工作;)

var myB64Data  = myB64WavString.split(',');
var myB64Chunk = myB64Data[1];
var myBuffer1 =  base64ToArrayBuffer(myB64Chunk);
var myBuffer2 = ""; //Same process

var myFinalBuffer = appendBuffer (myBuffer1, myBuffer2);

var myFinalBuffer = getWavBytes( arrBytesFinal, {
  isFloat: false,       // floating point or 16-bit integer
  numChannels: 2,     //1 for mono recordings
  sampleRate: 48000, //Depends on your file audio bitrate !! 32000
})              


var myFinalB64 = 'data:audio/x-wav;base64,' + arrayBufferToBase64(myFinalBuffer); 

console.log( myFinalB64 );

//Then you can asign to an audio HTML control

myAudioControl.src = myFinalB64;

附加功能:

function appendBuffer(buffer1, buffer2) {
  var tmp = new Uint8Array(buffer1.byteLength + buffer2.byteLength);
  tmp.set(new Uint8Array(buffer1), 0);
  tmp.set(new Uint8Array(buffer2), buffer1.byteLength);
  return tmp;
};
 

function getWavBytes(buffer, options) {
  const type = options.isFloat ? Float32Array : Uint16Array
  const numFrames = buffer.byteLength / type.BYTES_PER_ELEMENT

  const headerBytes = getWavHeader(Object.assign({}, options, { numFrames }))
  const wavBytes = new Uint8Array(headerBytes.length + buffer.byteLength);

  // prepend header, then add pcmBytes
  wavBytes.set(headerBytes, 0)
  wavBytes.set(new Uint8Array(buffer), headerBytes.length)

  return wavBytes
}

// adapted from https://gist.github.com/also/900023
// returns Uint8Array of WAV header bytes
function getWavHeader(options) {
  const numFrames =      options.numFrames
  const numChannels =    options.numChannels || 2
  const sampleRate =     options.sampleRate || 44100
  const bytesPerSample = options.isFloat? 4 : 2
  const format =         options.isFloat? 3 : 1

  const blockAlign = numChannels * bytesPerSample
  const byteRate = sampleRate * blockAlign
  const dataSize = numFrames * blockAlign

  const buffer = new ArrayBuffer(44)
  const dv = new DataView(buffer)

  let p = 0

  function writeString(s) {
    for (let i = 0; i < s.length; i++) {
      dv.setUint8(p + i, s.charCodeAt(i))
    }
    p += s.length
  }

  function writeUint32(d) {
    dv.setUint32(p, d, true)
    p += 4
  }

  function writeUint16(d) {
    dv.setUint16(p, d, true)
    p += 2
  }

  writeString('RIFF')              // ChunkID
  writeUint32(dataSize + 36)       // ChunkSize
  writeString('WAVE')              // Format
  writeString('fmt ')              // Subchunk1ID
  writeUint32(16)                  // Subchunk1Size
  writeUint16(format)              // AudioFormat
  writeUint16(numChannels)         // NumChannels
  writeUint32(sampleRate)          // SampleRate
  writeUint32(byteRate)            // ByteRate
  writeUint16(blockAlign)          // BlockAlign
  writeUint16(bytesPerSample * 8)  // BitsPerSample
  writeString('data')              // Subchunk2ID
  writeUint32(dataSize)            // Subchunk2Size

  return new Uint8Array(buffer)
}

关于javascript - 是否可以合并两个音频 'base64data' 字符串来创建一个独特的音频文件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65767933/

相关文章:

javascript - 动态谷歌代码美化不起作用

javascript - Angularjs Controller

javascript - 在警告框后重定向

.net - 将两个音频文件合并为一个文件,然后保存在磁盘中

javascript - 尝试抽象 WebAudio API xhr 请求的部分时,无法将 DOM 元素传递给 Javascript 中的构造函数

javascript - 如何在单击按钮时将可编辑的 div 内容保存在数组中

algorithm - 为什么声波的逆向声音与原始声音完全一样?

iphone - 如何使用特定时间瞬间的 openAL 命令播放声音文件(时间输入是 double 或 float )

javascript - Web Audio AudioBufferSourceNode失谐VSplaybackRate

javascript - 用于复杂播放列表的 Web Audio API 或 <audio>?