Обширный проект: потоковое аудио с микрофона на устройство Android

Я хочу взять аудиовход с микрофона Bluetooth и транслировать его громко - как мегафон или простая система громкой связи -и транслировать его в режиме реального времени.

Для этой цели я использую классы AudioRecord и AudioTrack - поскольку MediaRecorder и MediaPlayer записывают и читают во внешний файл, что, я могу себе представить, задерживает звук намного больше, чем необходимо (это правда?).

Я отказался от идеи использовать какие-либо классы Bluetooth, поскольку API Android не поддерживает устройство Android как приемник в сценарии «источник / приемник» (по крайней мере, пока), а затем потребует собственного программирования библиотек Android (это тоже правда, правда?)

Сейчас. Приложение работает, нозадержка слишком длинная и приложение должно воспроизводить звук в реальном времени.

Мой первый вопрос: являются ли AudioRecord / AudioTrack подходящими классами для этой цели (потоковая передача звука через микрофон Bluetooth на динамики устройства и громкое воспроизведение в режиме реального времени)?

И если это так:Как я могу уменьшить задержку звука так что он передает аудио с микрофона вфактическое в реальном времени? Весь код указан здесь, поэтому, пожалуйста, помогите себе:

В Manifest требуется разрешение на запись аудио.

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

У меня есть специальный класс, который расширяет поток для обработки аудио здесь:

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;
p,rivate 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");
    }
}

}

А мой основной класс снабжен интерактивными кнопками, которые вызывают методы start / stop в аудиопотоке:

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();
}

}

Которые отображаются через графический макет с кнопками, как это:

<?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>

Как я могу уменьшить задержку аудиопотока? Я использую правильные классы, или есть другой / лучший подход к этой проблеме?

Кроме того: кажется, что аудиовход поступает не через микрофон Bluetooth, а через аппаратный микрофон Android - но это не идея.Как я могу направить чтение аудиовхода на микрофон Bluetooth вместо считывания с внутреннего?

Ответы на вопрос(0)

Ваш ответ на вопрос