[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:

committed by
Commit Bot

parent
5341aaccdb
commit
ce27875b83
1
AUTHORS
1
AUTHORS
@ -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>
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user