2013-07-26 14 views
11

Ho avuto difficoltà con un bug di distorsione audio elusivo utilizzando webkitAudioContext in HTML5 su iOS 6. Può accadere in altre circostanze, ma l'unico modo che posso ottenere una repro al 100% è la prima volta che visita la mia pagina dopo aver spento il dispositivo. Sembra che se visiti una pagina con capacità audio prima di visitare questa, il problema non si verificherà.WebKit L'audio distorce su iOS 6 (iPhone 5) la prima volta dopo il power cycling

La distorsione avviene solo per l'audio generato da webkitAudioContext.decodeAudioData() e quindi riprodotto tramite webkitAudioContext.createBufferSource(). La riproduzione audio di webkitAudioContext.createMediaElementSource() sarà non distorsione.

Mi manca un passaggio di inizializzazione? Ecco il codice HTML e nella sua interezza che ho presentato ad Apple come un bug report (ma non ho ricevuto alcuna risposta):

<!DOCTYPE html> 
<html> 
    <head> 
     <script type="text/javascript"> 
     var buffer = null; 
     var context = null; 
     var voice = null; 

     function load_music(file) { 
      context = new webkitAudioContext(); 
      voice = context.createBufferSource(); 
      var request = new XMLHttpRequest(); 
      request.onload = function() { 
       context.decodeAudioData(request.response, function(result) { 
        buffer = result; 
        document.getElementById("start").value = "Start"; 
       }); 
      }; 
      var base = window.location.pathname; 
      base = base.substring(0, base.lastIndexOf("/") + 1); 
      request.open("GET", base + file, true); 
      request.responseType = "arraybuffer"; 
      request.send(null); 
     } 

     function start_music() { 
      if (!buffer) { 
       alert("Not ready yet"); 
       return; 
      } 
      voice.buffer = buffer; 
      voice.connect(context.destination); 
      voice.noteOn(0); 

      document.getElementById("compare").style.display = "block"; 
     } 
     </script>  
    </head> 

    <body onload="load_music('music.mp3')"> 
     <p>This is a simple demo page to reproduce a <strong>webkitAudio</strong> 
     problem occurring in Safari on iOS 6.1.4. This is a stripped down demo 
     of a phenomenon discovered in our HTML5 game under development, 
     using different assets.</p> 

     <p><u>Steps to reproduce:</u></p> 

     <ol> 
      <li>Power cycle <strong>iPhone 5 with iOS 6.1.4</strong>.</li> 
      <li>Launch Safari immediately, and visit this page.</li> 
      <li>Wait for &quot;Loading...&quot; below to change to 
       &quot;Start&quot;.</li> 
      <li>Tap &quot;Start&quot;.</li> 
     </ol> 

     <p><u>Issue:</u></p> 

     <p>Audio will be excessively distorted and play at wrong pitch. If 
     another audio-enabled web site is visited before this one, or this 
     site is reloaded, the audio will fix. The distortion only happens on 
     the first visit after cold boot. <strong>To reproduce the bug, it is 
     critical to power cycle before testing.</strong></p> 

     <p>This bug has not been observed on any other iOS version (e.g. does 
     not occur on iPad Mini or iPod 5 using iOS 6.1.3).</p> 

     <input id="start" type="button" value="Loading..." onmousedown="start_music()" /> 

     <span id="compare" style="display:none;"><p><a href="music.mp3">Direct link</a> to audio file, for 
     comparison.</p></span> 
    </body> 
</html> 

Nota: il testo del corpo suggerisce che questo si verifica solo su iOS 6.1.4, ma voglio dire per dire che il problema si verifica solo con il power cycling in questa situazione. Ho riscontrato il problema anche su iPad Mini alla versione 6.1.3, ma non sul ciclo di alimentazione.

Modifica: alcune cose che ho provato ... Il rinvio della creazione della sorgente del buffer non fa differenza. L'uso di transcoder diversi per generare il file .mp3 riprodotto non fa differenza. Riproduzione del silenzio "a perdere" poiché il primo suono non fa alcuna differenza poiché la distorsione continua per ogni decodifica del suono AudioData finché la pagina non viene ricaricata. Se le origini createMediaElementSource e createBufferSource sono miste nella stessa pagina, solo l'audio createBufferSource (utilizzando decodeAudioData) verrà distorto. Quando controllo request.response.byteLength nel caso di errore e nel caso di non fallimento, sono uguali, suggerendo che XMLHttpRequest non restituisca dati errati, anche se penserei che il danneggiamento dei dati danneggerebbe l'intestazione MP3 e renderizzerebbe il file comunque non riproducibile.

C'è una differenza osservabile tra la condizione di errore e la condizione di non fallimento. Il valore di sola lettura context.sampleRate sarà 48000 nello stato di errore e 44100 nello stato di non fallimento. (Eppure lo stato di errore suona più basso dello stato di non fallimento.) L'unica cosa che mi viene in mente è un hack in cui aggiorno la pagina tramite JavaScript se 48000 viene rilevato su un browser che dovrebbe segnalare 44100, ma questo è grave screening e non molto a prova di futuro, il che mi rende nervoso.

risposta

7

Ho trovato un bug correlato con video HTML5 e penso di aver scoperto la radice del problema.
Ho notato che se riproduci un video utilizzando un tag <video>, imposta il valore context.sampleRate su qualunque sia l'audio del video codificato. Sembra che iOS Safari abbia un sampleRate globale che usa per tutto. Per vedere questo, provare quanto segue:

// Play a video with audio encoded at 44100 Hz 
video.play(); 

// This will console log 44100 
var ctx = new webkitAudioContext(); 
console.log(ctx.sampleRate); 

// Play a video with audio encoded at 48000 Hz 
video2.play(); 

// This will console log 48000 
var ctx = new webkitAudioContext(); 
console.log(ctx.sampleRate); 

Questa frequenza di campionamento globale sembra persistere in tutta caricamento della pagina ed è condivisa tra le schede e le istanze del browser. Quindi, la riproduzione di un video su YouTube in un'altra scheda potrebbe interrompere tutto il tuo audio decodificato.

L'audio viene distorto quando viene decodificato a una frequenza di campionamento e riprodotto con un altro.

  1. Decodifica audio e memorizzare il buffer
  2. fare qualcosa per cambiare la frequenza di campionamento, come ad esempio la riproduzione di un file video o audio
  3. tampone Play (distorta)

Non lo so perché sta succedendo dopo una partenza a freddo. Se dovessi indovinare, è che Safari non inizializza questa frequenza di campionamento globale finché non provi ad usarla.

Il problema è ancora presente su iOS 7, quindi non credo che una correzione verrà presto. Siamo bloccati con gli hack nel frattempo, come verificare una variazione della frequenza di campionamento.

+2

E 'ancora un problema su IOS 8. –

+1

Così come 9.2.1 (la versione più recente come di questa scrittura) –

8

Ho avuto problemi simili, anche su iOS 9.2.

Anche senza tag <video>, la riproduzione è distorta quando si riproduce per la prima volta l'audio nella pagina dopo l'avvio a freddo. Dopo una ricarica, funziona bene.

L'iniziale AudioContext sembra di default a 48 kHz, che è dove si sta verificando la distorsione (anche con il nostro audio con frequenza di campionamento di 48 kHz). Quando la riproduzione funziona correttamente, lo AudioContext ha una frequenza di campionamento di 44,1 kHz.

Ho trovato una soluzione alternativa: è possibile ricreare lo AudioContext dopo aver riprodotto un suono iniziale. Il nuovo AudioContext sembra avere la frequenza di campionamento corretta. Per fare questo:

// inside the click/touch handler 
var playInitSound = function playInitSound() { 
    var source = context.createBufferSource(); 
    source.buffer = context.createBuffer(1, 1, 48000); 
    source.connect(context.destination); 
    if (source.start) { 
     source.start(0); 
    } else { 
     source.noteOn(0); 
    } 
}; 

playInit(); 
if (context.sampleRate === 48000) { 
    context = new AudioContext(); 
    playInit(); 
} 
+0

Funziona per me, grazie! Metti questo in un tocco iniziale Handler per sbloccare anche l'audio web di iOS. –

+0

Questo mi aiuta davvero! molte grazie – iownthegame

Problemi correlati