实时播放来自麦克风的音频 [英] Play Back audio from mic in real Time
问题描述
我有一个函数,可以记录音频并将其存储到文件中.这是它的样子:
I have a function , that records audio, and stores it into a file. This is what is looks like:
private void startRecord(){
File file = new File(Environment.getExternalStorageDirectory(), "test.pcm");
int sampleFreq = (Integer)spFrequency.getSelectedItem();
try {
file.createNewFile();
OutputStream outputStream = new FileOutputStream(file);
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(outputStream);
DataOutputStream dataOutputStream = new DataOutputStream(bufferedOutputStream);
int minBufferSize = AudioRecord.getMinBufferSize(sampleFreq,
AudioFormat.CHANNEL_CONFIGURATION_MONO,
AudioFormat.ENCODING_PCM_16BIT);
short[] audioData = new short[minBufferSize];
AudioRecord audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC,
sampleFreq,
AudioFormat.CHANNEL_CONFIGURATION_MONO,
AudioFormat.ENCODING_PCM_16BIT,
minBufferSize);
audioRecord.startRecording();
while(recording){
int numberOfShort = audioRecord.read(audioData, 0, minBufferSize);
for(int i = 0; i < numberOfShort; i++){
dataOutputStream.writeShort(audioData[i]);
}
}
audioRecord.stop();
dataOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
我有另一个函数,叫做 playrecord ,可以回放这个录制的音频:
I have another function, called playrecord , that plays back this recorded audio:
void playRecord(){
File file = new File(Environment.getExternalStorageDirectory(), "test.pcm");
int shortSizeInBytes = Short.SIZE/Byte.SIZE;
int bufferSizeInBytes = (int)(file.length()/shortSizeInBytes);
short[] audioData = new short[bufferSizeInBytes];
try {
InputStream inputStream = new FileInputStream(file);
BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
DataInputStream dataInputStream = new DataInputStream(bufferedInputStream);
int i = 0;
while(dataInputStream.available() > 0){
audioData[i] = dataInputStream.readShort();
i++;
}
dataInputStream.close();
int sampleFreq = (Integer)spFrequency.getSelectedItem();
AudioTrack audioTrack = new AudioTrack(
AudioManager.STREAM_MUSIC,
sampleFreq,
AudioFormat.CHANNEL_CONFIGURATION_MONO,
AudioFormat.ENCODING_PCM_16BIT,
bufferSizeInBytes,
AudioTrack.MODE_STREAM);
audioTrack.play();
audioTrack.write(audioData, 0, bufferSizeInBytes);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
这两个函数独立工作正常.如果我调用 startRecord() ,然后调用 playRecord,我可以听到音频.但我想要做的是实时回放声音,即一旦我开始录音,我就想要播放音频.我应该怎么做才能做到这一点?
These two functions work fine independently. If I call startRecord() , and then call playRecord, I am able to hear the audio. But what I want to do is, play back the sound in REAL TIME , i.e. as soon as I start recording, I want the audio to play. What should I do to achieve that ?
推荐答案
这对我有用:
boolean isRecording = false;
AudioManager am = null;
AudioRecord record = null;
AudioTrack track = null;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setVolumeControlStream(AudioManager.MODE_IN_COMMUNICATION);
initRecordAndTrack();
am = (AudioManager) this.getSystemService(Context.AUDIO_SERVICE);
am.setSpeakerphoneOn(true);
(new Thread()
{
@Override
public void run()
{
recordAndPlay();
}
}).start();
Button startButton = (Button) findViewById(R.id.start_button);
startButton.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View v)
{
if (!isRecording)
{
startRecordAndPlay();
}
}
});
Button stopButton = (Button) findViewById(R.id.stop_button);
stopButton.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View v)
{
if (isRecording)
{
stopRecordAndPlay();
}
}
});
}
private void initRecordAndTrack()
{
int min = AudioRecord.getMinBufferSize(8000, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT);
record = new AudioRecord(MediaRecorder.AudioSource.VOICE_COMMUNICATION, 8000, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT,
min);
if (AcousticEchoCanceler.isAvailable())
{
AcousticEchoCanceler echoCancler = AcousticEchoCanceler.create(record.getAudioSessionId());
echoCancler.setEnabled(true);
}
int maxJitter = AudioTrack.getMinBufferSize(8000, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT);
track = new AudioTrack(AudioManager.MODE_IN_COMMUNICATION, 8000, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT, maxJitter,
AudioTrack.MODE_STREAM);
}
private void recordAndPlay()
{
short[] lin = new short[1024];
int num = 0;
am.setMode(AudioManager.MODE_IN_COMMUNICATION);
while (true)
{
if (isRecording)
{
num = record.read(lin, 0, 1024);
track.write(lin, 0, num);
}
}
}
private void startRecordAndPlay()
{
record.startRecording();
track.play();
isRecording = true;
}
private void stopRecordAndPlay()
{
record.stop();
track.pause();
isRecording = false;
}
您的 activity_main
布局中还需要两个按钮,id 为 start_button
和 stop_button
.
You also need two buttons in your activity_main
layout with the id start_button
and stop_button
.
此示例还包含一个 EchoCanceler!
This sample also contains an EchoCanceler!
祝你好运!
这篇关于实时播放来自麦克风的音频的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!