2016-03-22 4 views
8

Buduję grę javascript i chcę utworzyć podkład muzyczny oparty na fragmentach plików dźwiękowych. Krótkie pliki mp3, aby odtwarzać je jako jeden ciągły utwór. Próbowałem powiązać "zakończoną" procedurę obsługi zdarzenia w pliku audio, jednak powoduje to opóźnienie między fragmentami audio.Jak usunąć pauzę między ścieżkami audio w JavaScript

Aby rozwiązać ten problem, stworzyłem niełatwe rozwiązanie, które wciąż nie działa, zmieniając dźwięk na 1 sekundę przed zakończeniem.

Ebuc.manageAudio = function(){ 
    var listener = function (event) { 
     if (this.currentTime > (this.duration - 1) && Ebuc.bgnext) { 
      Ebuc.manageAudio(); 
      console.log("aduio"); 
      Ebuc.bgnext = false; 
     } 
     if(this.currentTime < 2){ 
      Ebuc.bgnext = true; 
      console.log("reset"); 
     } 
     console.log(event); 
     console.log("listener active") 

    }; 
    var color = Level.current.color; 
    if(Ebuc.bgsong == null) { 
     Ebuc.bgsong = new Audio('assets/sound/' + Resources.audioSetList[color].getcurrentsong()); 
     Ebuc.bgsong.addEventListener('timeupdate', listener, true); 

    } 
    else{ 
     Ebuc.bgsong = new Audio('assets/sound/' + Resources.audioSetList[color].getcurrentsong()); 
    } 

    Ebuc.bgsong.play(); 
    Resources.audioSetList[color].next(); 

}; 

Ta próbka działa raz, gdy nadejdzie czas przełączenia fragmentu 2 na fragment 3, zatrzymanie pętli. Rejestrowanie konsoli detektora zdarzeń daje 4 razy dziennik przed zatrzymaniem.

Pytanie 1: Dlaczego ten eventlistener nagle znika? Q2: Czy istnieje niezatwierdzone rozwiązanie do łączenia tych fragmentów audio?

Dziękuję z góry.

Odpowiedz

7

Będziesz miał więcej niż tylko pauzowanie problemów, próbując szybko przełączać się między dwoma krótkimi klipami audio, prawdopodobnie będziesz chciał również szybko przechodzić między dwoma ścieżkami audio, aby zapobiec poppingowi, artefaktom itp.

Oto przykład crossfadingu przy użyciu modułu obsługi z howler's github issues. Prawdopodobnie możesz użyć tego przykładu i zachować kolejkę załadowanych instancji do przejścia. Mam nadzieję że to pomogło.

//you'll probably want this crossfade duration to be shorter. 
var crossfadeDuration = 5000, 
    volume   = 0.7; 

var instance1, instance2, soundDuration; 

// Singleton helper to build similar instances 
var createHowlerInstance = function (urls, onload) { 
    return new Howl({ 
    urls: urls, 
    loop: false, 
    volume: 0, 
    onload: onload 
    }); 
}; 

// Create "slave" instance. This instance is meant 
// to be played after the first one is done. 
instance2 = createHowlerInstance(['file2.mp3']); 

// Create "master" instance. The onload function passed to 
// the singleton creator will coordinate the crossfaded loop 
instance1 = createHowlerInstance(['file1.mp3'], function(){ 

    // Get the sound duration in ms from the Howler engine 
    soundDuration = Math.floor(instance1._duration * 1000); 

    (function crossfadedLoop(enteringInstance, leavingInstance){ 

    // Fade in entering instance 
    enteringInstance.pos(0).play().fade(0, volume, crossfadeDuration); 

    // Wait for the audio end to fade out entering instance 
    // white fading in leaving instance 
    setTimeout(function(){ 

     enteringInstance.fade(volume, 0, crossfadeDuration); 
     crossfadedLoop(leavingInstance, enteringInstance); 

    }, soundDuration - crossfadeDuration); 

    })(instance1, instance2); 

}); 
+0

Dziękuję za odpowiedź, chociaż to nie jest odpowiedź na pytanie. Problem polega na opóźnieniach w detektorach zdarzeń, po prostu zanikają, a pliki biją na cel tej modularnej pętli dźwiękowej. –

+1

To nie jest "po prostu blaknięcie i zejście", nazywa się to przenikaniem i to tak, jak płynnie łączysz dwa fragmenty audio, które nie są częścią ciągłego przebiegu. W twoim przypadku byłaby bardzo, bardzo krótka i płynnie przechodziłaby między plikami audio bez opóźnień, których obecnie doświadczasz. Przez te kilka ms oba pliki były odtwarzane w tym samym czasie.To może nie odpowiedzieć na twoje pierwsze pytanie, ale jest to zdecydowanie nie-hackowy sposób osiągnięcia tego, o co prosisz. 'setTimeout (function() {...}, soundDuration - crossfadeDuration)' co rozwiązuje problem opóźnienia. – pantalohnes

+0

Tak więc podczas gdy plik file1 znika, plik2 zanika. – pantalohnes

3

Wykorzystując ideę ustawienie limitu czasu na odpowiedź z pantalohnes Stworzyłem poniższy kod, żeby rozwiązać tę lukę:

Ebuc.manageAudio = function(){ 
     var color = Level.current.color; 
     Ebuc.bgsong = new Audio('assets/sound/' + Resources.audioSetList[color].getcurrentsong()); 
     Ebuc.bgsong.addEventListener("loadedmetadata",function(){ 
      setTimeout(Ebuc.manageAudio, (Ebuc.bgsong.duration * 1000) - 50); 
      Ebuc.bgsong.play(); 
      console.log(Ebuc.bgsong.duration); 
      Resources.audioSetList[color].next(); 
     }); 
    }; 

50-ms czas oczekiwania wypełnia lukę pomiędzy sekwencjonowane plików dokładnie .

1

Odpowiadając na pytanie (choć widzę, że znalazł inne rozwiązanie), myślę, że znalazłem swój błąd:

Po raz drugi swój wejść Ebuc.manageAudio(), Ebuc.bgsong jest już ustawiony i po prostu stworzyć nowy Audio Ebuc.bgsong = new Audio(...) bez dołączania do niego odbiornika, więc nie będziesz otrzymywać powiadomień o żadnych zdarzeniach "timeupdate" emitowanych podczas odtwarzania drugiego pliku audio.

Powinieneś również usunąć słuchacza z poprzedniego odtwarzanego dźwięku.

Tak więc, jeśli wszystko inne jest w porządku, myślę, że to powinno go naprawić:

Ebuc.manageAudio = function(){ 
    var listener = function (event) { 
     if (this.currentTime > (this.duration - 1) && Ebuc.bgnext) { 
      Ebuc.manageAudio(); 
      console.log("aduio"); 
      Ebuc.bgnext = false; 
     } 
     if(this.currentTime < 2){ 
      Ebuc.bgnext = true; 
      console.log("reset"); 
     } 
     console.log(event); 
     console.log("listener active") 

    }; 
    var color = Level.current.color; 
    if(Ebuc.bgsong != null) { 
     Ebuc.bgsong.removeEventListener('timeupdate', listener, true); 
    } 
    Ebuc.bgsong = new Audio('assets/sound/' + Resources.audioSetList[color].getcurrentsong()); 
    Ebuc.bgsong.addEventListener('timeupdate', listener, true); 

    Ebuc.bgsong.play(); 
    Resources.audioSetList[color].next(); 

}; 

Co więcej, myślę, że jeśli prawidłowo usunąć słuchacza z poprzedniej gry dźwiękiem, nie trzeba będzie że bgnext siekać w ogóle:

var listener = function (event) { 
    if (this.currentTime > (this.duration - 1)) { 
     Ebuc.manageAudio(); 
     console.log("aduio"); 
    } 
    console.log(event); 
    console.log("listener active") 
}; 

Ebuc.manageAudio = function() { 
    var color = Level.current.color; 
    if (Ebuc.bgsong != null) { 
     Ebuc.bgsong.removeEventListener('timeupdate', listener, true); 
    } 
    Ebuc.bgsong = new Audio('assets/sound/' + Resources.audioSetList[color].getcurrentsong()); 
    Ebuc.bgsong.addEventListener('timeupdate', listener, true); 

    Ebuc.bgsong.play(); 
    Resources.audioSetList[color].next(); 

}; 

Daj mi znać, jeśli to działało :)