I fornitori possono implementare due funzionalità chiave per ridurre la latenza audio:
- FAST Mixer in AudioFlinger:introdotta in Android 4.1, questa funzionalità supporta le app che utilizzano Java AudioTrack e AAudio. Il mixer FAST comporta modifiche minime all'API client pubblica o all'API HAL.
- AAudio MMAP:introdotta in Android 8.1, questa funzionalità consente alle app native di ottenere una latenza ancora più bassa tramite AAudio. Per saperne di più, consulta AAudio e MMAP.
Questa pagina descrive la progettazione iniziale della latenza audio, che ha continuato a evolversi nel tempo. Una solida comprensione di questo design è fondamentale per gli OEM di dispositivi e i fornitori di SoC per garantire la corretta implementazione sui loro dispositivi e chipset specifici. Questa pagina non è destinata agli sviluppatori di app.
Creazione di tracce
Il client può impostare facoltativamente il bit AUDIO_OUTPUT_FLAG_FAST
nel parametro
audio_output_flags_t
del costruttore C++ AudioTrack o
AudioTrack::set()
. Al momento, gli unici clienti che lo fanno sono:
- Audio nativo di Android basato su OpenSL ES o AAudio
android.media.SoundPool
android.media.ToneGenerator
L'implementazione C++ di AudioTrack esamina la AUDIO_OUTPUT_FLAG_FAST
richiesta e può facoltativamente rifiutarla a livello di client. Se
decide di inoltrare la richiesta, lo fa utilizzando il bit TRACK_FAST
del parametro track_flags_t
del metodo factory IAudioTrack
IAudioFlinger::createTrack()
.
Il server audio AudioFlinger esamina la richiesta TRACK_FAST
e può
facoltativamente rifiutarla a livello di server. Informa il client
se la richiesta è stata accettata o meno, tramite il bit CBLK_FAST
del
blocco di controllo della memoria condivisa.
I fattori che influiscono sulla decisione includono:
- Presenza di un thread di mixer veloce per questo output (vedi sotto)
- Frequenza di campionamento della traccia
- Presenza di un thread client per eseguire i gestori di callback per questa traccia
- Dimensione del buffer di traccia
- Slot disponibili per la procedura rapida (vedi sotto)
Se la richiesta del cliente è stata accettata, si parla di procedura rapida. In caso contrario, si parla di traccia normale.
Thread del mixer
Quando AudioFlinger crea un normale thread del mixer, decide se creare o meno anche un thread del mixer veloce. Il mixer normale e quello veloce non sono associati a una traccia specifica, ma a un insieme di tracce. Esiste sempre un thread di mixer normale. Il thread del mixer rapido, se esiste, è subordinato al thread del mixer normale e agisce sotto il suo controllo.
Fast mixer
Funzionalità
Il filo del mixer rapido offre le seguenti funzionalità:
- Mixaggio del submix del mixer normale e di un massimo di sette tracce veloci del client
- Attenuazione per traccia
Funzionalità omesse:
- Conversione della frequenza di campionamento per traccia
- Effetti per traccia
- Per effetti di mixaggio
Punto
Il mixer veloce viene eseguito periodicamente, con un periodo consigliato di 2-3 millisecondi o un periodo leggermente superiore di 5 ms, se necessario per la stabilità della pianificazione. Questo numero è stato scelto in modo che, tenendo conto della pipeline completa del buffer, la latenza totale sia dell'ordine di 10 ms. Sono possibili valori più piccoli, ma potrebbero comportare un aumento del consumo energetico e la possibilità di problemi a seconda della prevedibilità della pianificazione della CPU. Sono possibili valori più grandi, fino a 20 ms, ma comportano una latenza totale ridotta e pertanto devono essere evitati.
Pianificazione
Il mixer veloce viene eseguito con priorità SCHED_FIFO
elevata. Richiede pochissimo tempo CPU, ma deve essere eseguito spesso e con un basso jitter di pianificazione.
Jitter
esprime la variazione del tempo di ciclo: è la differenza tra il
tempo di ciclo effettivo e il tempo di ciclo previsto.
Se il programma viene eseguito troppo tardi, si verificano problemi a causa dell'underrun. L'esecuzione
troppo presto comporta problemi dovuti al recupero da una traccia rapida
prima che la traccia abbia fornito i dati.
Blocco
Idealmente, il thread del mixer veloce non si blocca mai, tranne che in HAL
write()
. Altri casi di blocco all'interno del mixer veloce sono
considerati bug. In particolare, vengono evitati i mutex.
Vengono invece utilizzati algoritmi non bloccanti (noti anche come algoritmi senza blocchi).
Per saperne di più su questo argomento, consulta la sezione Evitare l'inversione di priorità.
Relazione con altri componenti
Il mixer veloce ha poca interazione diretta con i clienti. In particolare, non vede le operazioni a livello di binder, ma accede al blocco di controllo della memoria condivisa del client.
Il mixer rapido riceve i comandi dal mixer normale tramite una coda di stato.
A parte l'estrazione dei dati delle tracce, l'interazione con i client avviene tramite il mixer normale.
Il sink principale del mixer rapido è l'HAL audio.
Mixer normale
Funzionalità
Tutte le funzionalità sono attive:
- Fino a 32 tracce
- Attenuazione per traccia
- Conversione della frequenza di campionamento per traccia
- Elaborazione degli effetti
Punto
Il periodo viene calcolato in modo che sia il primo multiplo intero del periodo del mixer veloce che sia >= 20 ms.
Pianificazione
Il mixer normale viene eseguito con priorità SCHED_OTHER
elevata.
Blocco
Il mixer normale può bloccare e spesso lo fa in vari mutex e in una pipe di blocco per scrivere il sub-mix.
Relazione con altri componenti
Il mixer normale interagisce ampiamente con il mondo esterno, inclusi i thread del binder, Audio Policy Manager, il thread del mixer rapido e le tracce client.
Il sink del mixer normale è un tubo di blocco per la traccia 0 del mixer veloce.
Bandiere
Il bit AUDIO_OUTPUT_FLAG_FAST
è un suggerimento. Non è garantito che la
richiesta verrà soddisfatta.
AUDIO_OUTPUT_FLAG_FAST
è un concetto a livello di cliente. Non viene visualizzato
nel server.
TRACK_FAST
è un concetto client-server.