1

I'm working on a "studio" website where you can perform different sound edits on a clip of audio you record. In order to do the sound editing, Fourier Transforms have to be performed on windows of the recorded sound. This is the code for recording audio:

const signalArray = []

//once record button is clicked, record.
recordBtn.addEventListener('click', () => {
    navigator.getUserMedia({ audio: true }, onStream, onError)
})

//success callback for get user media (yes I know this method is outdated)
function onStream(stream){
    var audioCtx = new AudioContext({
        latencyHint: "interactive",
        sampleRate: sampleRate,
    });
    var inputNode = audioCtx.createMediaStreamSource(stream)
    var tunerNode = audioCtx.realTimeAudioEdit()
    var outputNode = audioCtx.destination

    inputNode.connect(tunerNode)
    tunerNode.connect(outputNode)

    setTimeout(function(){
        audioCtx.close()
    }, recordDuration)
};

function onError(){console.log("error")};

//get audio Float values as they are recorded and push them to an array
AudioContext.prototype.realTimeAudioEdit = function () {
    function edit(input, output) {
        for (var i = 0; i < output.length; i++){
            output[i] = input[i];
            signalArray.push(output[i])
        }
        return output;
    }

    var tuner = this.createScriptProcessor(bufferSize, 1, 1);
    tuner.onaudioprocess = function (e) {
        var input = e.inputBuffer.getChannelData(0);
        var output = e.outputBuffer.getChannelData(0);
        output = edit(input, output);
    };
    return tuner;
};

The code above basically just records audio and creates an array of the data. Then the data is divided into windows and a DFT is performed on each window. This is my DFT code:

function dft(data){
    const pCords = []
    for(var k = 0; k < data.length ; k++){
        var re = 0
        var im = 0
        for(var n = 0; n < data.length; n++){
            const arg = (2 * Math.PI * k * n) / data.length
            re += data[n] * Math.cos(arg)
            im -= data[n] * Math.sin(arg)
        }
        pCords.push({
            re: re/data.length,
            im: im/data.length
        })
    }
    return pCords
}

This is an algorithm I wrote based on the DFT equation. I don't know why but its very slow. On my good computer it takes 30 seconds to convert a 45 second signal into DFT data. So my question is this: Is there a more efficient DFT method? I feel like there has to be as 30 seconds to compute the DFTs is kind of absurd. Also, if there is a more efficient method to perform the DFT, is there also an efficient way to perform an IDFT?

Thank you to anyone who can provide insight!

  • 1
    Well, DFT is pretty slow because of `O(n^2)` time complexity. If you need something faster, you can try FFT. You can read more here for example: https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/math/fourier-transform – tarkh Oct 12 '22 at 21:04

0 Answers0