如何在 Android 中以更好的质量录制声音并降低噪音
Posted
技术标签:
【中文标题】如何在 Android 中以更好的质量录制声音并降低噪音【英文标题】:How To Record Sound in Android with Better Quality and Reduce Noise 【发布时间】:2014-04-12 12:06:48 【问题描述】:我正在尝试为安卓平台构建一个音乐分析应用程序。
该应用正在使用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);
提前致谢
【问题讨论】:
这能回答你的问题吗? Appropriate audio capture and noise reduction 【参考方案1】:上面的解决方案对我不起作用。
所以,我四处寻找,发现this article。
长话短说,我使用了MediaRecorder.AudioSource.VOICE_RECOGNITION 而不是AudioSource.MIC,这给了我非常好的结果,并且背景中的噪音确实减少了很多。
这个解决方案的伟大之处在于,它可以与 AudioRecord 和 MediaRecorder 类一起使用。
【讨论】:
【参考方案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,则设备中的采样率不可用的逻辑。您应该针对您的特定用例试验这些值。
【讨论】:
嗨@Bartol,请帮助提供 selectBestValue() 方法。谢谢【参考方案3】:虽然这是一个老问题,但以下解决方案会有所帮助。 我们可以使用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
AudioEncodingBitRate 应根据需要使用 96000 或 128000 以确保声音清晰。
【讨论】:
以上是关于如何在 Android 中以更好的质量录制声音并降低噪音的主要内容,如果未能解决你的问题,请参考以下文章