superpoweredSDK/web-audio-javascript-webassembly-SDK-interactive-audio

Analyzing in chunks

robclouth opened this issue · 11 comments

I'm trying to analyze some audio in chunks to avoid the OOM errors of doing the whole thing at once. However, the waveforms are always 0 after the first hundred or so elements. Does this look ok?

analyseTrack() {
    const blockLength = Math.min(
      this.channelData[0].length,
      maxAnalysisBlockLength
    );
    let interleavedBuffer = Superpowered.createFloatArray(blockLength * 2);

    const channelBuffers = [
      Superpowered.createFloatArray(blockLength),
      Superpowered.createFloatArray(blockLength)
    ];

    let analyzer = Superpowered.new(
      "Analyzer",
      this.trackSampleRate,
      this.trackDuration
    );

    for (
      let blockStart = 0;
      blockStart < this.channelData[0].length - blockLength;
      blockStart += blockLength
    ) {
      for (let i = 0; i < blockLength; i++) {
        channelBuffers[0].array[i] = this.channelData[0][blockStart + i];
        channelBuffers[1].array[i] = this.channelData[1][blockStart + i];
      }

      Superpowered.Interleave(
        channelBuffers[0].pointer,
        channelBuffers[1].pointer,
        interleavedBuffer.pointer,
        blockLength
      );

      analyzer.process(interleavedBuffer.pointer, blockLength, -1);

      this.sendMessageToMainScope({
        type: "analysisProgress",
        data: blockStart / this.channelData[0].length
      });
    }

    analyzer.makeResults(
      60, // Detected bpm will be more than or equal to this. Recommended value: 60.
      200, // Detected bpm will be less than or equal to this. Recommended value: 200.
      0, // If you know the bpm set it here. Use 0 otherwise.
      0, // Provides a "hint" for the analyzer with this. Use 0 otherwise.
      true, // True: calculate beatgridStartMs. False: save some CPU with not calculating it.
      0, // Provides a "hint" for the analyzer with this. Use 0 otherwise.
      true, // True: make overviewWaveform. False: save some CPU and memory with not making it.
      false, // True: make the low/mid/high waveforms. False: save some CPU and memory with not making them.
      false // True: calculate keyIndex. False: save some CPU with not calculating it.
    );

    const results = {
      bpm: analyzer.bpm,
      beatgridStartMs: analyzer.beatgridStartMs,
      overviewWaveform: analyzer.overviewWaveform,
      peakWaveform: analyzer.peakWaveform
    };

    analyzer.destruct();

    Superpowered.destroyFloatArray(interleavedBuffer);
    for (let buffer of channelBuffers) Superpowered.destroyFloatArray(buffer);

    return results;
  }

From the documentation: "1 point/sec waveform data displaying the average volume in decibels."
The overview waveform has one number for every second. Therefore 100 numbers will represent 100 seconds.

Thanks for the reply. The documentation says 150 points per second for all other waveforms than the overview. Also the file is over 100 seconds and the output is nearly the same for all input files.

How many frames (the sum of blocklength) do you submit to the analyzer, what's the value of trackSampleRate, and what's the value of analyzer.overviewSize and analyzer.waveformSize in this case?

Sorry about the late reply. I've been with another project for while.
Duration: 332.97s
Total frames: 14684006
Sample rate: 44100
waveformSize: 49950
OverviewSize: 333
blocklength: 50000

No matter what track I give it the waveform values go to 0 after 25ish elements.
I've tried with analyzer.process(interleavedBuffer.pointer, blockLength * 2, -1); instead of analyzer.process(interleavedBuffer.pointer, blockLength, -1); but that didn't work.

Should the last argument be -1? It's not real-time, just chunked processing.

Guro commented

@robclouth I have a similar problem, are you able to get bpm or beatgridStartMs? for me it's always 0
would be good to have an example of a correctly functioning analyzer

We're working on a larger update and bypassing Emscripten from some parts, it seems like it interferes with this.

Just updated the SDK, please check.

Still having this issue with the latest update (2.2.0)?