La versione Android 4.1 ha introdotto modifiche al framework interno per un percorso di uscita audio a latenza inferiore . Sono state apportate modifiche minime all'API client pubblica o all'API HAL. Questo documento descrive il progetto iniziale, che ha continuato ad evolversi nel tempo. Avere una buona conoscenza di questo progetto dovrebbe aiutare gli OEM dei dispositivi e i fornitori di SoC a implementare correttamente il progetto sui loro dispositivi e chipset specifici. Questo articolo non è destinato agli sviluppatori di applicazioni.
Creazione traccia
Il client può facoltativamente impostare il bit AUDIO_OUTPUT_FLAG_FAST
nel parametro audio_output_flags_t
del costruttore AudioTrack C++ o AudioTrack::set()
. Attualmente gli unici client che lo fanno sono:
- Audio nativo Android basato su OpenSL ES o AAudio
- android.media.SoundPool
- android.media.ToneGenerator
L'implementazione AudioTrack C++ esamina la richiesta AUDIO_OUTPUT_FLAG_FAST
e facoltativamente può rifiutare la richiesta 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ò opzionalmente negare la richiesta 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 influenzano la decisione includono:
- Presenza di un thread del mixer veloce per questa uscita (vedi sotto)
- Tieni traccia della frequenza di campionamento
- Presenza di un thread client per eseguire gestori di callback per questa traccia
- Tieni traccia delle dimensioni del buffer
- Slot prioritari disponibili (vedi sotto)
Se la richiesta del cliente è stata accettata, si parla di "fast track". Altrimenti si chiama "traccia normale".
Fili del miscelatore
Nel momento in cui AudioFlinger crea un normale thread del mixer, decide se creare o meno anche un thread del mixer veloce. Sia il mixer normale che il mixer veloce non sono associati ad una traccia particolare, ma piuttosto ad un insieme di tracce. C'è sempre un normale thread del mixer. Il thread del mixer veloce, se esiste, è asservito al thread del mixer normale e agisce sotto il suo controllo.
Miscelatore veloce
Caratteristiche
Il thread del mixer veloce fornisce queste funzionalità:
- Mixaggio del sub-mix del mixer normale e fino a 7 tracce veloci client
- Attenuazione per traccia
Caratteristiche omesse:
- Conversione della frequenza di campionamento per traccia
- Effetti per traccia
- Effetti per mix
Periodo
Il mixer veloce viene eseguito periodicamente, con un periodo consigliato compreso tra due e tre millisecondi (ms) o un periodo leggermente superiore di cinque ms se necessario per la stabilità della pianificazione. Questo numero è stato scelto in modo tale che, tenendo conto dell'intera pipeline 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 anomalie a seconda della prevedibilità della pianificazione della CPU. Sono possibili valori più grandi, fino a 20 ms, ma comportano una latenza totale ridotta e quindi dovrebbero essere evitati.
Pianificazione
Il mixer veloce funziona con priorità SCHED_FIFO
elevata. Richiede pochissimo tempo di CPU, ma deve essere eseguito spesso e con un basso jitter di pianificazione. Il jitter esprime la variazione del tempo di ciclo: è la differenza tra il tempo di ciclo effettivo e il tempo di ciclo previsto. Correre troppo tardi comporterà problemi dovuti al sottocorsa. Correre troppo presto causerà problemi dovuti alla partenza da una pista veloce prima che la pista 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 si evitano i mutex. Vengono invece utilizzati algoritmi non bloccanti (noti anche come algoritmi senza blocco). Vedi Evitare l'inversione di priorità per ulteriori informazioni su questo argomento.
Relazione con altri componenti
Il mixer veloce ha poca interazione diretta con i clienti. In particolare, non vede le operazioni a livello di raccoglitore, ma accede al blocco di controllo della memoria condivisa del client.
Il mixer veloce riceve comandi dal mixer normale tramite una coda di stato.
Oltre a estrarre i dati della traccia, l'interazione con i client avviene tramite il normale mixer.
Il sink principale del mixer veloce è l'HAL audio.
Miscelatore normale
Caratteristiche
Tutte le funzionalità sono abilitate:
- Fino a 32 tracce
- Attenuazione per traccia
- Conversione della frequenza di campionamento per traccia
- Elaborazione degli effetti
Periodo
Il periodo viene calcolato come il primo multiplo integrale del periodo del mixer veloce che è >= 20 ms.
Pianificazione
Il mixer normale funziona con priorità SCHED_OTHER
elevata.
Blocco
Al mixer normale è consentito bloccarsi, e spesso lo fa in vari mutex così come in una pipe di blocco per scrivere il suo sub-mix.
Relazione con altri componenti
Il mixer normale interagisce ampiamente con il mondo esterno, inclusi i thread del raccoglitore, il gestore dei criteri audio, il thread del mixer veloce e le tracce client.
Il lavello del miscelatore normale è un tubo che ostruisce la traccia 0 del miscelatore veloce.
Bandiere
Il bit AUDIO_OUTPUT_FLAG_FAST
è un suggerimento. Non esiste alcuna garanzia che la richiesta venga soddisfatta.
AUDIO_OUTPUT_FLAG_FAST
è un concetto a livello di client. Non appare nel server.
TRACK_FAST
è un concetto client -> server.