簡體   English   中英

安卓錄音通話參數

[英]Android Recording Call parameters

我正在開發一個 DTMF 解碼器。 我需要的是錄制語音通話,然后提取頻率范圍。 一切正常,但有一些 android 版本在我設置音頻源時出現以下錯誤

“音頻屬性的捕獲預設 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());
                }
            }
        }
    }

沒有為 api 19 或 22 找到正確的參數來設置 AudioRecord。 在每種情況下都會引發異常。 我對此很困惑。 我不考慮使用 MediaRecoder 類,因為我無法直接從重新編碼器讀取緩沖區,這對於 dtmf 解碼過程至關重要。 我也看到了一些dtmf開源解碼器,但他們都有這個問題

結論

安卓官方BUG

第一的

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

第二

你可以試試

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

參考資源

錄音文件

音頻屬性.java

音頻屬性.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

某些 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:
                mSource = preset;
                break;
            default:
                Log.e(TAG, "Invalid capture preset " + preset + " for AudioAttributes");
        }
        return 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