android - handy - smartphone mikrofon test



Ein umfangreiches Projekt: Streaming von Audio vom Mikrofon zum Android-Gerät (0)

Ich möchte Audio-Input von einem Bluetooth-Mikrofon nehmen und es laut ausstrahlen - wie ein Megaphon oder ein einfaches PA-System - und es in Echtzeit senden .

Zu diesem Zweck verwende ich die AudioRecord- und AudioTrack-Klassen - da MediaRecorder und MediaPlayer in eine externe Datei schreibt und liest, was ich mir vorstellen könnte, verzögert das Audio viel mehr als nötig (ist das wahr?).

Ich habe die Idee, irgendwelche Bluetooth-Klassen zu verwenden, verworfen, da die Android-API das Android-Gerät als Sink in einem Source / Sink-Szenario (zumindest noch nicht) nicht unterstützt und dann eine native Programmierung der Android-Bibliotheken erfordern würde stimmt auch, oder?)

Jetzt. Die App funktioniert , aber die Verzögerung ist viel zu lang und die App soll Audio in Echtzeit abspielen.

Meine erste Frage ist: Sind AudioRecord / AudioTrack die richtigen Klassen für diesen Zweck (Streaming Audio über ein Bluetooth-Mikrofon zu den Gerätelautsprechern und spielen es laut in Echtzeit)?

Und wenn ja: Wie kann ich die Verzögerung des Audiosignals verringern, so dass es das Audiosignal von einem Mikrofon in Echtzeit streamt ? Der gesamte Code ist hier aufgelistet, also bitte hilf dir selbst:

In Manifest ist eine Berechtigung zum Aufzeichnen von Audio erforderlich.

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

Ich habe eine dedizierte Klasse, die einen Thread für den Umgang mit Audio hier erweitert:

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

}

Und meine Hauptklasse verfügt über anklickbare Schaltflächen, die start / stop-Methoden im Audiostream aufrufen:

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

}

Welche werden durch ein grafisches Layout mit Schaltflächen wie folgt angezeigt:

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

Wie kann ich die Verzögerung im Audiostream verringern? Verwende ich die richtigen Klassen oder gibt es einen anderen / besseren Ansatz für dieses Problem?

Außerdem: Der Audio-Eingang scheint nicht durch das eigentliche Bluetooth-Mikrofon, sondern vom Android-Hardware-Mikrofon zu kommen - was nicht die Idee ist. Wie kann ich den Audioeingang zum Bluetooth-Mikrofon leiten, anstatt den internen zu lesen?





android-audiorecord