Rubriques audio et vidéo Android (2) Utilisez AudioRecord et l'API AudioTrack pour collecter et lire des données audio PCM sur la plate-forme Android, et réaliser la lecture et l'écriture de fichiers audio wav

1. Utilisation de base d'AudioTrack

La classe AudioTrack peut terminer la tâche de sortie de données audio sur la plate-forme Android. AudioTrack a deux modes de chargement de données (MODE_STREAM et MODE_STATIC), correspondant au mode de chargement des données et au type de flux audio, correspondant à deux scénarios d'utilisation complètement différents.

  • MODE_STREAM: Dans ce mode, les données audio sont écrites sur AudioTrack par écrit encore et encore. Ceci est généralement similaire à l'écriture de données dans un fichier via l'appel système d'écriture, mais cette façon de travailler nécessite de copier les données du tampon fourni par l'utilisateur vers le tampon à l'intérieur de l'AudioTrack à chaque fois, ce qui introduira un délai dans une certaine mesure. . Pour résoudre ce problème, AudioTrack a introduit le deuxième mode.
  • MODE_STATIC: Dans ce mode, il vous suffit de transférer toutes les données vers la mémoire tampon interne d'AudioTrack via un appel d'écriture avant de jouer, et vous n'avez pas besoin de transférer les données dans la suite. Ce mode convient aux fichiers avec une faible empreinte mémoire et des exigences de latence élevées telles que les sonneries. Mais cela présente également un inconvénient, c'est-à-dire que vous ne pouvez pas écrire trop de données à la fois, sinon le système ne peut pas allouer suffisamment de mémoire pour stocker toutes les données.

1.1 Mode MODE_STATIC

La façon de sortir l'audio en mode MODE_STATIC est la suivante ( Remarque: si vous utilisez le mode STATIC, vous devez d'abord appeler write pour écrire des données, puis appeler play. ):

Copier le code

public class AudioTrackPlayerDemoActivity étend les implémentations d'activité 
        OnClickListener { 

    private static final String TAG = "AudioTrackPlayerDemoActivity"; 
    bouton Button privé; 
    octet privé [] audioData; 
    AudioTrack privé audioTrack; 

    @Override 
    public void onCreate (Bundle savedInstanceState) { 
        super.onCreate (savedInstanceState); 
        super.setContentView (R.layout.main); 
        this.button = (Bouton) super.findViewById (R.id.play); 
        this.button.setOnClickListener (this); 
        this.button.setEnabled (false); 
        new AsyncTask <Void, Void, Void> () {  
            @Override
            protected Void doInBackground (Void ... params) {
                essayez { 
                    InputStream in = getResources (). openRawResource (R.raw.ding); 
                    essayez { 
                        ByteArrayOutputStream out = new ByteArrayOutputStream ( 
                                264848); 
                        pour (int b; (b = in.read ())! = -1;) { 
                            out.write (b); 
                        } 
                        Log.d (TAG, "Got the data"); 
                        audioData = out.toByteArray (); 
                    } enfin { 
                        in.close ();  
                    Log.wtf (TAG, "Failed to read", e);
                    }
                } catch (IOException e) { 
                } 
                return null; 
            } 

            @Override 
            protected void onPostExecute (Void v) { 
                Log.d (TAG, "Créer une trace ..."); 
                button.setEnabled (true); 
                Log.d (TAG, "Bouton activé"); 
            } 
        } .execute (); 
    } 

    public void onClick (vue vue) { 
        this.button.setEnabled (false); 
        this.releaseAudioTrack (); 
        this.audioTrack = nouveau AudioTrack (AudioManager.STREAM_MUSIC, 44100, 
                AudioFormat.CHANNEL_OUT_STEREO, AudioFormat.ENCODING_PCM_16BIT,
                audioData.length, AudioTrack.MODE_STATIC); 
        Log.d (TAG, "Ecrire des données audio ...");
        this.audioTrack.write (audioData, 0, audioData.length); 
        Log.d (TAG, "Démarrage de la lecture"); 
        audioTrack.play (); 
        Log.d (TAG, "Lecture"); 
        this.button.setEnabled (true); 
    } 

    private void releaseAudioTrack () { 
        if (this.audioTrack! = null) { 
            Log.d (TAG, "Stopping"); 
            audioTrack.stop (); 
            Log.d (TAG, "Libération"); 
            audioTrack.release (); 
            Log.d (TAG, "Annulation"); 
        } 
    } 

    public void onPause () { 
        super.onPause (); 
        this.releaseAudioTrack (); 
    } 
}

Copier le code

1.2 Mode MODE_STREAM

La façon de sortir l'audio en mode MODE_STREAM est la suivante:

Copier le code

byte [] tempBuffer = nouvel octet [bufferSize]; 
int readCount = 0; 
while (dis.available ()> 0) { 
    readCount = dis.read (tempBuffer); 
    if (readCount == AudioTrack.ERROR_INVALID_OPERATION || readCount == AudioTrack.ERROR_BAD_VALUE) { 
        continue; 
    } 
    if (readCount! = 0 && readCount! = -1) { 
        audioTrack.play (); 
        audioTrack.write (tempBuffer, 0, readCount); 
    } 

Copier le code

Deuxièmement, AudioTrack détaillé

 2.1 Types de flux audio

Dans le constructeur AudioTrack, le paramètre AudioManager.STREAM_MUSIC sera exposé. Sa signification est liée à la gestion et à la classification des flux audio par le système Android.

Android divise le son du système en plusieurs types de flux, les suivants en sont quelques-uns les plus courants:

· STREAM_ALARM: son d'avertissement

· STREAM_MUSIC: sons de musique, tels que la musique, etc.

· STREAM_RING: sonnerie

· STREAM_SYSTEM: sons du système, tels que l'invite de batterie faible, le son de l'écran de verrouillage, etc.

· STREAM_VOCIE_CALL: son d'appel

Remarque: les types de divisions ci-dessus n'ont rien à voir avec les données audio elles-mêmes. Par exemple, les deux types MUSIC et RING peuvent être une certaine chanson MP3. De plus, il n'y a pas de norme fixe pour la sélection du type de flux audio. Par exemple, la sonnerie dans l'aperçu de la sonnerie peut être réglée sur le type MUSIQUE. La division des types de flux audio est liée à la stratégie de gestion audio du système audio.

 

2.2 Allocation de tampon et concept de trame

Lors du calcul de la taille de l'allocation de tampon, une méthode que nous utilisons souvent est: getMinBufferSize. Cette fonction détermine la quantité de tampon de données allouée par la couche application.

AudioTrack.getMinBufferSize (8000, // 8K points d'échantillonnage par seconde                               
        AudioFormat.CHANNEL_CONFIGURATION_STEREO, // AudioFormat double                   
        canal.ENCODING_PCM_16BIT);

À partir d'AudioTrack.getMinBufferSize pour tracer le code, vous pouvez constater qu'il existe un concept très important dans le code sous-jacent: Frame. Frame est une unité utilisée pour décrire la quantité de données. Une unité de Frame est égale au nombre d'octets d'un point d'échantillonnage × le nombre de canaux (par exemple, PCM16, une trame de deux canaux est égale à 2 × 2 = 4 octets). Un point d'échantillonnage n'est que pour un canal, mais en fait il peut y avoir un ou plusieurs canaux. Puisqu'une unité indépendante ne peut pas être utilisée pour représenter la quantité de données échantillonnées en même temps pour tous les canaux, le concept de trame est introduit. La taille de la trame est le nombre d'octets d'un point d'échantillonnage × le nombre de canaux. De plus, dans le pilote actuel de la carte son, sa mémoire tampon interne est également allouée et gérée en utilisant Frame comme unité.

Voici la méthode qui remonte à la couche native:

Copier le code

// minBufCount représente le nombre minimum de tampons, il utilise Frame comme unité 
   uint32_t minBufCount = afLatency / ((1000 * afFrameCount) / afSamplingRate); 
    if (minBufCount <2) minBufCount = 2; // Au moins deux tampons sont requis 
 
   / / Calculer le nombre minimum d'images 
   uint32_tminFrameCount =                
         (afFrameCount * sampleRateInHertz * minBufCount) / afSamplingRate; 
  // Ce qui suit calcule la taille minimale de la mémoire tampon en fonction du plus petit FrameCount    
   intminBuffSize = minFrameCount // La méthode de calcul est entièrement conforme à notre introduction précédente à Frame 
           * (audioFormat == javaAudioTrackFields .PCM16? 2: 1) 
           * nbChannels; 
 
    returnminBuffSize;

Copier le code

getMinBufSize considérera de manière exhaustive la situation matérielle (par exemple si la fréquence d'échantillonnage est prise en charge, le retard du matériel lui-même, etc.) pour arriver à une taille de tampon minimale. En général, la taille de la mémoire tampon que nous allouons sera un multiple entier de celle-ci.

2.3 Processus de construction d'AudioTrack

Chaque flux audio correspond à une instance de la classe AudioTrack. Chaque AudioTrack sera enregistré dans AudioFlinger lors de sa création, et AudioFlinger mélangera tous les AudioTracks (Mixer), puis les enverra à AudioHardware pour lecture. Actuellement, Android peut à Créez 32 flux audio, c'est-à-dire que Mixer traitera jusqu'à 32 flux de données AudioTrack en même temps. 

3. Comparaison entre AudioTrack et MediaPlayer

Pour lire des sons, vous pouvez utiliser MediaPlayer et AudioTrack, qui fournissent tous deux une API Java que les développeurs d'applications peuvent utiliser. Bien que les deux puissent jouer des sons, il y a encore une grande différence entre les deux.

3.1 Différence

La plus grande différence est que MediaPlayer peut lire des fichiers audio dans plusieurs formats, tels que MP3, AAC, WAV, OGG, MIDI, etc. MediaPlayer créera le décodeur audio correspondant dans la couche cadre. AudioTrack ne peut lire que les flux PCM décodés. Si vous comparez les formats de fichiers pris en charge, AudioTrack ne prend en charge que les fichiers audio au format wav, car la plupart des fichiers audio au format wav sont des flux PCM. AudioTrack ne crée pas de décodeur, il ne peut donc lire que les fichiers wav qui n'ont pas besoin d'être décodés.

3.2 Contact

MediaPlayer créera toujours AudioTrack dans la couche de structure, transmettra le flux PCM décodé à AudioTrack, puis le passera à AudioFlinger pour le mixage, puis le transmettra au matériel pour la lecture, MediaPlayer inclut donc AudioTrack.

3.3 SoundPool

En contactant l'API de lecture audio Android, j'ai trouvé que SoundPool peut également être utilisé pour lire de l'audio. Voici les scénarios d'utilisation des trois: MediaPlayer est plus adapté à la lecture de fichiers musicaux locaux ou de ressources de streaming en ligne pendant une longue période en arrière-plan; SoundPool convient à la lecture de clips audio relativement courts, tels que des sons de jeu, des sons de boutons, des sonneries , etc., il peut lire plusieurs audios en même temps; AudioTrack est plus proche de la couche inférieure, offre des capacités de contrôle très puissantes, prend en charge la lecture à faible latence et convient aux scénarios tels que le streaming multimédia et les appels vocaux VoIP.

Quatrièmement, le code source 

https://github.com/renhui/AudioDemo 

Je suppose que tu aimes

Origine blog.csdn.net/xfb1989/article/details/113348396
conseillé
Classement