Implementation Example of Audio Acquisition in Android Audio Development
- 2021-08-31 09:19:31
- OfStack
In an Android system, AudioRecord or MediaRecord is generally used to collect audio.
AudioRecord is a relatively low-level API, which can obtain one frame of PCM data, and then process these data.
MediaRecorder is an API based on AudioRecorder (AudioRecord will eventually be created to interact with AudioFlinger), which can directly convert the collected audio data into the encoding format for execution and save it.
The live broadcast technology uses AudioRecorder to collect audio data.
This paper mainly introduces, for example, AudioRecord for audio acquisition.
Basic API
Gets the minimum buffer size for storing audio data collected by AudioRecord.
static public int getMinBufferSize(int sampleRateInHz, int channelConfig, int audioFormat)
AudioRecord construction method
According to the specific parameter configuration, request hardware resources to create an AudioRecord object that can be used to collect audio.
Parameter description:
Basic Concepts of Audio Acquisition
Audio acquisition 1 generally uses AudioRecod or MediaRecord
What is the source of audio acquisition?
MediaRecorder. AudioSource. MIC 1 is generally a microphone
Sampling rate (in Hertz)
Number of audio sampling points per second (8000/44100 Hz)
Vocal tract
AudioFormat.CHANNEL_IN_MONO Mono, 1 channel for sampling AudioFormat.CHANNEL_IN_STEREO two channels, two channels for sampling
Audio sampling accuracy
Specifies the format of sampled data and the size of each sample.
The data return format is PCM format
The bit width of each sample is 16bit
1 generally uses this AudioFormat.ENCODING_PCM_16BIT (official documentation indicates that this sampling accuracy is guaranteed to be supported by all devices)
Bit rate
Number of bits transmitted per second (bit). The unit is bps (Bit Per Second). The higher the bit rate, the faster the data transmission speed.
Sampling rate x sampling size x channel number
Sample size per second = 16bit (bit width) 2 (dual channel) 44100 (number of times per sample hz) = 1411200b = 1411.2 kbps
The larger the bit rate, the more data sampled and the larger the amount of data transmitted in a unit time.
audioResource
Sources of audio acquisition
audioSampleRate
Audio sampling rate
channelConfig
Vocal tract
audioFormat
Audio sampling accuracy, specifying the format of sampled data and the size of each sample.
bufferSizeInBytes
Buffer size of audio data collected by AudioRecord.
// Set the acquisition source to microphone
private static final int AUDIO_RESOURCE = MediaRecorder.AudioSource.MIC;
// Set the sampling rate to 44100 The current sampling rate is commonly used, and the official document indicates that this value can be compatible with all settings
private final static int AUDIO_SAMPLE_RATE = 44100;
// Set the number of channels to two channels
private final static int CHANNEL_CONFIG = AudioFormat.CHANNEL_IN_STEREO;
// Set the sampling accuracy, and set the sampled data to PCM Encoding is performed, and the bit width of data collected each time is 16bit .
private final static int AUDIO_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
public AudioRecord(int audioSource, int sampleRateInHz, int channelConfig, int audioFormat, int bufferSizeInBytes)
Start collecting
After starting the acquisition, the state changes to RECORDSTATE_RECORDING.
public void startRecording ()
Read the recorded content, and read the collected data to the buffer
The status code of the return value of the method call:
Abnormal situation:
1.ERROR_INVALID_OPERATION if the object wasn't properly initialized
2.ERROR_BAD_VALUE if the parameters don't resolve to valid data and indexes.
Condition is normal: the number of bytes that were read
public int read (ByteBuffer audioBuffer, int sizeInBytes)
public int read (byte[] audioData, int offsetInBytes, int sizeInBytes)
public int read (short[] audioData, int offsetInShorts, int sizeInShorts)
Stop acquisition
After the acquisition is stopped, the state changes to RECORDSTATE_STOPPED.
public void stop ()
Get the status of AudioRecord
Used to detect whether the AudioRecord ensures that appropriate hardware resources are obtained. Called after the AudioRecord object is instantiated.
STATE_INITIALIZED Initial complete
STATE_UNINITIALIZED not initialized
public int getState ()
Returns the current acquisition status of AudioRecord
public static final int RECORDSTATE_STOPPED = 1; Stop state
State after calling void stop ()
public static final int RECORDSTATE_RECORDING = 3; Collecting
State after calling startRecording ()
public int getRecordingState()
Basic Flow of AudioRecord Audio Acquisition
Authority
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Construct an AudioRecord object.
Start collecting.
Read the collected data.
Stop collecting.
Construct an AudioRecord object
AudioRecord audioRecord = new AudioRecord(audioResource, audioSampleRate, channelConfig, audioFormat, bufferSizeInBytes);
Get the bufferSizeInBytes value
bufferSizeInBytes is the buffer size of the audio data collected by AudioRecord.
Note: This size cannot be set casually. AudioRecord provides the corresponding API to get this value.
this.bufferSizeInBytes = AudioRecord.getMinBufferSize(audioSampleRate, channelConfig, audioFormat);
The bufferSizeInBytes return lets you know whether the parameters passed in to AudioRecord. getMinBufferSize support the current hardware device.
if (AudioRecord.ERROR_BAD_VALUE == bufferSizeInBytes || AudioRecord.ERROR == bufferSizeInBytes) {
throw new RuntimeException("Unable to getMinBufferSize");
}
//bufferSizeInBytes is available...
Start collecting
Before you start recording, you should first judge whether the state of AudioRecord under 1 has been initialized.
// Judge AudioRecord Is the state of initialized
// In AudioRecord After the object is constructed, it is in the AudioRecord.STATE_INITIALIZED State.
int state = audioRecord.getState();
if (state == AudioRecord.STATE_UNINITIALIZED) {
throw new RuntimeException("AudioRecord STATE_UNINITIALIZED");
}
Start collecting
audioRecord.startRecording();
// Open a thread to read data
new Thread(recordTask).start();
Read the collected data
As mentioned above, AudioRecord stores the data in the buffer when collecting data, so we only need to create a data stream to read the collected data from the buffer.
Create a data stream, read audio data from AudioRecord to the buffer, and write the data from the buffer to the data stream.
Because the IO operation is required, the process of reading data should be performed in child threads
public void startRecording ()
0
Stop acquisition
public void startRecording ()
1
A few small problems
After collecting data, the saved file is audio-record. pcm, which cannot be played by ordinary player. It is an original file without any playback format, so it cannot be recognized and played by the player.
There are two ways to solve the above problem
Play audio data in pcm format using AudioTrack. Convert pcm data into wav format data so that it can be recognized by the player.