左通道提取/用Javascript在WAV文件上淡出

问题描述

因此,我正在为这个任务而苦苦挣扎,我需要从用户上传(基本上是文件输入)中获取WAV文件,并且必须对此进行一些操作:

@H_404_2@
  • 验证这是有效的.wav文件
  • 如果用户上传了立体声文件,请提取一个通道(左)
  • 在末尾添加w淡出(文件的最后50个样本)
  • 我的第一个念头是hey,there's an api for that (web audio),所以我做了类似的事情:

    const source = audioContext.createBufferSource();
    const splitter = audioContext.createChannelSplitter(audioBuffer.numberOfChannels);
    const gainNode = audioContext.createGain();
    
    source.buffer = audioBuffer;
    source.connect(splitter);
    
    gainNode.gain.linearRampTovalueAtTime(0,audioBuffer.duration);
    
    splitter.connect(gainNode,0);
    

    我想将第一个通道从信号源中删除,并添加线性淡入淡出(实际上不是在最近的50个样本中,但这不是现在所说的重点)

    但是...

    如何将其输出提取文件中?我知道如何播放受控声音的前端,但是我可以将其转换回文件吗?

    因此,在某个时候我以为没有办法做到这一点,所以我提出了另一种解决方案,该解决方案使用低级文件操作,如下所示:

      // const arrayBuffer = await toArrayBuffer(file);
      const audioBuffer = await decodeAudio(audioContext,arrayBuffer);
    
      const channels = 1;
      const duration = audioBuffer.duration;
      const rate = audioBuffer.sampleRate;
      const length = Math.ceil(duration * rate * channels * 2 + 44);
      const buffer = new ArrayBuffer(length);
      const view = new DataView(buffer);
      let position = 0;
      let offset = 0;
    
      const setUint16 = (data) => {
        view.setUint16(position,data,true);
        position += 2;
      };
    
      const setUint32 = (data) => {
        view.setUint32(position,true);
        position += 4;
      };
    
      setUint32(0x46464952); // RIFF
      setUint32(length - 8); // file length
      setUint32(0x45564157); // WAV
    
      setUint32(0x20746d66); // fmt
      setUint32(16); // data size
      setUint16(1); // PCM
      setUint16(channels);
      setUint32(rate);
      setUint32(rate * 16 * channels);
      setUint16(channels * 2);
      setUint16(16);
    
      setUint32(0x61746164); // "data"
      setUint32(length - position - 4);
    
      const leftChannel = audioBuffer.getChannelData(0);
      let sample;
    
      console.log('left',leftChannel);
      console.log('length',length);
      while (position < length) {
        sample = leftChannel[offset];
        sample = sample < 0 ? sample * 0x8000 : sample * 0x7FFF;
        view.setInt16(position,sample,true);
        position += 2;
        offset++;
      }
    
      console.log('buffer',buffer);
    
      const blob = new Blob([buffer],{ type: file.type });
    

    但似乎流量很大,输出失真/采样率不同,依此类推...

    那么我的问题将是:

    @H_404_2@
  • 如果可能的话,如何从网络音频api中提取文件?导致做那个恕我直言的最好方法
  • 如果不可能(1),那么第二种方法我做错了什么?
  • 解决方法

    WebAudio无法将音频保存到文件。您可以使用MediaRecorder作为一种方式,但是我认为这不是支持WAV文件所必需的。或者,您也可以按照上面的显示手工操作。乍一看,我发现您所做的工作没有任何问题。在测试套件中查看Chrome对save files的作用可能会有所帮助;它基本上可以完成您的工作。