Audio a bassa latenza

L'audio a bassa latenza rende i giochi più realistici e reattivi.

Completa il seguente elenco di controllo per attivare l'audio a bassa latenza nel tuo gioco Android

  1. Usa l'oboe
  2. Richiedere la modalità prestazioni "bassa latenza"
  3. Richiedi modalità di condivisione "esclusiva"
  4. Utilizza 48000 Hz o il convertitore della frequenza di campionamento Oboe
  5. Imposta l'utilizzo su AAUDIO_USAGE_GAME
  6. Utilizzare i callback di dati
  7. Evitare di bloccare le operazioni nel callback
  8. Regola la dimensione del buffer su "doppio buffer"

1. Utilizzare l'API Oboe

L'API Oboe è un wrapper C++ che chiama AAudio su Android 8.1 (livello API 27) o versioni successive. Nelle versioni precedenti di Android, Oboe utilizza OpenSL ES.

Oboe è disponibile su GitHub o come un programma binario predefinito. Oboe ha anche un QuirksManager che corregge problemi su dispositivi specifici, rendendo la tua app compatibile con più dispositivi. Se non puoi utilizzare Oboe, usa direttamente AAudio.

2. Richiedi modalità a bassa latenza

Richiedi la modalità a bassa latenza con Oboe o AAudio. Altrimenti, otterrai un aumento del modalità di latenza per impostazione predefinita.

Oboe

builder.setPerformanceMode(oboe::PerformanceMode::LowLatency);

AAudio

AAudioStreamBuilder_setPerformanceMode(builder, AAUDIO_PERFORMANCE_MODE_LOW_LATENCY);

3. Richiedi modalità esclusiva

Puoi anche richiedere l'accesso esclusivo al buffer MMAP. La tua app potrebbe non ricevere esclusivo, ma se lo fa, la tua app scrive direttamente in un buffer viene letto dal DSP, che offre all'app la latenza più bassa possibile.

Oboe

builder.setSharingMode(oboe::SharingMode::Exclusive);

AAudio

AAudioStreamBuilder_setSharingMode(builder, AAUDIO_SHARING_MODE_EXCLUSIVE);

4. Evita la conversione della frequenza di campionamento

Utilizza la frequenza di campionamento naturale del dispositivo. Puoi farlo non specificando un e la frequenza di campionamento è quasi certamente a 48.000 Hz. Se specifichi un esempio predefinita, il framework audio invia i dati su un percorso diverso che può con una latenza molto maggiore.

Se devi utilizzare una frequenza di campionamento diversa, utilizza Oboe per eseguire la frequenza di campionamento conversione:

builder->setSampleRateConversionQuality(oboe::SampleRateConversionQuality::Medium);

5. Dichiara correttamente il tuo caso d'uso

L'indicazione del motivo per cui l'app riproduce l'audio è fondamentale affinché il sistema possa applicarla le impostazioni corrette per routing, volume e prestazioni. Ad esempio, i giochi indica l'utilizzo AAUDIO_USAGE_GAME per sfruttare appieno la latenza ottimizzazioni, in particolare se collegate ad auricolari Bluetooth.

Oboe

builder.setUsage(oboe::Usage::Game);

AAudio

AAudioStreamBuilder_setUsage(builder, AAUDIO_USAGE_GAME);

6. Utilizzare una funzione di callback

Utilizza un callback per lo stream di output. Se utilizzi il blocco delle scritture e sei attivo un dispositivo che non supporta la modalità MMAP AAudio, la latenza potrebbe essere molto in alto.

Oboe

builder.setDataCallback(&myCallbackObject);

AAudio

AAudioStreamBuilder_setDataCallback(builder, &my_callback_proc);

7. Evita di bloccare il callback

Quando utilizzi uno stream a bassa latenza, il tempo tra i callback può essere molto solo pochi millisecondi. È quindi molto importante non eseguire qualsiasi elemento nel callback che potrebbe bloccare per molto tempo. Se il callback è bloccato, l'audio del buffer presenta un underflow e glitch.

Evita di fare quanto segue in un callback:

  • Allocazione o liberazione di memoria
  • I/O su file o rete
  • In attesa di un mutex o di una serratura
  • Sonno
  • Calcoli intensivi della CPU una tantum

I callback dovrebbero fare i calcoli a un ritmo uniforme per una riproduzione fluida senza glitch.

8. Ottimizza la dimensione del buffer

Una volta che l'app apre lo stream audio, devi regolare la dimensione del buffer utilizzabile per una latenza ottimale. Oboe imposta automaticamente la dimensione del buffer su due raffica. Ma con AAudio, il valore predefinito è molto più alto. Utilizza il doppio buffering impostando la dimensione del buffer al doppio della dimensione della raffica. La dimensione della serie di foto a raffica è il numero massimo di callback dimensioni.

Audio:

int32_t frames = AAudioStream_getFramesPerBurst() * 2;
AAudioStream_setBufferSizeInFrames(stream, frames);

Se la dimensione del buffer è troppo piccola, potrebbero verificarsi degli errori causati dal inferiore. Puoi contare gli errori chiamandoli AAudioStream_getXRunCount(stream). Aumenta la dimensione del buffer in base alle esigenze.

Consulta le Documentazione su oboe GitHub per una spiegazione della terminologia relativa al buffer.

OpenSL ES

Se vengono supportate versioni di Android precedenti alla 8.1, devi utilizzare OpenSL ES. Se usi Oboe, puoi configurare la tua app per migliorare la latenza. Consulta Come ottenere una latenza ottimale nella documentazione di GitHub.

Risultati dell'elenco di controllo

La tabella seguente contiene Tester Oboe misurazioni della latenza di andata e ritorno (da input a output).

Configurazione Latenza (ms)
Segui tutti i consigli 20
Modalità prestazioni non bassa latenza 205
Non ESCLUSIVO (CONDIVISI) 26
44100 Hz (audio audio) 160
44100 Hz (SRC Oboe) 23
Mancato utilizzo di un callback di output (MMAP) 21
Mancato utilizzo di un callback di output (non MMAP) 62
Dimensione del buffer impostata al massimo 53