[英]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");
}
某些 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.