简体   繁体   English

安卓录音通话参数

[英]Android Recording Call parameters

Im developing a DTMF decoder.我正在开发一个 DTMF 解码器。 What I need is to record a voice call and then extract the frecuency range.我需要的是录制语音通话,然后提取频率范围。 Everything is working ok but there are some android versions in which I get the following error when I set up the audio source一切正常,但有一些 android 版本在我设置音频源时出现以下错误

"Invalid capture preset 3 for AudioAttributes" “音频属性的捕获预设 3 无效”

In order to get the right parameters I have developed an algorithm:为了获得正确的参数,我开发了一个算法:

private static final int[] FREQUENCY = {8000, 11025, 16000, 22050, 44100}; // 44100 is guaranteed to work in all devices

private static final int[] CHANNEL_CONFIGURATION = {AudioFormat.CHANNEL_IN_MONO,
                                                    AudioFormat.CHANNEL_IN_STEREO};

private static final int[] AUDIO_ENCODING = {AudioFormat.ENCODING_DEFAULT,
                                             AudioFormat.ENCODING_PCM_8BIT,
                                             AudioFormat.ENCODING_PCM_16BIT};

for (int i = 0; i < FREQUENCY.length && !found; i ++) {
        for (int j = 0; j < CHANNEL_CONFIGURATION.length && !found; j ++) {
            for (int k = 0; k < AUDIO_ENCODING.length && !found; k ++) {
                try {
                    bufferSize = AudioRecord.getMinBufferSize(FREQUENCY[i], CHANNEL_CONFIGURATION[j], AUDIO_ENCODING[k]);
                    if (bufferSize != AudioRecord.ERROR_BAD_VALUE && bufferSize != AudioRecord.ERROR) {
                        audioRecord = new AudioRecord(MediaRecorder.AudioSource.VOICE_DOWNLINK, FREQUENCY[i], CHANNEL_CONFIGURATION[j], AUDIO_ENCODING[k], bufferSize);
                        found = true;
                    }
                } catch (Exception e) {
                    Log.e(TAG, e.toString());
                }
            }
        }
    }

There are no correct parameters found for api 19 or 22 in order to set up an AudioRecord.没有为 api 19 或 22 找到正确的参数来设置 AudioRecord。 In every case an exception is raised.在每种情况下都会引发异常。 I'm quite locked with this.我对此很困惑。 Im not thinking about to use MediaRecoder class because I can not read a buffer directly from the recoder and this is critical for the dtmf decoding proccess.我不考虑使用 MediaRecoder 类,因为我无法直接从重新编码器读取缓冲区,这对于 dtmf 解码过程至关重要。 I have also seen some dtmf open source decoder but all of them have this problem我也看到了一些dtmf开源解码器,但他们都有这个问题

Conclusion结论

Android official BUG安卓官方BUG

first第一的

AudioRecord.java It's constructor public AudioRecord(int audioSource, int sampleRateInHz, int channelConfig, int audioFormat,int bufferSizeInBytes) may NOT recommend for use(I think), an IllegalArgumentException was throwed directly, another constructor metho like below(especially CANDIDATE FOR PUBLIC API ): AudioRecord.java它的构造函数public AudioRecord(int audioSource, int sampleRateInHz, int channelConfig, int audioFormat,int bufferSizeInBytes)可能不推荐使用(我认为),一个IllegalArgumentException被直接抛出另一个像下面这样的构造函数方法(尤其是CANDIDATE FOR PUBLIC API ):

 /**
 * @hide
 * CANDIDATE FOR PUBLIC API
 * Class constructor with {@link AudioAttributes} and {@link AudioFormat}.
 * @param attributes a non-null {@link AudioAttributes} instance. Use
 *     {@link AudioAttributes.Builder#setCapturePreset(int)} for configuring the capture
 *     preset for this instance.
 * @param format a non-null {@link AudioFormat} instance describing the format of the data
 *     that will be recorded through this AudioRecord. See {@link AudioFormat.Builder} for
 *     configuring the audio format parameters such as encoding, channel mask and sample rate.
 * @param bufferSizeInBytes the total size (in bytes) of the buffer where audio data is written
 *   to during the recording. New audio data can be read from this buffer in smaller chunks
 *   than this size. See {@link #getMinBufferSize(int, int, int)} to determine the minimum
 *   required buffer size for the successful creation of an AudioRecord instance. Using values
 *   smaller than getMinBufferSize() will result in an initialization failure.
 * @param sessionId ID of audio session the AudioRecord must be attached to, or
 *   {@link AudioManager#AUDIO_SESSION_ID_GENERATE} if the session isn't known at construction
 *   time. See also {@link AudioManager#generateAudioSessionId()} to obtain a session ID before
 *   construction.
 * @throws IllegalArgumentException
 */
public AudioRecord(AudioAttributes attributes, AudioFormat format, int bufferSizeInBytes,int sessionId) throws IllegalArgumentException {
}

second第二

you can try你可以试试

/** Voice call uplink + downlink audio source */ public static final int VOICE_CALL = 4;

third第三

 /**
     * @hide
     * Sets the capture preset.
     * Use this audio attributes configuration method when building an {@link AudioRecord}
     * instance with {@link AudioRecord#AudioRecord(AudioAttributes, AudioFormat, int)}.
     * @param preset one of {@link MediaRecorder.AudioSource#DEFAULT},
     *     {@link MediaRecorder.AudioSource#MIC}, {@link MediaRecorder.AudioSource#CAMCORDER},
     *     {@link MediaRecorder.AudioSource#VOICE_RECOGNITION} or
     *     {@link MediaRecorder.AudioSource#VOICE_COMMUNICATION}.
     * @return the same Builder instance.
     */
    @SystemApi
    public Builder setCapturePreset(int preset) {
        //....
        Log.e(TAG, "Invalid capture preset " + preset + " for AudioAttributes");
    }

Reference resources参考资源

AudioRecord.java 录音文件

AudioAttributes.java 音频属性.java

AudioAttributes.java 音频属性.java

@SystemApi @hide @SystemApi @hide

https://code.google.com/p/android/issues/detail?id=2117&q=call%20recorder&colspec=ID%20Type%20Status%20Owner%20Summary%20Stars https://code.google.com/p/android/issues/detail?id=2117&q=call%20recorder&colspec=ID%20Type%20Status%20Owner%20Summary%20Stars

https://code.google.com/p/android/issues/detail?id=4075 https://code.google.com/p/android/issues/detail?id=4075

Some android versions have this feature disabled.某些 android 版本禁用了此功能。 If you have the android source code you can make it works.如果你有 android 源代码,你可以让它工作。 Im currently working with cyanogenmod so I have customized the AudioAttributes.java class in order to not to raise an exception when it happens.我目前正在使用 cyanogenmod,所以我自定义了 AudioAttributes.java 类,以便在发生异常时不引发异常。

We only have to changhe the setCapturePreset() method in AudioAttributes.java by adding all Audio sources that we want within the switch/case structure.我们只需要通过在 switch/case 结构中添加我们想要的所有音频源来更改 AudioAttributes.java 中的 setCapturePreset() 方法。

This is the original:这是原文:

/**
     * @hide
     * Sets the capture preset.
     * Use this audio attributes configuration method when building an {@link AudioRecord}
     * instance with {@link AudioRecord#AudioRecord(AudioAttributes, AudioFormat, int)}.
     * @param preset one of {@link MediaRecorder.AudioSource#DEFAULT},
     *     {@link MediaRecorder.AudioSource#MIC}, {@link MediaRecorder.AudioSource#CAMCORDER},
     *     {@link MediaRecorder.AudioSource#VOICE_RECOGNITION} or
     *     {@link MediaRecorder.AudioSource#VOICE_COMMUNICATION}.
     * @return the same Builder instance.
     */
    @SystemApi
    public Builder setCapturePreset(int preset) {
        switch (preset) {
            case MediaRecorder.AudioSource.DEFAULT:
            case MediaRecorder.AudioSource.MIC:
            case MediaRecorder.AudioSource.CAMCORDER:
            case MediaRecorder.AudioSource.VOICE_RECOGNITION:
            case MediaRecorder.AudioSource.VOICE_COMMUNICATION:
                mSource = preset;
                break;
            default:
                Log.e(TAG, "Invalid capture preset " + preset + " for AudioAttributes");
        }
        return this;
    }

And I replaced with this:我用这个代替:

/**
     * @hide
     * Sets the capture preset.
     * Use this audio attributes configuration method when building an {@link AudioRecord}
     * instance with {@link AudioRecord#AudioRecord(AudioAttributes, AudioFormat, int)}.
     * @param preset one of {@link MediaRecorder.AudioSource#DEFAULT},
     *     {@link MediaRecorder.AudioSource#MIC}, {@link MediaRecorder.AudioSource#CAMCORDER},
     *     {@link MediaRecorder.AudioSource#VOICE_RECOGNITION} or
     *     {@link MediaRecorder.AudioSource#VOICE_COMMUNICATION}.
     * @return the same Builder instance.
     */
    @SystemApi
    public Builder setCapturePreset(int preset) {
        switch (preset) {
            case MediaRecorder.AudioSource.DEFAULT:
            case MediaRecorder.AudioSource.MIC:
            case MediaRecorder.AudioSource.CAMCORDER:
            case MediaRecorder.AudioSource.VOICE_RECOGNITION:
            case MediaRecorder.AudioSource.VOICE_COMMUNICATION:
            case MediaRecorder.AudioSource.VOICE_DOWNLINK:
            case MediaRecorder.AudioSource.VOICE_UPLINK:
            case MediaRecorder.AudioSource.VOICE_CALL:
                mSource = preset;
                break;
            default:
                Log.e(TAG, "Invalid capture preset " + preset + " for AudioAttributes");
        }
        return this;
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM