2

I’m trying to build a music analytics app for android platform.

the app is using MediaRecorder.AudioSource.MIC to record the music form the MIC and them encode it PCM 16BIT with 11025 freq, but the recorded audio sample are very low quality is there any way to make it better, decrease the noise?

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);

Thanks in Advance

Hamed mayahian
  • 2,465
  • 6
  • 27
  • 49
  • Does this answer your question? [Appropriate audio capture and noise reduction](https://stackoverflow.com/questions/11087672/appropriate-audio-capture-and-noise-reduction) – Fates Jun 15 '21 at 12:53

3 Answers3

4

The solution above didnt work for me.

So, i searched around and found this article.

Long story short, I used MediaRecorder.AudioSource.VOICE_RECOGNITION instead of AudioSource.MIC, which gave me really good results and noise in the background did reduce very much.

The great thing about this solution is, it can be used with both AudioRecord and MediaRecorder class.

MiaN KhaLiD
  • 1,478
  • 1
  • 16
  • 28
2

The best combination of SR and buffer size is very device dependant, so your results will vary depending on the hardware. I use this utility to figure out what the best combination is for devices running Android 4.2 and above;

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);
    }
}

This uses reflection to check if the getProperty method is available, because this method was introduced in API level 17. If you are developing for a specific device type, you might want to experiment with various buffer sizes and sample rates. The defaults that I use as a fallback are;

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

Additionally I check the various SR by seeing if getMinBufferSize returns a reasonable value for use;

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;
}

This depends on the logic that if getMinBufferSize returns 0, the sample rate is not available in the device. You should experiment with these values for your particular use case.

Merve Sahin
  • 1,008
  • 2
  • 14
  • 26
Bartol Karuza
  • 128
  • 1
  • 6
1

Though it is an old question following solution will be helpful. We can use MediaRecorder to record audio with ease.

  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();
}

Note:

  • MediaRecorder.AudioEncoder.AAC is used as MediaRecorder.AudioEncoder.AMR_NB encoding is no longer supported in iOS. Reference
  • AudioEncodingBitRate should be used either 96000 or 128000 as required for clarity of sound.
Nischal
  • 870
  • 1
  • 10
  • 16