2

我正在尝试为 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);

提前致谢

4

3 回答 3

4

上面的解决方案对我不起作用。

所以,我四处搜索,找到了这篇文章

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

这个解决方案的伟大之处在于,它可以与 AudioRecord 和 MediaRecorder 类一起使用。

于 2015-06-19T06:14:08.557 回答
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, (String)bufferSizeField.get(am)));
            int sampleRate = Integer.valueOf((String)getProperty.invoke(am, (String)sampleRateField.get(am)));
            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,则设备中的采样率不可用的逻辑。您应该针对您的特定用例试验这些值。

于 2014-03-09T13:14:00.287 回答
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_NBiOS 中不再支持编码。参考
  • AudioEncodingBitRate 应根据声音清晰度的要求使用 96000 或 128000。
于 2020-09-08T09:28:02.913 回答