0

I'm completely new to the Web Audio API, and not too terribly proficient in javascript. However, I had a specific function that I want to implement into a website I'm working on that requires Google's TTS API, which returns Base64 audio, to go through a reverb filter and then (preferably) autoplay the resulting audio.

So here's how the workflow looks.

TTS request to Google => Base64 response from Google => Base64 converted & sent through Convolver (reverb) node => Output sent to user's output device.

So what I'm struggling on first and foremost is getting ANY sort of response from an audio file going through the nodes. After that, I can deal with the Base64 conversions.

Any help would be appreciated. My IDE's are no help whatsoever. They all basically tell me "Congrats, this code looks fantastic!". Meanwhile, I'm over here pulling my hairs out and 2 lines of code away from jumping out my window.

Here's the code I've been working with. This obviously wouldn't be the entirety of it, but I thought I should first get some sound coming out of it before moving on.

let context;

let compressor;
let reverb;

let source1

let lowpassFilter;
let waveShaper;
let panner;

let wet;
let dry;

let masterDry;
let masterWet;




function effectsBoard () {
    context = new (window.AudioContext || window.webkitAudioContext)();

    // Effects Setup
    lowpassFilter = context.createBiquadFilter();
    waveShaper = context.createWaveShaper();
    panner = context.createPanner();
    compressor = context.createDynamicsCompressor();
    reverb = context.createConvolver();

    //Master Gains for Wet and Dry
    masterDry = context.createGain();
    masterWet = context.createGain();

    //Connect the compressor (the last effect) to the final destination (audio output)
    compressor.connect(context.destination);

    //Connect the Master Wet and Dry signals to the compressor for mixing before the output.
    masterDry.connect(compressor);
    masterWet.connect(compressor);

    //Connect Reverb to the Wet Master Gain
    reverb.connect(masterWet);

    //Connect source1 to the effectt - first the dry signal and then the wet
    source1.connect(lowpassFilter);
    lowpassFilter.connect(masterDry);
    lowpassFilter.connect(reverb);

    //Create a Source Buffer
    fetch("voice.mp3")
        .then(data => data.arrayBuffer())
        .then(arrayBuffer => context.decodeAudioData(arrayBuffer))
        .then(decodedAudio => {
            avaAudio = decodedAudio;
        });

    //Then start the sources on run event
    function playback() {
        source1 = context.createBufferSource();
        source1.buffer = avaAudio;
        source1.start(context.currentTime);
    }

window.addEventListener("mousedown", playback);
sportzpikachu
  • 831
  • 5
  • 18

1 Answers1

0

In skimming through your code, it looks okay. I think you're getting bit by autoplay policy.

When you create an audio context, it usually starts out as paused. You need to call context.resume(), but you can only do that on a trusted event.

mousedown isn't a trusted event. You actually need a full click event for that.

Also, at least in the code you show here, it seems effectsBoard() is never called, but I assume that there's more code.

Use your browser's developer tools to see what errors you need to see.

Brad
  • 159,648
  • 54
  • 349
  • 530
  • That actually helped a bit, so thanks! I ended up completely redoing a lot of the code, and I think it fixed it, but now I'm running into a new issue... I posted it here: https://stackoverflow.com/questions/65298075/base64toarraybuffer-error-failed-to-execute-atob-on-window-web-audio-api I'd appreciate any thoughts you may have! – Heleus Brands - Dev Dec 14 '20 at 23:43
  • No problem, glad you found this answer helpful. If you'd like, you can accept it as your answer by clicking the checkmark next to it, and/or clicking the upvote arrow. That helps future readers find the answer if they have the same question. – Brad Dec 14 '20 at 23:58