[AndroidAudioRecord] Added audio format parameter to configure AudioRecord - JavaAudioDeviceModule

Added audio format field and set method to Builder. - WebRTCAudioRecord. Added audio format field, added to constructor. Default audio format value AudioFormat.ENCODING_PCM_16BIT. initRecord(), added how to calculate bytesPerFrame, depends on audioFormat.

First commit and contribution, updated AUTHORS file

Bug: None
Change-Id: I16f660d42350ec9ce2e329b239bd7f6324e76dfe
Reviewed-on: https://webrtc-review.googlesource.com/c/122302
Commit-Queue: Magnus Jedvert <magjed@webrtc.org>
Reviewed-by: Magnus Jedvert <magjed@webrtc.org>
Reviewed-by: Artem Titov <titovartem@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#26775}
This commit is contained in:
Alvaro Martinez
2019-02-19 08:57:52 +01:00
committed by Commit Bot
parent 5341aaccdb
commit ce27875b83
3 changed files with 49 additions and 15 deletions

View File

@ -108,3 +108,4 @@ Vewd Software AS <*@vewd.com>
Highfive, Inc. <*@highfive.com>
CoSMo Software Consulting, Pte Ltd <*@cosmosoftware.io>
Tuple, LLC <*@tuple.app>
Videona Socialmedia <*@videona.com>

View File

@ -31,6 +31,7 @@ public class JavaAudioDeviceModule implements AudioDeviceModule {
private final AudioManager audioManager;
private int sampleRate;
private int audioSource = WebRtcAudioRecord.DEFAULT_AUDIO_SOURCE;
private int audioFormat = WebRtcAudioRecord.DEFAULT_AUDIO_FORMAT;
private AudioTrackErrorCallback audioTrackErrorCallback;
private AudioRecordErrorCallback audioRecordErrorCallback;
private SamplesReadyCallback samplesReadyCallback;
@ -65,6 +66,17 @@ public class JavaAudioDeviceModule implements AudioDeviceModule {
return this;
}
/**
* Call this to change the audio format. The argument should be one of the values from
* android.media.AudioFormat ENCODING_PCM_8BIT, ENCODING_PCM_16BIT or ENCODING_PCM_FLOAT.
* Default audio data format is PCM 16 bit per sample.
* Guaranteed to be supported by all devices.
*/
public Builder setAudioFormat(int audioFormat) {
this.audioFormat = audioFormat;
return this;
}
/**
* Set a callback to retrieve errors from the AudioTrack.
*/
@ -154,9 +166,9 @@ public class JavaAudioDeviceModule implements AudioDeviceModule {
}
Logging.d(TAG, "HW AEC will not be used.");
}
final WebRtcAudioRecord audioInput =
new WebRtcAudioRecord(context, audioManager, audioSource, audioRecordErrorCallback,
samplesReadyCallback, useHardwareAcousticEchoCanceler, useHardwareNoiseSuppressor);
final WebRtcAudioRecord audioInput = new WebRtcAudioRecord(context, audioManager, audioSource,
audioFormat, audioRecordErrorCallback, samplesReadyCallback,
useHardwareAcousticEchoCanceler, useHardwareNoiseSuppressor);
final WebRtcAudioTrack audioOutput =
new WebRtcAudioTrack(context, audioManager, audioTrackErrorCallback);
return new JavaAudioDeviceModule(context, audioManager, audioInput, audioOutput, sampleRate,

View File

@ -32,10 +32,6 @@ import org.webrtc.audio.JavaAudioDeviceModule.SamplesReadyCallback;
class WebRtcAudioRecord {
private static final String TAG = "WebRtcAudioRecordExternal";
// Default audio data format is PCM 16 bit per sample.
// Guaranteed to be supported by all devices.
private static final int BITS_PER_SAMPLE = 16;
// Requested size of each recorded buffer provided to the client.
private static final int CALLBACK_BUFFER_SIZE_MS = 10;
@ -53,9 +49,14 @@ class WebRtcAudioRecord {
public static final int DEFAULT_AUDIO_SOURCE = AudioSource.VOICE_COMMUNICATION;
// Default audio data format is PCM 16 bit per sample.
// Guaranteed to be supported by all devices.
public static final int DEFAULT_AUDIO_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
private final Context context;
private final AudioManager audioManager;
private final int audioSource;
private final int audioFormat;
private long nativeAudioRecord;
@ -145,13 +146,14 @@ class WebRtcAudioRecord {
@CalledByNative
WebRtcAudioRecord(Context context, AudioManager audioManager) {
this(context, audioManager, DEFAULT_AUDIO_SOURCE, null /* errorCallback */,
null /* audioSamplesReadyCallback */, WebRtcAudioEffects.isAcousticEchoCancelerSupported(),
this(context, audioManager, DEFAULT_AUDIO_SOURCE, DEFAULT_AUDIO_FORMAT,
null /* errorCallback */, null /* audioSamplesReadyCallback */,
WebRtcAudioEffects.isAcousticEchoCancelerSupported(),
WebRtcAudioEffects.isNoiseSuppressorSupported());
}
public WebRtcAudioRecord(Context context, AudioManager audioManager, int audioSource,
@Nullable AudioRecordErrorCallback errorCallback,
int audioFormat, @Nullable AudioRecordErrorCallback errorCallback,
@Nullable SamplesReadyCallback audioSamplesReadyCallback,
boolean isAcousticEchoCancelerSupported, boolean isNoiseSuppressorSupported) {
if (isAcousticEchoCancelerSupported && !WebRtcAudioEffects.isAcousticEchoCancelerSupported()) {
@ -163,6 +165,7 @@ class WebRtcAudioRecord {
this.context = context;
this.audioManager = audioManager;
this.audioSource = audioSource;
this.audioFormat = audioFormat;
this.errorCallback = errorCallback;
this.audioSamplesReadyCallback = audioSamplesReadyCallback;
this.isAcousticEchoCancelerSupported = isAcousticEchoCancelerSupported;
@ -203,7 +206,7 @@ class WebRtcAudioRecord {
reportWebRtcAudioRecordInitError("InitRecording called twice without StopRecording.");
return -1;
}
final int bytesPerFrame = channels * (BITS_PER_SAMPLE / 8);
final int bytesPerFrame = channels * getBytesPerSample(audioFormat);
final int framesPerBuffer = sampleRate / BUFFERS_PER_SECOND;
byteBuffer = ByteBuffer.allocateDirect(bytesPerFrame * framesPerBuffer);
if (!(byteBuffer.hasArray())) {
@ -221,8 +224,7 @@ class WebRtcAudioRecord {
// an AudioRecord object, in byte units.
// Note that this size doesn't guarantee a smooth recording under load.
final int channelConfig = channelCountToConfiguration(channels);
int minBufferSize =
AudioRecord.getMinBufferSize(sampleRate, channelConfig, AudioFormat.ENCODING_PCM_16BIT);
int minBufferSize = AudioRecord.getMinBufferSize(sampleRate, channelConfig, audioFormat);
if (minBufferSize == AudioRecord.ERROR || minBufferSize == AudioRecord.ERROR_BAD_VALUE) {
reportWebRtcAudioRecordInitError("AudioRecord.getMinBufferSize failed: " + minBufferSize);
return -1;
@ -235,8 +237,8 @@ class WebRtcAudioRecord {
int bufferSizeInBytes = Math.max(BUFFER_SIZE_FACTOR * minBufferSize, byteBuffer.capacity());
Logging.d(TAG, "bufferSizeInBytes: " + bufferSizeInBytes);
try {
audioRecord = new AudioRecord(audioSource, sampleRate, channelConfig,
AudioFormat.ENCODING_PCM_16BIT, bufferSizeInBytes);
audioRecord =
new AudioRecord(audioSource, sampleRate, channelConfig, audioFormat, bufferSizeInBytes);
} catch (IllegalArgumentException e) {
reportWebRtcAudioRecordInitError("AudioRecord ctor error: " + e.getMessage());
releaseAudioResources();
@ -363,4 +365,23 @@ class WebRtcAudioRecord {
errorCallback.onWebRtcAudioRecordError(errorMessage);
}
}
// Reference from Android code, AudioFormat.getBytesPerSample. BitPerSample / 8
// Default audio data format is PCM 16 bits per sample.
// Guaranteed to be supported by all devices
private static int getBytesPerSample(int audioFormat) {
switch (audioFormat) {
case AudioFormat.ENCODING_PCM_8BIT:
return 1;
case AudioFormat.ENCODING_PCM_16BIT:
case AudioFormat.ENCODING_IEC61937:
case AudioFormat.ENCODING_DEFAULT:
return 2;
case AudioFormat.ENCODING_PCM_FLOAT:
return 4;
case AudioFormat.ENCODING_INVALID:
default:
throw new IllegalArgumentException("Bad audio format " + audioFormat);
}
}
}