La numériastion de données audio brutes sur Android repose sur l'API AudioRecord. Les flux PCM représentent des signaux numériques non compressés, définis par plusieurs paramètres clés.
Paramètres fondamentaux du PCM :
- Profondeur de bits (quantification) : influence la plage dynamique de l'enregistrement.
- Fréquence d'échantillonnage : détermine les fréquences captruables.
- Nombre de canaux : mono ou stéréo selon la configuration.
Pour estimer la taille d'un fichier PCM (exemple : 44100 Hz, 16 bits, stéréo, 60 secondes) :
Taille = Débit binaire × Durée ÷ 8 = (Profondeur × Fréquence × Canaux × Temps) ÷ 8 ≈ 10,34 Mo
Configuration de l'enregistreur Audio
AudioRecord capturer = new AudioRecord(
MediaRecorder.AudioSource.MIC,
44100,
AudioFormat.CHANNEL_IN_STEREO,
AudioFormat.ENCODING_PCM_16BIT,
tailleBuffer
);
La variable tailleBuffer est obtenue via AudioRecord.getMinBufferSize().
Processus de capture en arrière-plan
class ThreadEnregistrement implements Runnable {
public void run() {
capturer.startRecording();
FileOutputStream sortie = null;
try {
sortie = new FileOutputStream(cheminFichier);
byte[] echantillons = new byte[tailleBuffer];
while (actif) {
int lu = capturer.read(echantillons, 0, echantillons.length);
sortie.write(echantillons, 0, lu);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
capturer.stop();
if (sortie != null) {
try { sortie.close(); } catch (IOException e) {}
}
}
}
}
Le booléen "actif" permet de contrôler la boucle d'enregistrement.
Interruption de la capture
public void arreterEnregistrement() {
actif = false;
}
Génération d'un fichier WAV
Le format WAV encapsule des données PCM dans une structure standardisée avec un en-tête de 44 octets. Voici une implémentation pour construire cet en-tête :
private void ajouterEnteteWAV(FileOutputStream sortie, long tailleAudio, int freqEchantillon, int canaux, int bitsParEchantillon) throws IOException {
byte[] entete = new byte[44];
long debit = freqEchantillon * canaux * bitsParEchantillon / 8;
long tailleTotale = tailleAudio + 36;
// Section RIFF
entete[0] = 'R'; entete[1] = 'I'; entete[2] = 'F'; entete[3] = 'F';
entete[4] = (byte)(tailleTotale & 0xFF);
entete[5] = (byte)((tailleTotale >> 8) & 0xFF);
entete[6] = (byte)((tailleTotale >> 16) & 0xFF);
entete[7] = (byte)((tailleTotale >> 24) & 0xFF);
// Type de fichier WAVE
entete[8] = 'W'; entete[9] = 'A'; entete[10] = 'V'; entete[11] = 'E';
// Sous-bloc format PCM
entete[12] = 'f'; entete[13] = 'm'; entete[14] = 't'; entete[15] = ' ';
entete[16] = 16; // taille du sous-bloc
entete[20] = 1; // format PCM
entete[22] = (byte)canaux;
entete[24] = (byte)(freqEchantillon & 0xFF);
entete[25] = (byte)((freqEchantillon >> 8) & 0xFF);
entete[26] = (byte)((freqEchantillon >> 16) & 0xFF);
entete[27] = (byte)((freqEchantillon >> 24) & 0xFF);
entete[28] = (byte)(debit & 0xFF);
entete[29] = (byte)((debit >> 8) & 0xFF);
entete[30] = (byte)((debit >> 16) & 0xFF);
entete[31] = (byte)((debit >> 24) & 0xFF);
entete[32] = (byte)(canaux * bitsParEchantillon / 8);
entete[34] = (byte)bitsParEchantillon;
// Sous-bloc data
entete[36] = 'd'; entete[37] = 'a'; entete[38] = 't'; entete[39] = 'a';
entete[40] = (byte)(tailleAudio & 0xFF);
entete[41] = (byte)((tailleAudio >> 8) & 0xFF);
entete[42] = (byte)((tailleAudio >> 16) & 0xFF);
entete[43] = (byte)((tailleAudio >> 24) & 0xFF);
sortie.write(entete, 0, 44);
}
Compression vers le format MP3
La conversion PCM vers MP3 exploite la bibliothèque LAME pour appliquer une compression preceptuelle, réduisant la taille du fichier tout en préservant la qualité audible.