How to change the tone of an audio with Javascript?

Asked

Viewed 284 times

0

Consider that I have the following HTML body and JS script:

<!DOCTYPE html>
<html>
<head><title>Mudar tom do áudio</title></head>
<body>
    <p>Mudar tom do áudio</p>
    <input type=button value="Tocar áudio">
    <p>Tom: <input type=range min=-5 max=5></p>
    <p id=tom></p>
</body>
<script>
     let audio;
     let range = document.querySelector("input[type=range]");
    /*A função abaixo é ativada quando o botão for clicado, e ela teoricamente deve dar 'play' no áudio com o tom alterado!*/
    range.addEventListener("click", function() {
        audio = new Audio();
        audio.src = /*Endereço do áudio*/
        /*O que fazer aqui para mudar o tom do áudio?*/
    } /*A função abaixo é ativada quando o valor do 'range' for alterado, mudando o valor do parágrafo de id 'tom'*/
    document.querySelector("input[type=range").addEventListener("input", function() {
        let txtParag;
        let valor = range.value;
        if(valor == 0) {
            txtParag = "Áudio em seu tom original"
        } else {
            let add = "ns";
            if(Math.abs(valor) == 1) {
                add = "m";
            } txtParag = Math.abs(valor) + " to" + add + " ";
            if(valor < 0) {
                txtParag += "acima";
            } else {
                txtParag += "abaixo";
            }
        } document.getElementById("tom").textContent = txtParag;
    });
</script>
<html>

What I want to know is the necessary command (or commands) so that when you play the audio, its tone will be changed: will you need to use the JS audio API? I thank anyone who can help me!

  • Have you tried using the API audio or the lib tone js.?

  • I didn’t try to use.

  • I find this question very interesting and I will follow it. If no one answers before I will answer in a few weeks when I have more time.

  • I’ll be waiting for the answer! ; )

1 answer

1

It seems a silly question but the answer is complex ...

I’ll try to give you an Overview of how to change the tone of an existing sound, this is complex to do in any language, so I’ll try to give you a northern on the necessary steps ...

I rarely see API’s to do this, it’s hard to see this kind of manipulation out of a DAW (Digital audio Workstation).

In the world of DSP (Digital Signal Processing / Digital Signal Processing), we call this Pitch Shift (tone change), this tone change happens without changing the audio speed.

No matter what language you will use, you will have to decode your audio in order to modify it, the part of Code is just one of the tricky parts of the joke, if your audio is a file .wav things get simpler because the files .wav are not complicated to achieve the values PCM(Pulse code Modulation), with its audio decoded it is possible to make several modifications, change the volume, play the audio backwards, let the audio slower or faster, change the tone of the audio, plot the waveform of the audio, etc, etc ... or it is only possible to manipulate and visualize a sound if this step is done before OK...

The above step is only a prerequisite for the next step, now with the audio decoded you will have a vector or array (if the audio is stereo) with the values of your audio, a set of values/samples varying in float point or short int, if you plot or have draw these values you will have the waveform of your music ...

Something like that just to illustrate:

inserir a descrição da imagem aqui

If you’ve come this far, you’ll be able to manipulate the waveform vector of your audio, a Pitch Shift is kind of considered mystical, there are some techniques to do that, one of them is stretch or compress your audio and then interpolate in the inverse fraction, by doing this you can change the tone of the audio without keeping the formants (Keeping the formants means keeping the same characteristic of the timbre, when the formants are not maintained, if the tone gets too high it will leave with a squirrel rsrs tone or if change to the bass it will get demon tone...)

That is if you want your sound to be twice as low(2x) vc should slow the sound twice and then interpolate the audio in its inverse factor or be interpolar (resample) by 0.5, most pq 0.5 ????? if you left twice as slow the inverse ratio would be 1/2=0.5

To make the tone twice as high, you will have to make your audio twice as fast 0.5 and then interpolate by 2 === 1/0.5 = 2

That’s the secret of play, but how I make the sound faster and slower??

when you want a sound to be faster, you will remove pieces/data from your vector, that is to say it will leave the audio fast, when you want to slow down your audio, you will put/repeating data in your vector... I was simplistic too, this process is complicated, you can’t keep taking and repeating data like that out of nowhere rsrs, if you do that your audio will start making noises, sounds, clicks, Pops and this is where the tricky part of the joke lives, Find the right places to cut your vector, find the points within your vector that have correlation to be able to cut or repeat, overlap (overlap) between these points to ensure a smooth junction.

Techniques in the field of time you will have to read scientific articles:

  • TDHS (Time Domain Harmonic Sacaling)
  • SOLA (Synchronous Overlap Add)
  • PSOLA (Synchronous Pitch Overlap Add)
  • WSOLA (Waveform Similarity and Overlap Add)

Another problem, these techniques will only work for monophonic audios, from the above techniques I consider the simplest TDHS of all I posted an explanation with a small pseudo code here, except the PSOLA technique all the others are will serve until the moment to leave an audio slower or faster, still will miss the part of the interpolation/ resample to be able to return the sound at the original speed with the tone changed...

Interpolation/resampling:

It has different types of interpolations, you can start with something simpler, a linear interpolation for example:

for (int i=0; i<tam*fator; ++i)
    {
        float a = i / fator;
        int b1 = floor(a);
        int b2 = ceil(a);
        float x = a - b1;
        out[i] = sinal[b1] * x + sinal[b2] * (1-x);
    }

But what if I just apply interpolation ? and don’t change the speed before ?

A: If you just apply interpolation you change the tone and speed at the same time, that is, if you let the sound fast it gets fast and high at the same time if you let the slow sound it gets slow bass at the same time (I don’t know your age, but it’s a similar effect when you take a vinyl record and turn it with your finger...)

OK these are the techniques used to do this in the time domain and with monophonic audio, for polyphonic audios, have nowhere to run you will have to go to the Frequency domain and use a technique called Phase vocoder or derived from it, the process is mathematically complex, I put an answer in Stackoverflow DSP with a code I made here...

The above Link code applies the Phase Vocoder technique in an audio, the process slows or faster audio, after that would just apply the above code interpolation to change the audio tone ...

I developed and replicated virtually all the algorithms techniques mentioned above, if you were curious take a look at some videos demonstrating the results ...

Pitch shift real-time with python

Pitch shift with time stretch and Freeze real-time with python

Prototype of Autotune keeping the formants

  • Gee! Apparently it’s not an easy thing to do hehehe. Thank you for the answer! Just one more question I wanted to ask: is there any way to apply these methods (change speed, apply interpolation...) with the JS audio API?

  • https://github.com/Collaboarator/PitchShifterJS/blob/master/Example.html, copy this html to your PC and test, not real time, an mp3 of approximately 4 min took almost 1 min to start playing after the Decode process, the code does all the process I told you about, is based on a phasevocoder that scales frequencies directly via Fourier

  • Blz, I’ll take a look. Thank you!

Browser other questions tagged

You are not signed in. Login or sign up in order to post.