Android录制通话参数

时间:2015-11-06 13:41:11

标签: android format call record

开发DTMF解码器。我需要的是录制语音呼叫,然后提取频率范围。一切正常,但有一些Android版本,我在设置音频源时出现以下错误

“AudioAttributes的捕获预设3无效”

为了获得正确的参数,我开发了一种算法:

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

为了设置AudioRecord,没有为api 19或22找到正确的参数。在每种情况下都会引发异常。 我对此非常感兴趣。我没有考虑使用MediaRecoder类,因为我无法直接从重新编码器读取缓冲区,这对于dtmf解码过程至关重要。我也看过一些dtmf开源解码器,但所有这些都有这个问题

2 个答案:

答案 0 :(得分:1)

结论

Android官方BUG

第一

AudioRecord.java它的构造函数public AudioRecord(int audioSource, int sampleRateInHz, int channelConfig, int audioFormat,int bufferSizeInBytes)可能不推荐使用(我认为), IllegalArgumentException 直接抛出,另一个下面的构造函数方法(特别是 PUBLID 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 {
}

第二

你可以尝试

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

第三

 /**
     * @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");
    }

参考资源

AudioRecord.java

AudioAttributes.java

AudioAttributes.java

@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=4075

答案 1 :(得分:1)

某些Android版本禁用此功能。如果您有Android源代码,您可以使其工作。我目前正在使用cyanogenmod,所以我已经定制了AudioAttributes.java类,以便在它发生时不引发异常。

我们只需通过在switch / case结构中添加我们想要的所有音频源来改变AudioAttributes.java中的setCapturePreset()方法。

这是原作:

/**
     * @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;
    }

我用这个替换了:

<button on-touch="click()">
    Avvia Scansione
</button>