it-swarm.com.de

Tonwiedergabe vom Mikrofon in Echtzeit

Ich habe versucht, meine Anwendung dazu zu bringen, den Ton vom Mikrofon aufzunehmen und (ungefähr) in Echtzeit abzuspielen, jedoch ohne Erfolg.

Ich verwende AudioRecord- und AudioTrack-Klassen für die Aufnahme bzw. Wiedergabe. Ich habe verschiedene Ansätze ausprobiert, ich habe versucht, den eingehenden Ton aufzunehmen und in eine Datei zu schreiben, und es hat gut funktioniert. Ich habe auch versucht, Ton aus dieser Datei nach AudioTrack wiederzugeben, und es hat auch gut funktioniert. Das Problem ist, wenn ich versuche, den Sound in Echtzeit abzuspielen, anstatt eine Datei nach dem Schreiben zu lesen.

Hier ist der Code:

//variables
private int audioSource = MediaRecorder.AudioSource.MIC;
private int samplingRate = 44100; /* in Hz*/
private int channelConfig = AudioFormat.CHANNEL_CONFIGURATION_MONO;
private int audioFormat = AudioFormat.ENCODING_PCM_16BIT;
private int bufferSize = AudioRecord.getMinBufferSize(samplingRate, channelConfig, audioFormat);
private int sampleNumBits = 16;
private int numChannels = 1;

// …

AudioRecord recorder = new AudioRecord(audioSource, samplingRate, channelConfig, audioFormat, bufferSize);
                recorder.startRecording();
                isRecording = true;

AudioTrack audioPlayer = new AudioTrack(AudioManager.STREAM_MUSIC, 44100, AudioFormat.CHANNEL_CONFIGURATION_MONO,
                        AudioFormat.ENCODING_PCM_16BIT, bufferSize, AudioTrack.MODE_STREAM);

if(audioPlayer.getPlayState() != AudioTrack.PLAYSTATE_PLAYING)
    audioPlayer.play();

//capture data and record to file
int readBytes=0, writtenBytes=0;
do{
   readBytes = recorder.read(data, 0, bufferSize);

   if(AudioRecord.ERROR_INVALID_OPERATION != readBytes){
      writtenBytes += audioPlayer.write(data, 0, readBytes);
   }
}
while(isRecording);

Es wird eine Java.lang.IllegalStateException ausgelöst, deren Ursache durch "play () bei einem nicht initialisierten AudioTrack-Aufruf" verursacht wird.

Wenn ich jedoch die AudioTrack-Initialisierung für die Verwendung einer Abtastrate von 8000 Hz und eines Abtastformats von 8 Bit (anstelle von 16) ändere, wird die Ausnahme nicht mehr ausgelöst, und die Anwendung wird ausgeführt, obwohl sie schreckliches Rauschen erzeugt.

Wenn ich AudioTrack von einer Datei aus wiedergebe, gibt es kein Problem mit der Initialisierung des AudioTrack. Ich habe 44100 und 16 Bit ausprobiert, und es funktionierte einwandfrei und erzeugte den richtigen Ton.

Irgendeine Hilfe ?

30
Jonny

Das gesamte native Android-Audio ist codiert . Sie können nur PCM -formate in Echtzeit abspielen oder einen speziellen Streaming - Codec verwenden, der auf Android nicht trivial ist.

Wenn Sie Audio gleichzeitig aufnehmen und wiedergeben möchten, müssen Sie einen eigenen Audiopuffer erstellen und rohe, PCM-codierte Audio-Samples dort speichern (ich bin nicht sicher, ob Sie an duh denken! oder ob das alles über dem Kopf ist, also versuche ich klar zu sein, aber nicht, um dein eigenes Kaugummi zu kauen.

PCM ist eine digitale Darstellung eines analogen Signals, in dem Ihr Audio Samples eine Menge von "Schnappschüssen" der ursprünglichen akustischen Welle ist. Da alle möglichen klugen Mathematiker und Ingenieure das Potenzial erkannt haben, die Anzahl der Bits, mit denen diese Daten dargestellt werden, zu reduzieren, haben sie alle möglichen Arten von Encoder gefunden. Das codierte (komprimierte) Signal wird sehr unterschiedlich vom rohen PCM-Signal dargestellt und muss decodiert werden (en -cod -er + dec -oder = codec). Wenn Sie keine speziellen Algorithmen und Media-Streaming-Codecs verwenden, ist es unmöglich, ein codiertes Signal so wiederzugeben, wie Sie es versuchen, da es nicht von Sample zu Sample codiert wird, sondern von Frame zu Frame. Wenn nicht das komplette Signal, um diesen Frame zu decodieren.

Dazu können Sie Audio-Samples, die aus dem Mikrofonpuffer stammen, manuell speichern und manuell dem Ausgangspuffer zuführen. Sie müssen dafür einige Codierungen vornehmen, aber ich glaube, es gibt einige Open-Source-Apps, die Sie sich ansehen und einen Spitzenwert an der Quelle erzielen können (es sei denn, Sie möchten Ihre App später verkaufen, natürlich, aber das ist es eine ganz andere Diskussion).

Wenn Sie für Android 2.3 oder höher entwickeln und keine Angst vor der Programmierung in nativer Code haben, können Sie OpenSL ES ausprobieren. Die Android-spezifischen Funktionen von OpenSL ES sind hier aufgelistet. Diese Plattform ermöglicht Ihnen eine etwas flexiblere Audiomanipulation und Sie können genau das finden, was Sie brauchen, wenn Ihre App in hohem Maße von der Audiobearbeitung abhängt.

29
Phonon

Es wird eine Java.lang.IllegalStateException mit dem Grund .__ ausgelöst. verursacht durch "play () bei einem nicht initialisierten AudioTrack aufgerufen".

Es liegt daran, dass die Puffergröße zu klein ist. Ich habe versucht "bufferSize + = 2048;", dann ist es ok.

3
Haisea

Ich hatte ein ähnliches Problem und habe dieses Problem gelöst, indem ich der Manifestdatei diese Berechtigung hinzufügte:

<uses-permission Android:name="Android.permission.MODIFY_AUDIO_SETTINGS"/>
0
Ahmed