Android 는 AudioRecord 로 녹음 을 합 니 다.
15733 단어 AndroidAudioRecord녹음 하 다.
1.simple Rate 샘플링 율,샘플링 율 은 샘플링 빈도 이 고 매 초 에 몇 개의 견본 을 기록 하 는 지 합 니 다.
2.channelConfig 채널 설정,사실은 이른바 단일 채널,이중 채널 과 같은,AudioFormat.CHANNELIN_MONO 단일 채널,AudioFormat.CHANNELIN_STEREO 2 채널,여 기 는 이 두 가지 만 열거 되 어 있 고 다른 것 도 있 으 니 스스로 찾 아 볼 수 있 습 니 다.
3.audioFormat 오디 오 형식,사실은 샘플링 의 정밀도,각 견본 의 자릿수,AudioFormat.ENCODINGPCM_8BIT 샘플 당 8 위,AudioFormat.ENCODINGPCM_16BIT 는 각 견본 이 16 위 를 차지 하 는데 여기 도 이 두 개 만 사 용 했 고 다른 것 은 연구 하지 않 았 다.
학습 과정 에서 사용 할 수 있 는 매개 변 수 는 다음 과 같 습 니 다.
public class AudioParams {
enum Format {
SINGLE_8_BIT, DOUBLE_8_BIT, SINGLE_16_BIT, DOUBLE_16_BIT
}
private Format format;
int simpleRate;
AudioParams(int simpleRate, Format f) {
this.simpleRate = simpleRate;
this.format = f;
}
AudioParams(int simpleRate, int channelCount, int bits) {
this.simpleRate = simpleRate;
set(channelCount, bits);
}
int getBits() {
return (format == Format.SINGLE_8_BIT || format == Format.DOUBLE_8_BIT) ? 8 : 16;
}
int getEncodingFormat() {
return (format == Format.SINGLE_8_BIT || format == Format.DOUBLE_8_BIT) ? AudioFormat.ENCODING_PCM_8BIT :
AudioFormat.ENCODING_PCM_16BIT;
}
int getChannelCount() {return (format == Format.SINGLE_8_BIT || format == Format.SINGLE_16_BIT) ? 1 : 2;}
int getChannelConfig() {
return (format == Format.SINGLE_8_BIT || format == Format.SINGLE_16_BIT) ? AudioFormat.CHANNEL_IN_MONO :
AudioFormat.CHANNEL_IN_STEREO;
}
int getOutChannelConfig() {
return (format == Format.SINGLE_8_BIT || format == Format.SINGLE_16_BIT) ? AudioFormat.CHANNEL_OUT_MONO :
AudioFormat.CHANNEL_OUT_STEREO;
}
void set(int channelCount, int bits) {
if ((channelCount != 1 && channelCount != 2) || (bits != 8 && bits != 16)) {
throw new IllegalArgumentException(" channelCount=$channelCount bits=$bits");
}
if (channelCount == 1) {
if (bits == 8) {
format = Format.SINGLE_8_BIT;
} else {
format = Format.SINGLE_16_BIT;
}
} else {
if (bits == 8) {
format = Format.DOUBLE_8_BIT;
} else {
format = Format.DOUBLE_16_BIT;
}
}
}
}
이곳 은 1 채널 8 비트,2 채널 8 비트,1 채널 16 비트,2 채널 16 비트 를 고정 적 으로 사용 하기 때문에 매 거 진 으로 제한 했다.녹음 데 이 터 를 꺼 내 표시 하고 저장 하 는 데 편리 하도록 여기에 리 셋 방법 을 다음 과 같이 썼 다.
public interface RecordCallback {
/**
*
*
* @param bytes
* @param len ,-1
*/
void onRecord(byte[] bytes, int len);
}
이런 매개 변수 가 있 으 면 지금 녹음 할 수 있 으 니 먼저 사례 를 보 세 요.
public void startRecord(AudioParams params, RecordCallback callback) {
int simpleRate = params.simpleRate;
int channelConfig = params.getChannelConfig();
int audioFormat = params.getEncodingFormat();
// AudioRecord api
int bufferSize = AudioRecord.getMinBufferSize(simpleRate, channelConfig, audioFormat);
// Record
record = new AudioRecord(MediaRecorder.AudioSource.MIC, simpleRate, channelConfig, audioFormat, bufferSize);
recordThread = new Thread(() -> {
byte[] buffer = new byte[bufferSize];
record.startRecording();
recording = true;
while (recording) {
int read = record.read(buffer, 0, bufferSize);
//
if (read > 0 && callback != null) {
callback.onRecord(buffer, read);
}
}
if (callback != null) {
// len -1
callback.onRecord(buffer, -1);
recording = false;
}
//
release();
});
recordThread.start();
}
이 방법 은 오디 오 데 이 터 를 간단하게 수집 하 는 것 입 니 다.이 데 이 터 는 가장 원시 적 인 pcm 데이터 입 니 다.pcm 데 이 터 를 받 은 후 파일 에 직접 저장 하면 재생 할 수 없습니다.이것 은 데이터 더미 이기 때문에 형식 설명 이 없습니다.일반 재생 기 를 재생 할 수 있 도록 하려 면 파일 에 파일 헤드 를 추가 하여 재생 기 라 는 데이터 의 형식 을 알려 야 합 니 다.여 기 는 wav 형식 으로 직접 저장 되 는 데이터 입 니 다.다음은 wav 형식 파일 헤드 를 추가 하 는 방법 입 니 다.
private static byte[] getWaveFileHeader(int totalDataLen, int sampleRate, int channelCount, int bits) {
byte[] header = new byte[44];
// RIFF/WAVE header
header[0] = 'R';
header[1] = 'I';
header[2] = 'F';
header[3] = 'F';
int fileLength = totalDataLen + 36;
header[4] = (byte) (fileLength & 0xff);
header[5] = (byte) (fileLength >> 8 & 0xff);
header[6] = (byte) (fileLength >> 16 & 0xff);
header[7] = (byte) (fileLength >> 24 & 0xff);
//WAVE
header[8] = 'W';
header[9] = 'A';
header[10] = 'V';
header[11] = 'E';
// 'fmt ' chunk
header[12] = 'f';
header[13] = 'm';
header[14] = 't';
header[15] = ' ';
// 4 bytes: size of 'fmt ' chunk
header[16] = 16;
header[17] = 0;
header[18] = 0;
header[19] = 0;
// pcm format = 1
header[20] = 1;
header[21] = 0;
header[22] = (byte) channelCount;
header[23] = 0;
header[24] = (byte) (sampleRate & 0xff);
header[25] = (byte) (sampleRate >> 8 & 0xff);
header[26] = (byte) (sampleRate >> 16 & 0xff);
header[27] = (byte) (sampleRate >> 24 & 0xff);
int byteRate = sampleRate * bits * channelCount / 8;
header[28] = (byte) (byteRate & 0xff);
header[29] = (byte) (byteRate >> 8 & 0xff);
header[30] = (byte) (byteRate >> 16 & 0xff);
header[31] = (byte) (byteRate >> 24 & 0xff);
// block align
header[32] = (byte) (channelCount * bits / 8);
header[33] = 0;
// bits per sample
header[34] = (byte) bits;
header[35] = 0;
//data
header[36] = 'd';
header[37] = 'a';
header[38] = 't';
header[39] = 'a';
header[40] = (byte) (totalDataLen & 0xff);
header[41] = (byte) (totalDataLen >> 8 & 0xff);
header[42] = (byte) (totalDataLen >> 16 & 0xff);
header[43] = (byte) (totalDataLen >> 24 & 0xff);
return header;
}
몇 개의 매개 변수 에 따라 파일 헤드 를 설정 한 다음 에 녹음 에서 수집 한 pcm 데 이 터 를 직접 기록 하면 정상적으로 재생 할 수 있 습 니 다.wav 파일 헤더 형식 정의오디 오 녹음 을 통 해 파일 에 직접 저장 하려 면 다음 방법 을 참고 하 세 요.
public void startRecord(String filePath, AudioParams params, RecordCallback callback) {
int channelCount = params.getChannelCount();
int bits = params.getBits();
final boolean storeFile = filePath != null && !filePath.isEmpty();
startRecord(params, (bytes, len) -> {
if (storeFile) {
if (file == null) {
File f = new File(filePath);
if (f.exists()) {
f.delete();
}
try {
file = new RandomAccessFile(f, "rw");
file.write(getWaveFileHeader(0, params.simpleRate, channelCount, bits));
} catch (IOException e) {
e.printStackTrace();
}
}
if (len > 0) {
try {
file.write(bytes, 0, len);
} catch (IOException e) {
e.printStackTrace();
}
} else {
try {
// ,
int length = (int) file.length() - 44;
file.seek(0);
file.write(getWaveFileHeader(length, params.simpleRate, channelCount, bits));
file.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
if (callback != null) {
callback.onRecord(bytes, len);
}
});
}
먼저 RandomAccessFile 을 통 해 파일 을 만 들 고 파일 헤더 에 먼저 기록 합 니 다.얼마나 녹음 할 지 모 르 기 때문에 pcm 데이터 가 얼마나 있 는 지,길 이 는 0 으로 표시 합 니 다.녹음 이 끝 난 후에 seek(int)방법 으로 파일 헤더 정 보 를 다시 기록 할 수도 있 습 니 다.먼저 pcm 데 이 터 를 임시 파일 에 저장 한 다음 에 새로운 파일 에 기록 할 수도 있 습 니 다.여기 서 예 를 들 어 설명 하지 않 습 니 다.마지막 으로 전체 종류의 코드 를 넣 습 니 다.
package cn.sskbskdrin.record.audio;
import android.media.AudioRecord;
import android.media.MediaRecorder;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
/**
* @author sskbskdrin
* @date 2019/April/3
*/
public class AudioRecordManager {
private AudioParams DEFAULT_FORMAT = new AudioParams(8000, 1, 16);
private AudioRecord record;
private Thread recordThread;
private boolean recording = false;
private RandomAccessFile file;
public void startRecord(String filePath, RecordCallback callback) {
startRecord(filePath, DEFAULT_FORMAT, callback);
}
public void startRecord(String filePath, AudioParams params, RecordCallback callback) {
int channelCount = params.getChannelCount();
int bits = params.getBits();
final boolean storeFile = filePath != null && !filePath.isEmpty();
startRecord(params, (bytes, len) -> {
if (storeFile) {
if (file == null) {
File f = new File(filePath);
if (f.exists()) {
f.delete();
}
try {
file = new RandomAccessFile(f, "rw");
file.write(getWaveFileHeader(0, params.simpleRate, channelCount, bits));
} catch (IOException e) {
e.printStackTrace();
}
}
if (len > 0) {
try {
file.write(bytes, 0, len);
} catch (IOException e) {
e.printStackTrace();
}
} else {
try {
// ,
int length = (int) file.length() - 44;
file.seek(0);
file.write(getWaveFileHeader(length, params.simpleRate, channelCount, bits));
file.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
if (callback != null) {
callback.onRecord(bytes, len);
}
});
}
public void startRecord(AudioParams params, RecordCallback callback) {
int simpleRate = params.simpleRate;
int channelConfig = params.getChannelConfig();
int audioFormat = params.getEncodingFormat();
// AudioRecord api
int bufferSize = AudioRecord.getMinBufferSize(simpleRate, channelConfig, audioFormat);
// Record
record = new AudioRecord(MediaRecorder.AudioSource.MIC, simpleRate, channelConfig, audioFormat, bufferSize);
recordThread = new Thread(() -> {
byte[] buffer = new byte[bufferSize];
record.startRecording();
recording = true;
while (recording) {
int read = record.read(buffer, 0, bufferSize);
//
if (read > 0 && callback != null) {
callback.onRecord(buffer, read);
}
}
if (callback != null) {
// len -1
callback.onRecord(buffer, -1);
recording = false;
}
//
release();
});
recordThread.start();
}
public void stop() {
recording = false;
}
public void release() {
recording = false;
if (record != null) {
record.stop();
record.release();
}
record = null;
file = null;
recordThread = null;
}
private static byte[] getWaveFileHeader(int totalDataLen, int sampleRate, int channelCount, int bits) {
byte[] header = new byte[44];
// RIFF/WAVE header
header[0] = 'R';
header[1] = 'I';
header[2] = 'F';
header[3] = 'F';
int fileLength = totalDataLen + 36;
header[4] = (byte) (fileLength & 0xff);
header[5] = (byte) (fileLength >> 8 & 0xff);
header[6] = (byte) (fileLength >> 16 & 0xff);
header[7] = (byte) (fileLength >> 24 & 0xff);
//WAVE
header[8] = 'W';
header[9] = 'A';
header[10] = 'V';
header[11] = 'E';
// 'fmt ' chunk
header[12] = 'f';
header[13] = 'm';
header[14] = 't';
header[15] = ' ';
// 4 bytes: size of 'fmt ' chunk
header[16] = 16;
header[17] = 0;
header[18] = 0;
header[19] = 0;
// pcm format = 1
header[20] = 1;
header[21] = 0;
header[22] = (byte) channelCount;
header[23] = 0;
header[24] = (byte) (sampleRate & 0xff);
header[25] = (byte) (sampleRate >> 8 & 0xff);
header[26] = (byte) (sampleRate >> 16 & 0xff);
header[27] = (byte) (sampleRate >> 24 & 0xff);
int byteRate = sampleRate * bits * channelCount / 8;
header[28] = (byte) (byteRate & 0xff);
header[29] = (byte) (byteRate >> 8 & 0xff);
header[30] = (byte) (byteRate >> 16 & 0xff);
header[31] = (byte) (byteRate >> 24 & 0xff);
// block align
header[32] = (byte) (channelCount * bits / 8);
header[33] = 0;
// bits per sample
header[34] = (byte) bits;
header[35] = 0;
//data
header[36] = 'd';
header[37] = 'a';
header[38] = 't';
header[39] = 'a';
header[40] = (byte) (totalDataLen & 0xff);
header[41] = (byte) (totalDataLen >> 8 & 0xff);
header[42] = (byte) (totalDataLen >> 16 & 0xff);
header[43] = (byte) (totalDataLen >> 24 & 0xff);
return header;
}
public interface RecordCallback {
/**
*
*
* @param bytes
* @param len ,-1
*/
void onRecord(byte[] bytes, int len);
}
}
잘못된 점 이 있 으 면 댓 글로 지적 해 주세요.이상 은 안 드 로 이 드 가 오디 오 레코드 로 녹음 하 는 상세 한 내용 입 니 다.안 드 로 이 드 오디 오 레코드 에 관 한 자 료 는 다른 관련 글 을 주목 하 세 요!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Bitrise에서 배포 어플리케이션 설정 테스트하기이 글은 Bitrise 광고 달력의 23일째 글입니다. 자체 또는 당사 등에서 Bitrise 구축 서비스를 사용합니다. 그나저나 며칠 전 Bitrise User Group Meetup #3에서 아래 슬라이드를 발표했...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.