2011-01-16 13 views
4

Ich habe mich mit der AudioRecord-Funktion der Android-API beschäftigt und einige merkwürdige Verhaltensweisen gefunden.Android AudioRecord Fragen?

Hintergrundinfo: Mein Telefon ist ein HTC Incredible Ich benutze das Eclipse-Plugin für die Android-Entwicklung mit dem Emulator. Gezielte Plattform oder OS ist 2.2 ... Da ist es was mein Handy benutzt.

Einige Code:

bufferSize = AudioRecord.getMinBufferSize(FREQUENCY, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT); 
audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC, FREQUENCY, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT, bufferSize); 

Dies ist der Code, den ich zu Setup verwenden die AudioRecord API mit. Nun, für den Emulator mag es, dass FREQUENCY auf 8000 gesetzt wird, damit es funktioniert. Kommt mit einer Puffergröße von 640 zurück. Für das Telefon verwende ich 44100. Ein Problem hier scheint, dass die resultierenden PCM-Daten für die Welle eine acht Bit signierte Welle zu sein scheinen. Ich bekomme Werte von -127 bis 128. Ich dachte, der Wert AudioFormat.ENCODING_PCM_16BIT würde etwas anderes produzieren.

I verarbeitet die Audio mit einem Gewinde,

public void run() { 
    while(isRecording) { 
    audioRecord.startRecording(); 
    byte[] data = new byte[bufferSize]; 
    audioRecord.read(data, 0, bufferSize); 
    listener.setData(data); 
    handleData(data); 
    } 
    audioRecord.release(); 
} 

Ich habe eine Art und Weise in Echtzeit grafisch mit Hilfe eines SurfaceView zu entsprechenden Wellen anzuzeigen. Es scheint eine Menge Lärm vom MIC zu kommen. Ich bekomme dieses Geräusch vom Emulator und vom Telefon. Muss ich die Daten durch einen oder mehrere Filter laufen lassen? Ich würde gerne diese Daten verwenden, um etwas Spaß FFT und Sachen zu berechnen, nur um mit der Welle herumzuspielen. Aber ich muss irgendwie den Lärm reduzieren.

Hat jemand anderes dies auch erlebt. Hat jemand eine Lösung?

schätzte ich Ihre Zeit und Antworten, Dank, dk

Antwort

3

ich in der Lage vielleicht ein kleines bisschen zu helfen. Ich bin jedoch in der gleichen Situation wie du, also kann ich nur über meine Erfahrungen berichten.

Ich glaube, Sie auf Ihrem Gerät bevorzugt sample wie so erhalten können:

int sampleRate = AudioTrack.getNativeOutputSampleRate(AudioManager.STREAM_SYSTEM); 

Der 16Bit-Codierungsmodus die einzige ist, die mit AudioRecord arbeitet. Ich bin nicht sicher, warum Sie 8Bit wie Ausgabe bekommen (richtig?). Vielleicht weiß es jemand.

Ich bin auch unsicher, wie Sie die Amplitude aus den abgerufenen Bytes ziehen, haben Sie das getan?

Schließlich glaube ich, müssen Sie die periodischen Listener-Funktionen verwenden, etwa so:

int sampleRate = AudioTrack.getNativeOutputSampleRate(AudioManager.STREAM_SYSTEM); 
int channelMode = AudioFormat.CHANNEL_IN_MONO; 
int encodingMode = AudioFormat.ENCODING_PCM_16BIT; 
int bufferSize = AudioRecord.getMinBufferSize(sampleRate, channelMode, encodingMode); 

AudioRecord recorder = new AudioRecord(MediaRecorder.AudioSource.MIC, sampleRate, channelMode, encodingMode, bufferSize); 

recorder.setPositionNotificationPeriod(intervalFrames); 
recorder.setRecordPositionUpdateListener(recordListener); 
recorder.startRecording(); 

private RecordListener recordListener = new RecordListener(); 
private class RecordListener implements AudioRecord.OnRecordPositionUpdateListener { 
    public void onMarkerReached(AudioRecord recorder) { 
     Log.v("MicInfoService", "onMarkedReached CALL"); 
    } 

    public void onPeriodicNotification(AudioRecord recorder) { 
     Log.v("MicInfoService", "onPeriodicNotification CALL"); 
    } 
} 

Es gibt zwei große Fragen hier, die ich nicht beantworten kann und will die Antwort von mir wissen, wie gut:

  1. Was sollte als intervalFrames eingestellt werden?
  2. Warum werden die Listener-Methoden nie aufgerufen?

Ich wünschte, ich könnte mehr helfen.

+0

Ich habe das Rauschen mit einigen FFT-Techniken reduziert und habe einige Codebeispiele dazu. Ich bin gerade unterwegs, möchte aber die Diskussion fortsetzen, wenn ich zurück bin. Danke für deinen Beitrag. – dakira

+3

intervalFrames ist die Anzahl der Stichproben, für die Sie benachrichtigt werden möchten. Wenn Sie Stichproben bei 8000 durchführen, ruft intervalFrames = 4000 Ihren Benachrichtigungs-Listener alle 1/(8000/4000) = 0,5 Sekunden auf. Sie müssen Ihren Lesevorgang für die Listener-Funktion starten, die aufgerufen werden soll. Außerdem müssen Sie sicherstellen, dass Ihre Lesepuffergröße> = intervalFrames ist. –

+1

+1 für getNativeOutputSampleRate(); Wie hast du dein Problem gelöst? Ich kämpfe auch mit ähnlichen Problemen? http://stackoverflow.com/questions/9413998/live-audio-recording-and-play-in-android – aProgrammer

9

Es ist eine Weile her, seit diese Frage gestellt wurde, also weiß ich nicht, ob die Antwort mehr relevant ist.

Der Grund Sie Werte von -127 bis 128 erhalten ist, dass Sie in ein Array von Bytes lesen, von denen jeder eine signierte 8-Bit-Zahl zu halten. Für 16-Bit-Audio lesen Sie eine Reihe von Kurzschlüssen.

Ich fürchte, ich nicht mit dem Lärm Problem helfen kann.

+4

Peter genannt, denken Sie darüber nach, wenn er das untere Byte jedes Samples verwendet, dann wären diese Werte sehr verrauscht, wenn man bedenkt, dass es 8 weitere Bytes mit höherer Amplitudeninformation geben soll. Diese Information wäre konsistenter. Ich gehe davon aus, dass die "kurze" Einstellung auch das Geräuschproblem behebt. –

+0

@ Mike, ich habe auch ein ähnliches Problem, bitte sehen Sie meine Frage bei http: //stackoverflow.com/questions/9413998/live-audio-recording-and-play-in-android#comment12005651_9413998 .... Hilfe !!! – aProgrammer

12

Wenn Sie Bytes aus einem "AudioFormat.ENCODING_PCM_16BIT" -Stream lesen, gibt es tatsächlich sowohl das obere als auch das untere Byte jeder Stichprobe als 2 sequentielle Bytes. Dies wird extrem laut erscheinen, wenn Sie jedes Byte nur als Beispiel nehmen (anstelle des halben Samples, das es tatsächlich ist), und die Signierung wird für das erste Byte falsch sein (es ist in Little-Endian-Reihenfolge).

Um aussagekräftige Daten aus dem Stream zu bekommen, über Shorts lesen, z.B.

public void run() { 
    while(isRecording) { 
    audioRecord.startRecording(); 
    short[] data = new short[bufferSize/2]; 
    audioRecord.read(data, 0, bufferSize/2); 
    listener.setData(data); 
    handleData(data); 
    } 
    audioRecord.release(); 
} 
+0

Was macht der Hörer in diesem Fall ....? Ich habe auch ähnliches Problem bitte sehen Sie meine Frage an http://stackoverflow.com/questions/9413998/live-audio-recording-and-play-in-android#comment12005651_9413998 – aProgrammer