回放从麦克风实时声音到来 [英] Playing back sound coming from microphone in real-time

查看:266
本文介绍了回放从麦克风实时声音到来的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在试图让我的应用程序记录从话筒传来的声音和发挥它回(约)的实时,但没有成功。

I've been trying to get my application recording the sound coming from the microphone and playing it back in (approximately) real-time, however without success.

我使用AudioRecord和AudioTrack类的录制和回放,分别。我尝试过不同的方法,我试图记录收到的声音,并将其写入到一个文件,它工作得很好。我也试着从该文件后,用AudioTrack播放的声音和它的工作也没关系。问题是,当我尝试播放,而不是读文件它写后的声音在实时。

I'm using AudioRecord and AudioTrack classes for record and playback, respectively. I've tried different approaches, I've tried to record the incoming sound and write it to a file and it worked fine. I've also tried to playback sound from that file AFTER with AudioTrack and it worked fine too. The problem is when I try to play the sound in real-time, instead of reading a file after it's written.

下面是code:

//variables
private int audioSource = MediaRecorder.AudioSource.MIC;
private int samplingRate = 44100; /* in Hz*/
private int channelConfig = AudioFormat.CHANNEL_CONFIGURATION_MONO;
private int audioFormat = AudioFormat.ENCODING_PCM_16BIT;
private int bufferSize = AudioRecord.getMinBufferSize(samplingRate, channelConfig, audioFormat);
private int sampleNumBits = 16;
private int numChannels = 1;

// …

AudioRecord recorder = new AudioRecord(audioSource, samplingRate, channelConfig, audioFormat, bufferSize);
                recorder.startRecording();
                isRecording = true;

AudioTrack audioPlayer = new AudioTrack(AudioManager.STREAM_MUSIC, 44100, AudioFormat.CHANNEL_CONFIGURATION_MONO,
                        AudioFormat.ENCODING_PCM_16BIT, bufferSize, AudioTrack.MODE_STREAM);

if(audioPlayer.getPlayState() != AudioTrack.PLAYSTATE_PLAYING)
    audioPlayer.play();

//capture data and record to file
int readBytes=0, writtenBytes=0;
do{
   readBytes = recorder.read(data, 0, bufferSize);

   if(AudioRecord.ERROR_INVALID_OPERATION != readBytes){
      writtenBytes += audioPlayer.write(data, 0, readBytes);
   }
}
while(isRecording);

据抛出的原因java.lang.IllegalStateException,不会引起玩()呼吁一个未初始化的AudioTrack。

It is thrown a java.lang.IllegalStateException with the reason being caused by "play() called on a uninitialized AudioTrack".

不过,如果我改变AudioTrack初始化,例如使用的采样率8000Hz的和样本格式8位(而不是16),它不会抛出异常了,并在应用程序运行,但它会产生可怕的噪音。

However, if I change the AudioTrack initialization for example to use sampling rate 8000Hz and sample format 8 bits (instead of 16), it doesn't throw the exception anymore and the application runs, although it produces horrible noise.

当我玩AudioTrack从一个文件中,没有与AudioTrack的初始化没问题,我试过44100位和16位,它的工作正常,产生正确的声音。

When I play AudioTrack from a file, there is no problem with the initialization of the AudioTrack, I tried 44100 and 16 bits and it worked properly, producing the correct sound.

任何帮助吗?

推荐答案

所有Android原生音频的恩codeD 。你只能发挥出 PCM 格式实时,或使用特殊的 codeC,我不认为这是小事在Android

All native Android audio is encoded. You can only play out PCM formats in real time, or use a special streaming codec, which I don't think is trivial on Android.

的一点是,如果你想记录/同时播放出声音,你就必须创建自己的声音缓冲存储原始PCM-CN codeD音频样本中有(我不知道,如果你'重新思考的咄!的或者这是否是遍布你(R)头,所以我会尽量清楚,但不要咀嚼自己胶)。

The point is that if you want to record/play out audio simultaneously, you would have to create your own audio buffer and store raw PCM-encoded audio samples in there (I'm not sure if you're thinking duh! or whether this is all over you r head, so I'll try to be clear but not to chew your own gum).

PCM是模拟信号的数字再presentation在音频样本是一组原声波的快照的。由于各种巧妙的数学家和工程师看到了潜力,努力降低比特重新present此数据的数量,他们想出了种种的恩codeRS 。带连接codeD(COM pressed)信号重新$ P $从原始的PCM信号psented非常不同且必须去codeD(恩的 COD 的-er + 的-oder =的 codeC 的)。除非你使用特殊的算法和流媒体codeCS,这是不可能播放的连接codeD信号像你想的,因为它不是连接通过样本codeD样品,而是一帧一框,在这里你需要样品的整体框架,如果没有完整的信号,脱$ C C这个框架$。

PCM is a digital representation of an analog signal in which your audio samples are a set of "snapshots" of the original acoustic wave. Because all kinds of clever mathematicians and engineers saw the potential in trying to reduce the number of bits you represent this data with, they came up with all sorts of encoders. The encoded (compressed) signal is represented very differently from the raw PCM signal and has to be decoded (en-cod-er+dec-oder = codec). Unless you're using special algorithms and media streaming codecs, it's impossible to play back an encoded signal like you're trying to, because it's not encoded sample by sample, but rather frame by frame, where you need the whole frame of samples, if not the complete signal, to decode this frame.

要做到这一点的方法是手动存储音频样本来自麦克风缓冲未来和手动将它们馈送到输出缓冲区。你将不得不做一些编码,但我相信有一些,你可以看看,并采取一个高峰,其源(除非你愿意出售,当然你的应用程序以后,开放源代码的应用程序,但是这一个完全不同的讨论)。

The way to do it is to manually store audio samples coming from the microphone buffer and manually feeding them to the output buffer. You will have to do some coding for that, but i believe there are some open-source apps that you can look at and take a peak at their source (unless you're willing to sell your app later on, of course, but that's a whole different discussion).

如果您正在开发适用于Android 2.3或更高版本,并没有太害怕编程的本土$ C $ Ç,您可以尝试使用 OpelSL ES 。 OpenSL ES的Andr​​oid的特定功能列这里。这个平台可以让你较为灵活的音频处理,你可能会发现正是你所需要的,如果你的应用程序将在音频处理高度依赖。

If you're developing for Android 2.3 or later and are not too scared of programming in native code, you can try using OpelSL ES. The Android-specific features of OpenSL ES are listed here. This platform allows you somewhat more flexible audio manipulation and you might find just what you need, if your app will be highly reliant on audio processing.

希望有所帮助。干杯! =)

Hope that helps. Cheers! = )

这篇关于回放从麦克风实时声音到来的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆