如何在Android中以更好的质量录制声音并降低噪音

时间:2014-03-09 12:47:20

标签: android filter audio-recording android-audiorecord noise-reduction

我正在尝试为Android平台构建音乐分析应用程序。

该应用正在使用MediaRecorder.AudioSource.MIC 记录MIC的音乐,他们用11025频率编码PCM 16BIT,但录制的音频样本质量很低有没有办法让它更好,降低噪音?

mRecordInstance = new AudioRecord(MediaRecorder.AudioSource.MIC,FREQUENCY, CHANNEL,ENCODING, minBufferSize);

mRecordInstance.startRecording();

do 

{

samplesIn += mRecordInstance.read(audioData, samplesIn, bufferSize - samplesIn);

if(mRecordInstance.getRecordingState() == AudioRecord.RECORDSTATE_STOPPED)

break;

} 

while (samplesIn < bufferSize);

先谢谢

3 个答案:

答案 0 :(得分:3)

上述解决方案对我没有用。

所以,我四处搜寻,发现this article

长话短说,我使用MediaRecorder.AudioSource.VOICE_RECOGNITION代替AudioSource.MIC,这给了我非常好的结果,背景中的噪音确实减少了很多。

这个解决方案的优点是,它可以与AudioRecord和MediaRecorder类一起使用。

答案 1 :(得分:2)

SR和缓冲区大小的最佳组合取决于设备,因此您的结果将根据硬件而有所不同。我使用此实用程序来确定运行Android 4.2及更高版本的设备的最佳组合;

public static DeviceValues getDeviceValues(Context context) {
    try {
        AudioManager am = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
        try {
            Method getProperty = AudioManager.class.getMethod("getProperty", String.class);
            Field bufferSizeField = AudioManager.class.getField("PROPERTY_OUTPUT_FRAMES_PER_BUFFER");
            Field sampleRateField = AudioManager.class.getField("PROPERTY_OUTPUT_SAMPLE_RATE");
            int bufferSize = Integer.valueOf((String)getProperty.invoke(am, bufferSizeField));
            int sampleRate = Integer.valueOf((String)getProperty.invoke(am, sampleRateField));
            return new DeviceValues(sampleRate, bufferSize);
        } catch(NoSuchMethodException e) {
            return selectBestValue(getValidSampleRates(context));
        }
    } catch(Exception e) {
        return new DeviceValues(DEFAULT_SAMPLE_RATE, DEFAULT_BUFFER_SIZE);
    }
}

这使用反射来检查getProperty方法是否可用,因为此方法是在API级别17中引入的。如果您正在针对特定设备类型进行开发,则可能需要尝试各种缓冲区大小和采样率。我用作后备的默认值是;

private static final int DEFAULT_SAMPLE_RATE = 22050; private static final int DEFAULT_BUFFER_SIZE = 1024;

另外,我通过查看getMinBufferSize是否返回合理的值来检查各种SR;

private static List<DeviceValues> getValidSampleRates(Context context) {
    List<DeviceValues> available = new ArrayList<DeviceValues>();
    for (int rate : new int[] {8000, 11025, 16000, 22050, 32000, 44100, 48000, 96000}) {  // add the rates you wish to check against
        int bufferSize = AudioRecord.getMinBufferSize(rate, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT);
        if (bufferSize > 0 && bufferSize < 2048) {
            available.add(new DeviceValues(rate, bufferSize * 2));
        }
    }
    return available;
}

这取决于如果getMinBufferSize返回0的逻辑,则设备中的采样率不可用。您应该针对特定用例试验这些值。

答案 2 :(得分:1)

尽管这是一个古老的问题,但遵循以下解决方案将有所帮助。 我们可以使用MediaRecorder轻松录制音频。

  private void startRecording() {
    MediaRecorder recorder = new MediaRecorder();
    recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
    recorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
    recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
    recorder.setAudioEncodingBitRate(96000)
    recorder.setAudioSamplingRate(44100)
    recorder.setOutputFile(".../audioName.m4a");

    try {
        recorder.prepare();
    } catch (IOException e) {
        Log.e(LOG_TAG, "prepare() failed");
    }

    recorder.start();
}

注意:

  • MediaRecorder.AudioEncoder.AAC被用作MediaRecorder.AudioEncoder.AMR_NB编码,在iOS中不再受支持。 Reference
  • 为清晰起见,应根据需要使用96000或128000的AudioEncodingBitRate。