summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Laurent <elaurent@google.com>2010-09-30 16:38:39 -0700
committerEric Laurent <elaurent@google.com>2010-10-01 14:58:12 -0700
commitbc4a3e85df64485dbe02a879bae9048579d88ac2 (patch)
treec9aa38a642585dbc738be0b0fe1d91128e1a81cf
parent6413e53edc03faa28de42bde30e14f94c4666571 (diff)
downloaddevice_samsung_crespo-bc4a3e85df64485dbe02a879bae9048579d88ac2.zip
device_samsung_crespo-bc4a3e85df64485dbe02a879bae9048579d88ac2.tar.gz
device_samsung_crespo-bc4a3e85df64485dbe02a879bae9048579d88ac2.tar.bz2
Workaround in audio HAL to fix audio input
Patched audio HAL to allow minimal audio input functionality until real fixes are submitted. This will allow features like voice search, VoIP, camcorder and mms audio record to work (with poor audio quality). Change-Id: I18acb120c5c398ccaeac11c462d629d41e33eef4
-rw-r--r--libaudio/AudioHardwareALSA.cpp663
-rwxr-xr-xlibaudio/AudioHardwareALSA.h73
2 files changed, 423 insertions, 313 deletions
diff --git a/libaudio/AudioHardwareALSA.cpp b/libaudio/AudioHardwareALSA.cpp
index 88598b7..52d0418 100644
--- a/libaudio/AudioHardwareALSA.cpp
+++ b/libaudio/AudioHardwareALSA.cpp
@@ -23,6 +23,7 @@
#include <stdlib.h>
#include <unistd.h>
+//#define LOG_NDEBUG 0
#define LOG_TAG "AudioHardwareALSA"
#include <utils/Log.h>
#include <utils/String8.h>
@@ -40,9 +41,6 @@
// sangsu fix : headers for IPC
#include <telephony/ril.h>
#endif
-#ifndef ALSA_DEFAULT_SAMPLE_RATE
-#define ALSA_DEFAULT_SAMPLE_RATE 44100 // in Hz
-#endif
#define SND_MIXER_VOL_RANGE_MIN (0)
#define SND_MIXER_VOL_RANGE_MAX (100)
@@ -53,10 +51,6 @@
if (strlen(x) + strlen(y) < ALSA_NAME_MAX) \
strcat(x, y);
-#define PERIOD_PLAYBACK 4
-#define PERIOD_CAPTURE 4
-#define PLAYBACK 0
-#define CAPTURE 1
// If you want to dump PCM data, activate this feature
//#define PCM_INPUT_DUMP
@@ -128,7 +122,6 @@ typedef AudioSystem::audio_devices audio_routes;
#endif
// ----------------------------------------------------------------------------
-static const int DEFAULT_SAMPLE_RATE = ALSA_DEFAULT_SAMPLE_RATE;
static const char _nullALSADeviceName[] = "NULL_Device";
@@ -163,7 +156,7 @@ static const char *deviceSuffix[] = {
/* ROUTE_HEADSET */ "_Headset",
/* ROUTE_HEADPHONE */ "_Headset",
/* ROUTE_BLUETOOTH_SCO */ "_Bluetooth",
- /* ROUTE_BLUETOOTH_SCO_HEADSET */ "_Bluetooth",
+ /* ROUTE_BLUETOOTH_SCO_HEADSET */ "_Bluetooth",
/* ROUTE_BLUETOOTH_SCO_CARKIT */ "_Bluetooth", //"_Bluetooth_Carkit"
/* ROUTE_BLUETOOTH_A2DP */ "_Bluetooth", //"_Bluetooth-A2DP"
/* ROUTE_BLUETOOTH_A2DP_HEADPHONES */ "_Bluetooth", //"_Bluetooth-A2DP_HeadPhone"
@@ -174,7 +167,7 @@ static const char *deviceSuffix[] = {
/* ROUTE_NULL */ "_Null",
/* ROUTE_NULL */ "_Null",
/* ROUTE_DEFAULT */ "_OutDefault",
-
+
// input devices
/* ROUTE_COMMUNICATION */ "_Communication",
/* ROUTE_AMBIENT */ "_Ambient",
@@ -250,6 +243,10 @@ mixerProp[][SND_PCM_STREAM_LAST+1] = {
}
};
+const uint32_t AudioHardwareALSA::inputSamplingRates[] = {
+ 44100, 22050, 11025
+};
+
// ----------------------------------------------------------------------------
AudioHardwareALSA::AudioHardwareALSA() :
@@ -261,7 +258,7 @@ AudioHardwareALSA::AudioHardwareALSA() :
#if defined TURN_ON_DEVICE_ONLY_USE
,mActivatedInputDevice(false)
#endif
-#if defined SYNCHRONIZE_CP
+#if defined SYNCHRONIZE_CP
,mActivatedCP(false)
#endif
@@ -315,12 +312,12 @@ status_t AudioHardwareALSA::setVoiceVolume(float volume)
LOGI("### earpiece call volume");
mIPC->transmitVolumeIPC(OEM_SOUND_TYPE_VOICE, volume);
break;
-
- case AudioSystem::ROUTE_SPEAKER:
+
+ case AudioSystem::ROUTE_SPEAKER:
LOGI("### speaker call volume");
mIPC->transmitVolumeIPC(OEM_SOUND_TYPE_SPEAKER, volume);
break;
-
+
case AudioSystem::ROUTE_BLUETOOTH_SCO:
case AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_HEADSET:
case AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_CARKIT:
@@ -328,15 +325,15 @@ status_t AudioHardwareALSA::setVoiceVolume(float volume)
LOGI("### bluetooth call volume");
mIPC->transmitVolumeIPC(OEM_SOUND_TYPE_BTVOICE, volume);
break;
-
+
case AudioSystem::ROUTE_HEADSET:
LOGI("### headset call volume");
mIPC->transmitVolumeIPC(OEM_SOUND_TYPE_HEADSET, volume);
break;
-
+
default:
LOGE("### Call volume setting error!!!0x%08x \n", routes);
- break;
+ break;
}
}
// sangsu fix end
@@ -405,7 +402,7 @@ AudioHardwareALSA::openOutputStream(
{
fpOutput = fopen(PCM_OUTPUT_DUMP_PATH, "w");
if (fpOutput == NULL)
- LOGE("fpOutput File Open Error!!");
+ LOGE("fpOutput File Open Error!!");
}
#endif
@@ -418,6 +415,7 @@ AudioHardwareALSA::openOutputStream(
//mOutput->setDevice(mMode, routes);
LOGI("%s] Setting ALSA device.", __func__);
mOutput->setDevice(mMode, devices, PLAYBACK); /* tushar - Enable all devices as of now */
+ mOutput->setWakeLock();
}
else {
delete out;
@@ -426,7 +424,7 @@ AudioHardwareALSA::openOutputStream(
return mOutput;
}
-void
+void
AudioHardwareALSA::closeOutputStream(AudioStreamOut* out)
{
/* TODO:Tushar: May lead to segmentation fault - check*/
@@ -456,7 +454,7 @@ AudioHardwareALSA::openInputStream(int format,
status_t *status,
AudioSystem::audio_in_acoustics acoustics)
#else
-AudioStreamIn*
+AudioStreamIn*
AudioHardwareALSA::openInputStream(
uint32_t devices,
int *format,
@@ -482,23 +480,23 @@ AudioHardwareALSA::openInputStream(
// Some information is expected to be available immediately after
// the device is open.
//uint32_t routes = mRoutes[mMode];
- //mInput->setDevice(mMode, routes);
+ //mInput->setDevice(mMode, routes);
mInput->setDevice(mMode, devices, CAPTURE); /* Tushar - as per modified arch */
+ mInput->setWakeLock();
#if defined TURN_ON_DEVICE_ONLY_USE
mActivatedInputDevice = true;
setMicStatus(1);
-
+#endif
#ifdef PCM_INPUT_DUMP
- if(fpInput == NULL)
- {
- fpInput = fopen(PCM_INPUT_DUMP_PATH, "w");
- if (fpInput == NULL)
- LOGE("fpInput File Open Error!!");
- }
+ if(fpInput == NULL)
+ {
+ fpInput = fopen(PCM_INPUT_DUMP_PATH, "w");
+ if (fpInput == NULL)
+ LOGE("fpInput File Open Error!!");
+ }
#endif
-#endif
- return mInput;
+ return mInput;
}
else {
delete in;
@@ -547,9 +545,9 @@ status_t AudioHardwareALSA::doRouting(uint32_t device)
// Setup sound path for CP clocking
#if defined SEC_IPC
-
+
if (AudioSystem::MODE_IN_CALL == mode)
- {
+ {
LOGI("### incall mode route (%d)", routes);
switch(routes){
@@ -557,12 +555,12 @@ status_t AudioHardwareALSA::doRouting(uint32_t device)
LOGI("### incall mode earpiece route");
mIPC->transmitAudioPathIPC(OEM_SOUND_AUDIO_PATH_HANDSET);
break;
-
+
case AudioSystem::ROUTE_SPEAKER:
LOGI("### incall mode speaker route");
mIPC->transmitAudioPathIPC(OEM_SOUND_AUDIO_PATH_SPEAKER);
break;
-
+
case AudioSystem::ROUTE_BLUETOOTH_SCO:
case AudioSystem::ROUTE_BLUETOOTH_SCO_HEADSET:
case AudioSystem::ROUTE_BLUETOOTH_SCO_CARKIT:
@@ -570,7 +568,7 @@ status_t AudioHardwareALSA::doRouting(uint32_t device)
if(mBluetoothECOff)
{
LOGI("### incall mode bluetooth EC OFF route");
- mIPC->transmitAudioPathIPC(OEM_SOUND_AUDIO_PATH_BT_NSEC_OFF);
+ mIPC->transmitAudioPathIPC(OEM_SOUND_AUDIO_PATH_BT_NSEC_OFF);
}
else
{
@@ -604,8 +602,8 @@ status_t AudioHardwareALSA::doRouting(uint32_t device)
#if defined SEC_IPC
if (AudioSystem::MODE_IN_CALL == mode)
- {
-#if defined SYNCHRONIZE_CP
+ {
+#if defined SYNCHRONIZE_CP
if(!mActivatedCP)
{
mIPC->transmitClock_IPC(OEM_SOUND_CLOCK_START);
@@ -616,7 +614,7 @@ status_t AudioHardwareALSA::doRouting(uint32_t device)
if (AudioSystem::MODE_NORMAL== mode) // Call stop.
{
-#if defined SYNCHRONIZE_CP
+#if defined SYNCHRONIZE_CP
if(mActivatedCP)
mActivatedCP = false;
#endif
@@ -624,8 +622,8 @@ status_t AudioHardwareALSA::doRouting(uint32_t device)
}
#endif // end of #if defined SEC_IPC
-#ifndef SYNCHRONIZE_CP
- ret = mOutput->setDevice(mode, routes, PLAYBACK);
+#ifndef SYNCHRONIZE_CP
+// ret = mOutput->setDevice(mode, routes, PLAYBACK);
#endif
return ret;
}
@@ -675,8 +673,7 @@ status_t AudioHardwareALSA::dump(int fd, const Vector<String16>& args)
size_t AudioHardwareALSA::getInputBufferSize(uint32_t sampleRate, int format, int channelCount)
{
- if (sampleRate != 8000 && sampleRate != 11025 && sampleRate != 16000 && sampleRate != 22050 &&
- sampleRate != 24000 && sampleRate != 32000 && sampleRate != 44100 && sampleRate != 48000) {
+ if (sampleRate < 8000 || sampleRate > 48000) {
LOGW("getInputBufferSize bad sampling rate: %d", sampleRate);
return 0;
}
@@ -689,14 +686,33 @@ size_t AudioHardwareALSA::getInputBufferSize(uint32_t sampleRate, int format, in
return 0;
}
-#if defined SEC_SWP_SOUND
- if (sampleRate == 32000 || sampleRate == 44100 || sampleRate == 48000)
- return READ_FRAME_SIZE_STANDARD;
- else
- return READ_FRAME_SIZE;
-#else /* SEC_SWP_SOUND */
- return 320;
-#endif /* SEC_SWP_SOUND */
+ uint32_t shift = checkInputSampleRate(sampleRate);
+ size_t size = (PERIOD_SZ_CAPTURE >> shift) * sizeof(int16_t);
+ LOGV("getInputBufferSize() rate %d, shift %d, size %d", sampleRate, shift, size);
+ return size;
+
+//#if defined SEC_SWP_SOUND
+// if (sampleRate == 32000 || sampleRate == 44100 || sampleRate == 48000)
+// return READ_FRAME_SIZE_STANDARD;
+// else
+// return READ_FRAME_SIZE;
+//#else /* SEC_SWP_SOUND */
+// return 320;
+//#endif /* SEC_SWP_SOUND */
+}
+
+uint32_t AudioHardwareALSA::checkInputSampleRate(uint32_t sampleRate)
+{
+ uint32_t i;
+ uint32_t prevDelta;
+ uint32_t delta;
+
+ for (i = 0, prevDelta = 0xFFFFFFFF; i < sizeof(inputSamplingRates)/sizeof(uint32_t); i++, prevDelta = delta) {
+ delta = abs(sampleRate - inputSamplingRates[i]);
+ if (delta > prevDelta) break;
+ }
+ // i is always > 0 here
+ return i-1;
}
// ----------------------------------------------------------------------------
@@ -741,23 +757,35 @@ status_t ALSAStreamOps::set(int *pformat,
LOGD("ALSAStreamOps - input - format = %d, channels = %d, rate = %d\n", lformat, lchannels, lrate);
- LOGD("ALSAStreamOps - default - format = %d, channels = %d, rate = %d\n", mDefaults->format, mDefaults->channels, mDefaults->sampleRate);
+ LOGD("ALSAStreamOps - default - format = %d, channelCount = %d, rate = %d\n", mDefaults->format, mDefaults->channelCount, mDefaults->sampleRate);
if(lformat == 0) lformat = getAndroidFormat(mDefaults->format);//format();
- if(lchannels == 0) lchannels = getAndroidChannels(mDefaults->channels);// channelCount();
- if(lrate == 0) lrate = mDefaults->sampleRate;
+ if(lchannels == 0) lchannels = getAndroidChannels(mDefaults->channelCount);// channelCount();
+ if(lrate == 0) lrate = mDefaults->sampleRate;
if((lformat != getAndroidFormat(mDefaults->format)) ||
- (lchannels != getAndroidChannels(mDefaults->channels)) ||
- (lrate != mDefaults->sampleRate)){
+ (lchannels != getAndroidChannels(mDefaults->channelCount))) {
if(pformat) *pformat = getAndroidFormat(mDefaults->format);
- if(pchannels) *pchannels = getAndroidChannels(mDefaults->channels);
- if(prate) *prate = mDefaults->sampleRate;
+ if(pchannels) *pchannels = getAndroidChannels(mDefaults->channelCount);
return BAD_VALUE;
- }
+ }
+ if (mDefaults->direction == SND_PCM_STREAM_PLAYBACK) {
+ if (lrate != mDefaults->sampleRate) {
+ if(prate) *prate = mDefaults->sampleRate;
+ return BAD_VALUE;
+ }
+ } else {
+ mDefaults->smpRateShift = AudioHardwareALSA::checkInputSampleRate(lrate);
+ // audioFlinger will reopen the input stream with correct smp rate
+ if (AudioHardwareALSA::inputSamplingRates[mDefaults->smpRateShift] != lrate) {
+ if(prate) *prate = AudioHardwareALSA::inputSamplingRates[mDefaults->smpRateShift];
+ return BAD_VALUE;
+ }
+ }
+ mDefaults->sampleRate = lrate;
if(pformat) *pformat = getAndroidFormat(mDefaults->format);
- if(pchannels) *pchannels = getAndroidChannels(mDefaults->channels);
+ if(pchannels) *pchannels = getAndroidChannels(mDefaults->channelCount);
if(prate) *prate = mDefaults->sampleRate;
return NO_ERROR;
@@ -766,14 +794,16 @@ status_t ALSAStreamOps::set(int *pformat,
uint32_t ALSAStreamOps::sampleRate() const
{
- unsigned int rate;
- int err;
-
- if (! mHandle)
- return NO_INIT;
+// unsigned int rate;
+// int err;
+//
+// if (! mHandle)
+// return NO_INIT;
+//
+// return snd_pcm_hw_params_get_rate(mHardwareParams, &rate, 0) < 0
+// ? 0 : static_cast<uint32_t>(rate);
- return snd_pcm_hw_params_get_rate(mHardwareParams, &rate, 0) < 0
- ? 0 : static_cast<uint32_t>(rate);
+ return mDefaults->sampleRate;
}
status_t ALSAStreamOps::sampleRate(uint32_t rate)
@@ -817,18 +847,12 @@ size_t ALSAStreamOps::bufferSize() const
{
int err;
- if (!mHandle)
- return -1;
+ size_t size = ((mDefaults->periodSize >> mDefaults->smpRateShift) * mDefaults->channelCount *
+ snd_pcm_format_physical_width(mDefaults->format)) / 8;
+ LOGV("bufferSize() channelCount %d, shift %d, size %d",
+ mDefaults->channelCount, mDefaults->smpRateShift, size);
+ return size;
- snd_pcm_uframes_t bufferSize = 0;
- snd_pcm_uframes_t periodSize = 0;
-
- err = snd_pcm_get_params(mHandle, &bufferSize, &periodSize);
-
- if (err < 0)
- return -1;
-
- return static_cast<size_t>(snd_pcm_frames_to_bytes(mHandle, bufferSize));
}
int ALSAStreamOps::getAndroidFormat(snd_pcm_format_t format)
@@ -861,8 +885,8 @@ int ALSAStreamOps::format() const
int pcmFormatBitWidth;
int audioSystemFormat;
- if (!mHandle)
- return -1;
+// if (!mHandle)
+// return -1;
if (snd_pcm_hw_params_get_format(mHardwareParams, &ALSAFormat) < 0) {
return -1;
@@ -886,86 +910,70 @@ int ALSAStreamOps::format() const
return audioSystemFormat;
}
-uint32_t ALSAStreamOps::getAndroidChannels(int channels)
+uint32_t ALSAStreamOps::getAndroidChannels(int channelCount) const
{
int AudioSystemChannels = AudioSystem::DEFAULT;
- switch(channels){
- case 1:
- AudioSystemChannels = AudioSystem::CHANNEL_OUT_FRONT_RIGHT;
- break;
- case 2:
- AudioSystemChannels = AudioSystem::CHANNEL_OUT_STEREO;
- break;
- case 4:
- AudioSystemChannels = AudioSystem::CHANNEL_OUT_QUAD;
- break;
- case 6:
- AudioSystemChannels = AudioSystem::CHANNEL_OUT_5POINT1;
- break;
- defualt:
- LOGE("FATAL: AudioSystem does not support %d channels.", channels);
- }
+ if (mDefaults->direction == SND_PCM_STREAM_PLAYBACK) {
+ switch(channelCount){
+ case 1:
+ AudioSystemChannels = AudioSystem::CHANNEL_OUT_MONO;
+ break;
+ case 2:
+ AudioSystemChannels = AudioSystem::CHANNEL_OUT_STEREO;
+ break;
+ case 4:
+ AudioSystemChannels = AudioSystem::CHANNEL_OUT_QUAD;
+ break;
+ case 6:
+ AudioSystemChannels = AudioSystem::CHANNEL_OUT_5POINT1;
+ break;
+ default:
+ LOGE("FATAL: AudioSystem does not support %d output channels.", channelCount);
+ }
+ } else {
+ switch(channelCount){
+ case 1:
+ AudioSystemChannels = AudioSystem::CHANNEL_IN_MONO;
+ break;
+ case 2:
+ AudioSystemChannels = AudioSystem::CHANNEL_IN_STEREO;
+ break;
+ default:
+ LOGE("FATAL: AudioSystem does not support %d input channels.", channelCount);
+ }
+
+ }
return AudioSystemChannels;
}
-int ALSAStreamOps::channelCount() const
+uint32_t ALSAStreamOps::channels() const
{
- unsigned int val;
- int err;
-
- int AudioSystemChannels;
-
- if (!mHandle)
- return -1;
-
- err = snd_pcm_hw_params_get_channels(mHardwareParams, &val);
- if (err < 0) {
- LOGE("Unable to get device channel count: %s",
- snd_strerror(err));
- return -1;
- }
-
- AudioSystemChannels = AudioSystem::DEFAULT;
-
- switch(val){
- case 1:
- AudioSystemChannels = AudioSystem::CHANNEL_OUT_FRONT_RIGHT;
- break;
- case 2:
- AudioSystemChannels = AudioSystem::CHANNEL_OUT_STEREO;
- break;
- case 4:
- AudioSystemChannels = AudioSystem::CHANNEL_OUT_QUAD;
- break;
- case 6:
- AudioSystemChannels = AudioSystem::CHANNEL_OUT_5POINT1;
- break;
- defualt:
- LOGE("FATAL: AudioSystem does not support %d channels.", val);
- }
-
+ return getAndroidChannels(mDefaults->channelCount);
+}
- return AudioSystemChannels;
+int ALSAStreamOps::channelCount() const
+{
+ return mDefaults->channelCount;
}
-status_t ALSAStreamOps::channelCount(int channels) {
+status_t ALSAStreamOps::channelCount(int channelCount) {
int err;
if (!mHandle)
return NO_INIT;
- // if(channels == 1) channels = 2; //Kamat: This is a fix added to avoid audioflinger crash (current audio driver does not support mono). Please check and modify suitably later.
+ // if(channelCount == 1) channelCount = 2; //Kamat: This is a fix added to avoid audioflinger crash (current audio driver does not support mono). Please check and modify suitably later.
- err = snd_pcm_hw_params_set_channels(mHandle, mHardwareParams, channels);
+ err = snd_pcm_hw_params_set_channels(mHandle, mHardwareParams, channelCount);
if (err < 0) {
LOGE("Unable to set channel count to %i: %s",
- channels, snd_strerror(err));
+ channelCount, snd_strerror(err));
return BAD_VALUE;
}
LOGD("Using %i %s for %s.",
- channels, channels == 1 ? "channel" : "channels", streamName());
+ channelCount, channelCount == 1 ? "channel" : "channels", streamName());
return NO_ERROR;
}
@@ -1204,14 +1212,14 @@ status_t ALSAStreamOps::setDevice(int mode, uint32_t device, uint audio_mode)
// is queried before it has been set. i.e. calling channelCount()
// before channelCount(channels) may return -EINVAL.
//
- status = channelCount(mDefaults->channels);
+ status = channelCount(mDefaults->channelCount);
if (status != NO_ERROR)
return status;
// Don't check for failure; some devices do not support the default
// sample rate.
-
- sampleRate(mDefaults->sampleRate);
+ // FIXME:: always use default sampling rate
+ sampleRate(DEFAULT_SAMPLE_RATE);
// Disable hardware resampling.
status = setHardwareResample(false);
@@ -1219,6 +1227,8 @@ status_t ALSAStreamOps::setDevice(int mode, uint32_t device, uint audio_mode)
return status;
snd_pcm_uframes_t bufferSize = mDefaults->bufferSize;
+ snd_pcm_uframes_t periodSize = mDefaults->periodSize;
+ period_val = bufferSize/periodSize;
unsigned int latency = mDefaults->latency;
@@ -1230,67 +1240,98 @@ status_t ALSAStreamOps::setDevice(int mode, uint32_t device, uint audio_mode)
return NO_INIT;
}
- // Setup buffers for latency
- err = snd_pcm_hw_params_set_buffer_time_near (mHandle, mHardwareParams,
- &latency, NULL);
- if(audio_mode == PLAYBACK) {
- period_val = PERIOD_PLAYBACK;
- if(snd_pcm_hw_params_set_periods(mHandle, mHardwareParams, period_val, 0) < 0)
- LOGE("Fail to set period size %d for playback", period_val);
- }
- else
- period_val = PERIOD_CAPTURE;
-
- if (err < 0) {
- /* That didn't work, set the period instead */
- unsigned int periodTime = latency / period_val;
- err = snd_pcm_hw_params_set_period_time_near (mHandle, mHardwareParams,
- &periodTime, NULL);
- if (err < 0) {
- LOGE("Unable to set the period time for latency: %s", snd_strerror(err));
- return NO_INIT;
- }
- snd_pcm_uframes_t periodSize;
- err = snd_pcm_hw_params_get_period_size (mHardwareParams, &periodSize, NULL);
- if (err < 0) {
- LOGE("Unable to get the period size for latency: %s", snd_strerror(err));
- return NO_INIT;
- }
- bufferSize = periodSize * period_val;
- if (bufferSize < mDefaults->bufferSize)
- bufferSize = mDefaults->bufferSize;
- err = snd_pcm_hw_params_set_buffer_size_near (mHandle, mHardwareParams, &bufferSize);
- if (err < 0) {
- LOGE("Unable to set the buffer size for latency: %s", snd_strerror(err));
- return NO_INIT;
- }
- } else {
- // OK, we got buffer time near what we expect. See what that did for bufferSize.
- err = snd_pcm_hw_params_get_buffer_size (mHardwareParams, &bufferSize);
- if (err < 0) {
- LOGE("Unable to get the buffer size for latency: %s", snd_strerror(err));
- return NO_INIT;
- }
- // Does set_buffer_time_near change the passed value? It should.
- err = snd_pcm_hw_params_get_buffer_time (mHardwareParams, &latency, NULL);
- if (err < 0) {
- LOGE("Unable to get the buffer time for latency: %s", snd_strerror(err));
- return NO_INIT;
- }
- unsigned int periodTime = latency / period_val;
- err = snd_pcm_hw_params_set_period_time_near (mHandle, mHardwareParams,
- &periodTime, NULL);
- if (err < 0) {
- LOGE("Unable to set the period time for latency: %s", snd_strerror(err));
+// if(audio_mode == PLAYBACK) {
+// period_val = PERIODS_PLAYBACK;
+// }
+// else {
+// period_val = PERIODS_CAPTURE;
+// }
+ // not working for capture ?
+ if (mDefaults->direction == SND_PCM_STREAM_PLAYBACK) {
+ if(snd_pcm_hw_params_set_periods(mHandle, mHardwareParams,
+ period_val, mDefaults->direction) < 0) {
+ LOGE("Fail to set period size %d for %d direction",
+ period_val, mDefaults->direction);
return NO_INIT;
}
}
+ err = snd_pcm_hw_params_get_period_size (mHardwareParams, &periodSize, NULL);
+ if (err < 0) {
+ LOGE("Unable to get the period size for latency: %s", snd_strerror(err));
+ return NO_INIT;
+ }
+
+// // Setup buffers for latency
+// err = snd_pcm_hw_params_set_buffer_time_near (mHandle, mHardwareParams,
+// &latency, NULL);
+// if(audio_mode == PLAYBACK) {
+// period_val = PERIODS_PLAYBACK;
+// if(snd_pcm_hw_params_set_periods(mHandle, mHardwareParams, period_val, 0) < 0)
+// LOGE("Fail to set period size %d for playback", period_val);
+// }
+// else
+// period_val = PERIODS_CAPTURE;
+//
+// if (err < 0) {
+// LOGD("snd_pcm_hw_params_set_buffer_time_near() failed: %s", snd_strerror(err));
+// /* That didn't work, set the period instead */
+// unsigned int periodTime = latency / period_val;
+// err = snd_pcm_hw_params_set_period_time_near (mHandle, mHardwareParams,
+// &periodTime, NULL);
+// if (err < 0) {
+// LOGE("Unable to set the period time for latency: %s", snd_strerror(err));
+// return NO_INIT;
+// }
+// err = snd_pcm_hw_params_get_period_size (mHardwareParams, &periodSize, NULL);
+// if (err < 0) {
+// LOGE("Unable to get the period size for latency: %s", snd_strerror(err));
+// return NO_INIT;
+// }
+// bufferSize = periodSize * period_val;
+// if (bufferSize < mDefaults->bufferSize)
+// bufferSize = mDefaults->bufferSize;
+// err = snd_pcm_hw_params_set_buffer_size_near (mHandle, mHardwareParams, &bufferSize);
+// if (err < 0) {
+// LOGE("Unable to set the buffer size for latency: %s", snd_strerror(err));
+// return NO_INIT;
+// }
+// } else {
+// LOGD("snd_pcm_hw_params_set_buffer_time_near() OK");
+// // OK, we got buffer time near what we expect. See what that did for bufferSize.
+// err = snd_pcm_hw_params_get_buffer_size (mHardwareParams, &bufferSize);
+// if (err < 0) {
+// LOGE("Unable to get the buffer size for latency: %s", snd_strerror(err));
+// return NO_INIT;
+// }
+// // Does set_buffer_time_near change the passed value? It should.
+// err = snd_pcm_hw_params_get_buffer_time (mHardwareParams, &latency, NULL);
+// if (err < 0) {
+// LOGE("Unable to get the buffer time for latency: %s", snd_strerror(err));
+// return NO_INIT;
+// }
+// LOGD("got latency %d for bufferSize %d", latency, bufferSize);
+// unsigned int periodTime = latency / period_val;
+// LOGD("got latency %d for bufferSize %d => periodTime %d", latency, bufferSize, periodTime);
+// err = snd_pcm_hw_params_set_period_time_near (mHandle, mHardwareParams,
+// &periodTime, NULL);
+// if (err < 0) {
+// LOGE("Unable to set the period time for latency: %s", snd_strerror(err));
+// return NO_INIT;
+// }
+// err = snd_pcm_hw_params_get_period_size (mHardwareParams, &periodSize, NULL);
+// if (err < 0) {
+// LOGE("Unable to get the period size for latency: %s", snd_strerror(err));
+// return NO_INIT;
+// }
+// }
LOGD("Buffer size: %d", (int)bufferSize);
+ LOGD("Period size: %d", (int)periodSize);
LOGD("Latency: %d", (int)latency);
mDefaults->bufferSize = bufferSize;
mDefaults->latency = latency;
+ mDefaults->periodSize = periodSize;
// Commit the hardware parameters back to the device.
err = snd_pcm_hw_params(mHandle, mHardwareParams);
@@ -1348,10 +1389,12 @@ AudioStreamOutALSA::AudioStreamOutALSA(AudioHardwareALSA *parent) :
devicePrefix : "AndroidPlayback",
direction : SND_PCM_STREAM_PLAYBACK,
format : SND_PCM_FORMAT_S16_LE, // AudioSystem::PCM_16_BIT
- channels : 2,
+ channelCount : 2,
sampleRate : DEFAULT_SAMPLE_RATE,
- latency : 250000, // Desired Delay in usec
- bufferSize : 4096, // Desired Number of samples
+ smpRateShift : 0,
+ latency : LATENCY_PLAYBACK_MS, // Desired Delay in usec
+ bufferSize : BUFFER_SZ_PLAYBACK, // Desired Number of samples
+ periodSize : PERIOD_SZ_PLAYBACK
};
setStreamDefaults(&_defaults);
@@ -1363,16 +1406,6 @@ AudioStreamOutALSA::~AudioStreamOutALSA()
mParent->mOutput = NULL;
}
-//int AudioStreamOutALSA::channelCount() const
-uint32_t AudioStreamOutALSA::channels() const
-{
- uint32_t c = ALSAStreamOps::channelCount();
-
- // AudioMixer will seg fault if it doesn't have two channels.
- LOGW_IF(c != AudioSystem::CHANNEL_OUT_STEREO,
- "AudioMixer expects two channels, but only %i found!", c);
- return c;
-}
/* New arch */
status_t AudioStreamOutALSA::setVolume(float left, float right)
@@ -1380,7 +1413,7 @@ status_t AudioStreamOutALSA::setVolume(float left, float right)
if (! mParent->mMixer || ! mDevice)
return NO_INIT;
- /** Tushar - Need to decide on the volume value
+ /** Tushar - Need to decide on the volume value
* that we pass onto the mixer. */
return mParent->mMixer->setVolume (mDevice, (left + right)/2);
}
@@ -1402,24 +1435,24 @@ status_t AudioStreamOutALSA::setParameters(const String8& keyValuePairs)
int device;
int value;
LOGD("AudioStreamOutALSA::setParameters() %s", keyValuePairs.string());
-
- if (param.getInt(String8(AudioParameter::keyRouting), device) == NO_ERROR)
+
+ if (param.getInt(String8(AudioParameter::keyRouting), device) == NO_ERROR)
{
mDevice = device;
- if (mParent->mInput) mParent->mInput->mDevice = device;
- mParent->mRoutes[mParent->mMode] = mDevice;
+// if (mParent->mInput) mParent->mInput->mDevice = device;
+ mParent->mRoutes[mParent->mMode] = mDevice;
mParent->doRouting(mDevice);
param.remove(String8(AudioParameter::keyRouting));
}
else if (param.getInt(String8(AudioParameter::keySamplingRate), value) == NO_ERROR)
{
- mParent->mOutput->mDefaults->sampleRate = value;
- mParent->doRouting(mDevice);
- param.remove(String8(AudioParameter::keySamplingRate));
+ mParent->mOutput->mDefaults->sampleRate = value;
+ mParent->doRouting(mDevice);
+ param.remove(String8(AudioParameter::keySamplingRate));
}
-
+
if (param.size()) {
status = BAD_VALUE;
}
@@ -1435,7 +1468,7 @@ status_t AudioStreamOutALSA::setParameters(const String8& keyValuePairs)
int device = keyValuePairs.string()[keyValuePairs.length()-1] - 48 -1 ; //easy conversion frm ascii to int and then to required number
LOGV("\n\n-------->> ALSA SET PARAMS device %d \n\n",(1<<device));
mParent->mOutput->setDevice(mMode, 1<<device, PLAYBACK);
- return NO_ERROR;
+ return NO_ERROR;
#endif
}
String8 AudioStreamOutALSA::getParameters(const String8& keys)
@@ -1444,16 +1477,16 @@ String8 AudioStreamOutALSA::getParameters(const String8& keys)
AudioParameter param = AudioParameter(keys);
String8 value;
String8 key = String8(AudioParameter::keyRouting);
-
+
if (param.get(key, value) == NO_ERROR) {
param.addInt(key, (int)mDevice);
}
-
+
LOGD("AudioStreamOutALSA::getParameters() %s", param.toString().string());
return param.toString();
#else
/* TODO: Implement as per new arch */
- return keys;
+ return keys;
#endif
}
@@ -1474,7 +1507,8 @@ ssize_t AudioStreamOutALSA::write(const void *buffer, size_t bytes)
AutoMutex lock(mLock);
if (!mPowerLock) {
- ALSAStreamOps::setDevice(mMode, mDevice, PLAYBACK);
+ LOGD("Calling setDevice from write @..%d.\n",__LINE__);
+ ALSAStreamOps::setDevice(mMode, mDevice, PLAYBACK);
acquire_wake_lock (PARTIAL_WAKE_LOCK, "AudioOutLock");
mPowerLock = true;
}
@@ -1485,36 +1519,29 @@ ssize_t AudioStreamOutALSA::write(const void *buffer, size_t bytes)
fwrite(buffer, bytes, 1, fpOutput);
LOGD("Output PCM dumped!!");
#endif
- if (!mHandle){
- LOGD("Calling setDevice from write @..%d.\n",__LINE__);
- ALSAStreamOps::setDevice(mMode, mDevice, PLAYBACK);
- }
do {
- // write correct number of bytes per attempt
- n = snd_pcm_writei(mHandle,
- (char *)buffer + sent,
- snd_pcm_bytes_to_frames(mHandle, bytes-sent));
+ // write correct number of bytes per attempt
+ n = snd_pcm_writei(mHandle, (char *) buffer + sent, snd_pcm_bytes_to_frames(mHandle, bytes
+ - sent));
if (n == -EBADFD) {
- LOGD("Calling setDevice.. pcm_write returned error @..%d.\n",__LINE__);
- // Somehow the stream is in a bad state. The driver probably
- // has a bug and snd_pcm_recover() doesn't seem to handle this.
- ALSAStreamOps::setDevice(mMode, mDevice, PLAYBACK);
- }
- else if (n < 0) {
+ LOGD("Calling setDevice.. pcm_write returned error @..%d.\n",__LINE__);
+ // Somehow the stream is in a bad state. The driver probably
+ // has a bug and snd_pcm_recover() doesn't seem to handle this.
+ ALSAStreamOps::setDevice(mMode, mDevice, PLAYBACK);
+ } else if (n < 0) {
if (mHandle) {
- // snd_pcm_recover() will return 0 if successful in recovering from
- // // an error, or -errno if the error was unrecoverable.
- // We can make silent bit on as we are now handling the under-run and there will not be any data loss due to under-run
- n = snd_pcm_recover(mHandle, n, 1);
- if (n)
- return static_cast<ssize_t>(n);
+ // snd_pcm_recover() will return 0 if successful in recovering from
+ // // an error, or -errno if the error was unrecoverable.
+ // We can make silent bit on as we are now handling the under-run and there will not be any data loss due to under-run
+ n = snd_pcm_recover(mHandle, n, 1);
+ if (n)
+ return static_cast<ssize_t> (n);
}
- }
- else
- sent += static_cast<ssize_t>(snd_pcm_frames_to_bytes(mHandle, n));
+ } else
+ sent += static_cast<ssize_t> (snd_pcm_frames_to_bytes(mHandle, n));
} while (mHandle && sent < bytes);
//LOGI("Request Bytes=%d, Actual Written=%d",bytes,sent);
- return sent;
+ return snd_pcm_frames_to_bytes(mHandle, sent);
}
#else
ssize_t AudioStreamOutALSA::write(const void *buffer, size_t bytes)
@@ -1532,14 +1559,16 @@ ssize_t AudioStreamOutALSA::write(const void *buffer, size_t bytes)
ALSAStreamOps::setDevice(mMode, mDevice,PLAYBACK);
mPowerLock = true;
}
-
+ if (!mHandle) {
+ return -1;
+ }
n = snd_pcm_writei(mHandle,
buffer,
snd_pcm_bytes_to_frames(mHandle, bytes));
if (n < 0 && mHandle) {
// snd_pcm_recover() will return 0 if successful in recovering from
// an error, or -errno if the error was unrecoverable.
- //device driver sometimes does not recover -vladi
+ //device driver sometimes does not recover -vladi
n = snd_pcm_recover(mHandle, n, 0);
if(n < 0) //if recover fails
ALSAStreamOps::setDevice(mMode, mDevice, PLAYBACK);
@@ -1563,32 +1592,37 @@ status_t AudioStreamOutALSA::setDevice(int mode, uint32_t newDevice, uint32_t au
return ALSAStreamOps::setDevice(mode, newDevice, audio_mode);
}
-status_t AudioStreamOutALSA::standby()
-{
+status_t AudioStreamOutALSA::standby() {
AutoMutex lock(mLock);
LOGD("Inside AudioStreamOutALSA::standby\n");
if (mHandle)
- snd_pcm_drain (mHandle);
+ snd_pcm_drain ( mHandle);
if (mPowerLock) {
- if(!mParent->mActivatedInputDevice){ // Let PCM device alive on activating input stream.
- snd_pcm_close(mHandle);
- mHandle = NULL;
+ if (!mParent->mActivatedInputDevice) { // Let PCM device alive on activating input stream.
+ snd_pcm_close( mHandle);
+ mHandle = NULL;
#if 1 // Fix for underrun error
- release_wake_lock ("AudioOutLock");
+ release_wake_lock("AudioOutLock");
#else
- release_wake_lock ("AudioLock");
+ release_wake_lock ("AudioLock");
#endif
- mPowerLock = false;
- }
- }
-// close(); //Don't call this as this function will reset the mode also
+ mPowerLock = false;
+ }
+ }
+ // close(); //Don't call this as this function will reset the mode also
return NO_ERROR;
}
bool AudioStreamOutALSA::isStandby()
{
- return (!mHandle);
+ return (!mPowerLock);
+}
+
+void AudioStreamOutALSA::setWakeLock()
+{
+ acquire_wake_lock (PARTIAL_WAKE_LOCK, "AudioOutLock");
+ mPowerLock = true;
}
#define USEC_TO_MSEC(x) ((x + 999) / 1000)
@@ -1609,10 +1643,12 @@ AudioStreamInALSA::AudioStreamInALSA(AudioHardwareALSA *parent) :
devicePrefix : "AndroidRecord",
direction : SND_PCM_STREAM_CAPTURE,
format : SND_PCM_FORMAT_S16_LE, // AudioSystem::PCM_16_BIT
- channels : 1,
- sampleRate : AudioRecord::DEFAULT_SAMPLE_RATE,
- latency : 250000, // Desired Delay in usec
- bufferSize : 4096, // Desired Number of samples
+ channelCount : 1,
+ sampleRate : DEFAULT_SAMPLE_RATE,
+ smpRateShift : 0,
+ latency : LATENCY_CAPTURE_MS,// Desired Delay in usec
+ bufferSize : BUFFER_SZ_CAPTURE, // Desired Number of samples
+ periodSize : PERIOD_SZ_CAPTURE
};
setStreamDefaults(&_defaults);
@@ -1620,12 +1656,7 @@ AudioStreamInALSA::AudioStreamInALSA(AudioHardwareALSA *parent) :
AudioStreamInALSA::~AudioStreamInALSA()
{
- if (mPowerLock) {
- snd_pcm_close(mHandle);
- mHandle = NULL;
- release_wake_lock ("AudioInLock");
- mPowerLock = false;
- }
+ standby_l();
mParent->mInput = NULL;
}
@@ -1646,29 +1677,69 @@ ssize_t AudioStreamInALSA::read(void *buffer, ssize_t bytes)
if (!mPowerLock) {
acquire_wake_lock (PARTIAL_WAKE_LOCK, "AudioInLock");
-
+
#ifdef PCM_INPUT_DUMP
fwrite(buffer, readBytes, 1, fpInput);
LOGD("Input PCM dumped!!");
#endif
+#if defined TURN_ON_DEVICE_ONLY_USE
+ mParent->mActivatedInputDevice = true;
+// setMicStatus(1);
+#endif
LOGD("Calling setDevice from read@..%d.\n",__LINE__);
ALSAStreamOps::setDevice(mMode, mDevice,CAPTURE);
mPowerLock = true;
}
- n = snd_pcm_readi(mHandle,
- buffer,
- snd_pcm_bytes_to_frames(mHandle, bytes));
- if (n < 0 && mHandle) {
- n = snd_pcm_recover(mHandle, n, 0);
+ if (!mHandle) {
+ return -1;
+ }
+
+ // FIXME: only support reads of exactly bufferSize() for now
+ if (bytes != bufferSize()) {
+ LOGW("AudioStreamInALSA::read bad read size %d expected %d", bytes, bufferSize());
+ return -1;
}
+ size_t frames = snd_pcm_bytes_to_frames(mHandle, bytes);
+ uint32_t shift = mDefaults->smpRateShift;
+ do {
+ n = snd_pcm_readi(mHandle,
+ (uint8_t *)mBuffer,
+ frames << shift);
+ if (n < 0) {
+ LOGD("AudioStreamInALSA::read error %d", n);
+ n = snd_pcm_recover(mHandle, n, 0);
+ LOGD("AudioStreamInALSA::snd_pcm_recover error %d", n);
+ if (n)
+ return static_cast<ssize_t> (n);
+ } else {
+ n >>= shift;
+ }
+ } while (n == 0);
+
+ // FIXME: quick hack to enable simultaneous playback and record. input and output device
+ // drivers always operate at 44.1kHz. We do a dirty downsampling here by an entire ratio
+ // (4, 2 or 1) without filtering and the resampler in AudioFlinger does the remaining
+ // resampling if any (e.g. 11025 -> 8000). We do this because of the limitation of the
+ // downsampler in AudioFlinger (SR in < 2 * SR out)
+ int16_t *out = (int16_t *)buffer;
+ if (mDefaults->channelCount == 1) {
+ for (size_t i = 0; i < n; i++) {
+ out[i] = mBuffer[i << shift];
+ }
+ } else {
+ for (size_t i = 0; i < n; i++) {
+ out[i] = mBuffer[i << shift];
+ out[i + 1] = mBuffer[(i << shift) + 1];
+ }
+ }
#ifdef PCM_INPUT_DUMP
fwrite(buffer, bytes, 1, fpInput);
LOGD("Input PCM dumped!!");
#endif
- return static_cast<ssize_t>(n);
+ return snd_pcm_frames_to_bytes(mHandle, n);
}
status_t AudioStreamInALSA::dump(int fd, const Vector<String16>& args)
@@ -1687,10 +1758,16 @@ status_t AudioStreamInALSA::standby()
{
AutoMutex lock(mLock);
+ return standby_l();
+}
+
+status_t AudioStreamInALSA::standby_l()
+{
LOGD("Entering AudioStreamInALSA::standby\n");
if (mPowerLock) {
mParent->mActivatedInputDevice = false;
snd_pcm_close(mHandle);
+ LOGD("AudioStreamInALSA::standby snd_pcm_close()");
mHandle = NULL;
release_wake_lock ("AudioInLock");
mPowerLock = false;
@@ -1699,6 +1776,12 @@ status_t AudioStreamInALSA::standby()
return NO_ERROR;
}
+void AudioStreamInALSA::setWakeLock()
+{
+ acquire_wake_lock (PARTIAL_WAKE_LOCK, "AudioInLock");
+ mPowerLock = true;
+}
+
/* New Arch */
status_t AudioStreamInALSA::setParameters(const String8& keyValuePairs)
{
@@ -1708,14 +1791,14 @@ status_t AudioStreamInALSA::setParameters(const String8& keyValuePairs)
status_t status = NO_ERROR;
int device;
LOGD("AudioStreamInALSA::setParameters() %s", keyValuePairs.string());
-
+
if (param.getInt(key, device) == NO_ERROR) {
- mDevice = device;
- if(mDevice != 0)
- setDevice(mMode, mDevice, CAPTURE);
- param.remove(key);
+ mDevice = device;
+ if(mPowerLock && mDevice != 0)
+ setDevice(mMode, mDevice, CAPTURE);
+ param.remove(key);
}
-
+
if (param.size()) {
status = BAD_VALUE;
}
@@ -1743,11 +1826,11 @@ String8 AudioStreamInALSA::getParameters(const String8& keys)
AudioParameter param = AudioParameter(keys);
String8 value;
String8 key = String8(AudioParameter::keyRouting);
-
+
if (param.get(key, value) == NO_ERROR) {
param.addInt(key, (int)mDevice);
}
-
+
LOGD("AudioStreamInALSA::getParameters() %s", param.toString().string());
return param.toString();
#else
@@ -2139,7 +2222,7 @@ status_t ALSAControl::get(const char *name, unsigned int &value, int index)
snd_ctl_elem_id_alloca(&id);
snd_ctl_elem_info_alloca(&info);
snd_ctl_elem_value_alloca(&control);
-
+
snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_MIXER);
snd_ctl_elem_id_set_name(id, name);
snd_ctl_elem_info_set_id(info, id);
@@ -2191,7 +2274,7 @@ status_t ALSAControl::set(const char *name, unsigned int value, int index)
snd_ctl_elem_id_alloca(&id);
snd_ctl_elem_info_alloca(&info);
snd_ctl_elem_value_alloca(&control);
-
+
snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_MIXER);
snd_ctl_elem_id_set_name(id, name);
snd_ctl_elem_info_set_id(info, id);
@@ -2299,7 +2382,7 @@ status_t AudioHardwareIPC::transmitVolumeIPC(uint32_t type, float volume)
memset(data, 0, 100);
data[0] = OEM_FUNCTION_ID_SOUND;
data[1] = OEM_SOUND_SET_VOLUME_CTRL;
- data[2] = 0x00; // data length
+ data[2] = 0x00; // data length
data[3] = 0x06; // data length
data[4] = type; // volume type
data[5] = level; // volume level
@@ -2327,7 +2410,7 @@ status_t AudioHardwareIPC::transmitAudioPathIPC(uint32_t path)
memset(data, 0, 100);
data[0] = OEM_FUNCTION_ID_SOUND;
data[1] = OEM_SOUND_SET_AUDIO_PATH_CTRL;
- data[2] = 0x00; // data length
+ data[2] = 0x00; // data length
data[3] = 0x05; // data length
data[4] = path; // audio path
@@ -2357,12 +2440,12 @@ status_t AudioHardwareIPC::transmitClock_IPC(uint32_t condition)
memset(data, 0, 100);
data[0] = OEM_FUNCTION_ID_SOUND;
data[1] = OEM_SOUND_SET_CLOCK_CTRL;
- data[2] = 0x00; // data length
+ data[2] = 0x00; // data length
data[3] = 0x05; // data length
- data[4] = condition;
+ data[4] = condition;
ret = InvokeOemRequestHookRaw(mClient, data, 5); //sizeof(data));
-
+
if (ret != RIL_CLIENT_ERR_AGAIN && ret != RIL_CLIENT_ERR_SUCCESS){
LOGE("[*] InvokeOemRequestHookRaw() error ret = %d\n", ret);
return INVALID_OPERATION;
diff --git a/libaudio/AudioHardwareALSA.h b/libaudio/AudioHardwareALSA.h
index 5a4b5d5..0390beb 100755
--- a/libaudio/AudioHardwareALSA.h
+++ b/libaudio/AudioHardwareALSA.h
@@ -90,9 +90,29 @@
#define OEM_SOUND_TYPE_HEADSET 0x31 // Headset (0x30) + Voice(0x01)
#define OEM_SOUND_TYPE_BTVOICE 0x41 // BT(0x40) + Voice(0x01)
#endif
+
+#ifndef ALSA_DEFAULT_SAMPLE_RATE
+#define ALSA_DEFAULT_SAMPLE_RATE 44100 // in Hz
+#endif
+
+#define DEFAULT_SAMPLE_RATE ALSA_DEFAULT_SAMPLE_RATE
+
+#define PLAYBACK 0
+#define PERIOD_SZ_PLAYBACK 1024
+#define PERIODS_PLAYBACK 4
+#define BUFFER_SZ_PLAYBACK (PERIODS_PLAYBACK * PERIOD_SZ_PLAYBACK)
+#define LATENCY_PLAYBACK_MS ((BUFFER_SZ_PLAYBACK * 1000 / DEFAULT_SAMPLE_RATE) * 1000)
+
+#define CAPTURE 1
+#define PERIOD_SZ_CAPTURE 2048
+#define PERIODS_CAPTURE 2
+#define BUFFER_SZ_CAPTURE (PERIODS_CAPTURE * PERIOD_SZ_CAPTURE)
+#define LATENCY_CAPTURE_MS ((BUFFER_SZ_CAPTURE * 1000 / DEFAULT_SAMPLE_RATE) * 1000)
+
namespace android
{
+
class AudioHardwareALSA;
// ----------------------------------------------------------------------------
@@ -143,10 +163,12 @@ namespace android
const char * devicePrefix;
snd_pcm_stream_t direction; // playback or capture
snd_pcm_format_t format;
- int channels;
+ int channelCount;
uint32_t sampleRate;
+ uint32_t smpRateShift;
unsigned int latency; // Delay in usec
unsigned int bufferSize; // Size of sample buffer
+ unsigned int periodSize; // Size of sample buffer
};
ALSAStreamOps();
@@ -159,11 +181,12 @@ namespace android
status_t sampleRate(uint32_t rate);
virtual size_t bufferSize() const;
virtual int format() const;
- int getAndroidFormat(snd_pcm_format_t format);
+ int getAndroidFormat(snd_pcm_format_t format);
- virtual int channelCount() const;
- status_t channelCount(int channels);
- uint32_t getAndroidChannels(int channels);
+ virtual uint32_t channels() const;
+ int channelCount() const;
+ status_t channelCount(int channelCount);
+ uint32_t getAndroidChannels(int channelCount) const;
status_t open(int mode, uint32_t device);
void close();
@@ -201,14 +224,13 @@ namespace android
virtual ~AudioStreamOutALSA();
- status_t set(int *format,
- uint32_t *channelCount,
- uint32_t *sampleRate){
- return ALSAStreamOps::set(format, channelCount, sampleRate);
- }
+ status_t set(int *format,
+ uint32_t *channelCount,
+ uint32_t *sampleRate){
+ return ALSAStreamOps::set(format, channelCount, sampleRate);
+ }
- virtual uint32_t sampleRate() const
- {
+ virtual uint32_t sampleRate() const {
return ALSAStreamOps::sampleRate();
}
@@ -217,8 +239,10 @@ namespace android
return ALSAStreamOps::bufferSize();
}
- //virtual int channelCount() const;
- virtual uint32_t channels() const;
+ virtual uint32_t channels() const
+ {
+ return ALSAStreamOps::channels();
+ }
virtual int format() const
{
@@ -236,6 +260,7 @@ namespace android
status_t standby();
bool isStandby();
+ void setWakeLock();
virtual status_t setParameters(const String8& keyValuePairs);
virtual String8 getParameters(const String8& keys);
@@ -254,13 +279,12 @@ namespace android
AudioStreamInALSA(AudioHardwareALSA *parent);
virtual ~AudioStreamInALSA();
- status_t set(int *format,
- uint32_t *channelCount,
- uint32_t *sampleRate){
- return ALSAStreamOps::set(format, channelCount, sampleRate);
- }
+ status_t set(int *format,
+ uint32_t *channelCount,
+ uint32_t *sampleRate){
+ return ALSAStreamOps::set(format, channelCount, sampleRate);
+ }
- //virtual uint32_t sampleRate() {
virtual uint32_t sampleRate() const {
return ALSAStreamOps::sampleRate();
}
@@ -270,10 +294,9 @@ namespace android
return ALSAStreamOps::bufferSize();
}
- //virtual int channelCount() const
virtual uint32_t channels() const
{
- return ALSAStreamOps::channelCount();
+ return ALSAStreamOps::channels();
}
virtual int format() const
@@ -288,6 +311,8 @@ namespace android
virtual status_t setGain(float gain);
virtual status_t standby();
+ status_t standby_l();
+ void setWakeLock();
virtual status_t setParameters(const String8& keyValuePairs);
virtual String8 getParameters(const String8& keys);
@@ -297,6 +322,7 @@ namespace android
private:
AudioHardwareALSA *mParent;
bool mPowerLock;
+ int16_t mBuffer[2 * PERIOD_SZ_CAPTURE];
};
#if defined SEC_IPC
@@ -373,7 +399,8 @@ namespace android
AudioSystem::audio_in_acoustics acoustics);
virtual void closeInputStream(AudioStreamIn* in);
-
+ static uint32_t checkInputSampleRate(uint32_t sampleRate);
+ static const uint32_t inputSamplingRates[];
protected:
/**