aboutsummaryrefslogtreecommitdiff
path: root/webrtc/modules/audio_device/android/java
diff options
context:
space:
mode:
authorhenrike@webrtc.org <henrike@webrtc.org@4adac7df-926f-26a2-2b94-8c16560cd09d>2013-12-11 21:42:44 +0000
committerhenrike@webrtc.org <henrike@webrtc.org@4adac7df-926f-26a2-2b94-8c16560cd09d>2013-12-11 21:42:44 +0000
commit9ee75e9c77b467e74e470905822d0279b0e8a639 (patch)
tree2a481ef9afe8a72bab714e16b94fbb57c7cbd61c /webrtc/modules/audio_device/android/java
parentf41f06b916adc58745d5c5dbbd6803c7566dbedd (diff)
downloadwebrtc-9ee75e9c77b467e74e470905822d0279b0e8a639.tar.gz
Enables mixing and matching Java and native audio. It is used for getting best of both worlds capabilities (AEC and low latency).
BUG=N/A R=fischman@webrtc.org, niklas.enbom@webrtc.org Review URL: https://webrtc-codereview.appspot.com/4189004 git-svn-id: http://webrtc.googlecode.com/svn/trunk@5270 4adac7df-926f-26a2-2b94-8c16560cd09d
Diffstat (limited to 'webrtc/modules/audio_device/android/java')
-rw-r--r--webrtc/modules/audio_device/android/java/src/org/webrtc/voiceengine/WebRtcAudioRecord.java197
-rw-r--r--webrtc/modules/audio_device/android/java/src/org/webrtc/voiceengine/WebRtcAudioTrack.java (renamed from webrtc/modules/audio_device/android/java/src/org/webrtc/voiceengine/WebRTCAudioDevice.java)203
2 files changed, 201 insertions, 199 deletions
diff --git a/webrtc/modules/audio_device/android/java/src/org/webrtc/voiceengine/WebRtcAudioRecord.java b/webrtc/modules/audio_device/android/java/src/org/webrtc/voiceengine/WebRtcAudioRecord.java
new file mode 100644
index 0000000000..9167af02a5
--- /dev/null
+++ b/webrtc/modules/audio_device/android/java/src/org/webrtc/voiceengine/WebRtcAudioRecord.java
@@ -0,0 +1,197 @@
+/*
+ * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+package org.webrtc.voiceengine;
+
+import java.nio.ByteBuffer;
+import java.util.concurrent.locks.ReentrantLock;
+
+import android.content.Context;
+import android.media.AudioFormat;
+import android.media.AudioManager;
+import android.media.AudioRecord;
+import android.media.MediaRecorder.AudioSource;
+import android.util.Log;
+
+class WebRtcAudioRecord {
+ private AudioRecord _audioRecord = null;
+
+ private Context _context;
+
+ private ByteBuffer _recBuffer;
+ private byte[] _tempBufRec;
+
+ private final ReentrantLock _recLock = new ReentrantLock();
+
+ private boolean _doRecInit = true;
+ private boolean _isRecording = false;
+
+ private int _bufferedRecSamples = 0;
+
+ WebRtcAudioRecord() {
+ try {
+ _recBuffer = ByteBuffer.allocateDirect(2 * 480); // Max 10 ms @ 48
+ // kHz
+ } catch (Exception e) {
+ DoLog(e.getMessage());
+ }
+
+ _tempBufRec = new byte[2 * 480];
+ }
+
+ @SuppressWarnings("unused")
+ private int InitRecording(int audioSource, int sampleRate) {
+ audioSource = AudioSource.VOICE_COMMUNICATION;
+ // get the minimum buffer size that can be used
+ int minRecBufSize = AudioRecord.getMinBufferSize(
+ sampleRate,
+ AudioFormat.CHANNEL_IN_MONO,
+ AudioFormat.ENCODING_PCM_16BIT);
+
+ // DoLog("min rec buf size is " + minRecBufSize);
+
+ // double size to be more safe
+ int recBufSize = minRecBufSize * 2;
+ // On average half of the samples have been recorded/buffered and the
+ // recording interval is 1/100s.
+ _bufferedRecSamples = sampleRate / 200;
+ // DoLog("rough rec delay set to " + _bufferedRecSamples);
+
+ // release the object
+ if (_audioRecord != null) {
+ _audioRecord.release();
+ _audioRecord = null;
+ }
+
+ try {
+ _audioRecord = new AudioRecord(
+ audioSource,
+ sampleRate,
+ AudioFormat.CHANNEL_IN_MONO,
+ AudioFormat.ENCODING_PCM_16BIT,
+ recBufSize);
+
+ } catch (Exception e) {
+ DoLog(e.getMessage());
+ return -1;
+ }
+
+ // check that the audioRecord is ready to be used
+ if (_audioRecord.getState() != AudioRecord.STATE_INITIALIZED) {
+ // DoLog("rec not initialized " + sampleRate);
+ return -1;
+ }
+
+ // DoLog("rec sample rate set to " + sampleRate);
+
+ return _bufferedRecSamples;
+ }
+
+ @SuppressWarnings("unused")
+ private int StartRecording() {
+ // start recording
+ try {
+ _audioRecord.startRecording();
+
+ } catch (IllegalStateException e) {
+ e.printStackTrace();
+ return -1;
+ }
+
+ _isRecording = true;
+ return 0;
+ }
+
+ @SuppressWarnings("unused")
+ private int StopRecording() {
+ _recLock.lock();
+ try {
+ // only stop if we are recording
+ if (_audioRecord.getRecordingState() ==
+ AudioRecord.RECORDSTATE_RECORDING) {
+ // stop recording
+ try {
+ _audioRecord.stop();
+ } catch (IllegalStateException e) {
+ e.printStackTrace();
+ return -1;
+ }
+ }
+
+ // release the object
+ _audioRecord.release();
+ _audioRecord = null;
+
+ } finally {
+ // Ensure we always unlock, both for success, exception or error
+ // return.
+ _doRecInit = true;
+ _recLock.unlock();
+ }
+
+ _isRecording = false;
+ return 0;
+ }
+
+ @SuppressWarnings("unused")
+ private int RecordAudio(int lengthInBytes) {
+ _recLock.lock();
+
+ try {
+ if (_audioRecord == null) {
+ return -2; // We have probably closed down while waiting for rec
+ // lock
+ }
+
+ // Set priority, only do once
+ if (_doRecInit == true) {
+ try {
+ android.os.Process.setThreadPriority(
+ android.os.Process.THREAD_PRIORITY_URGENT_AUDIO);
+ } catch (Exception e) {
+ DoLog("Set rec thread priority failed: " + e.getMessage());
+ }
+ _doRecInit = false;
+ }
+
+ int readBytes = 0;
+ _recBuffer.rewind(); // Reset the position to start of buffer
+ readBytes = _audioRecord.read(_tempBufRec, 0, lengthInBytes);
+ // DoLog("read " + readBytes + "from SC");
+ _recBuffer.put(_tempBufRec);
+
+ if (readBytes != lengthInBytes) {
+ // DoLog("Could not read all data from sc (read = " + readBytes
+ // + ", length = " + lengthInBytes + ")");
+ return -1;
+ }
+
+ } catch (Exception e) {
+ DoLogErr("RecordAudio try failed: " + e.getMessage());
+
+ } finally {
+ // Ensure we always unlock, both for success, exception or error
+ // return.
+ _recLock.unlock();
+ }
+
+ return _bufferedRecSamples;
+ }
+
+ final String logTag = "WebRTC AD java";
+
+ private void DoLog(String msg) {
+ Log.d(logTag, msg);
+ }
+
+ private void DoLogErr(String msg) {
+ Log.e(logTag, msg);
+ }
+}
diff --git a/webrtc/modules/audio_device/android/java/src/org/webrtc/voiceengine/WebRTCAudioDevice.java b/webrtc/modules/audio_device/android/java/src/org/webrtc/voiceengine/WebRtcAudioTrack.java
index c324b9c082..273d03f352 100644
--- a/webrtc/modules/audio_device/android/java/src/org/webrtc/voiceengine/WebRTCAudioDevice.java
+++ b/webrtc/modules/audio_device/android/java/src/org/webrtc/voiceengine/WebRtcAudioTrack.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
@@ -20,106 +20,34 @@ import android.media.AudioRecord;
import android.media.AudioTrack;
import android.util.Log;
-class WebRTCAudioDevice {
+class WebRtcAudioTrack {
private AudioTrack _audioTrack = null;
- private AudioRecord _audioRecord = null;
private Context _context;
private AudioManager _audioManager;
private ByteBuffer _playBuffer;
- private ByteBuffer _recBuffer;
private byte[] _tempBufPlay;
- private byte[] _tempBufRec;
private final ReentrantLock _playLock = new ReentrantLock();
- private final ReentrantLock _recLock = new ReentrantLock();
private boolean _doPlayInit = true;
private boolean _doRecInit = true;
private boolean _isRecording = false;
private boolean _isPlaying = false;
- private int _bufferedRecSamples = 0;
private int _bufferedPlaySamples = 0;
private int _playPosition = 0;
- WebRTCAudioDevice() {
+ WebRtcAudioTrack() {
try {
_playBuffer = ByteBuffer.allocateDirect(2 * 480); // Max 10 ms @ 48
// kHz
- _recBuffer = ByteBuffer.allocateDirect(2 * 480); // Max 10 ms @ 48
- // kHz
} catch (Exception e) {
DoLog(e.getMessage());
}
_tempBufPlay = new byte[2 * 480];
- _tempBufRec = new byte[2 * 480];
- }
-
- @SuppressWarnings("unused")
- private int InitRecording(int audioSource, int sampleRate) {
- // get the minimum buffer size that can be used
- int minRecBufSize = AudioRecord.getMinBufferSize(
- sampleRate,
- AudioFormat.CHANNEL_IN_MONO,
- AudioFormat.ENCODING_PCM_16BIT);
-
- // DoLog("min rec buf size is " + minRecBufSize);
-
- // double size to be more safe
- int recBufSize = minRecBufSize * 2;
- _bufferedRecSamples = (5 * sampleRate) / 200;
- // DoLog("rough rec delay set to " + _bufferedRecSamples);
-
- // release the object
- if (_audioRecord != null) {
- _audioRecord.release();
- _audioRecord = null;
- }
-
- try {
- _audioRecord = new AudioRecord(
- audioSource,
- sampleRate,
- AudioFormat.CHANNEL_IN_MONO,
- AudioFormat.ENCODING_PCM_16BIT,
- recBufSize);
-
- } catch (Exception e) {
- DoLog(e.getMessage());
- return -1;
- }
-
- // check that the audioRecord is ready to be used
- if (_audioRecord.getState() != AudioRecord.STATE_INITIALIZED) {
- // DoLog("rec not initialized " + sampleRate);
- return -1;
- }
-
- // DoLog("rec sample rate set to " + sampleRate);
-
- return _bufferedRecSamples;
- }
-
- @SuppressWarnings("unused")
- private int StartRecording() {
- if (_isPlaying == false) {
- SetAudioMode(true);
- }
-
- // start recording
- try {
- _audioRecord.startRecording();
-
- } catch (IllegalStateException e) {
- e.printStackTrace();
- return -1;
- }
-
- _isRecording = true;
- return 0;
}
@SuppressWarnings("unused")
@@ -181,10 +109,6 @@ class WebRTCAudioDevice {
@SuppressWarnings("unused")
private int StartPlayback() {
- if (_isRecording == false) {
- SetAudioMode(true);
- }
-
// start playout
try {
_audioTrack.play();
@@ -199,41 +123,6 @@ class WebRTCAudioDevice {
}
@SuppressWarnings("unused")
- private int StopRecording() {
- _recLock.lock();
- try {
- // only stop if we are recording
- if (_audioRecord.getRecordingState() ==
- AudioRecord.RECORDSTATE_RECORDING) {
- // stop recording
- try {
- _audioRecord.stop();
- } catch (IllegalStateException e) {
- e.printStackTrace();
- return -1;
- }
- }
-
- // release the object
- _audioRecord.release();
- _audioRecord = null;
-
- } finally {
- // Ensure we always unlock, both for success, exception or error
- // return.
- _doRecInit = true;
- _recLock.unlock();
- }
-
- if (_isPlaying == false) {
- SetAudioMode(false);
- }
-
- _isRecording = false;
- return 0;
- }
-
- @SuppressWarnings("unused")
private int StopPlayback() {
_playLock.lock();
try {
@@ -262,10 +151,6 @@ class WebRTCAudioDevice {
_playLock.unlock();
}
- if (_isRecording == false) {
- SetAudioMode(false);
- }
-
_isPlaying = false;
return 0;
}
@@ -273,8 +158,6 @@ class WebRTCAudioDevice {
@SuppressWarnings("unused")
private int PlayAudio(int lengthInBytes) {
- int bufferedSamples = 0;
-
_playLock.lock();
try {
if (_audioTrack == null) {
@@ -311,10 +194,6 @@ class WebRTCAudioDevice {
_bufferedPlaySamples -= (pos - _playPosition);
_playPosition = pos;
- if (!_isRecording) {
- bufferedSamples = _bufferedPlaySamples;
- }
-
if (written != lengthInBytes) {
// DoLog("Could not write all data to sc (written = " + written
// + ", length = " + lengthInBytes + ")");
@@ -327,52 +206,7 @@ class WebRTCAudioDevice {
_playLock.unlock();
}
- return bufferedSamples;
- }
-
- @SuppressWarnings("unused")
- private int RecordAudio(int lengthInBytes) {
- _recLock.lock();
-
- try {
- if (_audioRecord == null) {
- return -2; // We have probably closed down while waiting for rec
- // lock
- }
-
- // Set priority, only do once
- if (_doRecInit == true) {
- try {
- android.os.Process.setThreadPriority(
- android.os.Process.THREAD_PRIORITY_URGENT_AUDIO);
- } catch (Exception e) {
- DoLog("Set rec thread priority failed: " + e.getMessage());
- }
- _doRecInit = false;
- }
-
- int readBytes = 0;
- _recBuffer.rewind(); // Reset the position to start of buffer
- readBytes = _audioRecord.read(_tempBufRec, 0, lengthInBytes);
- // DoLog("read " + readBytes + "from SC");
- _recBuffer.put(_tempBufRec);
-
- if (readBytes != lengthInBytes) {
- // DoLog("Could not read all data from sc (read = " + readBytes
- // + ", length = " + lengthInBytes + ")");
- return -1;
- }
-
- } catch (Exception e) {
- DoLogErr("RecordAudio try failed: " + e.getMessage());
-
- } finally {
- // Ensure we always unlock, both for success, exception or error
- // return.
- _recLock.unlock();
- }
-
- return (_bufferedPlaySamples);
+ return _bufferedPlaySamples;
}
@SuppressWarnings("unused")
@@ -463,35 +297,6 @@ class WebRTCAudioDevice {
return level;
}
- private void SetAudioMode(boolean startCall) {
- int apiLevel = android.os.Build.VERSION.SDK_INT;
-
- if (_audioManager == null && _context != null) {
- _audioManager = (AudioManager)
- _context.getSystemService(Context.AUDIO_SERVICE);
- }
-
- if (_audioManager == null) {
- DoLogErr("Could not set audio mode - no audio manager");
- return;
- }
-
- // ***IMPORTANT*** When the API level for honeycomb (H) has been
- // decided,
- // the condition should be changed to include API level 8 to H-1.
- if ((android.os.Build.BRAND.equals("Samsung") ||
- android.os.Build.BRAND.equals("samsung")) &&
- (8 == apiLevel)) {
- // Set Samsung specific VoIP mode for 2.2 devices
- // 4 is VoIP mode
- int mode = (startCall ? 4 : AudioManager.MODE_NORMAL);
- _audioManager.setMode(mode);
- if (_audioManager.getMode() != mode) {
- DoLogErr("Could not set audio mode for Samsung device");
- }
- }
- }
-
final String logTag = "WebRTC AD java";
private void DoLog(String msg) {