una transmitir sonido reproduce pero oye microfono interno grabar externo escucha consola como celular android bluetooth audio-streaming android-bluetooth android-audiorecord

android - sonido - transmitir audio chromecast



Un proyecto extenso: Transmisión de audio desde el micrófono al dispositivo Android (0)

Quiero tomar una entrada de audio desde un micrófono Bluetooth y transmitirla en voz alta, como un megáfono o un sistema de PA simple, y transmitirla en tiempo real .

Para este propósito estoy usando las clases AudioRecord y AudioTrack, ya que MediaRecorder y MediaPlayer escriben y leen en un archivo externo, lo que podría imaginar demora el audio mucho más de lo necesario (¿es esto cierto?).

He descartado la idea de utilizar cualquier clase de Bluetooth, ya que la API de Android no es compatible con el dispositivo Android como sumidero en un escenario fuente / sumidero (al menos no todavía) y requeriría entonces una programación nativa de las bibliotecas de Android (esto es también es cierto, ¿verdad?)

Ahora. La aplicación funciona , pero el retraso es demasiado largo y se supone que la aplicación debe reproducir audio en tiempo real.

Mi primera pregunta es: ¿Son AudioRecord / AudioTrack las clases correctas para este propósito (transmitir audio a través de un micrófono Bluetooth a los parlantes del dispositivo y reproducirlo en voz alta en tiempo real)?

Y si es así: ¿cómo puedo disminuir la demora en el audio para que transmita el audio desde un micrófono en tiempo real real? Todo el código enumerado aquí, así que por favor ayúdense a sí mismos:

En Manifest, se requiere un permiso para grabar audio.

<uses-permission android:name="android.permission.RECORD_AUDIO" />

Tengo una clase dedicada que amplía un subproceso para el manejo de audio aquí:

public class AudioStreamer extends Thread { /** * @Params: */ private int audioSource = MediaRecorder.AudioSource.MIC; private int sampleRate = 11025; private int streamType = AudioManager.STREAM_MUSIC; private int mode = AudioTrack.MODE_STREAM; private int audioFormat = AudioFormat.ENCODING_PCM_16BIT; private int channelConfigIn = AudioFormat.CHANNEL_IN_MONO; private int channelConfigOut = AudioFormat.CHANNEL_OUT_MONO; private int recordSize; private int trackSize; private AudioTrack track; private AudioRecord recorder; /** * Initializes the un-initialized params: buffer, bufferSize, track and recorder * starts recording/playing with AudioRecord and AudioTrack respectively */ public AudioStreamer() { System.out.println("New code!"); recordSize = AudioRecord.getMinBufferSize(sampleRate, channelConfigIn, audioFormat); System.out.println("recordSize: "+recordSize); trackSize = AudioTrack.getMinBufferSize(sampleRate, channelConfigOut, audioFormat); System.out.println("trackSize: "+trackSize); recorder = new AudioRecord(audioSource, sampleRate, channelConfigIn, audioFormat, recordSize); if (recorder.getState() == AudioRecord.STATE_INITIALIZED) { track = new AudioTrack(streamType, sampleRate, channelConfigOut, audioFormat, trackSize, mode); if (track.getState() == AudioTrack.STATE_INITIALIZED) { System.out.println("Record and Track initialized"); } else { System.out.println("Track != init"); } } else { System.out.println("Recorder != init"); } } /** * Runs thread--which reads and writes from/to the Android hardware */ public void run() { recorder.startRecording(); track.play(); if (recorder.getRecordingState() == AudioRecord.RECORDSTATE_RECORDING && track.getPlayState() == AudioTrack.PLAYSTATE_PLAYING) { System.out.println("Recorder and track playing"); } else { System.out.println("Track and recorder != PLAYING"); } short[] buffer = new short[recordSize]; int audioLenght = 0; while (recorder.getRecordingState() == AudioRecord.RECORDSTATE_RECORDING && track.getPlayState() == AudioTrack.PLAYSTATE_PLAYING) { audioLenght = recorder.read(buffer, 0, recordSize); track.write(buffer, 0, audioLenght); } } /** * sets up the AudioManager for bluetooth audio streaming */ public void setAudioManager(AudioManager manager) { manager.setMode(AudioManager.MODE_IN_COMMUNICATION); // set true and test manager.setBluetoothScoOn(true); manager.setSpeakerphoneOn(true); System.out.println("bluetoothScoOn: " + manager.isBluetoothScoOn() + ", bluetoothA2DP: " + manager.isBluetoothA2dpOn() +", speakerPhone: "+manager.isSpeakerphoneOn()); /** * Start BluetoothSCO */ if (manager.isBluetoothA2dpOn()) { manager.startBluetoothSco(); System.out.println("BtSco started"); } } /** * Pauses the audio stream */ public void pause() { if (recorder.getRecordingState() == AudioRecord.RECORDSTATE_RECORDING) { recorder.stop(); } if (track.getPlayState() == AudioTrack.PLAYSTATE_PLAYING) { track.pause(); track.flush(); } if (track.getPlayState() == AudioTrack.PLAYSTATE_PAUSED && recorder.getRecordingState() == AudioRecord.RECORDSTATE_STOPPED) { System.out.println("Stopped"); } } }

Y mi clase principal cuenta con botones en los que se puede hacer clic que llaman a los métodos de inicio / detención en la transmisión de audio:

public class MainActivity extends AppCompatActivity { private AudioStreamer audioStreamer; private AudioManager manager; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); System.out.println("Program running ... "); audioStreamer = new AudioStreamer(); manager = (AudioManager) this.getSystemService(Context.AUDIO_SERVICE); audioStreamer.setAudioManager(manager); } public void startAudioStreamer(View view) { audioStreamer.start(); } public void pauseAudioStreamer(View view) { audioStreamer.pause(); } }

Que se muestran a través de un diseño gráfico con botones como este:

<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.android.audiorecordrevisited.MainActivity"> <Button android:id="@+id/startAudioStreamer" android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="startAudioStreamer" android:text="Start AudioStreamer" /> <Button android:id="@+id/stopAudioStreamer" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@id/startAudioStreamer" android:onClick="pauseAudioStreamer" android:text="Stop Audio recording" /> </RelativeLayout>

¿Cómo puedo disminuir el retraso en la transmisión de audio? ¿Estoy usando las clases correctas, o hay otro / mejor enfoque para este problema?

Además: La entrada de audio no parece venir a través del micrófono Bluetooth real, sino del micrófono de hardware Android, lo cual no es la idea. ¿Cómo puedo dirigir la lectura de la entrada de audio al micrófono Bluetooth en lugar de leer el interno?