Changing Speed of Audio Using the Web Audio API Without Changing Pitch
Asked Answered
E

3

29

Is it possible to change the tempo of audio (in the form of loaded MP3 files) without changing the pitch using the Web Audio API?

I'm aware of the playbackRate property on the AudioBufferSourceNode, but that also changes pitch. I'm also aware of the playbackRate property for <audio> and <video> elements, but I need to use the Web Audio API.

I'm very new to the Web Audio API. Is there anything I can do?

Exemplary answered 7/7, 2015 at 16:57 Comment(4)
Web Audio doesn't support this out of the box. You'll need specialized software to change the tempo of a sound file.Multifid
It will be possible due to the low level access you get via AudioBuffer.getChannelData() but will need coding from scratch. Do you need to speed up, slow down or both?Eximious
@Eximious i want to do the both . can u explain how to go for thisMuscular
Did you solve it in the end?Urinal
L
19

There is a way to do this - its called granular synthesis (link points to a pd theory link, but the theory is universal). The idea of granular synthesis is that a sound is sampled at the original speed, but it is played at a different speed from each sample point, however with the advantage that the pitch is not altered.

These Github Web Audio Granular Synthesiser links may help you (the first one is better): 1. Web-Audio-Granular-synthesis 2. Another link on Github2

Failing any success with WebAudio, there is the alternative; bring the mp3 into Audacity and change the tempo that way, and then use the new file! ;)

Believe me, I understand your pain, I spent weeks in uni trying to do exactly the same thing with pd-extended. Came near to tearing my hair out. My professor introduced me to the concept of granular synthesis - saved the day!

Good luck!

Lucilla answered 13/5, 2016 at 22:51 Comment(9)
Based on your research, do you have any idea if "preserve pitch" is going to be added natively to the Web Audio API?Gahan
@BrianFitzGerald i don't think it has been raised as an issue with the developers of the WebAudioAPI, but as others have developed plugins for it, i see it as a possibility that they will integrate them. I don't know for sure!Lucilla
Thanks Rachel! I have raised it on the Chromium issue tracker just now. Not sure if that's the best place, but hopefully someone sees it: bugs.chromium.org/p/chromium/issues/detail?id=627111Gahan
@BrianFitzGerald brilliant, you may have paved the way for developers everywhere!!! :)Lucilla
Thank you, thank you. You're too kind. First, I would like to thank my parents for inspiring me to be my best, my fellow developers for always pushing the limits of technology, and finally the Chromium team (in advance) for adding this wonderful feature to the Web Audio API. You da real MVP.Gahan
@hahaha your oscar awaits!! ;)Lucilla
@BrianFitzGerald i raised it just now with w3c, they developed it initially. w3.org/Bugs/Public/show_bug.cgi?id=29728 add yourself to the cc list!Lucilla
CC Added! Thanks a lot for doing that Rachel. It would be an amazing feature to have.Gahan
Hi, changing AudioBufferSourceNode.playbackRate still doesn't seem to preserve pitch as of 2021. Do you know any way to preserve the pitch when changing playbackRate?Urinal
D
5

That's not natively (easily) supported by the current version of WebAudio, but it's possible using Tone.js:

let semitones = 3;
let source = new Tone.Player(AudioBuffer);
let shift = new Tone.PitchShift(semitones);
source.connect(shift);
shift.toMaster();
source.start();
Dunbar answered 18/8, 2018 at 4:58 Comment(5)
This will work to slow playback down, and to shift the pitch… but how do you figure the relation between the two? i.e.: which speed requires which pitch shift?Corwin
@FabienSnauwaert try shiftToSemitones = shift => -12*Math.log2(1/shift) and semitonesToShift = semitones => (2 ** (1/12)) ** semitonesDunbar
Hi Jacob, can you give some examples using playbackRate as an example? For example, when I change playbackRate to 1.5, how much pitchShift do I need? Thank youUrinal
@Jun711 You can use the functions in my previous comment to calculate the necessary pitch shift. For example, shiftToSemitones(1.5) returns just over 7 semitones (a perfect 5th). In other words, increasing the playbackRate by 1.5 will shift up by 7 semitones, so you'll need to shift down by 7 semitones to compensate. Here's a chart you can also refer to: moz.ac.at/sem/lehre/lib/cdp/cdpr5/html/TRNSCHRT.HTMDunbar
@Dunbar ok, I will try your suggestion tomorrow. I asked on Tone.js github and github.com/Tonejs/Tone.js/issues/951 and Yotam asked me to try GrainPlayer from Tone.js I tried it and it seems to have some echo compared to changing playbackRate using audio element codepen.io/juny711/pen/abwjaJE You can read more on the Github threadUrinal
T
1

There is now a property called playbackRate on the audio and video elements that do just this. I don't need modify the audio data itself, just play it back more slowly - so this is perfect for my scenario.

var myAudio = document.createElement('audio');
myAudio.setAttribute('src','audiofile.mp3');
myAudio.playbackRate = 0.5;

More Info:

https://developer.mozilla.org/en-US/docs/Web/Guide/Audio_and_video_delivery/WebAudio_playbackRate_explained

Live Example:

https://jsbin.com/UGIxoJis/1/edit?html,output

Teagan answered 3/2, 2022 at 15:43 Comment(1)
Note that playbackRate property on media elements had already been mentioned in the original post. This should not be a valid answer.Serosa

© 2022 - 2024 — McMap. All rights reserved.