Estoy tratando de transmitir audio desde el micrófono de 1 Android a otro a través de WiFi. Después de ver algunos ejemplos hice 2 aplicaciones con una sola actividad en cada una, 1 para capturar y enviar audio y la otra para recibir.Transmisión de voz entre teléfonos Android a través de WiFi
He utilizado las clases Audiorecord y Audiotrack para capturar y reproducir. Sin embargo, acabo de escuchar un sonido crepitante (que ahora se detuvo después de que hice algunos cambios aunque volví)
La actividad para enviar la voz.
public class VoiceSenderActivity extends Activity {
private EditText target;
private TextView streamingLabel;
private Button startButton,stopButton;
public byte[] buffer;
public static DatagramSocket socket;
private int port=50005; //which port??
AudioRecord recorder;
//Audio Configuration.
private int sampleRate = 8000; //How much will be ideal?
private int channelConfig = AudioFormat.CHANNEL_CONFIGURATION_MONO;
private int audioFormat = AudioFormat.ENCODING_PCM_16BIT;
private boolean status = true;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
target = (EditText) findViewById (R.id.target_IP);
streamingLabel = (TextView) findViewById(R.id.streaming_label);
startButton = (Button) findViewById (R.id.start_button);
stopButton = (Button) findViewById (R.id.stop_button);
streamingLabel.setText("Press Start! to begin");
startButton.setOnClickListener (startListener);
stopButton.setOnClickListener (stopListener);
}
private final OnClickListener stopListener = new OnClickListener() {
@Override
public void onClick(View arg0) {
status = false;
recorder.release();
Log.d("VS","Recorder released");
}
};
private final OnClickListener startListener = new OnClickListener() {
@Override
public void onClick(View arg0) {
status = true;
startStreaming();
}
};
public void startStreaming() {
Thread streamThread = new Thread(new Runnable() {
@Override
public void run() {
try {
int minBufSize = AudioRecord.getMinBufferSize(sampleRate, channelConfig, audioFormat);
DatagramSocket socket = new DatagramSocket();
Log.d("VS", "Socket Created");
byte[] buffer = new byte[minBufSize];
Log.d("VS","Buffer created of size " + minBufSize);
DatagramPacket packet;
final InetAddress destination = InetAddress.getByName(target.getText().toString());
Log.d("VS", "Address retrieved");
recorder = new AudioRecord(MediaRecorder.AudioSource.MIC,sampleRate,channelConfig,audioFormat,minBufSize);
Log.d("VS", "Recorder initialized");
recorder.startRecording();
while(status == true) {
//reading data from MIC into buffer
minBufSize = recorder.read(buffer, 0, buffer.length);
//putting buffer in the packet
packet = new DatagramPacket (buffer,buffer.length,destination,port);
socket.send(packet);
}
} catch(UnknownHostException e) {
Log.e("VS", "UnknownHostException");
} catch (IOException e) {
Log.e("VS", "IOException");
}
}
});
streamThread.start();
}
}
La actividad para recibir voz
public class VoiceReceiverActivity extends Activity {
private Button receiveButton,stopButton;
public static DatagramSocket socket;
private AudioTrack speaker;
//Audio Configuration.
private int sampleRate = 8000; //How much will be ideal?
private int channelConfig = AudioFormat.CHANNEL_CONFIGURATION_MONO;
private int audioFormat = AudioFormat.ENCODING_PCM_16BIT;
private boolean status = true;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
receiveButton = (Button) findViewById (R.id.receive_button);
stopButton = (Button) findViewById (R.id.stop_button);
findViewById(R.id.receive_label);
receiveButton.setOnClickListener(receiveListener);
stopButton.setOnClickListener(stopListener);
}
private final OnClickListener stopListener = new OnClickListener() {
@Override
public void onClick(View v) {
status = false;
speaker.release();
Log.d("VR","Speaker released");
}
};
private final OnClickListener receiveListener = new OnClickListener() {
@Override
public void onClick(View arg0) {
status = true;
startReceiving();
}
};
public void startReceiving() {
Thread receiveThread = new Thread (new Runnable() {
@Override
public void run() {
try {
DatagramSocket socket = new DatagramSocket(50005);
Log.d("VR", "Socket Created");
byte[] buffer = new byte[256];
//minimum buffer size. need to be careful. might cause problems. try setting manually if any problems faced
int minBufSize = AudioRecord.getMinBufferSize(sampleRate, channelConfig, audioFormat);
speaker = new AudioTrack(AudioManager.STREAM_MUSIC,sampleRate,channelConfig,audioFormat,minBufSize,AudioTrack.MODE_STREAM);
speaker.play();
while(status == true) {
try {
DatagramPacket packet = new DatagramPacket(buffer,buffer.length);
socket.receive(packet);
Log.d("VR", "Packet Received");
//reading content from packet
buffer=packet.getData();
Log.d("VR", "Packet data read into buffer");
//sending data to the Audiotrack obj i.e. speaker
speaker.write(buffer, 0, minBufSize);
Log.d("VR", "Writing buffer content to speaker");
} catch(IOException e) {
Log.e("VR","IOException");
}
}
} catch (SocketException e) {
Log.e("VR", "SocketException");
}
}
});
receiveThread.start();
}
}
Solía Wireshark para comprobar si se están enviando los paquetes y puedo ver los paquetes. Sin embargo, la fuente es la dirección MAC del dispositivo de envío y el destino también es algo así como una dirección física. Sin embargo, no estoy seguro de si esto es relevante.
¿Cuál es el problema?
Hay al menos tres problemas con los que debe lidiar: datos demorados (o perdidos), rendimiento total de los datos y la posibilidad de frecuencias de muestreo discrepantes. La telefonía IP práctica tiene que tener un medio para tratar con los tres. Los relojes no coincidentes son sorprendentemente complicados: inicialmente, puede introducir un retraso para dar un margen de almacenamiento en búfer, pero si el emisor es más lento, utilizará el búfer y el receptor morirá de hambre por los datos; mientras que si el emisor es más rápido, el búfer finalmente se desbordará con datos no reproducidos. –
Me las arreglé para hacer que esto funcione realmente. Realmente no tuve un problema de frecuencias no coincidentes. Demora en los datos, sí. Tenía una especie de protocolo propio para que coincida con los relojes del receptor/emisor. Al final funcionó, pero solo con algo de retraso (que aumentó con la distancia desde el enrutador inalámbrico) – Alabhya
Hola, he implementado una aplicación de prueba para el código que tienes arriba, realizando todos los cambios necesarios que se sugieren a continuación pero sigo teniendo un problema . Estoy recibiendo comunicaciones entre los dos teléfonos sin problema, pero no creo que el micrófono esté grabando correctamente, ya que no escucho ningún sonido en el otro extremo. ¿Tal vez tenga un enlace a una solución de muestra que podría ver? – chuckliddell0