PCM - > AAC (Encoder) - > PCM (décoder) en temps réel avec une optimisation correcte
je suis en train de mettre en œuvre
AudioRecord (MIC) ->
PCM -> AAC Encoder
AAC -> PCM Decode
-> AudioTrack?? (SPEAKER)
avec MediaCodec
sur Android 4.1+ (API16).
tout D'abord, j'ai réussi (mais pas sûr optimisé correctement) à implémenter PCM -> AAC Encoder
par MediaCodec
comme prévu comme ci-dessous
private boolean setEncoder(int rate)
{
encoder = MediaCodec.createEncoderByType("audio/mp4a-latm");
MediaFormat format = new MediaFormat();
format.setString(MediaFormat.KEY_MIME, "audio/mp4a-latm");
format.setInteger(MediaFormat.KEY_CHANNEL_COUNT, 1);
format.setInteger(MediaFormat.KEY_SAMPLE_RATE, 44100);
format.setInteger(MediaFormat.KEY_BIT_RATE, 64 * 1024);//AAC-HE 64kbps
format.setInteger(MediaFormat.KEY_AAC_PROFILE, MediaCodecInfo.CodecProfileLevel.AACObjectHE);
encoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
return true;
}
entrée: Bitrate PCM = 44100 (Hz) x 16 (bit) x 1 (Monoral) = 705600 bit / s
sortie: débit AAC-HE = 64 x 1024(bits) = 65536 bits/s
ainsi, la taille des données est approximativement compressée x11
, et j'ai confirmé ce travail en observant un log
- audiorecoder փ 4096 octets read
- audioencoder: 369 octets encodés
la taille des données est approximativement compressée x11
, jusqu'ici si bon.
maintenant, j'ai un UDP Serveur pour recevoir les données codées, puis le décoder.
le profil du décodeur est défini comme suit:
private boolean setDecoder(int rate)
{
decoder = MediaCodec.createDecoderByType("audio/mp4a-latm");
MediaFormat format = new MediaFormat();
format.setString(MediaFormat.KEY_MIME, "audio/mp4a-latm");
format.setInteger(MediaFormat.KEY_CHANNEL_COUNT, 1);
format.setInteger(MediaFormat.KEY_SAMPLE_RATE, 44100);
format.setInteger(MediaFormat.KEY_BIT_RATE, 64 * 1024);//AAC-HE 64kbps
format.setInteger(MediaFormat.KEY_AAC_PROFILE, MediaCodecInfo.CodecProfileLevel.AACObjectHE);
decoder.configure(format, null, null, 0);
return true;
}
depuis UDPserver packet buffer size est 1024
- UDPserver փ 1024 bytes received
et puisqu'il s'agit des données compressées de L'AAC, Je m'attendrais à ce que la taille de décodage soit
environ 1024 x11
, cependant le résultat réel est
- audiodecoder: 8192 octets décodés
c'est approximativement x8
, et je sens quelque chose de mal.
le code du décodeur est le suivant:
IOudpPlayer = new Thread(new Runnable()
{
public void run()
{
SocketAddress sockAddress;
String address;
int len = 1024;
byte[] buffer2 = new byte[len];
DatagramPacket packet;
byte[] data;
ByteBuffer[] inputBuffers;
ByteBuffer[] outputBuffers;
ByteBuffer inputBuffer;
ByteBuffer outputBuffer;
MediaCodec.BufferInfo bufferInfo;
int inputBufferIndex;
int outputBufferIndex;
byte[] outData;
try
{
decoder.start();
isPlaying = true;
while (isPlaying)
{
try
{
packet = new DatagramPacket(buffer2, len);
ds.receive(packet);
sockAddress = packet.getSocketAddress();
address = sockAddress.toString();
Log.d("UDP Receiver"," received !!! from " + address);
data = new byte[packet.getLength()];
System.arraycopy(packet.getData(), packet.getOffset(), data, 0, packet.getLength());
Log.d("UDP Receiver", data.length + " bytes received");
//===========
inputBuffers = decoder.getInputBuffers();
outputBuffers = decoder.getOutputBuffers();
inputBufferIndex = decoder.dequeueInputBuffer(-1);
if (inputBufferIndex >= 0)
{
inputBuffer = inputBuffers[inputBufferIndex];
inputBuffer.clear();
inputBuffer.put(data);
decoder.queueInputBuffer(inputBufferIndex, 0, data.length, 0, 0);
}
bufferInfo = new MediaCodec.BufferInfo();
outputBufferIndex = decoder.dequeueOutputBuffer(bufferInfo, 0);
while (outputBufferIndex >= 0)
{
outputBuffer = outputBuffers[outputBufferIndex];
outputBuffer.position(bufferInfo.offset);
outputBuffer.limit(bufferInfo.offset + bufferInfo.size);
outData = new byte[bufferInfo.size];
outputBuffer.get(outData);
Log.d("AudioDecoder", outData.length + " bytes decoded");
decoder.releaseOutputBuffer(outputBufferIndex, false);
outputBufferIndex = decoder.dequeueOutputBuffer(bufferInfo, 0);
}
//===========
}
catch (IOException e)
{
}
}
decoder.stop();
}
catch (Exception e)
{
}
}
});
le code complet:
https://gist.github.com/kenokabe/9029256
aussi besoin de Permission:
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
<uses-permission android:name="android.permission.RECORD_AUDIO"></uses-permission>
Un membre fadden qui travaille pour Google m'a dit
ressemble à Je ne mets pas position & limit sur le tampon de sortie.
j'ai lu VP8 Encoding Nexus 5 retourne vide/0-Frames , mais ne sait pas comment implémenter correctement.
mise à jour: j'ai en quelque sorte compris où Modifier pour
ressemble à Je ne mets pas position & limit sur le tampon de sortie.
, donc ajouter 2 lignes dans la boucle while de L'encodeur et du décodeur comme suit:
outputBuffer.position(bufferInfo.offset);
outputBuffer.limit(bufferInfo.offset + bufferInfo.size);
https://gist.github.com/kenokabe/9029256/revisions
Cependant, le résultat est le même.
et maintenant, je pense, les erreurs:
W/SoftAAC2﹕ AAC decoder returned error 16388, substituting silence.
indique que ce décodeur ne fonctionne plus du premier. C'est encore the data is not seekable
. Seeking in AAC streams on Android il est très décevant si le décodeur AAC ne peut pas gérer les données de streaming de cette façon, mais seulement avec l'ajout d'un en-tête.
UPDATE2: récepteur UDP a fait une erreur, ainsi modifié
https://gist.github.com/kenokabe/9029256
maintenant, l'erreur
W/SoftAAC2﹕ AAC decoder returned error 16388, substituting silence.
disparu!!
Donc, il indique que le décodeur fonctionne sans erreur, au moins,
cependant, ceci est le log d'un cycle:
D/AudioRecoder﹕ 4096 bytes read
D/AudioEncoder﹕ 360 bytes encoded
D/UDP Receiver﹕ received !!! from /127.0.0.1:39000
D/UDP Receiver﹕ 360 bytes received
D/AudioDecoder﹕ 8192 bytes decoded
PCM (4096) - >AACencoded (360) - > UDP-AAC (360) - >(supposed to be )PCM (8192)
le résultat final est environ 2x la taille du PCM original, quelque chose ne va toujours pas.
donc ma Question ici serait
-
Pouvez-vous correctement optimiser mon code exemple pour travailler correctement?
-
est-ce une bonne façon d'utiliser
AudioTrack
API pour lire les données brutes PCM décodées à la volée, et pouvez-vous me montrer la bonne façon de le faire? Un l'exemple de code est apprécié.
Merci.
PS. Mon projet vise Android4.1+(API16), j'ai lu les choses sont plus faciles sur API18(Andeoid 4.3+), mais pour des raisons de compatibilité évidentes, malheureusement, je dois sauter MediaMuxer etc ici...
6 réponses
après avoir testé, voici ce que j'ai trouvé en modifiant votre code:
package com.example.app;
import android.app.Activity;
import android.media.AudioManager;
import android.media.MediaCodecInfo;
import android.media.MediaFormat;
import android.os.Bundle;
import android.media.AudioFormat;
import android.media.AudioRecord;
import android.media.AudioTrack;
import android.media.MediaCodec;
import android.media.MediaRecorder.AudioSource;
import android.util.Log;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketAddress;
import java.net.SocketException;
import java.nio.ByteBuffer;
public class MainActivity extends Activity
{
private AudioRecord recorder;
private AudioTrack player;
private MediaCodec encoder;
private MediaCodec decoder;
private short audioFormat = AudioFormat.ENCODING_PCM_16BIT;
private short channelConfig = AudioFormat.CHANNEL_IN_MONO;
private int bufferSize;
private boolean isRecording;
private boolean isPlaying;
private Thread IOrecorder;
private Thread IOudpPlayer;
private DatagramSocket ds;
private final int localPort = 39000;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
IOrecorder = new Thread(new Runnable()
{
public void run()
{
int read;
byte[] buffer1 = new byte[bufferSize];
ByteBuffer[] inputBuffers;
ByteBuffer[] outputBuffers;
ByteBuffer inputBuffer;
ByteBuffer outputBuffer;
MediaCodec.BufferInfo bufferInfo;
int inputBufferIndex;
int outputBufferIndex;
byte[] outData;
DatagramPacket packet;
try
{
encoder.start();
recorder.startRecording();
isRecording = true;
while (isRecording)
{
read = recorder.read(buffer1, 0, bufferSize);
// Log.d("AudioRecoder", read + " bytes read");
//------------------------
inputBuffers = encoder.getInputBuffers();
outputBuffers = encoder.getOutputBuffers();
inputBufferIndex = encoder.dequeueInputBuffer(-1);
if (inputBufferIndex >= 0)
{
inputBuffer = inputBuffers[inputBufferIndex];
inputBuffer.clear();
inputBuffer.put(buffer1);
encoder.queueInputBuffer(inputBufferIndex, 0, buffer1.length, 0, 0);
}
bufferInfo = new MediaCodec.BufferInfo();
outputBufferIndex = encoder.dequeueOutputBuffer(bufferInfo, 0);
while (outputBufferIndex >= 0)
{
outputBuffer = outputBuffers[outputBufferIndex];
outputBuffer.position(bufferInfo.offset);
outputBuffer.limit(bufferInfo.offset + bufferInfo.size);
outData = new byte[bufferInfo.size];
outputBuffer.get(outData);
// Log.d("AudioEncoder ", outData.length + " bytes encoded");
//-------------
packet = new DatagramPacket(outData, outData.length,
InetAddress.getByName("127.0.0.1"), localPort);
ds.send(packet);
//------------
encoder.releaseOutputBuffer(outputBufferIndex, false);
outputBufferIndex = encoder.dequeueOutputBuffer(bufferInfo, 0);
}
// ----------------------;
}
encoder.stop();
recorder.stop();
}
catch (Exception e)
{
e.printStackTrace();
}
}
});
IOudpPlayer = new Thread(new Runnable()
{
public void run()
{
SocketAddress sockAddress;
String address;
int len = 2048
byte[] buffer2 = new byte[len];
DatagramPacket packet;
byte[] data;
ByteBuffer[] inputBuffers;
ByteBuffer[] outputBuffers;
ByteBuffer inputBuffer;
ByteBuffer outputBuffer;
MediaCodec.BufferInfo bufferInfo;
int inputBufferIndex;
int outputBufferIndex;
byte[] outData;
try
{
player.play();
decoder.start();
isPlaying = true;
while (isPlaying)
{
try
{
packet = new DatagramPacket(buffer2, len);
ds.receive(packet);
sockAddress = packet.getSocketAddress();
address = sockAddress.toString();
// Log.d("UDP Receiver"," received !!! from " + address);
data = new byte[packet.getLength()];
System.arraycopy(packet.getData(), packet.getOffset(), data, 0, packet.getLength());
// Log.d("UDP Receiver", data.length + " bytes received");
//===========
inputBuffers = decoder.getInputBuffers();
outputBuffers = decoder.getOutputBuffers();
inputBufferIndex = decoder.dequeueInputBuffer(-1);
if (inputBufferIndex >= 0)
{
inputBuffer = inputBuffers[inputBufferIndex];
inputBuffer.clear();
inputBuffer.put(data);
decoder.queueInputBuffer(inputBufferIndex, 0, data.length, 0, 0);
}
bufferInfo = new MediaCodec.BufferInfo();
outputBufferIndex = decoder.dequeueOutputBuffer(bufferInfo, 0);
while (outputBufferIndex >= 0)
{
outputBuffer = outputBuffers[outputBufferIndex];
outputBuffer.position(bufferInfo.offset);
outputBuffer.limit(bufferInfo.offset + bufferInfo.size);
outData = new byte[bufferInfo.size];
outputBuffer.get(outData);
// Log.d("AudioDecoder", outData.length + " bytes decoded");
player.write(outData, 0, outData.length);
decoder.releaseOutputBuffer(outputBufferIndex, false);
outputBufferIndex = decoder.dequeueOutputBuffer(bufferInfo, 0..
Auto Réponse, voici mon meilleur effort à ce jour
package com.example.app;
import android.app.Activity;
import android.media.AudioManager;
import android.media.MediaCodecInfo;
import android.media.MediaFormat;
import android.os.Bundle;
import android.media.AudioFormat;
import android.media.AudioRecord;
import android.media.AudioTrack;
import android.media.MediaCodec;
import android.media.MediaRecorder.AudioSource;
import android.util.Log;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketAddress;
import java.net.SocketException;
import java.nio.ByteBuffer;
public class MainActivity extends Activity
{
private AudioRecord recorder;
private AudioTrack player;
private MediaCodec encoder;
private MediaCodec decoder;
private short audioFormat = AudioFormat.ENCODING_PCM_16BIT;
private short channelConfig = AudioFormat.CHANNEL_IN_MONO;
private int bufferSize;
private boolean isRecording;
private boolean isPlaying;
private Thread IOrecorder;
private Thread IOudpPlayer;
private DatagramSocket ds;
private final int localPort = 39000;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
IOrecorder = new Thread(new Runnable()
{
public void run()
{
int read;
byte[] buffer1 = new byte[bufferSize];
ByteBuffer[] inputBuffers;
ByteBuffer[] outputBuffers;
ByteBuffer inputBuffer;
ByteBuffer outputBuffer;
MediaCodec.BufferInfo bufferInfo;
int inputBufferIndex;
int outputBufferIndex;
byte[] outData;
DatagramPacket packet;
try
{
encoder.start();
recorder.startRecording();
isRecording = true;
while (isRecording)
{
read = recorder.read(buffer1, 0, bufferSize);
// Log.d("AudioRecoder", read + " bytes read");
//------------------------
inputBuffers = encoder.getInputBuffers();
outputBuffers = encoder.getOutputBuffers();
inputBufferIndex = encoder.dequeueInputBuffer(-1);
if (inputBufferIndex >= 0)
{
inputBuffer = inputBuffers[inputBufferIndex];
inputBuffer.clear();
inputBuffer.put(buffer1);
encoder.queueInputBuffer(inputBufferIndex, 0, buffer1.length, 0, 0);
}
bufferInfo = new MediaCodec.BufferInfo();
outputBufferIndex = encoder.dequeueOutputBuffer(bufferInfo, 0);
while (outputBufferIndex >= 0)
{
outputBuffer = outputBuffers[outputBufferIndex];
outputBuffer.position(bufferInfo.offset);
outputBuffer.limit(bufferInfo.offset + bufferInfo.size);
outData = new byte[bufferInfo.size];
outputBuffer.get(outData);
// Log.d("AudioEncoder", outData.length + " bytes encoded");
//-------------
packet = new DatagramPacket(outData, outData.length,
InetAddress.getByName("127.0.0.1"), localPort);
ds.send(packet);
//------------
encoder.releaseOutputBuffer(outputBufferIndex, false);
outputBufferIndex = encoder.dequeueOutputBuffer(bufferInfo, 0);
}
// ----------------------;
}
encoder.stop();
recorder.stop();
}
catch (Exception e)
{
e.printStackTrace();
}
}
});
IOudpPlayer = new Thread(new Runnable()
{
public void run()
{
SocketAddress sockAddress;
String address;
int len = 1024;
byte[] buffer2 = new byte[len];
DatagramPacket packet;
byte[] data;
ByteBuffer[] inputBuffers;
ByteBuffer[] outputBuffers;
ByteBuffer inputBuffer;
ByteBuffer outputBuffer;
MediaCodec.BufferInfo bufferInfo;
int inputBufferIndex;
int outputBufferIndex;
byte[] outData;
try
{
player.play();
decoder.start();
isPlaying = true;
while (isPlaying)
{
try
{
packet = new DatagramPacket(buffer2, len);
ds.receive(packet);
sockAddress = packet.getSocketAddress();
address = sockAddress.toString();
// Log.d("UDP Receiver"," received !!! from " + address);
data = new byte[packet.getLength()];
System.arraycopy(packet.getData(), packet.getOffset(), data, 0, packet.getLength());
// Log.d("UDP Receiver", data.length + " bytes received");
//===========
inputBuffers = decoder.getInputBuffers();
outputBuffers = decoder.getOutputBuffers();
inputBufferIndex = decoder.dequeueInputBuffer(-1);
if (inputBufferIndex >= 0)
{
inputBuffer = inputBuffers[inputBufferIndex];
inputBuffer.clear();
inputBuffer.put(data);
decoder.queueInputBuffer(inputBufferIndex, 0, data.length, 0, 0);
}
bufferInfo = new MediaCodec.BufferInfo();
outputBufferIndex = decoder.dequeueOutputBuffer(bufferInfo, 0);
while (outputBufferIndex >= 0)
{
outputBuffer = outputBuffers[outputBufferIndex];
outputBuffer.position(bufferInfo.offset);
outputBuffer.limit(bufferInfo.offset + bufferInfo.size);
outData = new byte[bufferInfo.size];
outputBuffer.get(outData);
// Log.d("AudioDecoder", outData.length + " bytes decoded");
player.write(outData, 0, outData.length);
decoder.releaseOutputBuffer(outputBufferIndex, false);
outputBufferIndex = decoder.dequeueOutputBuffer(bufferInfo, 0);
}
//===========
}
catch (IOException e)
{
}
}
decoder.stop();
player.stop();
}
catch (Exception e)
{
}
}
});
//===========================================================
int rate = findAudioRecord();
if (rate != -1)
{
Log.v("=========media ", "ready: " + rate);
Log.v("=========media channel ", "ready: " + channelConfig);
boolean encoderReady = setEncoder(rate);
Log.v("=========encoder ", "ready: " + encoderReady);
if (encoderReady)
{
boolean decoderReady = setDecoder(rate);
Log.v("=========decoder ", "ready: " + decoderReady);
if (decoderReady)
{
Log.d("=======bufferSize========", "" + bufferSize);
try
{
setPlayer(rate);
ds = new DatagramSocket(localPort);
IOudpPlayer.start();
IOrecorder.start();
}
catch (SocketException e)
{
e.printStackTrace();
}
}
}
}
}
protected void onDestroy()
{
recorder.release();
player.release();
encoder.release();
decoder.release();
}
/*
protected void onResume()
{
// isRecording = true;
}
protected void onPause()
{
isRecording = false;
}
*/
private int findAudioRecord()
{
for (int rate : new int[]{44100})
{
try
{
Log.v("===========Attempting rate ", rate + "Hz, bits: " + audioFormat + ", channel: " + channelConfig);
bufferSize = AudioRecord.getMinBufferSize(rate, channelConfig, audioFormat);
if (bufferSize != AudioRecord.ERROR_BAD_VALUE)
{
// check if we can instantiate and have a success
recorder = new AudioRecord(AudioSource.MIC, rate, channelConfig, audioFormat, bufferSize);
if (recorder.getState() == AudioRecord.STATE_INITIALIZED)
{
Log.v("===========final rate ", rate + "Hz, bits: " + audioFormat + ", channel: " + channelConfig);
return rate;
}
}
}
catch (Exception e)
{
Log.v("error", "" + rate);
}
}
return -1;
}
private boolean setEncoder(int rate)
{
encoder = MediaCodec.createEncoderByType("audio/mp4a-latm");
MediaFormat format = new MediaFormat();
format.setString(MediaFormat.KEY_MIME, "audio/mp4a-latm");
format.setInteger(MediaFormat.KEY_CHANNEL_COUNT, 1);
format.setInteger(MediaFormat.KEY_SAMPLE_RATE, rate);
format.setInteger(MediaFormat.KEY_BIT_RATE, 64 * 1024);//AAC-HE 64kbps
format.setInteger(MediaFormat.KEY_AAC_PROFILE, MediaCodecInfo.CodecProfileLevel.AACObjectHE);
encoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
return true;
}
private boolean setDecoder(int rate)
{
decoder = MediaCodec.createDecoderByType("audio/mp4a-latm");
MediaFormat format = new MediaFormat();
format.setString(MediaFormat.KEY_MIME, "audio/mp4a-latm");
format.setInteger(MediaFormat.KEY_CHANNEL_COUNT, 1);
format.setInteger(MediaFormat.KEY_SAMPLE_RATE, rate);
format.setInteger(MediaFormat.KEY_BIT_RATE, 64 * 1024);//AAC-HE 64kbps
format.setInteger(MediaFormat.KEY_AAC_PROFILE, MediaCodecInfo.CodecProfileLevel.AACObjectHE);
decoder.configure(format, null, null, 0);
return true;
}
private boolean setPlayer(int rate)
{
int bufferSizePlayer = AudioTrack.getMinBufferSize(rate, AudioFormat.CHANNEL_OUT_MONO, audioFormat);
Log.d("====buffer Size player ", String.valueOf(bufferSizePlayer));
player= new AudioTrack(AudioManager.STREAM_MUSIC, rate, AudioFormat.CHANNEL_OUT_MONO, audioFormat, bufferSizePlayer, AudioTrack.MODE_STREAM);
if (player.getState() == AudioTrack.STATE_INITIALIZED)
{
return true;
}
else
{
return false;
}
}
}
j'ai essayé le code ci-dessus et il n'a pas fonctionné correctement.On injectait beaucoup de silence dans la sortie décodée. La question n'était pas de fixer la valeur "csd" appropriée au décodeur.
donc si vous voyez "silence" dans l'erreur de lancement de log ou de décodeur, assurez-vous d'avoir ajouté ce qui suit à votre format de décodeur de médias
int profile = 2; //AAC LC
int freqIdx = 11; //8KHz
int chanCfg = 1; //Mono
ByteBuffer csd = ByteBuffer.allocate(2);
csd.put(0, (byte) (profile << 3 | freqIdx >> 1));
csd.put(1, (byte)((freqIdx & 0x01) << 7 | chanCfg << 3));
mediaFormat.setByteBuffer("csd-0", csd);
votre code réseau combine des données. Vous avez 369 octets de données compressées, mais du côté de la réception vous avez fini avec 1024 octets. Ces 1024 octets se composent de deux images entières et d'une image partielle. Les deux cadres entiers se décodent de nouveau à 4096 octets, pour un total de 8192 octets que vous avez vus. Le reste de la trame partielle sera probablement décodé une fois que vous aurez envoyé suffisamment de données au décodeur, mais vous ne devriez généralement envoyer que des trames entières au décodeur.
de plus, MediaCodec.dequeueOutputBuffer()
ne renvoie pas seulement des indices (positifs) de tampon, mais aussi des codes (négatifs) de statut. Un des codes possibles est MediaCodec.INFO_OUTPUT_FORMAT_CHANGED
, qui indique que vous devez appeler MediaCodec.getOutputFormat()
pour obtenir le format des données audio. Vous pourriez voir la stéréo de sortie codec même si l'entrée était mono. Le code que vous avez posté sort tout simplement de la boucle lorsqu'il reçoit l'un de ces codes de statut.
j'ai testé avec votre source. il y a certains points.
-
débit binaire est un nombre naturel K, mais pas d'ordinateur K. 64k = 64000, mais pas 64 * 1024
-
il n'est pas recommandé d'écrire un code long qui partage certaines variables. A. séparer le fil codeur et le fil décodeur en deux classes indépendantes. B. Le DatagramSocket est partagé par L'expéditeur et le destinataire, il n'est pas bon.
-
énumérer Format Audio besoin de plus de valeurs. c'est-à-dire que les taux d'échantillonnage doivent être choisis à partir de : 8000, 11025, 22050, 44100
d / audio-codeur 4096 octets read D / audioencoder: 360 octets encodés D/UDP Récepteur﹕ reçu !!! à partir de /127.0.0.1:39000 D/UDP Récepteur﹕ 360 octets reçus D / AudioDecoder * * 8192 octets décodés
c'est parce que le décodeur acc décode toujours les canaux stéréo,même si les données codées sont MONO. donc, si votre encodage side est réglé sur les chaînes stéréo, ce sera comme:
d / audiorecoder buyer 8192 octets read D / audioencoder: 360 octets encodés D/UDP Récepteur﹕ reçu !!! à partir de /127.0.0.1:39000 D/UDP Récepteur﹕ 360 octets reçus D / AudioDecoder * * 8192 octets décodés