web-dev-qa-db-fra.com

Lecture du son provenant du microphone en temps réel

J'ai essayé d'obtenir que mon application enregistre le son provenant du microphone et le reproduise en (approximativement) en temps réel, mais sans succès.

J'utilise les classes AudioRecord et AudioTrack pour l'enregistrement et la lecture, respectivement. J'ai essayé différentes approches, j'ai essayé d'enregistrer le son entrant et de l'écrire dans un fichier et cela a bien fonctionné. J'ai également essayé de reproduire le son de ce fichier APRÈS avec AudioTrack et cela a bien fonctionné aussi. Le problème, c’est lorsque j’essaie de jouer le son en temps réel au lieu de lire un fichier après son écriture.

Voici le code:

//variables
private int audioSource = MediaRecorder.AudioSource.MIC;
private int samplingRate = 44100; /* in Hz*/
private int channelConfig = AudioFormat.CHANNEL_CONFIGURATION_MONO;
private int audioFormat = AudioFormat.ENCODING_PCM_16BIT;
private int bufferSize = AudioRecord.getMinBufferSize(samplingRate, channelConfig, audioFormat);
private int sampleNumBits = 16;
private int numChannels = 1;

// …

AudioRecord recorder = new AudioRecord(audioSource, samplingRate, channelConfig, audioFormat, bufferSize);
                recorder.startRecording();
                isRecording = true;

AudioTrack audioPlayer = new AudioTrack(AudioManager.STREAM_MUSIC, 44100, AudioFormat.CHANNEL_CONFIGURATION_MONO,
                        AudioFormat.ENCODING_PCM_16BIT, bufferSize, AudioTrack.MODE_STREAM);

if(audioPlayer.getPlayState() != AudioTrack.PLAYSTATE_PLAYING)
    audioPlayer.play();

//capture data and record to file
int readBytes=0, writtenBytes=0;
do{
   readBytes = recorder.read(data, 0, bufferSize);

   if(AudioRecord.ERROR_INVALID_OPERATION != readBytes){
      writtenBytes += audioPlayer.write(data, 0, readBytes);
   }
}
while(isRecording);

Une exception Java.lang.IllegalStateException est renvoyée. La raison en est "play () appelé sur un AudioTrack non initialisé".

Cependant, si je modifie l'initialisation AudioTrack pour utiliser par exemple une fréquence d'échantillonnage de 8000Hz et un format d'échantillonnage de 8 bits (au lieu de 16), l'exception ne sera plus levée et l'application s'exécute, bien qu'elle produise un bruit horrible.

Lorsque je lis AudioTrack à partir d’un fichier, il n’ya aucun problème avec l’initialisation de AudioTrack, j’ai essayé 44100 et 16 bits et cela a fonctionné correctement, produisant le son correct.

De l'aide ?

30
Jonny

Tout l'audio natif d'Android est codé . Vous pouvez uniquement lire les formats PCM _ en temps réel ou utiliser un codec spécial streaming , qui, selon moi, n'est pas trivial sur Android.

Le fait est que si vous voulez enregistrer/lire du son simultanément, vous devez créer votre propre tampon audio et y stocker des échantillons audio bruts codés en PCM (je ne suis pas sûr que vous pensiez duh! ou si cela est sur votre tête, alors je vais essayer d'être clair, mais pas de mâcher votre propre chewing-gum).

PCM est une représentation numérique d'un signal analogique dans lequel votre audio échantillons est un ensemble de "instantanés" de l'onde acoustique d'origine. Parce que toutes sortes de mathématiciens et d'ingénieurs intelligents ont compris le potentiel pour réduire le nombre de bits avec lesquels vous représentez ces données, ils ont créé toutes sortes de encodeurs . Le signal codé (compressé) est représenté très différemment du signal PCM brut et doit être décodé (en -cod -er + dec -oder = codec). Sauf si vous utilisez des algorithmes spéciaux et des codecs de diffusion multimédia en continu, il est impossible de reproduire un signal codé comme vous essayez de le faire, car ce n’est pas un échantillon encodé, mais plutôt une image à l’autre, où vous avez besoin de la totalité de la sinon le signal complet, décoder cette trame.

Pour ce faire, vous devez stocker manuellement les échantillons audio provenant de la mémoire tampon du microphone et les envoyer manuellement dans la mémoire tampon de sortie. Vous devrez coder pour cela, mais je crois qu’il existe certaines applications open source que vous pouvez consulter et en tirer un maximum à leur source (sauf si vous êtes prêt à vendre votre application plus tard, bien sûr, mais une discussion complètement différente).

Si vous développez pour Android 2.3 ou une version ultérieure et que vous n'avez pas trop peur de la programmation dans code natif , vous pouvez utiliser OpenSL ES . Les fonctionnalités spécifiques à Android d'OpenSL ES sont répertoriées ici . Cette plate-forme vous permet une manipulation audio un peu plus flexible et vous pourrez trouver exactement ce dont vous avez besoin si votre application dépend fortement du traitement audio.

29
Phonon

Il s'agit d'une exception Java.lang.IllegalStateException dont le motif est causé par "play () appelé sur un AudioTrack non initialisé".

C'est parce que la taille de la mémoire tampon est trop petite. J'ai essayé "bufferSize + = 2048;", c'est bon alors.

3
Haisea

J'ai eu un problème similaire et je l'ai résolu en ajoutant cette autorisation au fichier manifeste:

<uses-permission Android:name="Android.permission.MODIFY_AUDIO_SETTINGS"/>
0
Ahmed