Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Seamless looping not working #360

Closed
javismiles opened this issue Oct 10, 2015 · 22 comments
Closed

Seamless looping not working #360

javismiles opened this issue Oct 10, 2015 · 22 comments
Milestone

Comments

@javismiles
Copy link

Good day, i created a series of seamless loops, that play perfectly seamless in Adobe Audition but when on the web with your wonderful library and the browsers, a terrible gap appears, check here:

http://torchprinciple.com/looptest/test.html

and the code

var mysound = new Howl({
urls: ["atmosphere-loop-mono-1.mp3"],
volume: 1,
loop:1,
buffer: false,
onend: function() {
},
onplay: function() {},
onload: function() {
console.log ("loaded");
}

});
mysound.play();

how can i solve this? i need seamless loops, and im using your library which should be using web audio api which should work
thanks so much :)

@javismiles
Copy link
Author

in this article
http://www.flightarcade.com/learn/webaudio?WT.mc_id=13407-DEV-sitepoint-article31
the author says:
Fortunately, gapless audio playback with the Web Audio API is really straightforward. It's just a matter of setting a timestamp for the beginning and end of the looping portion of the audio (note that these values are relative to the audio source itself and not the AudioContext clock).
engineAudioSource.source.loopStart = 0.5;
engineAudioSource.source.loopEnd = 1.5;

i dont know if that's too overoptimistic from that writer :)

@javismiles
Copy link
Author

i have now used loopStart and loopEnd and that will reduce the gap but still a click remains, it doesnt solve the problem fully, i did manage in google chrome desktop with some specific loopStart and loopEnd values to make it seamless gapless, but same values wont work in firefox, Edge, or chrome for android , really so much for an amazing web audio api that cant even create seamless loops, unbelievable....... And thank you again for creating this wonderful howler.js, it is only thanks to people like you that we can experiment quickly; as for the issue with the loops... as an engineer myself, i am just speechless...

@javismiles
Copy link
Author

latest update, using source.loopStart and source.loopEnd i have improved a lot the gaps in loops,
how can use these 2 parameters loopStart and loopEnd in Howler.js? :) thank you :)

@goldfire goldfire added this to the 2.0 milestone Oct 13, 2015
@javismiles
Copy link
Author

Thank you for adding this to the 2.0 milestone, using loopStart and loopEnd i have now managed to create fantastic loops using the web audio api in raw state, hope to be able to access these parameters in howler.js soon, thank you :)

@goldfire
Copy link
Owner

You technically already have access to them with sprites. Even if you are just playing one sound, you can define a sprint for it and adjust the start and length, which then get used with loopStart and loopEnd internally.

@javismiles
Copy link
Author

thank you James, but in my web app i use lots of sounds, and i dont need
neither want to use sprites.... so having to create sprites for each sound
where i need to control loopStart/loopEnd sounds very inefficient.. ;)

Javier ideami
Ideami Studios
San Francisco / Barcelona
+1 408 634 9071
http://torchprinciple.com
http://ideami.com
http://posterini.com
http://incredivid.com
http://torchprinciple.com

On Thu, Oct 15, 2015 at 7:37 AM, James Simpson notifications@github.com
wrote:

You technically already have access to them with sprites. Even if you are
just playing one sound, you can define a sprint for it and adjust the start
and length, which then get used with loopStart and loopEnd internally.


Reply to this email directly or view it on GitHub
#360 (comment).

@goldfire
Copy link
Owner

You don't change anything about your sound files for it to work.

@javismiles
Copy link
Author

interesting, thank you James, let me see if i understand, do you refer to
something like this:

var sound = new Howl({
src: ['whatever.mp3'],
loop:1,
sprite: {
main: [100, 1000]
}
});

sound.play('main');

is that how i would control loopStart and loopEnd?
so those 100 and 1000 would be the values of loopStart and loopEnd?

Javier ideami
Ideami Studios
San Francisco / Barcelona
+1 408 634 9071
http://torchprinciple.com
http://ideami.com
http://posterini.com
http://incredivid.com
http://torchprinciple.com

On Thu, Oct 15, 2015 at 7:46 AM, James Simpson notifications@github.com
wrote:

You don't change anything about your sound files for it to work.


Reply to this email directly or view it on GitHub
#360 (comment).

@goldfire
Copy link
Owner

That is pretty close to right, but you'd want to define the sprite as [100, 1000, true] so that it is looping. Also, the way it is defined is [start, length, loop]. I'm going to reopen this for now so I can keep thinking about this one for the 2.0 release.

@goldfire goldfire reopened this Oct 15, 2015
@javismiles
Copy link
Author

very cool, thanks a lot, i will make a test, so i will:

src: ['whatever.mp3'],
loop:1,
sprite: {
main: [100, 1000, true]
}

will test it right now

Javier ideami
Ideami Studios
San Francisco / Barcelona
+1 408 634 9071
http://torchprinciple.com
http://ideami.com
http://posterini.com
http://incredivid.com
http://torchprinciple.com

On Thu, Oct 15, 2015 at 7:55 AM, James Simpson notifications@github.com
wrote:

That is pretty close to right, but you'd want to define the sprite as [100,
1000, true] so that it is looping. Also, the way it is defined is [start,
length, loop]. I'm going to reopen this for now so I can keep thinking
about this one for the 2.0 release.


Reply to this email directly or view it on GitHub
#360 (comment).

@javismiles
Copy link
Author

tested and it works to perfection ;)
i have a loop of 12 seconds, before using this there was still a clear gap,
after using the sprite thing with limits of 0 and 12000 (12 seconds loop) ,
the gap has disappeared and plays perfectly, so your suggestion does work,
thank you ;)

Javier ideami
Ideami Studios
San Francisco / Barcelona
+1 408 634 9071
http://torchprinciple.com
http://ideami.com
http://posterini.com
http://incredivid.com
http://torchprinciple.com

On Thu, Oct 15, 2015 at 7:59 AM, Javier Ideami ideami@gmail.com wrote:

very cool, thanks a lot, i will make a test, so i will:

src: ['whatever.mp3'],
loop:1,
sprite: {
main: [100, 1000, true]
}

will test it right now

Javier ideami
Ideami Studios
San Francisco / Barcelona
+1 408 634 9071
http://torchprinciple.com
http://ideami.com
http://posterini.com
http://incredivid.com
http://torchprinciple.com

On Thu, Oct 15, 2015 at 7:55 AM, James Simpson notifications@github.com
wrote:

That is pretty close to right, but you'd want to define the sprite as [100,
1000, true] so that it is looping. Also, the way it is defined is [start,
length, loop]. I'm going to reopen this for now so I can keep thinking
about this one for the 2.0 release.


Reply to this email directly or view it on GitHub
#360 (comment)
.

@peteoa12
Copy link

peteoa12 commented Aug 26, 2016

Hey guys!

I made this for a project I'm working on. I did everything you mentioned above. Would you mind taking a look and seeing if you see anything wrong? I am still getting a massive break in my loop. However, it is intermittent. It loops fine and then it doesn't. Not sure why. Thanks for the help!

// //<><><><><><>ALL SOUNDS IN THEIR BASIC FORM<><><><><><><><><><>//

// KICK
var kick = new Howl({
src: ['assets/audio/kick-mm.mp3'],
html5:true,
preload:true,
loop:1,
sprite:{
kick:[0,10000,true]
}
});
kick.play("kick");

// SNARE
var snare = new Howl({
src: ['assets/audio/snare-mm.mp3'],

html5:true,
preload:true,
loop:1,
    sprite:{
        snare:[0,10000,true]
    }

});
snare.play("snare");

// HATS
var hats = new Howl({
src: ['assets/audio/hats-mm.mp3'],
html5:true,
preload:true,
volume:0.4,
loop:1,
sprite:{
hats:[0,10000,true]
}
});
hats.play("hats");

// PERCUSSION
var percussion = new Howl({
src: ['assets/audio/percussion-mm.mp3'],
html5:true,
preload:true,
loop:1,

    sprite:{
        percussion:[0,10000,true]
    }

});
percussion.play("percussion");

// ARPEGIATOR
var arp = new Howl({
src: ['assets/audio/arp-mm.mp3'],
html5:true,
preload:true,
volume:0.3,
loop:1,
sprite:{
arp:[0,10000,true]
}
});
arp.play("arp");

// BASS
var bass = new Howl({
src: ['assets/audio/bass-mm.mp3'],
html5:true,
preload:true,
loop:1,
sprite:{
bass:[0,10000,true]
}
});
bass.play("bass");

// //<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>//

@huwllewellyn
Copy link

This was my solution

let gasLooper;
let gasSound = new Howl({
    preload:true
  , src: require('./assets/audio/Gas-loop.mp3')
  , autoplay: true
  , volume: 0.5
  , onplay: ()=>{
    gasLooper = setTimeout(()=>{
      gasSound.play();
    },450);
  }
  , onstop: ()=>{
    clearTimeout(gasLooper);
  }
});

@pedrocatre
Copy link

using sprites for looping works great. Thank you for the suggestion @goldfire!

@samends
Copy link

samends commented Jan 11, 2019

Wanted to offer a further iteration for those who need to loop when using sprites:

   sprites = {
      "bleep": [0, 1592],
      "boop": [0, 1509]
    }
    let looper = (type: AudioType, iterations: number = 1) => {
      sound.play(type);
      setTimeout(() => {
        sound.stop();
      }, (sprites[type][1] * iterations))
    };

@sakopov
Copy link

sakopov commented Apr 17, 2020

This still does not work in any browser with any file format in either html5 or web audio mode.

@themoonrat
Copy link
Contributor

I would disagree. Looping works fine here in m4a and ogg using WebAudio

@sakopov
Copy link

sakopov commented Apr 17, 2020

That's a big nope. Tried all of the above suggestions. The only thing that appears to work with any kind of success is @huwllewellyn's suggestion. Out of the box, Howler (v2.1.3) plays the loop (ogg) with a half second delay. The behavior is the same across latest versions of Firefox, Chrome and Edge.

@stephanbogner
Copy link

stephanbogner commented May 28, 2021

I switched from mp3 to webm and looping now works perfectly 🎉

This article helped me https://www.kevssite.com/seamless-audio-looping/:

Apparently there is a bug (or maybe its a feature!) in the mp3 spec that adds a few ms of silence at the start of the track. If you load a track into an editor like audacity you can see the gap.

I verified that claim for my files:

Screenshot 2021-05-28 at 10 24 53

I can recommend ffmpeg to convert sound files to webm (or any other file type for that matter):

I ended up using this to convert to webm and mp3 (as a fallback):
for i in *.wav; do /path/to/ffmpeg -i "$i" -b:a 320k "${i%.*}.webm" -b:a 320k "${i%.*}.mp3"; done
(Thanks to these links: batch converting and specifying bitrate)

Note: You can also remove the silence from mp3, which actually also made it loop seamlessly for me:

ffmpeg -i "INPUT.mp3" -af silenceremove=start_periods=1:stop_periods=1:detection=peak "OUTPUT.mp3" (via StackOverflow)

@wmonecke
Copy link

wmonecke commented Nov 2, 2021

@stephanbogner Hi Stephan!

I have been struggling for a while to get the looping to work.
I am using .webm files but I still hear the silence gap. Did you do anything else besides this?

@wmonecke
Copy link

wmonecke commented Nov 2, 2021

@sakopov Did you find a solution?

@stephanbogner
Copy link

@stephanbogner Hi Stephan!

I have been struggling for a while to get the looping to work. I am using .webm files but I still hear the silence gap. Did you do anything else besides this?

Hey @wmonecke,
in my case that's all I did to make it work. Two things that come to my mind to be considered:

  • I only needed it to work Chrome and thus only checked that browser (+ I am on Mac, but as far as I remember the seamless audio also worked on Windows)
  • Where did you get the .webm from? Maybe it was converted from .mp3 which would mean the silence in the beginning would also be present in the .webm-file
    • You could convert the .webm file to raw (.wav) and open it in Audacity to check whether there is silence in the file itself (as afaik Audacity can't open .webm)

Hope that helps! Let me know if it does ✌️

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

10 participants