audio: added support for dual mic capture
Added support for simultaneous capture of front and back mic.
Added device definitions for dual mic config for voice recognition use
case: no pre processing enabled.
stream->channels() reports actual channel mask instead of recontructing
it from channel count.
TODO: check if ACDB settings copied from single mic voice recognition
are correct.
Change-Id: I41282d0af5deb256ef68ec17ee34f5aae7807a6f
diff --git a/alsa_sound/ALSAStreamOps.cpp b/alsa_sound/ALSAStreamOps.cpp
index 4e534fd..c7c0ca1 100644
--- a/alsa_sound/ALSAStreamOps.cpp
+++ b/alsa_sound/ALSAStreamOps.cpp
@@ -101,42 +101,32 @@
if (mHandle->channels != popCount(*channels))
return BAD_VALUE;
} else if (channels) {
- *channels = 0;
if (mHandle->devices & AudioSystem::DEVICE_OUT_ALL) {
- switch(mHandle->channels) {
- case 6:
- case 5:
- *channels |= audio_channel_out_mask_from_count(mHandle->channels);
+ switch(*channels) {
+ case AUDIO_CHANNEL_OUT_5POINT1: // 5.0
+ case (AUDIO_CHANNEL_OUT_QUAD | AUDIO_CHANNEL_OUT_FRONT_CENTER): // 5.1
+ case AUDIO_CHANNEL_OUT_QUAD:
+ case AUDIO_CHANNEL_OUT_STEREO:
+ case AUDIO_CHANNEL_OUT_MONO:
break;
- // Do not fall through
- case 4:
- *channels |= AudioSystem::CHANNEL_OUT_BACK_LEFT;
- *channels |= AudioSystem::CHANNEL_OUT_BACK_RIGHT;
- // Fall through...
default:
- case 2:
- *channels |= AudioSystem::CHANNEL_OUT_FRONT_RIGHT;
- // Fall through...
- case 1:
- *channels |= AudioSystem::CHANNEL_OUT_FRONT_LEFT;
- break;
+ *channels = AUDIO_CHANNEL_OUT_STEREO;
+ return BAD_VALUE;
}
} else {
- switch(mHandle->channels) {
+ switch(*channels) {
#ifdef QCOM_SSR_ENABLED
// For 5.1 recording
- case 6 :
- *channels |= AudioSystem::CHANNEL_IN_5POINT1;
- break;
+ case AudioSystem::CHANNEL_IN_5POINT1:
#endif
// Do not fall through...
- default:
- case 2:
- *channels |= AudioSystem::CHANNEL_IN_RIGHT;
- // Fall through...
- case 1:
- *channels |= AudioSystem::CHANNEL_IN_LEFT;
+ case AUDIO_CHANNEL_IN_MONO:
+ case AUDIO_CHANNEL_IN_STEREO:
+ case AUDIO_CHANNEL_IN_FRONT_BACK:
break;
+ default:
+ *channels = AUDIO_CHANNEL_IN_MONO;
+ return BAD_VALUE;
}
}
}
@@ -352,47 +342,7 @@
uint32_t ALSAStreamOps::channels() const
{
- unsigned int count = mHandle->channels;
- uint32_t channels = 0;
-
- if (mDevices & AudioSystem::DEVICE_OUT_ALL)
- switch(count) {
- case 6:
- case 5:
- channels |=audio_channel_out_mask_from_count(count);
- break;
- // Do not fall through
- case 4:
- channels |= AudioSystem::CHANNEL_OUT_BACK_LEFT;
- channels |= AudioSystem::CHANNEL_OUT_BACK_RIGHT;
- // Fall through...
- default:
- case 2:
- channels |= AudioSystem::CHANNEL_OUT_FRONT_RIGHT;
- // Fall through...
- case 1:
- channels |= AudioSystem::CHANNEL_OUT_FRONT_LEFT;
- break;
- }
- else
- switch(count) {
-#ifdef QCOM_SSR_ENABLED
- // For 5.1 recording
- case 6 :
- channels |= AudioSystem::CHANNEL_IN_5POINT1;
- break;
- // Do not fall through...
-#endif
- default:
- case 2:
- channels |= AudioSystem::CHANNEL_IN_RIGHT;
- // Fall through...
- case 1:
- channels |= AudioSystem::CHANNEL_IN_LEFT;
- break;
- }
-
- return channels;
+ return mHandle->channelMask;
}
void ALSAStreamOps::close()
diff --git a/alsa_sound/AudioHardwareALSA.cpp b/alsa_sound/AudioHardwareALSA.cpp
index 4050777..508418c 100644
--- a/alsa_sound/AudioHardwareALSA.cpp
+++ b/alsa_sound/AudioHardwareALSA.cpp
@@ -779,6 +779,7 @@
else
alsa_handle.format = *format;
alsa_handle.channels = VOIP_DEFAULT_CHANNEL_MODE;
+ alsa_handle.channelMask = AUDIO_CHANNEL_IN_MONO;
alsa_handle.sampleRate = *sampleRate;
alsa_handle.latency = VOIP_PLAYBACK_LATENCY;
alsa_handle.rxHandle = 0;
@@ -857,6 +858,8 @@
} else {
alsa_handle.channels = AudioSystem::popCount(*channels);
}
+ alsa_handle.channelMask = *channels;
+
if (6 == alsa_handle.channels) {
alsa_handle.bufferSize = DEFAULT_MULTI_CHANNEL_BUF_SIZE;
} else {
@@ -916,6 +919,7 @@
alsa_handle.handle = 0;
alsa_handle.format = SNDRV_PCM_FORMAT_S16_LE;
alsa_handle.channels = DEFAULT_CHANNEL_MODE;
+ alsa_handle.channelMask = AUDIO_CHANNEL_OUT_STEREO;
alsa_handle.sampleRate = DEFAULT_SAMPLING_RATE;
alsa_handle.latency = PLAYBACK_LATENCY;
alsa_handle.rxHandle = 0;
@@ -1014,6 +1018,7 @@
alsa_handle.handle = 0;
alsa_handle.format = SNDRV_PCM_FORMAT_S16_LE;
alsa_handle.channels = DEFAULT_CHANNEL_MODE;
+ alsa_handle.channelMask = AUDIO_CHANNEL_OUT_STEREO;
alsa_handle.sampleRate = DEFAULT_SAMPLING_RATE;
alsa_handle.latency = VOICE_LATENCY;
alsa_handle.rxHandle = 0;
@@ -1142,6 +1147,7 @@
else
alsa_handle.format = *format;
alsa_handle.channels = VOIP_DEFAULT_CHANNEL_MODE;
+ alsa_handle.channelMask = AUDIO_CHANNEL_IN_MONO;
alsa_handle.sampleRate = *sampleRate;
alsa_handle.latency = VOIP_RECORD_LATENCY;
alsa_handle.rxHandle = 0;
@@ -1209,6 +1215,7 @@
alsa_handle.handle = 0;
alsa_handle.format = SNDRV_PCM_FORMAT_S16_LE;
alsa_handle.channels = VOICE_CHANNEL_MODE;
+ alsa_handle.channelMask = AUDIO_CHANNEL_IN_MONO;
alsa_handle.sampleRate = android::AudioRecord::DEFAULT_SAMPLE_RATE;
alsa_handle.latency = RECORD_LATENCY;
alsa_handle.rxHandle = 0;
@@ -1307,8 +1314,10 @@
#ifdef QCOM_SSR_ENABLED
| AudioSystem::CHANNEL_IN_5POINT1
#endif
- ));
- ALOGV("updated channel info: channels=%d", it->channels);
+ | AUDIO_CHANNEL_IN_FRONT_BACK));
+ it->channelMask = *channels;
+ ALOGV("updated channel info: channels=%d channelMask %08x",
+ it->channels, it->channelMask);
}
if (devices == AudioSystem::DEVICE_IN_VOICE_CALL){
/* Add current devices info to devices to do route */
@@ -1336,7 +1345,6 @@
mALSADevice->route(&(*it), devices, mode());
}
}
-
if(!strcmp(it->useCase, SND_USE_CASE_VERB_HIFI_REC) ||
!strcmp(it->useCase, SND_USE_CASE_VERB_HIFI_LOWLATENCY_REC) ||
#ifdef QCOM_FM_ENABLED
@@ -1444,6 +1452,7 @@
alsa_handle.handle = 0;
alsa_handle.format = SNDRV_PCM_FORMAT_S16_LE;
alsa_handle.channels = DEFAULT_CHANNEL_MODE;
+ alsa_handle.channelMask = AUDIO_CHANNEL_OUT_STEREO;
alsa_handle.sampleRate = DEFAULT_SAMPLING_RATE;
alsa_handle.latency = VOICE_LATENCY;
alsa_handle.rxHandle = 0;
@@ -1539,6 +1548,7 @@
alsa_handle.handle = 0;
alsa_handle.format = SNDRV_PCM_FORMAT_S16_LE;
alsa_handle.channels = VOICE_CHANNEL_MODE;
+ alsa_handle.channelMask = AUDIO_CHANNEL_IN_MONO;
alsa_handle.sampleRate = VOICE_SAMPLING_RATE;
alsa_handle.latency = VOICE_LATENCY;
alsa_handle.rxHandle = 0;
diff --git a/alsa_sound/AudioHardwareALSA.h b/alsa_sound/AudioHardwareALSA.h
index 932b18f..4ef878b 100644
--- a/alsa_sound/AudioHardwareALSA.h
+++ b/alsa_sound/AudioHardwareALSA.h
@@ -170,6 +170,7 @@
struct pcm * handle;
snd_pcm_format_t format;
uint32_t channels;
+ audio_channel_mask_t channelMask;
uint32_t sampleRate;
unsigned int latency; // Delay in usec
unsigned int bufferSize; // Size of sample buffer
diff --git a/alsa_sound/AudioStreamInALSA.cpp b/alsa_sound/AudioStreamInALSA.cpp
index 3b66c24..4771d42 100644
--- a/alsa_sound/AudioStreamInALSA.cpp
+++ b/alsa_sound/AudioStreamInALSA.cpp
@@ -239,6 +239,9 @@
}
}
}
+ if (mHandle->channelMask == AUDIO_CHANNEL_IN_FRONT_BACK) {
+ mHandle->module->setFlags(mParent->mDevSettingsFlag | DMIC_FLAG);
+ }
free(use_case);
if((!strcmp(mHandle->useCase, SND_USE_CASE_VERB_IP_VOICECALL)) ||
(!strcmp(mHandle->useCase, SND_USE_CASE_MOD_PLAY_VOIP))) {
@@ -596,6 +599,10 @@
mParent->closeUsbRecordingIfNothingActive();
#endif
+ if (mHandle->channelMask == AUDIO_CHANNEL_IN_FRONT_BACK) {
+ mHandle->module->setFlags(mParent->mDevSettingsFlag);
+ }
+
return NO_ERROR;
}
diff --git a/alsa_sound/alsa_default.cpp b/alsa_sound/alsa_default.cpp
index 55fe32d..2f043bb 100644
--- a/alsa_sound/alsa_default.cpp
+++ b/alsa_sound/alsa_default.cpp
@@ -1423,10 +1423,11 @@
} else {
if (!(mDevSettingsFlag & TTY_OFF) &&
(callMode == AudioSystem::MODE_IN_CALL) &&
- ((devices & AudioSystem::DEVICE_IN_WIRED_HEADSET))) {
+ ((devices & AudioSystem::DEVICE_IN_WIRED_HEADSET)
#ifdef QCOM_ANC_HEADSET_ENABLED
- ||(devices & AudioSystem::DEVICE_IN_ANC_HEADSET))) {
+ || (devices & AudioSystem::DEVICE_IN_ANC_HEADSET)
#endif
+ )) {
if (mDevSettingsFlag & TTY_HCO) {
return strdup(SND_USE_CASE_DEV_TTY_HEADSET_TX);
} else if (mDevSettingsFlag & TTY_FULL) {
@@ -1443,8 +1444,8 @@
return strdup(SND_USE_CASE_DEV_HANDSET); /* HANDSET TX */
} else {
if (mDevSettingsFlag & DMIC_FLAG) {
-#ifdef USES_FLUENCE_INCALL
if(callMode == AudioSystem::MODE_IN_CALL) {
+#ifdef USES_FLUENCE_INCALL
if (fluence_mode == FLUENCE_MODE_ENDFIRE) {
if(is_tmus)
return strdup(SND_USE_CASE_DEV_DUAL_MIC_ENDFIRE_TMUS); /* DUALMIC EF TX */
@@ -1455,26 +1456,42 @@
} else {
return strdup(SND_USE_CASE_DEV_HANDSET); /* BUILTIN-MIC TX */
}
+#endif
}
-#else
if (((rxDevice != NULL) &&
!strncmp(rxDevice, SND_USE_CASE_DEV_SPEAKER,
(strlen(SND_USE_CASE_DEV_SPEAKER)+1))) ||
!strncmp(curRxUCMDevice, SND_USE_CASE_DEV_SPEAKER,
(strlen(SND_USE_CASE_DEV_SPEAKER)+1))) {
if (fluence_mode == FLUENCE_MODE_ENDFIRE) {
- return strdup(SND_USE_CASE_DEV_SPEAKER_DUAL_MIC_ENDFIRE); /* DUALMIC EF TX */
+ if (input_source == AUDIO_SOURCE_VOICE_RECOGNITION) {
+// TODO: check if different ACDB settings are needed when speaker is enabled
+ return strdup(SND_USE_CASE_DEV_DUAL_MIC_ENDFIRE_VREC);
+ } else {
+ return strdup(SND_USE_CASE_DEV_SPEAKER_DUAL_MIC_ENDFIRE);
+ }
} else if (fluence_mode == FLUENCE_MODE_BROADSIDE) {
- return strdup(SND_USE_CASE_DEV_SPEAKER_DUAL_MIC_BROADSIDE); /* DUALMIC BS TX */
+ if (input_source == AUDIO_SOURCE_VOICE_RECOGNITION) {
+ return strdup(SND_USE_CASE_DEV_DUAL_MIC_BROADSIDE_VREC);
+ } else {
+ return strdup(SND_USE_CASE_DEV_SPEAKER_DUAL_MIC_BROADSIDE);
+ }
}
} else {
if (fluence_mode == FLUENCE_MODE_ENDFIRE) {
- return strdup(SND_USE_CASE_DEV_DUAL_MIC_ENDFIRE); /* DUALMIC EF TX */
+ if (input_source == AUDIO_SOURCE_VOICE_RECOGNITION) {
+ return strdup(SND_USE_CASE_DEV_DUAL_MIC_ENDFIRE_VREC);
+ } else {
+ return strdup(SND_USE_CASE_DEV_DUAL_MIC_ENDFIRE);
+ }
} else if (fluence_mode == FLUENCE_MODE_BROADSIDE) {
- return strdup(SND_USE_CASE_DEV_DUAL_MIC_BROADSIDE); /* DUALMIC BS TX */
+ if (input_source == AUDIO_SOURCE_VOICE_RECOGNITION) {
+ return strdup(SND_USE_CASE_DEV_DUAL_MIC_BROADSIDE_VREC);
+ } else {
+ return strdup(SND_USE_CASE_DEV_DUAL_MIC_BROADSIDE);
+ }
}
}
-#endif
} else if (mDevSettingsFlag & QMIC_FLAG){
return strdup(SND_USE_CASE_DEV_QUAD_MIC);
}
diff --git a/libalsa-intf/msm8960_use_cases.h b/libalsa-intf/msm8960_use_cases.h
index 103b508..4c37cd0 100644
--- a/libalsa-intf/msm8960_use_cases.h
+++ b/libalsa-intf/msm8960_use_cases.h
@@ -232,8 +232,10 @@
#define SND_USE_CASE_DEV_TTY_HANDSET_TX "TTY Handset Tx"
#define SND_USE_CASE_DEV_TTY_HANDSET_ANALOG_TX "TTY Handset Analog Tx"
#define SND_USE_CASE_DEV_DUAL_MIC_BROADSIDE "DMIC Broadside"
+#define SND_USE_CASE_DEV_DUAL_MIC_BROADSIDE_VREC "DMIC Broadside Voice Rec"
#define SND_USE_CASE_DEV_DUAL_MIC_ENDFIRE "DMIC Endfire"
#define SND_USE_CASE_DEV_DUAL_MIC_ENDFIRE_TMUS "DMIC Endfire TMUS"
+#define SND_USE_CASE_DEV_DUAL_MIC_ENDFIRE_VREC "DMIC Endfire Voice Rec"
#define SND_USE_CASE_DEV_SPEAKER_DUAL_MIC_BROADSIDE "Speaker DMIC Broadside"
#define SND_USE_CASE_DEV_SPEAKER_DUAL_MIC_ENDFIRE "Speaker DMIC Endfire"
#define SND_USE_CASE_DEV_HDMI_TX "HDMI Tx"