Merge "AudioRecord builder"

This commit is contained in:
Jean-Michel Trivi
2015-03-26 18:07:50 +00:00
committed by Android (Google) Code Review
4 changed files with 187 additions and 4 deletions

View File

@@ -14610,6 +14610,14 @@ package android.media {
field public static final int SUCCESS = 0; // 0x0
}
public static class AudioRecord.Builder {
ctor public AudioRecord.Builder();
method public android.media.AudioRecord build() throws java.lang.UnsupportedOperationException;
method public android.media.AudioRecord.Builder setAudioFormat(android.media.AudioFormat) throws java.lang.IllegalArgumentException;
method public android.media.AudioRecord.Builder setBufferSizeInBytes(int) throws java.lang.IllegalArgumentException;
method public android.media.AudioRecord.Builder setCapturePreset(int) throws java.lang.IllegalArgumentException;
}
public static abstract interface AudioRecord.OnRecordPositionUpdateListener {
method public abstract void onMarkerReached(android.media.AudioRecord);
method public abstract void onPeriodicNotification(android.media.AudioRecord);

View File

@@ -15808,6 +15808,16 @@ package android.media {
field public static final int SUCCESS = 0; // 0x0
}
public static class AudioRecord.Builder {
ctor public AudioRecord.Builder();
method public android.media.AudioRecord build() throws java.lang.UnsupportedOperationException;
method public android.media.AudioRecord.Builder setAudioAttributes(android.media.AudioAttributes) throws java.lang.IllegalArgumentException;
method public android.media.AudioRecord.Builder setAudioFormat(android.media.AudioFormat) throws java.lang.IllegalArgumentException;
method public android.media.AudioRecord.Builder setBufferSizeInBytes(int) throws java.lang.IllegalArgumentException;
method public android.media.AudioRecord.Builder setCapturePreset(int) throws java.lang.IllegalArgumentException;
method public android.media.AudioRecord.Builder setSessionId(int) throws java.lang.IllegalArgumentException;
}
public static abstract interface AudioRecord.OnRecordPositionUpdateListener {
method public abstract void onMarkerReached(android.media.AudioRecord);
method public abstract void onPeriodicNotification(android.media.AudioRecord);

View File

@@ -20,6 +20,7 @@ import java.lang.ref.WeakReference;
import java.nio.ByteBuffer;
import java.util.Iterator;
import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.os.Binder;
import android.os.Handler;
@@ -313,8 +314,14 @@ public class AudioRecord
audioParamCheck(attributes.getCapturePreset(), rate, encoding);
mChannelCount = AudioFormat.channelCountFromInChannelMask(format.getChannelMask());
mChannelMask = getChannelMaskFromLegacyConfig(format.getChannelMask(), false);
int channelMask = AudioFormat.CHANNEL_IN_DEFAULT;
if ((format.getPropertySetMask()
& AudioFormat.AUDIO_FORMAT_HAS_PROPERTY_CHANNEL_MASK) != 0)
{
channelMask = format.getChannelMask();
}
mChannelCount = AudioFormat.channelCountFromInChannelMask(channelMask);
mChannelMask = getChannelMaskFromLegacyConfig(channelMask, false);
audioBuffSizeCheck(bufferSizeInBytes);
@@ -335,6 +342,161 @@ public class AudioRecord
mState = STATE_INITIALIZED;
}
/**
* Builder class for {@link AudioRecord} objects.
* Use this class to configure and create an <code>AudioRecord</code> instance. By setting the
* recording preset (a.k.a. recording source) and audio format parameters, you indicate which of
* those vary from the default behavior on the device.
* <p> Here is an example where <code>Builder</code> is used to specify all {@link AudioFormat}
* parameters, to be used by a new <code>AudioRecord</code> instance:
*
* <pre class="prettyprint">
* AudioRecord recorder = new AudioRecord.Builder()
* .setCapturePreset(MediaRecorder.AudioSource.VOICE_COMMUNICATION)
* .setAudioFormat(new AudioFormat.Builder()
* .setEncoding(AudioFormat.ENCODING_PCM_16BIT)
* .setSampleRate(32000)
* .setChannelMask(AudioFormat.CHANNEL_IN_MONO)
* .build())
* .setBufferSize(2*minBuffSize)
* .build();
* </pre>
* <p>
* If the capture preset is not set with {@link #setCapturePreset(int)},
* {@link MediaRecorder.AudioSource#DEFAULT} is used.
* <br>If the audio format is not specified or is incomplete, its sample rate will be the
* default output sample rate of the device (see
* {@link AudioManager#PROPERTY_OUTPUT_SAMPLE_RATE}), its channel configuration will be
* {@link AudioFormat#CHANNEL_IN_DEFAULT}.
* <br>Failing to set an adequate buffer size with {@link #setBufferSizeInBytes(int)} will
* prevent the successful creation of an <code>AudioRecord</code> instance.
*/
public static class Builder {
private AudioAttributes mAttributes;
private AudioFormat mFormat;
private int mBufferSizeInBytes;
private int mSessionId = AudioManager.AUDIO_SESSION_ID_GENERATE;
/**
* Constructs a new Builder with the default values as described above.
*/
public Builder() {
}
/**
* @param preset the capture preset (also referred to as the recording source).
* See {@link MediaRecorder.AudioSource} for the supported capture preset definitions.
* @return the same Builder instance.
* @throws IllegalArgumentException
*/
public Builder setCapturePreset(int preset) throws IllegalArgumentException {
if ( (preset < MediaRecorder.AudioSource.DEFAULT) ||
(preset > MediaRecorder.getAudioSourceMax()) ) {
throw new IllegalArgumentException("Invalid audio source " + preset);
}
mAttributes = new AudioAttributes.Builder()
.setInternalCapturePreset(preset)
.build();
return this;
}
/**
* @hide
* To be only used by system components. Allows specifying non-public capture presets
* @param attributes a non-null {@link AudioAttributes} instance that contains the capture
* preset to be used.
* @return the same Builder instance.
* @throws IllegalArgumentException
*/
@SystemApi
public Builder setAudioAttributes(@NonNull AudioAttributes attributes)
throws IllegalArgumentException {
if (attributes == null) {
throw new IllegalArgumentException("Illegal null AudioAttributes argument");
}
if (attributes.getCapturePreset() == MediaRecorder.AudioSource.AUDIO_SOURCE_INVALID) {
throw new IllegalArgumentException(
"No valid capture preset in AudioAttributes argument");
}
// keep reference, we only copy the data when building
mAttributes = attributes;
return this;
}
/**
* Sets the format of the audio data to be captured.
* @param format a non-null {@link AudioFormat} instance
* @return the same Builder instance.
* @throws IllegalArgumentException
*/
public Builder setAudioFormat(@NonNull AudioFormat format) throws IllegalArgumentException {
if (format == null) {
throw new IllegalArgumentException("Illegal null AudioFormat argument");
}
// keep reference, we only copy the data when building
mFormat = format;
return this;
}
/**
* Sets the total size (in bytes) of the buffer where audio data is written
* during the recording. New audio data can be read from this buffer in smaller chunks
* than this size. See {@link #getMinBufferSize(int, int, int)} to determine the minimum
* required buffer size for the successful creation of an AudioRecord instance.
* Using values smaller than getMinBufferSize() will result in an initialization failure.
* @param bufferSizeInBytes a value strictly greater than 0
* @return the same Builder instance.
* @throws IllegalArgumentException
*/
public Builder setBufferSizeInBytes(int bufferSizeInBytes) throws IllegalArgumentException {
if (bufferSizeInBytes <= 0) {
throw new IllegalArgumentException("Invalid buffer size " + bufferSizeInBytes);
}
mBufferSizeInBytes = bufferSizeInBytes;
return this;
}
/**
* @hide
* To be only used by system components.
* @param sessionId ID of audio session the AudioRecord must be attached to, or
* {@link AudioManager#AUDIO_SESSION_ID_GENERATE} if the session isn't known at
* construction time.
* @return the same Builder instance.
* @throws IllegalArgumentException
*/
@SystemApi
public Builder setSessionId(int sessionId) throws IllegalArgumentException {
if (sessionId < 0) {
throw new IllegalArgumentException("Invalid session ID " + sessionId);
}
mSessionId = sessionId;
return this;
}
/**
* @return a new {@link AudioRecord} instance initialized with all the parameters set
* on this <code>Builder</code>
* @throws UnsupportedOperationException if the parameters set on the <code>Builder</code>
* were incompatible, or if they are not supported by the device.
*/
public AudioRecord build() throws UnsupportedOperationException {
if (mFormat == null) {
mFormat = new AudioFormat.Builder().build();
}
if (mAttributes == null) {
mAttributes = new AudioAttributes.Builder()
.setInternalCapturePreset(MediaRecorder.AudioSource.DEFAULT)
.build();
}
try {
return new AudioRecord(mAttributes, mFormat, mBufferSizeInBytes, mSessionId);
} catch (IllegalArgumentException e) {
throw new UnsupportedOperationException(e.getMessage());
}
}
}
// Convenience method for the constructor's parameter checks.
// This, getChannelMaskFromLegacyConfig and audioBuffSizeCheck are where constructor
// IllegalArgumentException-s are thrown

View File

@@ -157,8 +157,11 @@ public class MediaRecorder
}
/**
* Defines the audio source. These constants are used with
* {@link MediaRecorder#setAudioSource(int)}.
* Defines the audio source.
* An audio source defines both a default physical source of audio signal, and a recording
* configuration; it's also known as a capture preset. These constants are for instance used
* in {@link MediaRecorder#setAudioSource(int)} or
* {@link AudioRecord.Builder#setCapturePreset(int)}.
*/
public final class AudioSource {