3

I have an app that works perfectly on a bunch of devices (Xoom, Xyboard, etc) but that fails at this line on the Galaxy 10.1

mrec.setAudioSamplingRate(44100);

When I comment this line out, everything works swimmingly. (I'm not sure what rate it uses by default).

My guess is that the device doesn't support this particular sample rate, but I'm not seeing anything in the docs for what method of what Object I can look to, to find out what the supported sample rates are.

All help appreciated.

Reaz Murshed
  • 23,691
  • 13
  • 78
  • 98
Yevgeny Simkin
  • 27,946
  • 39
  • 137
  • 236

3 Answers3

14

Yes, Android does not provide an explicit method to check it but there is a work-around with AudioRecord class' getMinBufferSize function.

public void getValidSampleRates() {
    for (int rate : new int[] {8000, 11025, 16000, 22050, 44100}) {  // add the rates you wish to check against
        int bufferSize = AudioRecord.getMinBufferSize(rate, AudioFormat.CHANNEL_CONFIGURATION_DEFAULT, AudioFormat.ENCODING_PCM_16BIT);
        if (bufferSize > 0) {
            // buffer size is valid, Sample rate supported

        }
    }
}

If you checked the function description, it will return a negative value if one of the parameters entered are not supported. Assuming you enter all other inputs as valid, we are expecting it to return a negative buffersize if sample rate is not supported.

However, some people reported that it was returning positive even if sampling rate is not supported so an additional check could be done by trying to initialize an AudioRecord object, which will throw an IllegalArgumentException if it thinks it cannot deal with that sampling rate.

Finally, none of them provide a guaranteed check but using both increases your chances of getting the supported one.

Most of the time, 44100 and 48000 work for me but of course, it differs from device to device.

Erol
  • 6,478
  • 5
  • 41
  • 55
  • Thanks for that really detailed answer! I'm sort of inclined to just leave it recording at its default, to avoid this hassle. Do you know what method I call to find out *what it selects by default, if I don't override it? – Yevgeny Simkin Jul 19 '12 at 08:13
  • I assume you are using MediaRecorder class. If the rate is not supported, your prepare() call will fail. That's how you find out. If you go with the default, I think it will pick the one that is closely associated with the media format as said here: http://developer.android.com/reference/android/media/MediaRecorder.html#setAudioSamplingRate%28int%29. Maybe there are some external libraries that allow you to analyze recorded audio dynamically afterwards, but I do not know an Android defined way to learn what sampling rate it is picking. – Erol Jul 19 '12 at 15:33
  • Related: https://stackoverflow.com/questions/8043387/android-audiorecord-supported-sampling-rates – P i Mar 29 '18 at 14:08
7

Android has AudioManager.getProperty() function to acquire minimum buffer size and get the preferred sample rate for audio record and playback. But yes of course, AudioManager.getProperty() is not available on API level < 17. Here's an example code sample on how to use this API.

// To get preferred buffer size and sampling rate.
AudioManager audioManager = (AudioManager) this.getSystemService(Context.AUDIO_SERVICE);
String rate = audioManager.getProperty(AudioManager.PROPERTY_OUTPUT_SAMPLE_RATE);
String size = audioManager.getProperty(AudioManager.PROPERTY_OUTPUT_FRAMES_PER_BUFFER);
Log.d("Buffer Size and sample rate", "Size :" + size + " & Rate: " + rate);

Though its a late answer, I thought this might be useful.

Reaz Murshed
  • 23,691
  • 13
  • 78
  • 98
1

This does not use the buffer size as a test as it is not absolute. I tested said solution on my own ASUS MemoPad and the buffer size test will always return a positive integer, giving false positives.

The first method will test a passed sample rate and return true or false depending on whether or not the sample rate is supported by the device or not. The second method will iterate through a given list and return the maximum valid sampling rate (first in the list that is valid) - can be changed easily for other heuristics.

boolean validSampleRate(int sample_rate) {      
    AudioRecord recorder = null;
    try {
        int bufferSize = AudioRecord.getMinBufferSize(sample_rate, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT);
        recorder = new AudioRecord(MediaRecorder.AudioSource.MIC, sample_rate, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, bufferSize);
    } catch(IllegalArgumentException e) {
        return false; // cannot sample at this rate
    } finally {
        if(recorder != null)
            recorder.release(); // release resources to prevent a memory leak
    }
    return true; // if nothing has been returned yet, then we must be able to sample at this rate!
}

int maxValidSampleRate() {
    int[] sample_rates = new int[]{44100, 16000}; // pad list with other samples rates you want to test for
    for(int sample_rate : sample_rates) {
        if(validSampleRate(sample_rate))
            return sample_rate; // this rate is supported, so return it!
    }
    return -1; // no valid sample rate
}
Keir Simmons
  • 1,634
  • 7
  • 21
  • 37