How can I find out what Sampling rates are support

2020-02-24 04:24发布

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.

3条回答
家丑人穷心不美
2楼-- · 2020-02-24 05:04

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.

查看更多
迷人小祖宗
3楼-- · 2020-02-24 05:09

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
}
查看更多
一纸荒年 Trace。
4楼-- · 2020-02-24 05:26

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.

查看更多
登录 后发表回答