summaryrefslogtreecommitdiffstats
path: root/libaudio
diff options
context:
space:
mode:
authorPawit Pornkitprasan <p.pawit@gmail.com>2011-12-31 10:05:30 +0700
committerPawit Pornkitprasan <p.pawit@gmail.com>2011-12-31 10:05:30 +0700
commitf0e10ccdb5d65f65017b1c71a68022f63d0c23ef (patch)
tree2d89e2f58a87b86804ea7691c28b2a14a3e8f712 /libaudio
parent33d4bf28318157e23ba605cbcb4099aedef638a9 (diff)
downloaddevice_samsung_aries-common-f0e10ccdb5d65f65017b1c71a68022f63d0c23ef.zip
device_samsung_aries-common-f0e10ccdb5d65f65017b1c71a68022f63d0c23ef.tar.gz
device_samsung_aries-common-f0e10ccdb5d65f65017b1c71a68022f63d0c23ef.tar.bz2
Update libaudio from crespo (with FM added)
Diffstat (limited to 'libaudio')
-rw-r--r--libaudio/Android.mk74
-rw-r--r--libaudio/AudioHardware.cpp1175
-rw-r--r--libaudio/AudioHardware.h167
-rw-r--r--libaudio/AudioPolicyManager.cpp2
-rw-r--r--libaudio/alsa_audio.h77
-rw-r--r--libaudio/alsa_mixer.c371
-rw-r--r--libaudio/alsa_pcm.c405
-rw-r--r--libaudio/amix.c78
-rw-r--r--libaudio/aplay.c140
-rw-r--r--libaudio/arec.c128
-rw-r--r--libaudio/asound.h814
11 files changed, 757 insertions, 2674 deletions
diff --git a/libaudio/Android.mk b/libaudio/Android.mk
index 4af67bb..183ede3 100644
--- a/libaudio/Android.mk
+++ b/libaudio/Android.mk
@@ -1,65 +1,45 @@
-ifneq ($(TARGET_PROVIDES_LIBAUDIO),true)
-
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
-LOCAL_SRC_FILES:= aplay.c alsa_pcm.c alsa_mixer.c
-LOCAL_MODULE:= aplay
-LOCAL_SHARED_LIBRARIES:= libc libcutils
-LOCAL_MODULE_TAGS:= debug
-include $(BUILD_EXECUTABLE)
-
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES:= arec.c alsa_pcm.c
-LOCAL_MODULE:= arec
-LOCAL_SHARED_LIBRARIES:= libc libcutils
-LOCAL_MODULE_TAGS:= debug
-include $(BUILD_EXECUTABLE)
-
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES:= amix.c alsa_mixer.c
-LOCAL_MODULE:= amix
-LOCAL_SHARED_LIBRARIES := libc libcutils
-LOCAL_MODULE_TAGS:= debug
-include $(BUILD_EXECUTABLE)
+LOCAL_SRC_FILES:= \
+ AudioHardware.cpp
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES:= AudioHardware.cpp alsa_mixer.c alsa_pcm.c
+LOCAL_MODULE := audio.primary.aries
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
-LOCAL_MODULE:= audio.primary.aries
-LOCAL_MODULE_TAGS := optional
-LOCAL_STATIC_LIBRARIES := libmedia_helper
-LOCAL_WHOLE_STATIC_LIBRARIES := libaudiohw_legacy
-LOCAL_SHARED_LIBRARIES:= libc libcutils libutils libmedia libhardware_legacy
-# TODO: Fix A2DP
-#ifeq ($(BOARD_HAVE_BLUETOOTH),true)
-# LOCAL_SHARED_LIBRARIES += liba2dp
-#endif
+LOCAL_STATIC_LIBRARIES:= libmedia_helper
+LOCAL_SHARED_LIBRARIES:= \
+ libutils \
+ libhardware_legacy \
+ libtinyalsa \
+ libaudioutils
-# TODO: Fix FM
-#ifeq ($(BOARD_HAVE_FM_RADIO),true)
-# LOCAL_CFLAGS += -DHAVE_FM_RADIO
-#endif
+LOCAL_WHOLE_STATIC_LIBRARIES := libaudiohw_legacy
+LOCAL_MODULE_TAGS := optional
-ifeq ($(TARGET_SIMULATOR),true)
- LOCAL_LDLIBS += -ldl
-else
- LOCAL_SHARED_LIBRARIES += libdl
-endif
+LOCAL_SHARED_LIBRARIES += libdl
+LOCAL_C_INCLUDES += \
+ external/tinyalsa/include \
+ system/media/audio_effects/include \
+ system/media/audio_utils/include
include $(BUILD_SHARED_LIBRARY)
include $(CLEAR_VARS)
-LOCAL_SRC_FILES:= AudioPolicyManager.cpp
+
+LOCAL_SRC_FILES := AudioPolicyManager.cpp
+LOCAL_SHARED_LIBRARIES := libcutils libutils libmedia
+LOCAL_STATIC_LIBRARIES := libmedia_helper
+LOCAL_WHOLE_STATIC_LIBRARIES := libaudiopolicy_legacy
+LOCAL_MODULE := audio_policy.aries
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
-LOCAL_MODULE:= audio_policy.aries
LOCAL_MODULE_TAGS := optional
-LOCAL_STATIC_LIBRARIES := libmedia_helper
-LOCAL_WHOLE_STATIC_LIBRARIES:= libaudiopolicy_legacy
-LOCAL_SHARED_LIBRARIES:= libc libcutils libutils libmedia
+
ifeq ($(BOARD_HAVE_BLUETOOTH),true)
LOCAL_CFLAGS += -DWITH_A2DP
endif
-include $(BUILD_SHARED_LIBRARY)
+ifeq ($(BOARD_HAVE_FM_RADIO),true)
+ LOCAL_CFLAGS += -DHAVE_FM_RADIO
endif
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/libaudio/AudioHardware.cpp b/libaudio/AudioHardware.cpp
index 5d3f43a..b0f23c3 100644
--- a/libaudio/AudioHardware.cpp
+++ b/libaudio/AudioHardware.cpp
@@ -17,7 +17,6 @@
#include <math.h>
#define LOG_NDEBUG 0
-
#define LOG_TAG "AudioHardware"
#include <utils/Log.h>
@@ -34,10 +33,10 @@
#include "AudioHardware.h"
#include <media/AudioRecord.h>
-#include <hardware_legacy/power.h>
+#include <audio_effects/effect_aec.h>
extern "C" {
-#include "alsa_audio.h"
+#include <tinyalsa/asoundlib.h>
}
#ifdef HAVE_FM_RADIO
@@ -47,8 +46,13 @@ extern "C" {
namespace android_audio_legacy {
-const uint32_t AudioHardware::inputSamplingRates[] = {
- 8000, 11025, 16000, 22050, 44100
+const uint32_t AudioHardware::inputConfigTable[][AudioHardware::INPUT_CONFIG_CNT] = {
+ {8000, 4},
+ {11025, 4},
+ {16000, 2},
+ {22050, 2},
+ {32000, 1},
+ {44100, 1}
};
// trace driver operations for dump
@@ -80,7 +84,6 @@ enum {
const char *AudioHardware::inputPathNameDefault = "Default";
const char *AudioHardware::inputPathNameCamcorder = "Camcorder";
const char *AudioHardware::inputPathNameVoiceRecognition = "Voice Recognition";
-const char *AudioHardware::inputPathNameVoiceCommunication = "Voice Communication";
AudioHardware::AudioHardware() :
mInit(false),
@@ -90,12 +93,14 @@ AudioHardware::AudioHardware() :
mPcmOpenCnt(0),
mMixerOpenCnt(0),
mInCallAudioMode(false),
+ mVoiceVol(1.0f),
mInputSource(AUDIO_SOURCE_DEFAULT),
mBluetoothNrec(true),
mTTYMode(TTY_MODE_OFF),
mSecRilLibHandle(NULL),
mRilClient(0),
mActivatedCP(false),
+ mEchoReference(NULL),
#ifdef HAVE_FM_RADIO
mFmFd(-1),
mFmVolume(1),
@@ -251,6 +256,7 @@ AudioStreamOut* AudioHardware::openOutputStream(
void AudioHardware::closeOutputStream(AudioStreamOut* out) {
sp <AudioStreamOutALSA> spOut;
+ sp<AudioStreamInALSA> spIn;
{
Mutex::Autolock lock(mLock);
if (mOutput == 0 || mOutput.get() != out) {
@@ -259,7 +265,16 @@ void AudioHardware::closeOutputStream(AudioStreamOut* out) {
}
spOut = mOutput;
mOutput.clear();
+ if (mEchoReference != NULL) {
+ spIn = getActiveInput_l();
+ }
+ }
+ if (spIn != 0) {
+ // this will safely release the echo reference by calling releaseEchoReference()
+ // after placing the active input in standby
+ spIn->standby();
}
+
spOut.clear();
}
@@ -370,8 +385,10 @@ status_t AudioHardware::setMode(int mode)
status = AudioHardwareBase::setMode(mode);
LOGV("setMode() : new %d, old %d", mMode, prevMode);
if (status == NO_ERROR) {
+ bool modeNeedsCPActive = mMode == AudioSystem::MODE_IN_CALL ||
+ mMode == AudioSystem::MODE_RINGTONE;
// activate call clock in radio when entering in call or ringtone mode
- if (prevMode == AudioSystem::MODE_NORMAL)
+ if (modeNeedsCPActive)
{
if ((!mActivatedCP) && (mSecRilLibHandle) && (connectRILDIfRequired() == OK)) {
setCallClockSync(mRilClient, SOUND_CLOCK_START);
@@ -393,18 +410,19 @@ status_t AudioHardware::setMode(int mode)
openPcmOut_l();
openMixer_l();
setInputSource_l(AUDIO_SOURCE_DEFAULT);
+ setVoiceVolume_l(mVoiceVol);
mInCallAudioMode = true;
}
- if (mMode == AudioSystem::MODE_NORMAL && mInCallAudioMode) {
+ if (mMode != AudioSystem::MODE_IN_CALL && mInCallAudioMode) {
setInputSource_l(mInputSource);
if (mMixer != NULL) {
TRACE_DRIVER_IN(DRV_MIXER_GET)
- struct mixer_ctl *ctl= mixer_get_control(mMixer, "Playback Path", 0);
+ struct mixer_ctl *ctl= mixer_get_ctl_by_name(mMixer, "Playback Path");
TRACE_DRIVER_OUT
if (ctl != NULL) {
LOGV("setMode() reset Playback Path to RCV");
TRACE_DRIVER_IN(DRV_MIXER_SEL)
- mixer_ctl_select(ctl, "RCV");
+ mixer_ctl_set_enum_by_string(ctl, "RCV");
TRACE_DRIVER_OUT
}
}
@@ -424,7 +442,7 @@ status_t AudioHardware::setMode(int mode)
mInCallAudioMode = false;
}
- if (mMode == AudioSystem::MODE_NORMAL) {
+ if (!modeNeedsCPActive) {
if(mActivatedCP)
mActivatedCP = false;
}
@@ -444,6 +462,7 @@ status_t AudioHardware::setMode(int mode)
enableFMRadio();
}
#endif
+
return status;
}
@@ -487,6 +506,12 @@ status_t AudioHardware::setParameters(const String8& keyValuePairs)
const char TTY_MODE_VALUE_VCO[] = "tty_vco";
const char TTY_MODE_VALUE_HCO[] = "tty_hco";
const char TTY_MODE_VALUE_FULL[] = "tty_full";
+#ifdef HAVE_FM_RADIO
+ const char FM_RADIO_KEY_ON[] = "fm_on";
+ const char FM_RADIO_KEY_OFF[] = "fm_off";
+ const char FM_RADIO_VALUE_ON[] = "2055";
+ const char FM_RADIO_VALUE_OFF[] = "7";
+#endif
key = String8(BT_NREC_KEY);
if (param.get(key, value) == NO_ERROR) {
@@ -564,8 +589,8 @@ size_t AudioHardware::getInputBufferSize(uint32_t sampleRate, int format, int ch
LOGW("getInputBufferSize bad channel count: %d", channelCount);
return 0;
}
- if (sampleRate != 8000 && sampleRate != 11025 && sampleRate != 16000 &&
- sampleRate != 22050 && sampleRate != 44100) {
+
+ if (sampleRate != getInputSampleRate(sampleRate)) {
LOGW("getInputBufferSize bad sample rate: %d", sampleRate);
return 0;
}
@@ -573,12 +598,21 @@ size_t AudioHardware::getInputBufferSize(uint32_t sampleRate, int format, int ch
return AudioStreamInALSA::getBufferSize(sampleRate, channelCount);
}
-
status_t AudioHardware::setVoiceVolume(float volume)
{
- LOGD("### setVoiceVolume");
-
AutoMutex lock(mLock);
+
+ setVoiceVolume_l(volume);
+
+ return NO_ERROR;
+}
+
+void AudioHardware::setVoiceVolume_l(float volume)
+{
+ LOGD("### setVoiceVolume_l");
+
+ mVoiceVol = volume;
+
if ( (AudioSystem::MODE_IN_CALL == mMode) && (mSecRilLibHandle) &&
(connectRILDIfRequired() == OK) ) {
@@ -622,7 +656,6 @@ status_t AudioHardware::setVoiceVolume(float volume)
setCallVolume(mRilClient, type, int_volume);
}
- return NO_ERROR;
}
status_t AudioHardware::setMasterVolume(float volume)
@@ -775,13 +808,13 @@ status_t AudioHardware::setIncallPath_l(uint32_t device)
if (mMixer != NULL) {
TRACE_DRIVER_IN(DRV_MIXER_GET)
- struct mixer_ctl *ctl= mixer_get_control(mMixer, "Voice Call Path", 0);
+ struct mixer_ctl *ctl= mixer_get_ctl_by_name(mMixer, "Voice Call Path");
TRACE_DRIVER_OUT
LOGE_IF(ctl == NULL, "setIncallPath_l() could not get mixer ctl");
if (ctl != NULL) {
LOGV("setIncallPath_l() Voice Call Path, (%x)", device);
TRACE_DRIVER_IN(DRV_MIXER_SEL)
- mixer_ctl_select(ctl, getVoiceRouteFromDevice(device));
+ mixer_ctl_set_enum_by_string(ctl, getVoiceRouteFromDevice(device));
TRACE_DRIVER_OUT
}
}
@@ -930,14 +963,22 @@ struct pcm *AudioHardware::openPcmOut_l()
}
unsigned flags = PCM_OUT;
- flags |= (AUDIO_HW_OUT_PERIOD_MULT - 1) << PCM_PERIOD_SZ_SHIFT;
- flags |= (AUDIO_HW_OUT_PERIOD_CNT - PCM_PERIOD_CNT_MIN) << PCM_PERIOD_CNT_SHIFT;
+ struct pcm_config config = {
+ channels : 2,
+ rate : AUDIO_HW_OUT_SAMPLERATE,
+ period_size : AUDIO_HW_OUT_PERIOD_SZ,
+ period_count : AUDIO_HW_OUT_PERIOD_CNT,
+ format : PCM_FORMAT_S16_LE,
+ start_threshold : 0,
+ stop_threshold : 0,
+ silence_threshold : 0,
+ };
TRACE_DRIVER_IN(DRV_PCM_OPEN)
- mPcm = pcm_open(flags);
+ mPcm = pcm_open(0, 0, flags, &config);
TRACE_DRIVER_OUT
- if (!pcm_ready(mPcm)) {
- LOGE("openPcmOut_l() cannot open pcm_out driver: %s\n", pcm_error(mPcm));
+ if (!pcm_is_ready(mPcm)) {
+ LOGE("openPcmOut_l() cannot open pcm_out driver: %s\n", pcm_get_error(mPcm));
TRACE_DRIVER_IN(DRV_PCM_CLOSE)
pcm_close(mPcm);
TRACE_DRIVER_OUT
@@ -974,7 +1015,7 @@ struct mixer *AudioHardware::openMixer_l()
return NULL;
}
TRACE_DRIVER_IN(DRV_MIXER_OPEN)
- mMixer = mixer_open();
+ mMixer = mixer_open(0);
TRACE_DRIVER_OUT
if (mMixer == NULL) {
LOGE("openMixer_l() cannot open mixer");
@@ -1087,16 +1128,17 @@ const char *AudioHardware::getInputRouteFromDevice(uint32_t device)
uint32_t AudioHardware::getInputSampleRate(uint32_t sampleRate)
{
- uint32_t i;
+ size_t i;
uint32_t prevDelta;
uint32_t delta;
+ size_t size = sizeof(inputConfigTable)/sizeof(uint32_t)/INPUT_CONFIG_CNT;
- for (i = 0, prevDelta = 0xFFFFFFFF; i < sizeof(inputSamplingRates)/sizeof(uint32_t); i++, prevDelta = delta) {
- delta = abs(sampleRate - inputSamplingRates[i]);
+ for (i = 0, prevDelta = 0xFFFFFFFF; i < size; i++, prevDelta = delta) {
+ delta = abs(sampleRate - inputConfigTable[i][INPUT_CONFIG_SAMPLE_RATE]);
if (delta > prevDelta) break;
}
// i is always > 0 here
- return inputSamplingRates[i-1];
+ return inputConfigTable[i-1][INPUT_CONFIG_SAMPLE_RATE];
}
// getActiveInput_l() must be called with mLock held
@@ -1123,7 +1165,7 @@ status_t AudioHardware::setInputSource_l(audio_source source)
if ((source == AUDIO_SOURCE_DEFAULT) || (mMode != AudioSystem::MODE_IN_CALL)) {
if (mMixer) {
TRACE_DRIVER_IN(DRV_MIXER_GET)
- struct mixer_ctl *ctl= mixer_get_control(mMixer, "Input Source", 0);
+ struct mixer_ctl *ctl= mixer_get_ctl_by_name(mMixer, "Input Source");
TRACE_DRIVER_OUT
if (ctl == NULL) {
return NO_INIT;
@@ -1131,11 +1173,9 @@ status_t AudioHardware::setInputSource_l(audio_source source)
const char* sourceName;
switch (source) {
case AUDIO_SOURCE_DEFAULT: // intended fall-through
- case AUDIO_SOURCE_MIC:
- sourceName = inputPathNameDefault;
- break;
+ case AUDIO_SOURCE_MIC: // intended fall-through
case AUDIO_SOURCE_VOICE_COMMUNICATION:
- sourceName = inputPathNameVoiceCommunication;
+ sourceName = inputPathNameDefault;
break;
case AUDIO_SOURCE_CAMCORDER:
sourceName = inputPathNameCamcorder;
@@ -1149,9 +1189,9 @@ status_t AudioHardware::setInputSource_l(audio_source source)
default:
return NO_INIT;
}
- LOGV("mixer_ctl_select, Input Source, (%s)", sourceName);
+ LOGV("mixer_ctl_set_enum_by_string, Input Source, (%s)", sourceName);
TRACE_DRIVER_IN(DRV_MIXER_SEL)
- mixer_ctl_select(ctl, sourceName);
+ mixer_ctl_set_enum_by_string(ctl, sourceName);
TRACE_DRIVER_OUT
}
}
@@ -1161,6 +1201,42 @@ status_t AudioHardware::setInputSource_l(audio_source source)
return NO_ERROR;
}
+struct echo_reference_itfe *AudioHardware::getEchoReference(audio_format_t format,
+ uint32_t channelCount,
+ uint32_t samplingRate)
+{
+ LOGV("AudioHardware::getEchoReference %p", mEchoReference);
+ releaseEchoReference(mEchoReference);
+ if (mOutput != NULL) {
+ uint32_t wrChannelCount = popcount(mOutput->channels());
+ uint32_t wrSampleRate = mOutput->sampleRate();
+
+ int status = create_echo_reference(AUDIO_FORMAT_PCM_16_BIT,
+ channelCount,
+ samplingRate,
+ AUDIO_FORMAT_PCM_16_BIT,
+ wrChannelCount,
+ wrSampleRate,
+ &mEchoReference);
+ if (status == 0) {
+ mOutput->addEchoReference(mEchoReference);
+ }
+ }
+ return mEchoReference;
+}
+
+void AudioHardware::releaseEchoReference(struct echo_reference_itfe *reference)
+{
+ LOGV("AudioHardware::releaseEchoReference %p", mEchoReference);
+ if (mEchoReference != NULL && reference == mEchoReference) {
+ if (mOutput != NULL) {
+ mOutput->removeEchoReference(reference);
+ }
+ release_echo_reference(mEchoReference);
+ mEchoReference = NULL;
+ }
+}
+
//------------------------------------------------------------------------------
// AudioStreamOutALSA
@@ -1170,7 +1246,7 @@ AudioHardware::AudioStreamOutALSA::AudioStreamOutALSA() :
mHardware(0), mPcm(0), mMixer(0), mRouteCtl(0),
mStandby(true), mDevices(0), mChannels(AUDIO_HW_OUT_CHANNELS),
mSampleRate(AUDIO_HW_OUT_SAMPLERATE), mBufferSize(AUDIO_HW_OUT_PERIOD_BYTES),
- mDriverOp(DRV_NONE), mStandbyCnt(0), mSleepReq(false)
+ mDriverOp(DRV_NONE), mStandbyCnt(0), mSleepReq(false), mEchoReference(NULL)
{
}
@@ -1216,9 +1292,40 @@ AudioHardware::AudioStreamOutALSA::~AudioStreamOutALSA()
standby();
}
+int AudioHardware::AudioStreamOutALSA::getPlaybackDelay(size_t frames,
+ struct echo_reference_buffer *buffer)
+{
+ size_t kernelFr;
+
+ int rc = pcm_get_htimestamp(mPcm, &kernelFr, &buffer->time_stamp);
+ if (rc < 0) {
+ buffer->time_stamp.tv_sec = 0;
+ buffer->time_stamp.tv_nsec = 0;
+ buffer->delay_ns = 0;
+ LOGV("getPlaybackDelay(): pcm_get_htimestamp error, setting playbackTimestamp to 0");
+ return rc;
+ }
+
+ kernelFr = pcm_get_buffer_size(mPcm) - kernelFr;
+
+ // adjust render time stamp with delay added by current driver buffer.
+ // Add the duration of current frame as we want the render time of the last
+ // sample being written.
+ long delayNs = (long)(((int64_t)(kernelFr + frames)* 1000000000) /AUDIO_HW_OUT_SAMPLERATE);
+
+ LOGV("AudioStreamOutALSA::getPlaybackDelay delayNs: [%ld], "\
+ "kernelFr:[%d], frames:[%d], buffSize:[%d], time_stamp:[%ld].[%ld]",
+ delayNs, (int)kernelFr, (int)frames, pcm_get_buffer_size(mPcm),
+ (long)buffer->time_stamp.tv_sec, buffer->time_stamp.tv_nsec);
+
+ buffer->delay_ns = delayNs;
+
+ return 0;
+}
+
ssize_t AudioHardware::AudioStreamOutALSA::write(const void* buffer, size_t bytes)
{
- // LOGV("AudioStreamOutALSA::write(%p, %u)", buffer, bytes);
+ LOGV("-----AudioStreamInALSA::write(%p, %d) START", buffer, (int)bytes);
status_t status = NO_INIT;
const uint8_t* p = static_cast<const uint8_t*>(buffer);
int ret;
@@ -1239,8 +1346,6 @@ ssize_t AudioHardware::AudioStreamOutALSA::write(const void* buffer, size_t byte
AutoMutex hwLock(mHardware->lock());
LOGD("AudioHardware pcm playback is exiting standby.");
- acquire_wake_lock (PARTIAL_WAKE_LOCK, "AudioOutLock");
-
sp<AudioStreamInALSA> spIn = mHardware->getActiveInput_l();
while (spIn != 0) {
int cnt = spIn->prepareLock();
@@ -1272,29 +1377,37 @@ ssize_t AudioHardware::AudioStreamOutALSA::write(const void* buffer, size_t byte
spIn->unlock();
}
if (mPcm == NULL) {
- release_wake_lock("AudioOutLock");
goto Error;
}
mStandby = false;
}
+ if (mEchoReference != NULL) {
+ struct echo_reference_buffer b;
+ b.raw = (void *)buffer;
+ b.frame_count = bytes / frameSize();
+
+ getPlaybackDelay(bytes / frameSize(), &b);
+ mEchoReference->write(mEchoReference, &b);
+ }
+
TRACE_DRIVER_IN(DRV_PCM_WRITE)
ret = pcm_write(mPcm,(void*) p, bytes);
TRACE_DRIVER_OUT
if (ret == 0) {
+ LOGV("-----AudioStreamInALSA::write(%p, %d) END", buffer, (int)bytes);
return bytes;
}
LOGW("write error: %d", errno);
status = -errno;
}
Error:
-
standby();
// Simulate audio output timing in case of error
usleep((((bytes * 1000) / frameSize()) * 1000) / sampleRate());
-
+ LOGE("AudioStreamOutALSA::write END WITH ERROR !!!!!!!!!(%p, %u)", buffer, bytes);
return status;
}
@@ -1302,12 +1415,16 @@ status_t AudioHardware::AudioStreamOutALSA::standby()
{
if (mHardware == NULL) return NO_INIT;
- AutoMutex lock(mLock);
+ mSleepReq = true;
+ {
+ AutoMutex lock(mLock);
+ mSleepReq = false;
- { // scope for the AudioHardware lock
- AutoMutex hwLock(mHardware->lock());
+ { // scope for the AudioHardware lock
+ AutoMutex hwLock(mHardware->lock());
- doStandby_l();
+ doStandby_l();
+ }
}
return NO_ERROR;
@@ -1319,7 +1436,10 @@ void AudioHardware::AudioStreamOutALSA::doStandby_l()
if (!mStandby) {
LOGD("AudioHardware pcm playback is going to standby.");
- release_wake_lock("AudioOutLock");
+ // stop echo reference capture
+ if (mEchoReference != NULL) {
+ mEchoReference->write(mEchoReference, NULL);
+ }
mStandby = true;
}
@@ -1351,7 +1471,7 @@ status_t AudioHardware::AudioStreamOutALSA::open_l()
if (mMixer) {
LOGV("open playback normal");
TRACE_DRIVER_IN(DRV_MIXER_GET)
- mRouteCtl = mixer_get_control(mMixer, "Playback Path", 0);
+ mRouteCtl = mixer_get_ctl_by_name(mMixer, "Playback Path");
TRACE_DRIVER_OUT
}
if (mHardware->mode() != AudioSystem::MODE_IN_CALL) {
@@ -1359,7 +1479,7 @@ status_t AudioHardware::AudioStreamOutALSA::open_l()
LOGV("write() wakeup setting route %s", route);
if (mRouteCtl) {
TRACE_DRIVER_IN(DRV_MIXER_SEL)
- mixer_ctl_select(mRouteCtl, route);
+ mixer_ctl_set_enum_by_string(mRouteCtl, route);
TRACE_DRIVER_OUT
}
}
@@ -1413,16 +1533,16 @@ bool AudioHardware::AudioStreamOutALSA::checkStandby()
status_t AudioHardware::AudioStreamOutALSA::setParameters(const String8& keyValuePairs)
{
AudioParameter param = AudioParameter(keyValuePairs);
-
status_t status = NO_ERROR;
int device;
LOGD("AudioStreamOutALSA::setParameters() %s", keyValuePairs.string());
if (mHardware == NULL) return NO_INIT;
+ mSleepReq = true;
{
AutoMutex lock(mLock);
-
+ mSleepReq = false;
if (param.getInt(String8(AudioParameter::keyRouting), device) == NO_ERROR)
{
if (device != 0) {
@@ -1430,7 +1550,6 @@ status_t AudioHardware::AudioStreamOutALSA::setParameters(const String8& keyValu
if (mDevices != (uint32_t)device) {
mDevices = (uint32_t)device;
-
if (mHardware->mode() != AudioSystem::MODE_IN_CALL) {
doStandby_l();
}
@@ -1447,7 +1566,9 @@ status_t AudioHardware::AudioStreamOutALSA::setParameters(const String8& keyValu
status = BAD_VALUE;
}
+
return status;
+
}
String8 AudioHardware::AudioStreamOutALSA::getParameters(const String8& keys)
@@ -1488,6 +1609,24 @@ void AudioHardware::AudioStreamOutALSA::unlock() {
mLock.unlock();
}
+void AudioHardware::AudioStreamOutALSA::addEchoReference(struct echo_reference_itfe *reference)
+{
+ LOGV("AudioStreamOutALSA::addEchoReference %p", mEchoReference);
+ if (mEchoReference == NULL) {
+ mEchoReference = reference;
+ }
+}
+
+void AudioHardware::AudioStreamOutALSA::removeEchoReference(struct echo_reference_itfe *reference)
+{
+ LOGV("AudioStreamOutALSA::removeEchoReference %p", mEchoReference);
+ if (mEchoReference == reference) {
+ mEchoReference->write(mEchoReference, NULL);
+ mEchoReference = NULL;
+ }
+}
+
+
//------------------------------------------------------------------------------
// AudioStreamInALSA
//------------------------------------------------------------------------------
@@ -1496,8 +1635,10 @@ AudioHardware::AudioStreamInALSA::AudioStreamInALSA() :
mHardware(0), mPcm(0), mMixer(0), mRouteCtl(0),
mStandby(true), mDevices(0), mChannels(AUDIO_HW_IN_CHANNELS), mChannelCount(1),
mSampleRate(AUDIO_HW_IN_SAMPLERATE), mBufferSize(AUDIO_HW_IN_PERIOD_BYTES),
- mDownSampler(NULL), mReadStatus(NO_ERROR), mDriverOp(DRV_NONE),
- mStandbyCnt(0), mSleepReq(false)
+ mDownSampler(NULL), mReadStatus(NO_ERROR), mInputBuf(NULL),
+ mDriverOp(DRV_NONE), mStandbyCnt(0), mSleepReq(false),
+ mProcBuf(NULL), mProcBufSize(0), mRefBuf(NULL), mRefBufSize(0),
+ mEchoReference(NULL), mNeedEchoReference(false)
{
}
@@ -1534,38 +1675,283 @@ status_t AudioHardware::AudioStreamInALSA::set(
mChannelCount = AudioSystem::popCount(mChannels);
mSampleRate = rate;
if (mSampleRate != AUDIO_HW_OUT_SAMPLERATE) {
- mDownSampler = new AudioHardware::DownSampler(mSampleRate,
- mChannelCount,
- AUDIO_HW_IN_PERIOD_SZ,
- this);
- status_t status = mDownSampler->initCheck();
- if (status != NO_ERROR) {
- delete mDownSampler;
+ mBufferProvider.mProvider.get_next_buffer = getNextBufferStatic;
+ mBufferProvider.mProvider.release_buffer = releaseBufferStatic;
+ mBufferProvider.mInputStream = this;
+ int status = create_resampler(AUDIO_HW_OUT_SAMPLERATE,
+ mSampleRate,
+ mChannelCount,
+ RESAMPLER_QUALITY_VOIP,
+ &mBufferProvider.mProvider,
+ &mDownSampler);
+ if (status != 0) {
LOGW("AudioStreamInALSA::set() downsampler init failed: %d", status);
+ mDownSampler = NULL;
return status;
}
-
- mPcmIn = new int16_t[AUDIO_HW_IN_PERIOD_SZ * mChannelCount];
}
+ mInputBuf = new int16_t[AUDIO_HW_IN_PERIOD_SZ * mChannelCount];
+
return NO_ERROR;
}
AudioHardware::AudioStreamInALSA::~AudioStreamInALSA()
{
standby();
+
if (mDownSampler != NULL) {
- delete mDownSampler;
- if (mPcmIn != NULL) {
- delete[] mPcmIn;
+ release_resampler(mDownSampler);
+ }
+ delete[] mInputBuf;
+ delete[] mProcBuf;
+}
+
+// readFrames() reads frames from kernel driver, down samples to capture rate if necessary
+// and output the number of frames requested to the buffer specified
+ssize_t AudioHardware::AudioStreamInALSA::readFrames(void* buffer, ssize_t frames)
+{
+ ssize_t framesWr = 0;
+ while (framesWr < frames) {
+ size_t framesRd = frames - framesWr;
+ if (mDownSampler != NULL) {
+ mDownSampler->resample_from_provider(mDownSampler,
+ (int16_t *)((char *)buffer + framesWr * frameSize()),
+ &framesRd);
+ } else {
+ struct resampler_buffer buf = {
+ { raw : NULL, },
+ frame_count : framesRd,
+ };
+ getNextBuffer(&buf);
+ if (buf.raw != NULL) {
+ memcpy((char *)buffer + framesWr * frameSize(),
+ buf.raw,
+ buf.frame_count * frameSize());
+ framesRd = buf.frame_count;
+ }
+ releaseBuffer(&buf);
}
+ // mReadStatus is updated by getNextBuffer() also called by
+ // mDownSampler->resample_from_provider()
+ if (mReadStatus != 0) {
+ return mReadStatus;
+ }
+ framesWr += framesRd;
+ }
+ return framesWr;
+}
+
+// processFrames() reads frames from kernel driver (via readFrames()), calls the active
+// audio pre processings and output the number of frames requested to the buffer specified
+ssize_t AudioHardware::AudioStreamInALSA::processFrames(void* buffer, ssize_t frames)
+{
+ ssize_t framesWr = 0;
+ while (framesWr < frames) {
+ // first reload enough frames at the end of process input buffer
+ if (mProcFramesIn < (size_t)frames) {
+ // expand process input buffer if necessary
+ if (mProcBufSize < (size_t)frames) {
+ mProcBufSize = (size_t)frames;
+ mProcBuf = (int16_t *)realloc(mProcBuf,
+ mProcBufSize * mChannelCount * sizeof(int16_t));
+ LOGV("processFrames(): mProcBuf %p size extended to %d frames",
+ mProcBuf, mProcBufSize);
+ }
+ ssize_t framesRd = readFrames(mProcBuf + mProcFramesIn * mChannelCount,
+ frames - mProcFramesIn);
+ if (framesRd < 0) {
+ framesWr = framesRd;
+ break;
+ }
+ mProcFramesIn += framesRd;
+ }
+
+ if (mEchoReference != NULL) {
+ pushEchoReference(mProcFramesIn);
+ }
+
+ //inBuf.frameCount and outBuf.frameCount indicate respectively the maximum number of frames
+ //to be consumed and produced by process()
+ audio_buffer_t inBuf = {
+ mProcFramesIn,
+ {mProcBuf}
+ };
+ audio_buffer_t outBuf = {
+ frames - framesWr,
+ {(int16_t *)buffer + framesWr * mChannelCount}
+ };
+
+ for (size_t i = 0; i < mPreprocessors.size(); i++) {
+ (*mPreprocessors[i])->process(mPreprocessors[i],
+ &inBuf,
+ &outBuf);
+ }
+
+ // process() has updated the number of frames consumed and produced in
+ // inBuf.frameCount and outBuf.frameCount respectively
+ // move remaining frames to the beginning of mProcBuf
+ mProcFramesIn -= inBuf.frameCount;
+ if (mProcFramesIn) {
+ memcpy(mProcBuf,
+ mProcBuf + inBuf.frameCount * mChannelCount,
+ mProcFramesIn * mChannelCount * sizeof(int16_t));
+ }
+
+ // if not enough frames were passed to process(), read more and retry.
+ if (outBuf.frameCount == 0) {
+ continue;
+ }
+ framesWr += outBuf.frameCount;
+ }
+ return framesWr;
+}
+
+int32_t AudioHardware::AudioStreamInALSA::updateEchoReference(size_t frames)
+{
+ struct echo_reference_buffer b;
+ b.delay_ns = 0;
+
+ LOGV("updateEchoReference1 START, frames = [%d], mRefFramesIn = [%d], b.frame_count = [%d]",
+ frames, mRefFramesIn, frames - mRefFramesIn);
+ if (mRefFramesIn < frames) {
+ if (mRefBufSize < frames) {
+ mRefBufSize = frames;
+ mRefBuf = (int16_t *)realloc(mRefBuf,
+ mRefBufSize * mChannelCount * sizeof(int16_t));
+ }
+
+ b.frame_count = frames - mRefFramesIn;
+ b.raw = (void *)(mRefBuf + mRefFramesIn * mChannelCount);
+
+ getCaptureDelay(frames, &b);
+
+ if (mEchoReference->read(mEchoReference, &b) == NO_ERROR)
+ {
+ mRefFramesIn += b.frame_count;
+ LOGV("updateEchoReference2: mRefFramesIn:[%d], mRefBufSize:[%d], "\
+ "frames:[%d], b.frame_count:[%d]", mRefFramesIn, mRefBufSize,frames,b.frame_count);
+ }
+
+ }else{
+ LOGV("updateEchoReference3: NOT enough frames to read ref buffer");
+ }
+ return b.delay_ns;
+}
+
+void AudioHardware::AudioStreamInALSA::pushEchoReference(size_t frames)
+{
+ // read frames from echo reference buffer and update echo delay
+ // mRefFramesIn is updated with frames available in mRefBuf
+ int32_t delayUs = (int32_t)(updateEchoReference(frames)/1000);
+
+ if (mRefFramesIn < frames) {
+ frames = mRefFramesIn;
+ }
+
+ audio_buffer_t refBuf = {
+ frames,
+ {mRefBuf}
+ };
+
+ for (size_t i = 0; i < mPreprocessors.size(); i++) {
+ if ((*mPreprocessors[i])->process_reverse == NULL) {
+ continue;
+ }
+ (*mPreprocessors[i])->process_reverse(mPreprocessors[i],
+ &refBuf,
+ NULL);
+ setPreProcessorEchoDelay(mPreprocessors[i], delayUs);
+ }
+
+ mRefFramesIn -= refBuf.frameCount;
+ if (mRefFramesIn) {
+ LOGV("pushEchoReference5: shifting mRefBuf down by = %d frames", mRefFramesIn);
+ memcpy(mRefBuf,
+ mRefBuf + refBuf.frameCount * mChannelCount,
+ mRefFramesIn * mChannelCount * sizeof(int16_t));
+ }
+}
+
+status_t AudioHardware::AudioStreamInALSA::setPreProcessorEchoDelay(effect_handle_t handle,
+ int32_t delayUs)
+{
+ uint32_t buf[sizeof(effect_param_t) / sizeof(uint32_t) + 2];
+ effect_param_t *param = (effect_param_t *)buf;
+
+ param->psize = sizeof(uint32_t);
+ param->vsize = sizeof(uint32_t);
+ *(uint32_t *)param->data = AEC_PARAM_ECHO_DELAY;
+ *((int32_t *)param->data + 1) = delayUs;
+
+ LOGV("setPreProcessorEchoDelay: %d us", delayUs);
+
+ return setPreprocessorParam(handle, param);
+}
+
+status_t AudioHardware::AudioStreamInALSA::setPreprocessorParam(effect_handle_t handle,
+ effect_param_t *param)
+{
+ uint32_t size = sizeof(int);
+ uint32_t psize = ((param->psize - 1) / sizeof(int) + 1) * sizeof(int) + param->vsize;
+
+ status_t status = (*handle)->command(handle,
+ EFFECT_CMD_SET_PARAM,
+ sizeof (effect_param_t) + psize,
+ param,
+ &size,
+ &param->status);
+ if (status == NO_ERROR) {
+ status = param->status;
}
+ return status;
+}
+
+void AudioHardware::AudioStreamInALSA::getCaptureDelay(size_t frames,
+ struct echo_reference_buffer *buffer)
+{
+
+ // read frames available in kernel driver buffer
+ size_t kernelFr;
+ struct timespec tstamp;
+
+ if (pcm_get_htimestamp(mPcm, &kernelFr, &tstamp) < 0) {
+ buffer->time_stamp.tv_sec = 0;
+ buffer->time_stamp.tv_nsec = 0;
+ buffer->delay_ns = 0;
+ LOGW("read getCaptureDelay(): pcm_htimestamp error");
+ return;
+ }
+
+ // read frames available in audio HAL input buffer
+ // add number of frames being read as we want the capture time of first sample in current
+ // buffer
+ long bufDelay = (long)(((int64_t)(mInputFramesIn + mProcFramesIn) * 1000000000)
+ / AUDIO_HW_IN_SAMPLERATE);
+ // add delay introduced by resampler
+ long rsmpDelay = 0;
+ if (mDownSampler) {
+ rsmpDelay = mDownSampler->delay_ns(mDownSampler);
+ }
+
+ long kernelDelay = (long)(((int64_t)kernelFr * 1000000000) / AUDIO_HW_IN_SAMPLERATE);
+
+ // correct capture time stamp
+ long delayNs = kernelDelay + bufDelay + rsmpDelay;
+
+ buffer->time_stamp = tstamp;
+ buffer->delay_ns = delayNs;
+ LOGV("AudioStreamInALSA::getCaptureDelay TimeStamp = [%ld].[%ld], delayCaptureNs: [%d],"\
+ " kernelDelay:[%ld], bufDelay:[%ld], rsmpDelay:[%ld], kernelFr:[%d], "\
+ "mInputFramesIn:[%d], mProcFramesIn:[%d], frames:[%d]",
+ buffer->time_stamp.tv_sec , buffer->time_stamp.tv_nsec, buffer->delay_ns,
+ kernelDelay, bufDelay, rsmpDelay, kernelFr, mInputFramesIn, mProcFramesIn, frames);
+
}
ssize_t AudioHardware::AudioStreamInALSA::read(void* buffer, ssize_t bytes)
{
- // LOGV("AudioStreamInALSA::read(%p, %u)", buffer, bytes);
+ LOGV("-----AudioStreamInALSA::read(%p, %d) START", buffer, (int)bytes);
status_t status = NO_INIT;
- int ret;
if (mHardware == NULL) return NO_INIT;
@@ -1582,38 +1968,38 @@ ssize_t AudioHardware::AudioStreamInALSA::read(void* buffer, ssize_t bytes)
AutoMutex hwLock(mHardware->lock());
LOGD("AudioHardware pcm capture is exiting standby.");
- acquire_wake_lock (PARTIAL_WAKE_LOCK, "AudioInLock");
-
sp<AudioStreamOutALSA> spOut = mHardware->output();
while (spOut != 0) {
- if (!spOut->checkStandby()) {
- int cnt = spOut->prepareLock();
- mHardware->lock().unlock();
- mLock.unlock();
- // Mutex acquisition order is always out -> in -> hw
- spOut->lock();
- mLock.lock();
- mHardware->lock().lock();
- // make sure that another thread did not change output state
- // while the mutex is released
- if ((spOut == mHardware->output()) && (cnt == spOut->standbyCnt())) {
- LOGV("AudioStreamInALSA::read() force output standby");
- spOut->close_l();
- break;
- }
- spOut->unlock();
- spOut = mHardware->output();
- } else {
- spOut.clear();
+ spOut->prepareLock();
+ mHardware->lock().unlock();
+ mLock.unlock();
+ // Mutex acquisition order is always out -> in -> hw
+ spOut->lock();
+ mLock.lock();
+ mHardware->lock().lock();
+ // make sure that another thread did not change output state
+ // while the mutex is released
+ if (spOut == mHardware->output()) {
+ break;
}
+ spOut->unlock();
+ spOut = mHardware->output();
}
- // spOut is not 0 here only if the output was active and has been
- // closed above
-
// open output before input
if (spOut != 0) {
- if (spOut->open_l() != NO_ERROR) {
- spOut->doStandby_l();
+ if (!spOut->checkStandby()) {
+ LOGV("AudioStreamInALSA::read() force output standby");
+ spOut->close_l();
+ if (spOut->open_l() != NO_ERROR) {
+ spOut->doStandby_l();
+ }
+ }
+ LOGV("AudioStreamInALSA exit standby mNeedEchoReference %d mEchoReference %p",
+ mNeedEchoReference, mEchoReference);
+ if (mNeedEchoReference && mEchoReference == NULL) {
+ mEchoReference = mHardware->getEchoReference(AUDIO_FORMAT_PCM_16_BIT,
+ mChannelCount,
+ mSampleRate);
}
spOut->unlock();
}
@@ -1621,38 +2007,27 @@ ssize_t AudioHardware::AudioStreamInALSA::read(void* buffer, ssize_t bytes)
open_l();
if (mPcm == NULL) {
- release_wake_lock("AudioInLock");
goto Error;
}
mStandby = false;
}
+ size_t framesRq = bytes / mChannelCount/sizeof(int16_t);
+ ssize_t framesRd;
- if (mDownSampler != NULL) {
- size_t frames = bytes / frameSize();
- size_t framesIn = 0;
- mReadStatus = 0;
- do {
- size_t outframes = frames - framesIn;
- mDownSampler->resample(
- (int16_t *)buffer + (framesIn * mChannelCount),
- &outframes);
- framesIn += outframes;
- } while ((framesIn < frames) && mReadStatus == 0);
- ret = mReadStatus;
- bytes = framesIn * frameSize();
+ if (mPreprocessors.size() == 0) {
+ framesRd = readFrames(buffer, framesRq);
} else {
- TRACE_DRIVER_IN(DRV_PCM_READ)
- ret = pcm_read(mPcm, buffer, bytes);
- TRACE_DRIVER_OUT
+ framesRd = processFrames(buffer, framesRq);
}
- if (ret == 0) {
- return bytes;
+ if (framesRd >= 0) {
+ LOGV("-----AudioStreamInALSA::read(%p, %d) END", buffer, (int)bytes);
+ return framesRd * mChannelCount * sizeof(int16_t);
}
- LOGW("read error: %d", ret);
- status = ret;
+ LOGW("read error: %d", (int)framesRd);
+ status = framesRd;
}
Error:
@@ -1661,7 +2036,7 @@ Error:
// Simulate audio output timing in case of error
usleep((((bytes * 1000) / frameSize()) * 1000) / sampleRate());
-
+ LOGE("-----AudioStreamInALSA::read(%p, %d) END ERROR", buffer, (int)bytes);
return status;
}
@@ -1669,12 +2044,16 @@ status_t AudioHardware::AudioStreamInALSA::standby()
{
if (mHardware == NULL) return NO_INIT;
- AutoMutex lock(mLock);
+ mSleepReq = true;
+ {
+ AutoMutex lock(mLock);
+ mSleepReq = false;
- { // scope for AudioHardware lock
- AutoMutex hwLock(mHardware->lock());
+ { // scope for AudioHardware lock
+ AutoMutex hwLock(mHardware->lock());
- doStandby_l();
+ doStandby_l();
+ }
}
return NO_ERROR;
}
@@ -1685,7 +2064,24 @@ void AudioHardware::AudioStreamInALSA::doStandby_l()
if (!mStandby) {
LOGD("AudioHardware pcm capture is going to standby.");
- release_wake_lock("AudioInLock");
+ if (mEchoReference != NULL) {
+ // stop reading from echo reference
+ mEchoReference->read(mEchoReference, NULL);
+ // Mutex acquisition order is always out -> in -> hw
+ sp<AudioStreamOutALSA> spOut = mHardware->output();
+ if (spOut != 0) {
+ spOut->prepareLock();
+ mHardware->lock().unlock();
+ mLock.unlock();
+ spOut->lock();
+ mLock.lock();
+ mHardware->lock().lock();
+ mHardware->releaseEchoReference(mEchoReference);
+ spOut->unlock();
+ }
+ mEchoReference = NULL;
+ }
+
mStandby = true;
}
close_l();
@@ -1705,24 +2101,36 @@ void AudioHardware::AudioStreamInALSA::close_l()
TRACE_DRIVER_OUT
mPcm = NULL;
}
+
+ delete[] mProcBuf;
+ mProcBuf = NULL;
+ mProcBufSize = 0;
+ delete[] mRefBuf;
+ mRefBuf = NULL;
+ mRefBufSize = 0;
}
status_t AudioHardware::AudioStreamInALSA::open_l()
{
unsigned flags = PCM_IN;
- if (mChannels == AudioSystem::CHANNEL_IN_MONO) {
- flags |= PCM_MONO;
- }
- flags |= (AUDIO_HW_IN_PERIOD_MULT - 1) << PCM_PERIOD_SZ_SHIFT;
- flags |= (AUDIO_HW_IN_PERIOD_CNT - PCM_PERIOD_CNT_MIN)
- << PCM_PERIOD_CNT_SHIFT;
+
+ struct pcm_config config = {
+ channels : mChannelCount,
+ rate : AUDIO_HW_IN_SAMPLERATE,
+ period_size : AUDIO_HW_IN_PERIOD_SZ,
+ period_count : AUDIO_HW_IN_PERIOD_CNT,
+ format : PCM_FORMAT_S16_LE,
+ start_threshold : 0,
+ stop_threshold : 0,
+ silence_threshold : 0,
+ };
LOGV("open pcm_in driver");
TRACE_DRIVER_IN(DRV_PCM_OPEN)
- mPcm = pcm_open(flags);
+ mPcm = pcm_open(0, 0, flags, &config);
TRACE_DRIVER_OUT
- if (!pcm_ready(mPcm)) {
- LOGE("cannot open pcm_in driver: %s\n", pcm_error(mPcm));
+ if (!pcm_is_ready(mPcm)) {
+ LOGE("cannot open pcm_in driver: %s\n", pcm_get_error(mPcm));
TRACE_DRIVER_IN(DRV_PCM_CLOSE)
pcm_close(mPcm);
TRACE_DRIVER_OUT
@@ -1731,14 +2139,19 @@ status_t AudioHardware::AudioStreamInALSA::open_l()
}
if (mDownSampler != NULL) {
- mInPcmInBuf = 0;
- mDownSampler->reset();
+ mDownSampler->reset(mDownSampler);
}
+ mInputFramesIn = 0;
+
+ mProcBufSize = 0;
+ mProcFramesIn = 0;
+ mRefBufSize = 0;
+ mRefFramesIn = 0;
mMixer = mHardware->openMixer_l();
if (mMixer) {
TRACE_DRIVER_IN(DRV_MIXER_GET)
- mRouteCtl = mixer_get_control(mMixer, "Capture MIC Path", 0);
+ mRouteCtl = mixer_get_ctl_by_name(mMixer, "Capture MIC Path");
TRACE_DRIVER_OUT
}
@@ -1747,7 +2160,7 @@ status_t AudioHardware::AudioStreamInALSA::open_l()
LOGV("read() wakeup setting route %s", route);
if (mRouteCtl) {
TRACE_DRIVER_IN(DRV_MIXER_SEL)
- mixer_ctl_select(mRouteCtl, route);
+ mixer_ctl_set_enum_by_string(mRouteCtl, route);
TRACE_DRIVER_OUT
}
}
@@ -1806,8 +2219,10 @@ status_t AudioHardware::AudioStreamInALSA::setParameters(const String8& keyValue
if (mHardware == NULL) return NO_INIT;
+ mSleepReq = true;
{
AutoMutex lock(mLock);
+ mSleepReq = false;
if (param.getInt(String8(AudioParameter::keyInputSource), value) == NO_ERROR) {
AutoMutex hwLock(mHardware->lock());
@@ -1858,58 +2273,123 @@ String8 AudioHardware::AudioStreamInALSA::getParameters(const String8& keys)
return param.toString();
}
-status_t AudioHardware::AudioStreamInALSA::getNextBuffer(AudioHardware::BufferProvider::Buffer* buffer)
+status_t AudioHardware::AudioStreamInALSA::addAudioEffect(effect_handle_t effect)
+{
+ LOGV("AudioStreamInALSA::addAudioEffect() %p", effect);
+
+ effect_descriptor_t desc;
+ status_t status = (*effect)->get_descriptor(effect, &desc);
+ if (status == 0) {
+ if (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0) {
+ LOGV("AudioStreamInALSA::addAudioEffect() mNeedEchoReference true");
+ mNeedEchoReference = true;
+ standby();
+ }
+ LOGV("AudioStreamInALSA::addAudioEffect() name %s", desc.name);
+ } else {
+ LOGV("AudioStreamInALSA::addAudioEffect() get_descriptor() error");
+ }
+
+ AutoMutex lock(mLock);
+ mPreprocessors.add(effect);
+ return NO_ERROR;
+}
+
+status_t AudioHardware::AudioStreamInALSA::removeAudioEffect(effect_handle_t effect)
+{
+ status_t status = INVALID_OPERATION;
+ LOGV("AudioStreamInALSA::removeAudioEffect() %p", effect);
+ {
+ AutoMutex lock(mLock);
+ for (size_t i = 0; i < mPreprocessors.size(); i++) {
+ if (mPreprocessors[i] == effect) {
+ mPreprocessors.removeAt(i);
+ status = NO_ERROR;
+ break;
+ }
+ }
+ }
+
+ if (status == NO_ERROR) {
+ effect_descriptor_t desc;
+ if ((*effect)->get_descriptor(effect, &desc) == 0) {
+ if (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0) {
+ LOGV("AudioStreamInALSA::removeAudioEffect() mNeedEchoReference false");
+ mNeedEchoReference = false;
+ standby();
+ }
+ }
+ }
+
+ return status;
+}
+
+extern "C" {
+int AudioHardware::AudioStreamInALSA::getNextBufferStatic(
+ struct resampler_buffer_provider *provider,
+ struct resampler_buffer* buffer)
+{
+ ResamplerBufferProvider *bufferProvider = (ResamplerBufferProvider *)provider;
+ return bufferProvider->mInputStream->getNextBuffer(buffer);
+}
+
+void AudioHardware::AudioStreamInALSA::releaseBufferStatic(
+ struct resampler_buffer_provider *provider,
+ struct resampler_buffer* buffer)
+{
+ ResamplerBufferProvider *bufferProvider = (ResamplerBufferProvider *)provider;
+ return bufferProvider->mInputStream->releaseBuffer(buffer);
+}
+
+}; // extern "C"
+
+status_t AudioHardware::AudioStreamInALSA::getNextBuffer(struct resampler_buffer *buffer)
{
if (mPcm == NULL) {
buffer->raw = NULL;
- buffer->frameCount = 0;
+ buffer->frame_count = 0;
mReadStatus = NO_INIT;
return NO_INIT;
}
- if (mInPcmInBuf == 0) {
+ if (mInputFramesIn == 0) {
TRACE_DRIVER_IN(DRV_PCM_READ)
- mReadStatus = pcm_read(mPcm,(void*) mPcmIn, AUDIO_HW_IN_PERIOD_SZ * frameSize());
+ mReadStatus = pcm_read(mPcm,(void*) mInputBuf, AUDIO_HW_IN_PERIOD_SZ * frameSize());
TRACE_DRIVER_OUT
if (mReadStatus != 0) {
buffer->raw = NULL;
- buffer->frameCount = 0;
+ buffer->frame_count = 0;
return mReadStatus;
}
- mInPcmInBuf = AUDIO_HW_IN_PERIOD_SZ;
+ mInputFramesIn = AUDIO_HW_IN_PERIOD_SZ;
}
- buffer->frameCount = (buffer->frameCount > mInPcmInBuf) ? mInPcmInBuf : buffer->frameCount;
- buffer->i16 = mPcmIn + (AUDIO_HW_IN_PERIOD_SZ - mInPcmInBuf) * mChannelCount;
+ buffer->frame_count = (buffer->frame_count > mInputFramesIn) ? mInputFramesIn:buffer->frame_count;
+ buffer->i16 = mInputBuf + (AUDIO_HW_IN_PERIOD_SZ - mInputFramesIn) * mChannelCount;
return mReadStatus;
}
-void AudioHardware::AudioStreamInALSA::releaseBuffer(Buffer* buffer)
+void AudioHardware::AudioStreamInALSA::releaseBuffer(struct resampler_buffer *buffer)
{
- mInPcmInBuf -= buffer->frameCount;
+ mInputFramesIn -= buffer->frame_count;
}
size_t AudioHardware::AudioStreamInALSA::getBufferSize(uint32_t sampleRate, int channelCount)
{
- size_t ratio;
-
- switch (sampleRate) {
- case 8000:
- case 11025:
- ratio = 4;
- break;
- case 16000:
- case 22050:
- ratio = 2;
- break;
- case 44100:
- default:
- ratio = 1;
- break;
- }
+ size_t i;
+ size_t size = sizeof(inputConfigTable)/sizeof(uint32_t)/INPUT_CONFIG_CNT;
- return (AUDIO_HW_IN_PERIOD_SZ*channelCount*sizeof(int16_t)) / ratio ;
+ for (i = 0; i < size; i++) {
+ if (sampleRate == inputConfigTable[i][INPUT_CONFIG_SAMPLE_RATE]) {
+ return (AUDIO_HW_IN_PERIOD_SZ*channelCount*sizeof(int16_t)) /
+ inputConfigTable[i][INPUT_CONFIG_BUFFER_RATIO];
+ }
+ }
+ // this should never happen as getBufferSize() is always called after getInputSampleRate()
+ // that checks for valid sampling rates.
+ LOGE("AudioStreamInALSA::getBufferSize() invalid sampling rate %d", sampleRate);
+ return 0;
}
int AudioHardware::AudioStreamInALSA::prepareLock()
@@ -1931,375 +2411,6 @@ void AudioHardware::AudioStreamInALSA::unlock() {
}
//------------------------------------------------------------------------------
-// DownSampler
-//------------------------------------------------------------------------------
-
-/*
- * 2.30 fixed point FIR filter coefficients for conversion 44100 -> 22050.
- * (Works equivalently for 22010 -> 11025 or any other halving, of course.)
- *
- * Transition band from about 18 kHz, passband ripple < 0.1 dB,
- * stopband ripple at about -55 dB, linear phase.
- *
- * Design and display in MATLAB or Octave using:
- *
- * filter = fir1(19, 0.5); filter = round(filter * 2**30); freqz(filter * 2**-30);
- */
-static const int32_t filter_22khz_coeff[] = {
- 2089257, 2898328, -5820678, -10484531,
- 19038724, 30542725, -50469415, -81505260,
- 152544464, 478517512, 478517512, 152544464,
- -81505260, -50469415, 30542725, 19038724,
- -10484531, -5820678, 2898328, 2089257,
-};
-#define NUM_COEFF_22KHZ (sizeof(filter_22khz_coeff) / sizeof(filter_22khz_coeff[0]))
-#define OVERLAP_22KHZ (NUM_COEFF_22KHZ - 2)
-
-/*
- * Convolution of signals A and reverse(B). (In our case, the filter response
- * is symmetric, so the reversing doesn't matter.)
- * A is taken to be in 0.16 fixed-point, and B is taken to be in 2.30 fixed-point.
- * The answer will be in 16.16 fixed-point, unclipped.
- *
- * This function would probably be the prime candidate for SIMD conversion if
- * you want more speed.
- */
-int32_t fir_convolve(const int16_t* a, const int32_t* b, int num_samples)
-{
- int32_t sum = 1 << 13;
- for (int i = 0; i < num_samples; ++i) {
- sum += a[i] * (b[i] >> 16);
- }
- return sum >> 14;
-}
-
-/* Clip from 16.16 fixed-point to 0.16 fixed-point. */
-int16_t clip(int32_t x)
-{
- if (x < -32768) {
- return -32768;
- } else if (x > 32767) {
- return 32767;
- } else {
- return x;
- }
-}
-
-/*
- * Convert a chunk from 44 kHz to 22 kHz. Will update num_samples_in and num_samples_out
- * accordingly, since it may leave input samples in the buffer due to overlap.
- *
- * Input and output are taken to be in 0.16 fixed-point.
- */
-void resample_2_1(int16_t* input, int16_t* output, int* num_samples_in, int* num_samples_out)
-{
- if (*num_samples_in < (int)NUM_COEFF_22KHZ) {
- *num_samples_out = 0;
- return;
- }
-
- int odd_smp = *num_samples_in & 0x1;
- int num_samples = *num_samples_in - odd_smp - OVERLAP_22KHZ;
-
- for (int i = 0; i < num_samples; i += 2) {
- output[i / 2] = clip(fir_convolve(input + i, filter_22khz_coeff, NUM_COEFF_22KHZ));
- }
-
- memmove(input, input + num_samples, (OVERLAP_22KHZ + odd_smp) * sizeof(*input));
- *num_samples_out = num_samples / 2;
- *num_samples_in = OVERLAP_22KHZ + odd_smp;
-}
-
-/*
- * 2.30 fixed point FIR filter coefficients for conversion 22050 -> 16000,
- * or 11025 -> 8000.
- *
- * Transition band from about 14 kHz, passband ripple < 0.1 dB,
- * stopband ripple at about -50 dB, linear phase.
- *
- * Design and display in MATLAB or Octave using:
- *
- * filter = fir1(23, 16000 / 22050); filter = round(filter * 2**30); freqz(filter * 2**-30);
- */
-static const int32_t filter_16khz_coeff[] = {
- 2057290, -2973608, 1880478, 4362037,
- -14639744, 18523609, -1609189, -38502470,
- 78073125, -68353935, -59103896, 617555440,
- 617555440, -59103896, -68353935, 78073125,
- -38502470, -1609189, 18523609, -14639744,
- 4362037, 1880478, -2973608, 2057290,
-};
-#define NUM_COEFF_16KHZ (sizeof(filter_16khz_coeff) / sizeof(filter_16khz_coeff[0]))
-#define OVERLAP_16KHZ (NUM_COEFF_16KHZ - 1)
-
-/*
- * Convert a chunk from 22 kHz to 16 kHz. Will update num_samples_in and
- * num_samples_out accordingly, since it may leave input samples in the buffer
- * due to overlap.
- *
- * This implementation is rather ad-hoc; it first low-pass filters the data
- * into a temporary buffer, and then converts chunks of 441 input samples at a
- * time into 320 output samples by simple linear interpolation. A better
- * implementation would use a polyphase filter bank to do these two operations
- * in one step.
- *
- * Input and output are taken to be in 0.16 fixed-point.
- */
-
-#define RESAMPLE_16KHZ_SAMPLES_IN 441
-#define RESAMPLE_16KHZ_SAMPLES_OUT 320
-
-void resample_441_320(int16_t* input, int16_t* output, int* num_samples_in, int* num_samples_out)
-{
- const int num_blocks = (*num_samples_in - OVERLAP_16KHZ) / RESAMPLE_16KHZ_SAMPLES_IN;
- if (num_blocks < 1) {
- *num_samples_out = 0;
- return;
- }
-
- for (int i = 0; i < num_blocks; ++i) {
- uint32_t tmp[RESAMPLE_16KHZ_SAMPLES_IN];
- for (int j = 0; j < RESAMPLE_16KHZ_SAMPLES_IN; ++j) {
- tmp[j] = fir_convolve(input + i * RESAMPLE_16KHZ_SAMPLES_IN + j,
- filter_16khz_coeff,
- NUM_COEFF_16KHZ);
- }
-
- const float step_float = (float)RESAMPLE_16KHZ_SAMPLES_IN / (float)RESAMPLE_16KHZ_SAMPLES_OUT;
- const uint32_t step = (uint32_t)(step_float * 32768.0f + 0.5f); // 17.15 fixed point
-
- uint32_t in_sample_num = 0; // 17.15 fixed point
- for (int j = 0; j < RESAMPLE_16KHZ_SAMPLES_OUT; ++j, in_sample_num += step) {
- const uint32_t whole = in_sample_num >> 15;
- const uint32_t frac = (in_sample_num & 0x7fff); // 0.15 fixed point
- const int32_t s1 = tmp[whole];
- const int32_t s2 = tmp[whole + 1];
- *output++ = clip(s1 + (((s2 - s1) * (int32_t)frac) >> 15));
- }
-
- }
-
- const int samples_consumed = num_blocks * RESAMPLE_16KHZ_SAMPLES_IN;
- memmove(input, input + samples_consumed, (*num_samples_in - samples_consumed) * sizeof(*input));
- *num_samples_in -= samples_consumed;
- *num_samples_out = RESAMPLE_16KHZ_SAMPLES_OUT * num_blocks;
-}
-
-
-AudioHardware::DownSampler::DownSampler(uint32_t outSampleRate,
- uint32_t channelCount,
- uint32_t frameCount,
- AudioHardware::BufferProvider* provider)
- : mStatus(NO_INIT), mProvider(provider), mSampleRate(outSampleRate),
- mChannelCount(channelCount), mFrameCount(frameCount),
- mInLeft(NULL), mInRight(NULL), mTmpLeft(NULL), mTmpRight(NULL),
- mTmp2Left(NULL), mTmp2Right(NULL), mOutLeft(NULL), mOutRight(NULL)
-
-{
- LOGV("AudioHardware::DownSampler() cstor %p SR %d channels %d frames %d",
- this, mSampleRate, mChannelCount, mFrameCount);
-
- if (mSampleRate != 8000 && mSampleRate != 11025 && mSampleRate != 16000 &&
- mSampleRate != 22050) {
- LOGW("AudioHardware::DownSampler cstor: bad sampling rate: %d", mSampleRate);
- return;
- }
-
- mInLeft = new int16_t[mFrameCount];
- mInRight = new int16_t[mFrameCount];
- mTmpLeft = new int16_t[mFrameCount];
- mTmpRight = new int16_t[mFrameCount];
- mTmp2Left = new int16_t[mFrameCount];
- mTmp2Right = new int16_t[mFrameCount];
- mOutLeft = new int16_t[mFrameCount];
- mOutRight = new int16_t[mFrameCount];
-
- mStatus = NO_ERROR;
-}
-
-AudioHardware::DownSampler::~DownSampler()
-{
- if (mInLeft) delete[] mInLeft;
- if (mInRight) delete[] mInRight;
- if (mTmpLeft) delete[] mTmpLeft;
- if (mTmpRight) delete[] mTmpRight;
- if (mTmp2Left) delete[] mTmp2Left;
- if (mTmp2Right) delete[] mTmp2Right;
- if (mOutLeft) delete[] mOutLeft;
- if (mOutRight) delete[] mOutRight;
-}
-
-void AudioHardware::DownSampler::reset()
-{
- mInInBuf = 0;
- mInTmpBuf = 0;
- mInTmp2Buf = 0;
- mOutBufPos = 0;
- mInOutBuf = 0;
-}
-
-
-int AudioHardware::DownSampler::resample(int16_t* out, size_t *outFrameCount)
-{
- if (mStatus != NO_ERROR) {
- return mStatus;
- }
-
- if (out == NULL || outFrameCount == NULL) {
- return BAD_VALUE;
- }
-
- int16_t *outLeft = mTmp2Left;
- int16_t *outRight = mTmp2Left;
- if (mSampleRate == 22050) {
- outLeft = mTmpLeft;
- outRight = mTmpRight;
- } else if (mSampleRate == 8000){
- outLeft = mOutLeft;
- outRight = mOutRight;
- }
-
- int outFrames = 0;
- int remaingFrames = *outFrameCount;
-
- if (mInOutBuf) {
- int frames = (remaingFrames > mInOutBuf) ? mInOutBuf : remaingFrames;
-
- for (int i = 0; i < frames; ++i) {
- out[i] = outLeft[mOutBufPos + i];
- }
- if (mChannelCount == 2) {
- for (int i = 0; i < frames; ++i) {
- out[i * 2] = outLeft[mOutBufPos + i];
- out[i * 2 + 1] = outRight[mOutBufPos + i];
- }
- }
- remaingFrames -= frames;
- mInOutBuf -= frames;
- mOutBufPos += frames;
- outFrames += frames;
- }
-
- while (remaingFrames) {
- LOGW_IF((mInOutBuf != 0), "mInOutBuf should be 0 here");
-
- AudioHardware::BufferProvider::Buffer buf;
- buf.frameCount = mFrameCount - mInInBuf;
- int ret = mProvider->getNextBuffer(&buf);
- if (buf.raw == NULL) {
- *outFrameCount = outFrames;
- return ret;
- }
-
- for (size_t i = 0; i < buf.frameCount; ++i) {
- mInLeft[i + mInInBuf] = buf.i16[i];
- }
- if (mChannelCount == 2) {
- for (size_t i = 0; i < buf.frameCount; ++i) {
- mInLeft[i + mInInBuf] = buf.i16[i * 2];
- mInRight[i + mInInBuf] = buf.i16[i * 2 + 1];
- }
- }
- mInInBuf += buf.frameCount;
- mProvider->releaseBuffer(&buf);
-
- /* 44010 -> 22050 */
- {
- int samples_in_left = mInInBuf;
- int samples_out_left;
- resample_2_1(mInLeft, mTmpLeft + mInTmpBuf, &samples_in_left, &samples_out_left);
-
- if (mChannelCount == 2) {
- int samples_in_right = mInInBuf;
- int samples_out_right;
- resample_2_1(mInRight, mTmpRight + mInTmpBuf, &samples_in_right, &samples_out_right);
- }
-
- mInInBuf = samples_in_left;
- mInTmpBuf += samples_out_left;
- mInOutBuf = samples_out_left;
- }
-
- if (mSampleRate == 11025 || mSampleRate == 8000) {
- /* 22050 - > 11025 */
- int samples_in_left = mInTmpBuf;
- int samples_out_left;
- resample_2_1(mTmpLeft, mTmp2Left + mInTmp2Buf, &samples_in_left, &samples_out_left);
-
- if (mChannelCount == 2) {
- int samples_in_right = mInTmpBuf;
- int samples_out_right;
- resample_2_1(mTmpRight, mTmp2Right + mInTmp2Buf, &samples_in_right, &samples_out_right);
- }
-
-
- mInTmpBuf = samples_in_left;
- mInTmp2Buf += samples_out_left;
- mInOutBuf = samples_out_left;
-
- if (mSampleRate == 8000) {
- /* 11025 -> 8000*/
- int samples_in_left = mInTmp2Buf;
- int samples_out_left;
- resample_441_320(mTmp2Left, mOutLeft, &samples_in_left, &samples_out_left);
-
- if (mChannelCount == 2) {
- int samples_in_right = mInTmp2Buf;
- int samples_out_right;
- resample_441_320(mTmp2Right, mOutRight, &samples_in_right, &samples_out_right);
- }
-
- mInTmp2Buf = samples_in_left;
- mInOutBuf = samples_out_left;
- } else {
- mInTmp2Buf = 0;
- }
-
- } else if (mSampleRate == 16000) {
- /* 22050 -> 16000*/
- int samples_in_left = mInTmpBuf;
- int samples_out_left;
- resample_441_320(mTmpLeft, mTmp2Left, &samples_in_left, &samples_out_left);
-
- if (mChannelCount == 2) {
- int samples_in_right = mInTmpBuf;
- int samples_out_right;
- resample_441_320(mTmpRight, mTmp2Right, &samples_in_right, &samples_out_right);
- }
-
- mInTmpBuf = samples_in_left;
- mInOutBuf = samples_out_left;
- } else {
- mInTmpBuf = 0;
- }
-
- int frames = (remaingFrames > mInOutBuf) ? mInOutBuf : remaingFrames;
-
- for (int i = 0; i < frames; ++i) {
- out[outFrames + i] = outLeft[i];
- }
- if (mChannelCount == 2) {
- for (int i = 0; i < frames; ++i) {
- out[(outFrames + i) * 2] = outLeft[i];
- out[(outFrames + i) * 2 + 1] = outRight[i];
- }
- }
- remaingFrames -= frames;
- outFrames += frames;
- mOutBufPos = frames;
- mInOutBuf -= frames;
- }
-
- return 0;
-}
-
-
-
-
-
-
-
-//------------------------------------------------------------------------------
// Factory
//------------------------------------------------------------------------------
@@ -2307,4 +2418,4 @@ extern "C" AudioHardwareInterface* createAudioHardware(void) {
return new AudioHardware();
}
-}; // namespace android_audio_legacy
+}; // namespace android
diff --git a/libaudio/AudioHardware.h b/libaudio/AudioHardware.h
index 69bc2b4..d191f3f 100644
--- a/libaudio/AudioHardware.h
+++ b/libaudio/AudioHardware.h
@@ -25,9 +25,13 @@
#include <hardware_legacy/AudioHardwareBase.h>
#include <media/mediarecorder.h>
+#include <hardware/audio_effect.h>
#include "secril-client.h"
+#include <audio_utils/resampler.h>
+#include <audio_utils/echo_reference.h>
+
extern "C" {
struct pcm;
struct mixer;
@@ -35,8 +39,13 @@ extern "C" {
};
namespace android_audio_legacy {
-
-using namespace android;
+ using android::AutoMutex;
+ using android::Mutex;
+ using android::RefBase;
+ using android::SortedVector;
+ using android::sp;
+ using android::String16;
+ using android::Vector;
// TODO: determine actual audio DSP and hardware latency
// Additionnal latency introduced by audio DSP and hardware in ms
@@ -48,24 +57,20 @@ using namespace android;
// Default audio output sample format
#define AUDIO_HW_OUT_FORMAT (AudioSystem::PCM_16_BIT)
// Kernel pcm out buffer size in frames at 44.1kHz
-#define AUDIO_HW_OUT_PERIOD_MULT 8 // (8 * 128 = 1024 frames)
-#define AUDIO_HW_OUT_PERIOD_SZ (PCM_PERIOD_SZ_MIN * AUDIO_HW_OUT_PERIOD_MULT)
+#define AUDIO_HW_OUT_PERIOD_SZ 1024
#define AUDIO_HW_OUT_PERIOD_CNT 4
// Default audio output buffer size in bytes
#define AUDIO_HW_OUT_PERIOD_BYTES (AUDIO_HW_OUT_PERIOD_SZ * 2 * sizeof(int16_t))
// Default audio input sample rate
-#define AUDIO_HW_IN_SAMPLERATE 8000
+#define AUDIO_HW_IN_SAMPLERATE 44100
// Default audio input channel mask
#define AUDIO_HW_IN_CHANNELS (AudioSystem::CHANNEL_IN_MONO)
// Default audio input sample format
#define AUDIO_HW_IN_FORMAT (AudioSystem::PCM_16_BIT)
-// Number of buffers in audio driver for input
-#define AUDIO_HW_NUM_IN_BUF 2
// Kernel pcm in buffer size in frames at 44.1kHz (before resampling)
-#define AUDIO_HW_IN_PERIOD_MULT 16 // (16 * 128 = 2048 frames)
-#define AUDIO_HW_IN_PERIOD_SZ (PCM_PERIOD_SZ_MIN * AUDIO_HW_IN_PERIOD_MULT)
-#define AUDIO_HW_IN_PERIOD_CNT 2
+#define AUDIO_HW_IN_PERIOD_SZ 1024
+#define AUDIO_HW_IN_PERIOD_CNT 4
// Default audio input buffer size in bytes (8kHz mono)
#define AUDIO_HW_IN_PERIOD_BYTES ((AUDIO_HW_IN_PERIOD_SZ*sizeof(int16_t))/8)
@@ -74,13 +79,13 @@ class AudioHardware : public AudioHardwareBase
{
class AudioStreamOutALSA;
class AudioStreamInALSA;
+
public:
// input path names used to translate from input sources to driver paths
static const char *inputPathNameDefault;
static const char *inputPathNameCamcorder;
static const char *inputPathNameVoiceRecognition;
- static const char *inputPathNameVoiceCommunication;
AudioHardware();
virtual ~AudioHardware();
@@ -130,6 +135,8 @@ public:
status_t setInputSource_l(audio_source source);
+ void setVoiceVolume_l(float volume);
+
static uint32_t getInputSampleRate(uint32_t sampleRate);
sp <AudioStreamInALSA> getActiveInput_l();
@@ -143,6 +150,11 @@ public:
sp <AudioStreamOutALSA> output() { return mOutput; }
+ struct echo_reference_itfe *getEchoReference(audio_format_t format,
+ uint32_t channelCount,
+ uint32_t samplingRate);
+ void releaseEchoReference(struct echo_reference_itfe *reference);
+
protected:
virtual status_t dump(int fd, const Vector<String16>& args);
@@ -165,6 +177,7 @@ private:
uint32_t mPcmOpenCnt;
uint32_t mMixerOpenCnt;
bool mInCallAudioMode;
+ float mVoiceVol;
audio_source mInputSource;
bool mBluetoothNrec;
@@ -183,6 +196,7 @@ private:
int (*setCallClockSync)(HRilClient, SoundClockCondition);
void loadRILD(void);
status_t connectRILDIfRequired(void);
+ struct echo_reference_itfe *mEchoReference;
#ifdef HAVE_FM_RADIO
int mFmFd;
@@ -194,7 +208,17 @@ private:
int mDriverOp;
static uint32_t checkInputSampleRate(uint32_t sampleRate);
- static const uint32_t inputSamplingRates[];
+
+ // column index in inputConfigTable[][]
+ enum {
+ INPUT_CONFIG_SAMPLE_RATE,
+ INPUT_CONFIG_BUFFER_RATIO,
+ INPUT_CONFIG_CNT
+ };
+
+ // contains the list of valid sampling rates for input streams as well as the ratio
+ // between the kernel buffer size and audio hal buffer size for each sampling rate
+ static const uint32_t inputConfigTable[][INPUT_CONFIG_CNT];
class AudioStreamOutALSA : public AudioStreamOut, public RefBase
{
@@ -239,8 +263,14 @@ private:
void lock();
void unlock();
+ void addEchoReference(struct echo_reference_itfe *reference);
+ void removeEchoReference(struct echo_reference_itfe *reference);
+
private:
+ int computeEchoReferenceDelay(size_t frames, struct timespec *echoRefRenderTime);
+ int getPlaybackDelay(size_t frames, struct echo_reference_buffer *buffer);
+
Mutex mLock;
AudioHardware* mHardware;
struct pcm *mPcm;
@@ -256,65 +286,10 @@ private:
int mDriverOp;
int mStandbyCnt;
bool mSleepReq;
+ struct echo_reference_itfe *mEchoReference;
};
- class DownSampler;
-
- class BufferProvider
- {
- public:
-
- struct Buffer {
- union {
- void* raw;
- short* i16;
- int8_t* i8;
- };
- size_t frameCount;
- };
-
- virtual ~BufferProvider() {}
-
- virtual status_t getNextBuffer(Buffer* buffer) = 0;
- virtual void releaseBuffer(Buffer* buffer) = 0;
- };
-
- class DownSampler {
- public:
- DownSampler(uint32_t outSampleRate,
- uint32_t channelCount,
- uint32_t frameCount,
- BufferProvider* provider);
-
- virtual ~DownSampler();
-
- void reset();
- status_t initCheck() { return mStatus; }
- int resample(int16_t* out, size_t *outFrameCount);
-
- private:
- status_t mStatus;
- BufferProvider* mProvider;
- uint32_t mSampleRate;
- uint32_t mChannelCount;
- uint32_t mFrameCount;
- int16_t *mInLeft;
- int16_t *mInRight;
- int16_t *mTmpLeft;
- int16_t *mTmpRight;
- int16_t *mTmp2Left;
- int16_t *mTmp2Right;
- int16_t *mOutLeft;
- int16_t *mOutRight;
- int mInInBuf;
- int mInTmpBuf;
- int mInTmp2Buf;
- int mOutBufPos;
- int mInOutBuf;
- };
-
-
- class AudioStreamInALSA : public AudioStreamIn, public BufferProvider, public RefBase
+ class AudioStreamInALSA : public AudioStreamIn, public RefBase
{
public:
@@ -338,6 +313,9 @@ private:
virtual status_t setParameters(const String8& keyValuePairs);
virtual String8 getParameters(const String8& keys);
virtual unsigned int getInputFramesLost() const { return 0; }
+ virtual status_t addAudioEffect(effect_handle_t effect);
+ virtual status_t removeAudioEffect(effect_handle_t effect);
+
uint32_t device() { return mDevices; }
void doStandby_l();
void close_l();
@@ -346,19 +324,36 @@ private:
static size_t getBufferSize(uint32_t sampleRate, int channelCount);
- // BufferProvider
- virtual status_t getNextBuffer(BufferProvider::Buffer* buffer);
- virtual void releaseBuffer(BufferProvider::Buffer* buffer);
-
- // Stubs (ICS)
- virtual status_t addAudioEffect(effect_handle_t effect) { return INVALID_OPERATION; }
- virtual status_t removeAudioEffect(effect_handle_t effect) { return INVALID_OPERATION; }
+ // resampler_buffer_provider
+ static int getNextBufferStatic(struct resampler_buffer_provider *provider,
+ struct resampler_buffer* buffer);
+ static void releaseBufferStatic(struct resampler_buffer_provider *provider,
+ struct resampler_buffer* buffer);
int prepareLock();
void lock();
void unlock();
- private:
+ private:
+
+ struct ResamplerBufferProvider {
+ struct resampler_buffer_provider mProvider;
+ AudioStreamInALSA *mInputStream;
+ };
+
+ ssize_t readFrames(void* buffer, ssize_t frames);
+ ssize_t processFrames(void* buffer, ssize_t frames);
+ int32_t updateEchoReference(size_t frames);
+ void pushEchoReference(size_t frames);
+ void updateEchoDelay(size_t frames, struct timespec *echoRefRenderTime);
+ void getCaptureDelay(size_t frames, struct echo_reference_buffer *buffer);
+ status_t setPreProcessorEchoDelay(effect_handle_t handle, int32_t delayUs);
+ status_t setPreprocessorParam(effect_handle_t handle, effect_param_t *param);
+
+ // BufferProvider
+ status_t getNextBuffer(struct resampler_buffer* buffer);
+ void releaseBuffer(struct resampler_buffer* buffer);
+
Mutex mLock;
AudioHardware* mHardware;
struct pcm *mPcm;
@@ -371,18 +366,28 @@ private:
uint32_t mChannelCount;
uint32_t mSampleRate;
size_t mBufferSize;
- DownSampler *mDownSampler;
+ struct resampler_itfe *mDownSampler;
+ struct ResamplerBufferProvider mBufferProvider;
status_t mReadStatus;
- size_t mInPcmInBuf;
- int16_t *mPcmIn;
+ size_t mInputFramesIn;
+ int16_t *mInputBuf;
// trace driver operations for dump
int mDriverOp;
int mStandbyCnt;
bool mSleepReq;
+ SortedVector<effect_handle_t> mPreprocessors;
+ int16_t *mProcBuf;
+ size_t mProcBufSize;
+ size_t mProcFramesIn;
+ int16_t *mRefBuf;
+ size_t mRefBufSize;
+ size_t mRefFramesIn;
+ struct echo_reference_itfe *mEchoReference;
+ bool mNeedEchoReference;
};
};
-}; // namespace android_audio_legacy
+}; // namespace android
#endif
diff --git a/libaudio/AudioPolicyManager.cpp b/libaudio/AudioPolicyManager.cpp
index 4572729..bfa6c00 100644
--- a/libaudio/AudioPolicyManager.cpp
+++ b/libaudio/AudioPolicyManager.cpp
@@ -43,4 +43,4 @@ extern "C" void destroyAudioPolicyManager(AudioPolicyInterface *interface)
}
-}; // namespace android_audio_legacy
+}; // namespace android
diff --git a/libaudio/alsa_audio.h b/libaudio/alsa_audio.h
deleted file mode 100644
index 3cb86d9..0000000
--- a/libaudio/alsa_audio.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
-** Copyright 2010, The Android Open-Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-#ifndef _AUDIO_H_
-#define _AUDIO_H_
-
-struct pcm;
-
-#define PCM_OUT 0x00000000
-#define PCM_IN 0x10000000
-
-#define PCM_STEREO 0x00000000
-#define PCM_MONO 0x01000000
-
-#define PCM_44100HZ 0x00000000
-#define PCM_48000HZ 0x00100000
-#define PCM_8000HZ 0x00200000
-#define PCM_RATE_MASK 0x00F00000
-
-#define PCM_PERIOD_CNT_MIN 2
-#define PCM_PERIOD_CNT_SHIFT 16
-#define PCM_PERIOD_CNT_MASK (0xF << PCM_PERIOD_CNT_SHIFT)
-#define PCM_PERIOD_SZ_MIN 128
-#define PCM_PERIOD_SZ_SHIFT 12
-#define PCM_PERIOD_SZ_MASK (0xF << PCM_PERIOD_SZ_SHIFT)
-
-/* Acquire/release a pcm channel.
- * Returns non-zero on error
- */
-struct pcm *pcm_open(unsigned flags);
-int pcm_close(struct pcm *pcm);
-int pcm_ready(struct pcm *pcm);
-
-/* Returns a human readable reason for the last error. */
-const char *pcm_error(struct pcm *pcm);
-
-/* Returns the buffer size (int bytes) that should be used for pcm_write.
- * This will be 1/2 of the actual fifo size.
- */
-unsigned pcm_buffer_size(struct pcm *pcm);
-
-/* Write data to the fifo.
- * Will start playback on the first write or on a write that
- * occurs after a fifo underrun.
- */
-int pcm_write(struct pcm *pcm, void *data, unsigned count);
-int pcm_read(struct pcm *pcm, void *data, unsigned count);
-
-struct mixer;
-struct mixer_ctl;
-
-struct mixer *mixer_open(void);
-void mixer_close(struct mixer *mixer);
-void mixer_dump(struct mixer *mixer);
-
-struct mixer_ctl *mixer_get_control(struct mixer *mixer,
- const char *name, unsigned index);
-struct mixer_ctl *mixer_get_nth_control(struct mixer *mixer, unsigned n);
-
-int mixer_ctl_set(struct mixer_ctl *ctl, unsigned percent);
-int mixer_ctl_select(struct mixer_ctl *ctl, const char *value);
-void mixer_ctl_print(struct mixer_ctl *ctl);
-
-#endif
diff --git a/libaudio/alsa_mixer.c b/libaudio/alsa_mixer.c
deleted file mode 100644
index 3036ef8..0000000
--- a/libaudio/alsa_mixer.c
+++ /dev/null
@@ -1,371 +0,0 @@
-/*
-** Copyright 2010, The Android Open-Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <ctype.h>
-
-#include <linux/ioctl.h>
-#define __force
-#define __bitwise
-#define __user
-#include "asound.h"
-
-#include "alsa_audio.h"
-
-static const char *elem_iface_name(snd_ctl_elem_iface_t n)
-{
- switch (n) {
- case SNDRV_CTL_ELEM_IFACE_CARD: return "CARD";
- case SNDRV_CTL_ELEM_IFACE_HWDEP: return "HWDEP";
- case SNDRV_CTL_ELEM_IFACE_MIXER: return "MIXER";
- case SNDRV_CTL_ELEM_IFACE_PCM: return "PCM";
- case SNDRV_CTL_ELEM_IFACE_RAWMIDI: return "MIDI";
- case SNDRV_CTL_ELEM_IFACE_TIMER: return "TIMER";
- case SNDRV_CTL_ELEM_IFACE_SEQUENCER: return "SEQ";
- default: return "???";
- }
-}
-
-static const char *elem_type_name(snd_ctl_elem_type_t n)
-{
- switch (n) {
- case SNDRV_CTL_ELEM_TYPE_NONE: return "NONE";
- case SNDRV_CTL_ELEM_TYPE_BOOLEAN: return "BOOL";
- case SNDRV_CTL_ELEM_TYPE_INTEGER: return "INT32";
- case SNDRV_CTL_ELEM_TYPE_ENUMERATED: return "ENUM";
- case SNDRV_CTL_ELEM_TYPE_BYTES: return "BYTES";
- case SNDRV_CTL_ELEM_TYPE_IEC958: return "IEC958";
- case SNDRV_CTL_ELEM_TYPE_INTEGER64: return "INT64";
- default: return "???";
- }
-}
-
-
-struct mixer_ctl {
- struct mixer *mixer;
- struct snd_ctl_elem_info *info;
- char **ename;
-};
-
-struct mixer {
- int fd;
- struct snd_ctl_elem_info *info;
- struct mixer_ctl *ctl;
- unsigned count;
-};
-
-void mixer_close(struct mixer *mixer)
-{
- unsigned n,m;
-
- if (mixer->fd >= 0)
- close(mixer->fd);
-
- if (mixer->ctl) {
- for (n = 0; n < mixer->count; n++) {
- if (mixer->ctl[n].ename) {
- unsigned max = mixer->ctl[n].info->value.enumerated.items;
- for (m = 0; m < max; m++)
- free(mixer->ctl[n].ename[m]);
- free(mixer->ctl[n].ename);
- }
- }
- free(mixer->ctl);
- }
-
- if (mixer->info)
- free(mixer->info);
-
- free(mixer);
-}
-
-struct mixer *mixer_open(void)
-{
- struct snd_ctl_elem_list elist;
- struct snd_ctl_elem_info tmp;
- struct snd_ctl_elem_id *eid = NULL;
- struct mixer *mixer = NULL;
- unsigned n, m;
- int fd;
-
- fd = open("/dev/snd/controlC0", O_RDWR);
- if (fd < 0)
- return 0;
-
- memset(&elist, 0, sizeof(elist));
- if (ioctl(fd, SNDRV_CTL_IOCTL_ELEM_LIST, &elist) < 0)
- goto fail;
-
- mixer = calloc(1, sizeof(*mixer));
- if (!mixer)
- goto fail;
-
- mixer->ctl = calloc(elist.count, sizeof(struct mixer_ctl));
- mixer->info = calloc(elist.count, sizeof(struct snd_ctl_elem_info));
- if (!mixer->ctl || !mixer->info)
- goto fail;
-
- eid = calloc(elist.count, sizeof(struct snd_ctl_elem_id));
- if (!eid)
- goto fail;
-
- mixer->count = elist.count;
- mixer->fd = fd;
- elist.space = mixer->count;
- elist.pids = eid;
- if (ioctl(fd, SNDRV_CTL_IOCTL_ELEM_LIST, &elist) < 0)
- goto fail;
-
- for (n = 0; n < mixer->count; n++) {
- struct snd_ctl_elem_info *ei = mixer->info + n;
- ei->id.numid = eid[n].numid;
- if (ioctl(fd, SNDRV_CTL_IOCTL_ELEM_INFO, ei) < 0)
- goto fail;
- mixer->ctl[n].info = ei;
- mixer->ctl[n].mixer = mixer;
- if (ei->type == SNDRV_CTL_ELEM_TYPE_ENUMERATED) {
- char **enames = calloc(ei->value.enumerated.items, sizeof(char*));
- if (!enames)
- goto fail;
- mixer->ctl[n].ename = enames;
- for (m = 0; m < ei->value.enumerated.items; m++) {
- memset(&tmp, 0, sizeof(tmp));
- tmp.id.numid = ei->id.numid;
- tmp.value.enumerated.item = m;
- if (ioctl(fd, SNDRV_CTL_IOCTL_ELEM_INFO, &tmp) < 0)
- goto fail;
- enames[m] = strdup(tmp.value.enumerated.name);
- if (!enames[m])
- goto fail;
- }
- }
- }
-
- free(eid);
- return mixer;
-
-fail:
- if (eid)
- free(eid);
- if (mixer)
- mixer_close(mixer);
- else if (fd >= 0)
- close(fd);
- return 0;
-}
-
-void mixer_dump(struct mixer *mixer)
-{
- unsigned n, m;
-
- printf(" id iface dev sub idx num perms type name\n");
- for (n = 0; n < mixer->count; n++) {
- struct snd_ctl_elem_info *ei = mixer->info + n;
-
- printf("%4d %5s %3d %3d %3d %3d %c%c%c%c%c%c%c%c%c %-6s %s",
- ei->id.numid, elem_iface_name(ei->id.iface),
- ei->id.device, ei->id.subdevice, ei->id.index,
- ei->count,
- (ei->access & SNDRV_CTL_ELEM_ACCESS_READ) ? 'r' : ' ',
- (ei->access & SNDRV_CTL_ELEM_ACCESS_WRITE) ? 'w' : ' ',
- (ei->access & SNDRV_CTL_ELEM_ACCESS_VOLATILE) ? 'V' : ' ',
- (ei->access & SNDRV_CTL_ELEM_ACCESS_TIMESTAMP) ? 'T' : ' ',
- (ei->access & SNDRV_CTL_ELEM_ACCESS_TLV_READ) ? 'R' : ' ',
- (ei->access & SNDRV_CTL_ELEM_ACCESS_TLV_WRITE) ? 'W' : ' ',
- (ei->access & SNDRV_CTL_ELEM_ACCESS_TLV_COMMAND) ? 'C' : ' ',
- (ei->access & SNDRV_CTL_ELEM_ACCESS_INACTIVE) ? 'I' : ' ',
- (ei->access & SNDRV_CTL_ELEM_ACCESS_LOCK) ? 'L' : ' ',
- elem_type_name(ei->type),
- ei->id.name);
- switch (ei->type) {
- case SNDRV_CTL_ELEM_TYPE_INTEGER:
- printf(ei->value.integer.step ?
- " { %ld-%ld, %ld }\n" : " { %ld-%ld }",
- ei->value.integer.min,
- ei->value.integer.max,
- ei->value.integer.step);
- break;
- case SNDRV_CTL_ELEM_TYPE_INTEGER64:
- printf(ei->value.integer64.step ?
- " { %lld-%lld, %lld }\n" : " { %lld-%lld }",
- ei->value.integer64.min,
- ei->value.integer64.max,
- ei->value.integer64.step);
- break;
- case SNDRV_CTL_ELEM_TYPE_ENUMERATED: {
- unsigned m;
- printf(" { %s=0", mixer->ctl[n].ename[0]);
- for (m = 1; m < ei->value.enumerated.items; m++)
- printf(", %s=%d", mixer->ctl[n].ename[m],m);
- printf(" }");
- break;
- }
- }
- printf("\n");
- }
-}
-
-struct mixer_ctl *mixer_get_control(struct mixer *mixer,
- const char *name, unsigned index)
-{
- unsigned n;
- for (n = 0; n < mixer->count; n++) {
- if (mixer->info[n].id.index == index) {
- if (!strcmp(name, (char*) mixer->info[n].id.name)) {
- return mixer->ctl + n;
- }
- }
- }
- return 0;
-}
-
-struct mixer_ctl *mixer_get_nth_control(struct mixer *mixer, unsigned n)
-{
- if (n < mixer->count)
- return mixer->ctl + n;
- return 0;
-}
-
-void mixer_ctl_print(struct mixer_ctl *ctl)
-{
- struct snd_ctl_elem_value ev;
- unsigned n;
-
- memset(&ev, 0, sizeof(ev));
- ev.id.numid = ctl->info->id.numid;
- if (ioctl(ctl->mixer->fd, SNDRV_CTL_IOCTL_ELEM_READ, &ev))
- return;
- printf("%s:", ctl->info->id.name);
-
- switch (ctl->info->type) {
- case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
- for (n = 0; n < ctl->info->count; n++)
- printf(" %s", ev.value.integer.value[n] ? "ON" : "OFF");
- break;
- case SNDRV_CTL_ELEM_TYPE_INTEGER: {
- for (n = 0; n < ctl->info->count; n++)
- printf(" %ld", ev.value.integer.value[n]);
- break;
- }
- case SNDRV_CTL_ELEM_TYPE_INTEGER64:
- for (n = 0; n < ctl->info->count; n++)
- printf(" %lld", ev.value.integer64.value[n]);
- break;
- case SNDRV_CTL_ELEM_TYPE_ENUMERATED:
- for (n = 0; n < ctl->info->count; n++) {
- unsigned v = ev.value.enumerated.item[n];
- printf(" %d (%s)", v,
- (v < ctl->info->value.enumerated.items) ? ctl->ename[v] : "???");
- }
- break;
- default:
- printf(" ???");
- }
- printf("\n");
-}
-
-static long scale_int(struct snd_ctl_elem_info *ei, unsigned _percent)
-{
- long percent;
- long range;
-
- if (_percent > 100)
- percent = 100;
- else
- percent = (long) _percent;
-
- range = (ei->value.integer.max - ei->value.integer.min);
-
- return ei->value.integer.min + (range * percent) / 100LL;
-}
-
-static long long scale_int64(struct snd_ctl_elem_info *ei, unsigned _percent)
-{
- long long percent;
- long long range;
-
- if (_percent > 100)
- percent = 100;
- else
- percent = (long) _percent;
-
- range = (ei->value.integer.max - ei->value.integer.min) * 100LL;
-
- return ei->value.integer.min + (range / percent);
-}
-
-int mixer_ctl_set(struct mixer_ctl *ctl, unsigned percent)
-{
- struct snd_ctl_elem_value ev;
- unsigned n;
-
- memset(&ev, 0, sizeof(ev));
- ev.id.numid = ctl->info->id.numid;
- switch (ctl->info->type) {
- case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
- for (n = 0; n < ctl->info->count; n++)
- ev.value.integer.value[n] = !!percent;
- break;
- case SNDRV_CTL_ELEM_TYPE_INTEGER: {
- long value = scale_int(ctl->info, percent);
- for (n = 0; n < ctl->info->count; n++)
- ev.value.integer.value[n] = value;
- break;
- }
- case SNDRV_CTL_ELEM_TYPE_INTEGER64: {
- long long value = scale_int64(ctl->info, percent);
- for (n = 0; n < ctl->info->count; n++)
- ev.value.integer64.value[n] = value;
- break;
- }
- default:
- errno = EINVAL;
- return -1;
- }
-
- return ioctl(ctl->mixer->fd, SNDRV_CTL_IOCTL_ELEM_WRITE, &ev);
-}
-
-int mixer_ctl_select(struct mixer_ctl *ctl, const char *value)
-{
- unsigned n, max;
- struct snd_ctl_elem_value ev;
-
- if (ctl->info->type != SNDRV_CTL_ELEM_TYPE_ENUMERATED) {
- errno = EINVAL;
- return -1;
- }
-
- max = ctl->info->value.enumerated.items;
- for (n = 0; n < max; n++) {
- if (!strcmp(value, ctl->ename[n])) {
- memset(&ev, 0, sizeof(ev));
- ev.value.enumerated.item[0] = n;
- ev.id.numid = ctl->info->id.numid;
- if (ioctl(ctl->mixer->fd, SNDRV_CTL_IOCTL_ELEM_WRITE, &ev) < 0)
- return -1;
- return 0;
- }
- }
-
- errno = EINVAL;
- return -1;
-}
diff --git a/libaudio/alsa_pcm.c b/libaudio/alsa_pcm.c
deleted file mode 100644
index 5673391..0000000
--- a/libaudio/alsa_pcm.c
+++ /dev/null
@@ -1,405 +0,0 @@
-/*
-** Copyright 2010, The Android Open-Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-#define LOG_TAG "alsa_pcm"
-//#define LOG_NDEBUG 0
-#include <cutils/log.h>
-#include <cutils/config_utils.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <fcntl.h>
-#include <stdarg.h>
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-
-#include <sys/ioctl.h>
-#include <sys/mman.h>
-#include <sys/time.h>
-
-#include <linux/ioctl.h>
-
-#include "alsa_audio.h"
-
-#define __force
-#define __bitwise
-#define __user
-#include "asound.h"
-
-#define DEBUG 0
-
-/* alsa parameter manipulation cruft */
-
-#define PARAM_MAX SNDRV_PCM_HW_PARAM_LAST_INTERVAL
-
-static inline int param_is_mask(int p)
-{
- return (p >= SNDRV_PCM_HW_PARAM_FIRST_MASK) &&
- (p <= SNDRV_PCM_HW_PARAM_LAST_MASK);
-}
-
-static inline int param_is_interval(int p)
-{
- return (p >= SNDRV_PCM_HW_PARAM_FIRST_INTERVAL) &&
- (p <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL);
-}
-
-static inline struct snd_interval *param_to_interval(struct snd_pcm_hw_params *p, int n)
-{
- return &(p->intervals[n - SNDRV_PCM_HW_PARAM_FIRST_INTERVAL]);
-}
-
-static inline struct snd_mask *param_to_mask(struct snd_pcm_hw_params *p, int n)
-{
- return &(p->masks[n - SNDRV_PCM_HW_PARAM_FIRST_MASK]);
-}
-
-static void param_set_mask(struct snd_pcm_hw_params *p, int n, unsigned bit)
-{
- if (bit >= SNDRV_MASK_MAX)
- return;
- if (param_is_mask(n)) {
- struct snd_mask *m = param_to_mask(p, n);
- m->bits[0] = 0;
- m->bits[1] = 0;
- m->bits[bit >> 5] |= (1 << (bit & 31));
- }
-}
-
-static void param_set_min(struct snd_pcm_hw_params *p, int n, unsigned val)
-{
- if (param_is_interval(n)) {
- struct snd_interval *i = param_to_interval(p, n);
- i->min = val;
- }
-}
-
-static void param_set_max(struct snd_pcm_hw_params *p, int n, unsigned val)
-{
- if (param_is_interval(n)) {
- struct snd_interval *i = param_to_interval(p, n);
- i->max = val;
- }
-}
-
-static void param_set_int(struct snd_pcm_hw_params *p, int n, unsigned val)
-{
- if (param_is_interval(n)) {
- struct snd_interval *i = param_to_interval(p, n);
- i->min = val;
- i->max = val;
- i->integer = 1;
- }
-}
-
-static void param_init(struct snd_pcm_hw_params *p)
-{
- int n;
- memset(p, 0, sizeof(*p));
- for (n = SNDRV_PCM_HW_PARAM_FIRST_MASK;
- n <= SNDRV_PCM_HW_PARAM_LAST_MASK; n++) {
- struct snd_mask *m = param_to_mask(p, n);
- m->bits[0] = ~0;
- m->bits[1] = ~0;
- }
- for (n = SNDRV_PCM_HW_PARAM_FIRST_INTERVAL;
- n <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL; n++) {
- struct snd_interval *i = param_to_interval(p, n);
- i->min = 0;
- i->max = ~0;
- }
-}
-
-/* debugging gunk */
-
-#if DEBUG
-static const char *param_name[PARAM_MAX+1] = {
- [SNDRV_PCM_HW_PARAM_ACCESS] = "access",
- [SNDRV_PCM_HW_PARAM_FORMAT] = "format",
- [SNDRV_PCM_HW_PARAM_SUBFORMAT] = "subformat",
-
- [SNDRV_PCM_HW_PARAM_SAMPLE_BITS] = "sample_bits",
- [SNDRV_PCM_HW_PARAM_FRAME_BITS] = "frame_bits",
- [SNDRV_PCM_HW_PARAM_CHANNELS] = "channels",
- [SNDRV_PCM_HW_PARAM_RATE] = "rate",
- [SNDRV_PCM_HW_PARAM_PERIOD_TIME] = "period_time",
- [SNDRV_PCM_HW_PARAM_PERIOD_SIZE] = "period_size",
- [SNDRV_PCM_HW_PARAM_PERIOD_BYTES] = "period_bytes",
- [SNDRV_PCM_HW_PARAM_PERIODS] = "periods",
- [SNDRV_PCM_HW_PARAM_BUFFER_TIME] = "buffer_time",
- [SNDRV_PCM_HW_PARAM_BUFFER_SIZE] = "buffer_size",
- [SNDRV_PCM_HW_PARAM_BUFFER_BYTES] = "buffer_bytes",
- [SNDRV_PCM_HW_PARAM_TICK_TIME] = "tick_time",
-};
-
-static void param_dump(struct snd_pcm_hw_params *p)
-{
- int n;
-
- for (n = SNDRV_PCM_HW_PARAM_FIRST_MASK;
- n <= SNDRV_PCM_HW_PARAM_LAST_MASK; n++) {
- struct snd_mask *m = param_to_mask(p, n);
- LOGV("%s = %08x%08x\n", param_name[n],
- m->bits[1], m->bits[0]);
- }
- for (n = SNDRV_PCM_HW_PARAM_FIRST_INTERVAL;
- n <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL; n++) {
- struct snd_interval *i = param_to_interval(p, n);
- LOGV("%s = (%d,%d) omin=%d omax=%d int=%d empty=%d\n",
- param_name[n], i->min, i->max, i->openmin,
- i->openmax, i->integer, i->empty);
- }
- LOGV("info = %08x\n", p->info);
- LOGV("msbits = %d\n", p->msbits);
- LOGV("rate = %d/%d\n", p->rate_num, p->rate_den);
- LOGV("fifo = %d\n", (int) p->fifo_size);
-}
-
-static void info_dump(struct snd_pcm_info *info)
-{
- LOGV("device = %d\n", info->device);
- LOGV("subdevice = %d\n", info->subdevice);
- LOGV("stream = %d\n", info->stream);
- LOGV("card = %d\n", info->card);
- LOGV("id = '%s'\n", info->id);
- LOGV("name = '%s'\n", info->name);
- LOGV("subname = '%s'\n", info->subname);
- LOGV("dev_class = %d\n", info->dev_class);
- LOGV("dev_subclass = %d\n", info->dev_subclass);
- LOGV("subdevices_count = %d\n", info->subdevices_count);
- LOGV("subdevices_avail = %d\n", info->subdevices_avail);
-}
-#else
-static void param_dump(struct snd_pcm_hw_params *p) {}
-static void info_dump(struct snd_pcm_info *info) {}
-#endif
-
-#define PCM_ERROR_MAX 128
-
-struct pcm {
- int fd;
- unsigned flags;
- int running:1;
- int underruns;
- unsigned buffer_size;
- char error[PCM_ERROR_MAX];
-};
-
-unsigned pcm_buffer_size(struct pcm *pcm)
-{
- return pcm->buffer_size;
-}
-
-const char* pcm_error(struct pcm *pcm)
-{
- return pcm->error;
-}
-
-static int oops(struct pcm *pcm, int e, const char *fmt, ...)
-{
- va_list ap;
- int sz;
-
- va_start(ap, fmt);
- vsnprintf(pcm->error, PCM_ERROR_MAX, fmt, ap);
- va_end(ap);
- sz = strlen(pcm->error);
-
- if (errno)
- snprintf(pcm->error + sz, PCM_ERROR_MAX - sz,
- ": %s", strerror(e));
- return -1;
-}
-
-int pcm_write(struct pcm *pcm, void *data, unsigned count)
-{
- struct snd_xferi x;
-
- if (pcm->flags & PCM_IN)
- return -EINVAL;
-
- x.buf = data;
- x.frames = (pcm->flags & PCM_MONO) ? (count / 2) : (count / 4);
-
- for (;;) {
- if (!pcm->running) {
- if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_PREPARE))
- return oops(pcm, errno, "cannot prepare channel");
- if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_WRITEI_FRAMES, &x))
- return oops(pcm, errno, "cannot write initial data");
- pcm->running = 1;
- return 0;
- }
- if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_WRITEI_FRAMES, &x)) {
- pcm->running = 0;
- if (errno == EPIPE) {
- /* we failed to make our window -- try to restart */
- pcm->underruns++;
- continue;
- }
- return oops(pcm, errno, "cannot write stream data");
- }
- return 0;
- }
-}
-
-int pcm_read(struct pcm *pcm, void *data, unsigned count)
-{
- struct snd_xferi x;
-
- if (!(pcm->flags & PCM_IN))
- return -EINVAL;
-
- x.buf = data;
- x.frames = (pcm->flags & PCM_MONO) ? (count / 2) : (count / 4);
-
-// LOGV("read() %d frames", x.frames);
- for (;;) {
- if (!pcm->running) {
- if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_PREPARE))
- return oops(pcm, errno, "cannot prepare channel");
- if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_START))
- return oops(pcm, errno, "cannot start channel");
- pcm->running = 1;
- }
- if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_READI_FRAMES, &x)) {
- pcm->running = 0;
- if (errno == EPIPE) {
- /* we failed to make our window -- try to restart */
- pcm->underruns++;
- continue;
- }
- return oops(pcm, errno, "cannot read stream data");
- }
-// LOGV("read() got %d frames", x.frames);
- return 0;
- }
-}
-
-static struct pcm bad_pcm = {
- .fd = -1,
-};
-
-int pcm_close(struct pcm *pcm)
-{
- if (pcm == &bad_pcm)
- return 0;
-
- if (pcm->fd >= 0)
- close(pcm->fd);
- pcm->running = 0;
- pcm->buffer_size = 0;
- pcm->fd = -1;
- return 0;
-}
-
-struct pcm *pcm_open(unsigned flags)
-{
- const char *dname;
- struct pcm *pcm;
- struct snd_pcm_info info;
- struct snd_pcm_hw_params params;
- struct snd_pcm_sw_params sparams;
- unsigned period_sz;
- unsigned period_cnt;
-
- LOGV("pcm_open(0x%08x)",flags);
-
- pcm = calloc(1, sizeof(struct pcm));
- if (!pcm)
- return &bad_pcm;
-
- if (flags & PCM_IN) {
- dname = "/dev/snd/pcmC0D0c";
- } else {
- dname = "/dev/snd/pcmC0D0p";
- }
-
- LOGV("pcm_open() period sz multiplier %d",
- ((flags & PCM_PERIOD_SZ_MASK) >> PCM_PERIOD_SZ_SHIFT) + 1);
- period_sz = 128 * (((flags & PCM_PERIOD_SZ_MASK) >> PCM_PERIOD_SZ_SHIFT) + 1);
- LOGV("pcm_open() period cnt %d",
- ((flags & PCM_PERIOD_CNT_MASK) >> PCM_PERIOD_CNT_SHIFT) + PCM_PERIOD_CNT_MIN);
- period_cnt = ((flags & PCM_PERIOD_CNT_MASK) >> PCM_PERIOD_CNT_SHIFT) + PCM_PERIOD_CNT_MIN;
-
- pcm->flags = flags;
- pcm->fd = open(dname, O_RDWR);
- if (pcm->fd < 0) {
- oops(pcm, errno, "cannot open device '%s'");
- return pcm;
- }
-
- if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_INFO, &info)) {
- oops(pcm, errno, "cannot get info - %s");
- goto fail;
- }
- info_dump(&info);
-
- LOGV("pcm_open() period_cnt %d period_sz %d channels %d",
- period_cnt, period_sz, (flags & PCM_MONO) ? 1 : 2);
-
- param_init(&params);
- param_set_mask(&params, SNDRV_PCM_HW_PARAM_ACCESS,
- SNDRV_PCM_ACCESS_RW_INTERLEAVED);
- param_set_mask(&params, SNDRV_PCM_HW_PARAM_FORMAT,
- SNDRV_PCM_FORMAT_S16_LE);
- param_set_mask(&params, SNDRV_PCM_HW_PARAM_SUBFORMAT,
- SNDRV_PCM_SUBFORMAT_STD);
- param_set_min(&params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, period_sz);
- param_set_int(&params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS, 16);
- param_set_int(&params, SNDRV_PCM_HW_PARAM_FRAME_BITS,
- (flags & PCM_MONO) ? 16 : 32);
- param_set_int(&params, SNDRV_PCM_HW_PARAM_CHANNELS,
- (flags & PCM_MONO) ? 1 : 2);
- param_set_int(&params, SNDRV_PCM_HW_PARAM_PERIODS, period_cnt);
- param_set_int(&params, SNDRV_PCM_HW_PARAM_RATE, 44100);
-
- if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_HW_PARAMS, &params)) {
- oops(pcm, errno, "cannot set hw params");
- goto fail;
- }
- param_dump(&params);
-
- memset(&sparams, 0, sizeof(sparams));
- sparams.tstamp_mode = SNDRV_PCM_TSTAMP_NONE;
- sparams.period_step = 1;
- sparams.avail_min = 1;
- sparams.start_threshold = period_cnt * period_sz;
- sparams.stop_threshold = period_cnt * period_sz;
- sparams.xfer_align = period_sz / 2; /* needed for old kernels */
- sparams.silence_size = 0;
- sparams.silence_threshold = 0;
-
- if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_SW_PARAMS, &sparams)) {
- oops(pcm, errno, "cannot set sw params");
- goto fail;
- }
-
- pcm->buffer_size = period_cnt * period_sz;
- pcm->underruns = 0;
- return pcm;
-
-fail:
- close(pcm->fd);
- pcm->fd = -1;
- return pcm;
-}
-
-int pcm_ready(struct pcm *pcm)
-{
- return pcm->fd >= 0;
-}
diff --git a/libaudio/amix.c b/libaudio/amix.c
deleted file mode 100644
index d978caa..0000000
--- a/libaudio/amix.c
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
-** Copyright 2010, The Android Open-Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <ctype.h>
-
-#include "alsa_audio.h"
-
-
-struct mixer_ctl *get_ctl(struct mixer *mixer, char *name)
-{
- char *p;
- unsigned idx = 0;
-
- if (isdigit(name[0]))
- return mixer_get_nth_control(mixer, atoi(name) - 1);
-
- p = strrchr(name, '#');
- if (p) {
- *p++ = 0;
- idx = atoi(p);
- }
-
- return mixer_get_control(mixer, name, idx);
-}
-
-int main(int argc, char **argv)
-{
- struct mixer *mixer;
- struct mixer_ctl *ctl;
- int r;
-
- mixer = mixer_open();
- if (!mixer)
- return -1;
-
- if (argc == 1) {
- mixer_dump(mixer);
- return 0;
- }
-
- ctl = get_ctl(mixer, argv[1]);
- argc -= 2;
- argv += 2;
-
- if (!ctl) {
- fprintf(stderr,"can't find control\n");
- return -1;
- }
-
- if (argc) {
- if (isdigit(argv[0][0]))
- r = mixer_ctl_set(ctl, atoi(argv[0]));
- else
- r = mixer_ctl_select(ctl, argv[0]);
- if (r)
- fprintf(stderr,"oops: %s\n", strerror(errno));
- } else {
- mixer_ctl_print(ctl);
- }
- return 0;
-}
diff --git a/libaudio/aplay.c b/libaudio/aplay.c
deleted file mode 100644
index 0ac0ac0..0000000
--- a/libaudio/aplay.c
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
-** Copyright 2010, The Android Open-Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <stdint.h>
-#include <string.h>
-
-#include "alsa_audio.h"
-
-#define ID_RIFF 0x46464952
-#define ID_WAVE 0x45564157
-#define ID_FMT 0x20746d66
-#define ID_DATA 0x61746164
-
-#define FORMAT_PCM 1
-
-struct wav_header {
- uint32_t riff_id;
- uint32_t riff_sz;
- uint32_t riff_fmt;
- uint32_t fmt_id;
- uint32_t fmt_sz;
- uint16_t audio_format;
- uint16_t num_channels;
- uint32_t sample_rate;
- uint32_t byte_rate; /* sample_rate * num_channels * bps / 8 */
- uint16_t block_align; /* num_channels * bps / 8 */
- uint16_t bits_per_sample;
- uint32_t data_id;
- uint32_t data_sz;
-};
-
-int play_file(unsigned rate, unsigned channels, int fd, unsigned count)
-{
- struct pcm *pcm;
- struct mixer *mixer;
- struct pcm_ctl *ctl = NULL;
- unsigned bufsize;
- char *data;
- unsigned flags = PCM_OUT;
-
- if (channels == 1)
- flags |= PCM_MONO;
- else
- flags |= PCM_STEREO;
-
- pcm = pcm_open(flags);
- if (!pcm_ready(pcm)) {
- pcm_close(pcm);
- return -1;
- }
-
- mixer = mixer_open();
- if (mixer)
- ctl = mixer_get_control(mixer,"Playback Path", 0);
-
- bufsize = pcm_buffer_size(pcm);
- data = malloc(bufsize);
- if (!data) {
- fprintf(stderr,"could not allocate %d bytes\n", count);
- return -1;
- }
-
- while (read(fd, data, bufsize) == bufsize) {
- if (pcm_write(pcm, data, bufsize))
- break;
-
- /* HACK: remove */
- if (ctl) {
- //mixer_ctl_select(ctl, "SPK");
- ctl = 0;
- }
- }
- pcm_close(pcm);
- return 0;
-}
-
-int play_wav(const char *fn)
-{
- struct wav_header hdr;
- unsigned rate, channels;
- int fd;
- fd = open(fn, O_RDONLY);
- if (fd < 0) {
- fprintf(stderr, "aplay: cannot open '%s'\n", fn);
- return -1;
- }
- if (read(fd, &hdr, sizeof(hdr)) != sizeof(hdr)) {
- fprintf(stderr, "aplay: cannot read header\n");
- return -1;
- }
- fprintf(stderr,"aplay: %d ch, %d hz, %d bit, %s\n",
- hdr.num_channels, hdr.sample_rate, hdr.bits_per_sample,
- hdr.audio_format == FORMAT_PCM ? "PCM" : "unknown");
-
- if ((hdr.riff_id != ID_RIFF) ||
- (hdr.riff_fmt != ID_WAVE) ||
- (hdr.fmt_id != ID_FMT)) {
- fprintf(stderr, "aplay: '%s' is not a riff/wave file\n", fn);
- return -1;
- }
- if ((hdr.audio_format != FORMAT_PCM) ||
- (hdr.fmt_sz != 16)) {
- fprintf(stderr, "aplay: '%s' is not pcm format\n", fn);
- return -1;
- }
- if (hdr.bits_per_sample != 16) {
- fprintf(stderr, "aplay: '%s' is not 16bit per sample\n", fn);
- return -1;
- }
-
- return play_file(hdr.sample_rate, hdr.num_channels, fd, hdr.data_sz);
-}
-
-int main(int argc, char **argv)
-{
- if (argc != 2) {
- fprintf(stderr,"usage: aplay <file>\n");
- return -1;
- }
-
- return play_wav(argv[1]);
-}
-
diff --git a/libaudio/arec.c b/libaudio/arec.c
deleted file mode 100644
index b1e9eda..0000000
--- a/libaudio/arec.c
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
-** Copyright 2010, The Android Open-Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <stdint.h>
-#include <string.h>
-
-#include "alsa_audio.h"
-
-#define ID_RIFF 0x46464952
-#define ID_WAVE 0x45564157
-#define ID_FMT 0x20746d66
-#define ID_DATA 0x61746164
-
-#define FORMAT_PCM 1
-
-struct wav_header {
- uint32_t riff_id;
- uint32_t riff_sz;
- uint32_t riff_fmt;
- uint32_t fmt_id;
- uint32_t fmt_sz;
- uint16_t audio_format;
- uint16_t num_channels;
- uint32_t sample_rate;
- uint32_t byte_rate; /* sample_rate * num_channels * bps / 8 */
- uint16_t block_align; /* num_channels * bps / 8 */
- uint16_t bits_per_sample;
- uint32_t data_id;
- uint32_t data_sz;
-};
-
-int record_file(unsigned rate, unsigned channels, int fd, unsigned count)
-{
- struct pcm *pcm;
- unsigned avail, xfer, bufsize;
- char *data, *next;
- int r;
-
- pcm = pcm_open(PCM_IN|PCM_MONO);
- if (!pcm_ready(pcm)) {
- pcm_close(pcm);
- goto fail;
- }
-
- bufsize = pcm_buffer_size(pcm);
-
- data = malloc(bufsize);
- if (!data) {
- fprintf(stderr,"could not allocate %d bytes\n", count);
- return -1;
- }
-
- while (!pcm_read(pcm, data, bufsize)) {
- if (write(fd, data, bufsize) != bufsize) {
- fprintf(stderr,"could not write %d bytes\n", bufsize);
- return -1;
- }
- }
-
- close(fd);
- pcm_close(pcm);
- return 0;
-
-fail:
- fprintf(stderr,"pcm error: %s\n", pcm_error(pcm));
- return -1;
-}
-
-int rec_wav(const char *fn)
-{
- struct wav_header hdr;
- unsigned rate, channels;
- int fd;
- fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, 0664);
- if (fd < 0) {
- fprintf(stderr, "arec: cannot open '%s'\n", fn);
- return -1;
- }
-
- hdr.riff_id = ID_RIFF;
- hdr.riff_fmt = ID_WAVE;
- hdr.fmt_id = ID_FMT;
- hdr.audio_format = FORMAT_PCM;
- hdr.fmt_sz = 16;
- hdr.bits_per_sample = 16;
- hdr.num_channels = 1;
- hdr.data_sz = 0;
- hdr.sample_rate = 44100;
-
- if (write(fd, &hdr, sizeof(hdr)) != sizeof(hdr)) {
- fprintf(stderr, "arec: cannot write header\n");
- return -1;
- }
- fprintf(stderr,"arec: %d ch, %d hz, %d bit, %s\n",
- hdr.num_channels, hdr.sample_rate, hdr.bits_per_sample,
- hdr.audio_format == FORMAT_PCM ? "PCM" : "unknown");
-
-
- return record_file(hdr.sample_rate, hdr.num_channels, fd, hdr.data_sz);
-}
-
-int main(int argc, char **argv)
-{
- if (argc != 2) {
- fprintf(stderr,"usage: arec <file>\n");
- return -1;
- }
-
- return rec_wav(argv[1]);
-}
-
diff --git a/libaudio/asound.h b/libaudio/asound.h
deleted file mode 100644
index 6a17f29..0000000
--- a/libaudio/asound.h
+++ /dev/null
@@ -1,814 +0,0 @@
-/****************************************************************************
- ****************************************************************************
- ***
- *** This header was automatically generated from a Linux kernel header
- *** of the same name, to make information necessary for userspace to
- *** call into the kernel available to libc. It contains only constants,
- *** structures, and macros generated from the original header, and thus,
- *** contains no copyrightable information.
- ***
- ****************************************************************************
- ****************************************************************************/
-#ifndef __SOUND_ASOUND_H
-#define __SOUND_ASOUND_H
-
-#include <linux/types.h>
-
-#define SNDRV_PROTOCOL_VERSION(major, minor, subminor) (((major)<<16)|((minor)<<8)|(subminor))
-#define SNDRV_PROTOCOL_MAJOR(version) (((version)>>16)&0xffff)
-#define SNDRV_PROTOCOL_MINOR(version) (((version)>>8)&0xff)
-#define SNDRV_PROTOCOL_MICRO(version) ((version)&0xff)
-#define SNDRV_PROTOCOL_INCOMPATIBLE(kversion, uversion) (SNDRV_PROTOCOL_MAJOR(kversion) != SNDRV_PROTOCOL_MAJOR(uversion) || (SNDRV_PROTOCOL_MAJOR(kversion) == SNDRV_PROTOCOL_MAJOR(uversion) && SNDRV_PROTOCOL_MINOR(kversion) != SNDRV_PROTOCOL_MINOR(uversion)))
-
-struct snd_aes_iec958 {
- unsigned char status[24];
- unsigned char subcode[147];
- unsigned char pad;
- unsigned char dig_subframe[4];
-};
-
-#define SNDRV_HWDEP_VERSION SNDRV_PROTOCOL_VERSION(1, 0, 1)
-
-enum {
- SNDRV_HWDEP_IFACE_OPL2 = 0,
- SNDRV_HWDEP_IFACE_OPL3,
- SNDRV_HWDEP_IFACE_OPL4,
- SNDRV_HWDEP_IFACE_SB16CSP,
- SNDRV_HWDEP_IFACE_EMU10K1,
- SNDRV_HWDEP_IFACE_YSS225,
- SNDRV_HWDEP_IFACE_ICS2115,
- SNDRV_HWDEP_IFACE_SSCAPE,
- SNDRV_HWDEP_IFACE_VX,
- SNDRV_HWDEP_IFACE_MIXART,
- SNDRV_HWDEP_IFACE_USX2Y,
- SNDRV_HWDEP_IFACE_EMUX_WAVETABLE,
- SNDRV_HWDEP_IFACE_BLUETOOTH,
- SNDRV_HWDEP_IFACE_USX2Y_PCM,
- SNDRV_HWDEP_IFACE_PCXHR,
- SNDRV_HWDEP_IFACE_SB_RC,
- SNDRV_HWDEP_IFACE_HDA,
- SNDRV_HWDEP_IFACE_USB_STREAM,
-
- SNDRV_HWDEP_IFACE_LAST = SNDRV_HWDEP_IFACE_USB_STREAM
-};
-
-struct snd_hwdep_info {
- unsigned int device;
- int card;
- unsigned char id[64];
- unsigned char name[80];
- int iface;
- unsigned char reserved[64];
-};
-
-struct snd_hwdep_dsp_status {
- unsigned int version;
- unsigned char id[32];
- unsigned int num_dsps;
- unsigned int dsp_loaded;
- unsigned int chip_ready;
- unsigned char reserved[16];
-};
-
-struct snd_hwdep_dsp_image {
- unsigned int index;
- unsigned char name[64];
- unsigned char __user *image;
- size_t length;
- unsigned long driver_data;
-};
-
-#define SNDRV_HWDEP_IOCTL_PVERSION _IOR ('H', 0x00, int)
-#define SNDRV_HWDEP_IOCTL_INFO _IOR ('H', 0x01, struct snd_hwdep_info)
-#define SNDRV_HWDEP_IOCTL_DSP_STATUS _IOR('H', 0x02, struct snd_hwdep_dsp_status)
-#define SNDRV_HWDEP_IOCTL_DSP_LOAD _IOW('H', 0x03, struct snd_hwdep_dsp_image)
-
-#define SNDRV_PCM_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 10)
-
-typedef unsigned long snd_pcm_uframes_t;
-typedef signed long snd_pcm_sframes_t;
-
-enum {
- SNDRV_PCM_CLASS_GENERIC = 0,
- SNDRV_PCM_CLASS_MULTI,
- SNDRV_PCM_CLASS_MODEM,
- SNDRV_PCM_CLASS_DIGITIZER,
-
- SNDRV_PCM_CLASS_LAST = SNDRV_PCM_CLASS_DIGITIZER,
-};
-
-enum {
- SNDRV_PCM_SUBCLASS_GENERIC_MIX = 0,
- SNDRV_PCM_SUBCLASS_MULTI_MIX,
-
- SNDRV_PCM_SUBCLASS_LAST = SNDRV_PCM_SUBCLASS_MULTI_MIX,
-};
-
-enum {
- SNDRV_PCM_STREAM_PLAYBACK = 0,
- SNDRV_PCM_STREAM_CAPTURE,
- SNDRV_PCM_STREAM_LAST = SNDRV_PCM_STREAM_CAPTURE,
-};
-
-typedef int __bitwise snd_pcm_access_t;
-#define SNDRV_PCM_ACCESS_MMAP_INTERLEAVED ((__force snd_pcm_access_t) 0)
-#define SNDRV_PCM_ACCESS_MMAP_NONINTERLEAVED ((__force snd_pcm_access_t) 1)
-#define SNDRV_PCM_ACCESS_MMAP_COMPLEX ((__force snd_pcm_access_t) 2)
-#define SNDRV_PCM_ACCESS_RW_INTERLEAVED ((__force snd_pcm_access_t) 3)
-#define SNDRV_PCM_ACCESS_RW_NONINTERLEAVED ((__force snd_pcm_access_t) 4)
-#define SNDRV_PCM_ACCESS_LAST SNDRV_PCM_ACCESS_RW_NONINTERLEAVED
-
-typedef int __bitwise snd_pcm_format_t;
-#define SNDRV_PCM_FORMAT_S8 ((__force snd_pcm_format_t) 0)
-#define SNDRV_PCM_FORMAT_U8 ((__force snd_pcm_format_t) 1)
-#define SNDRV_PCM_FORMAT_S16_LE ((__force snd_pcm_format_t) 2)
-#define SNDRV_PCM_FORMAT_S16_BE ((__force snd_pcm_format_t) 3)
-#define SNDRV_PCM_FORMAT_U16_LE ((__force snd_pcm_format_t) 4)
-#define SNDRV_PCM_FORMAT_U16_BE ((__force snd_pcm_format_t) 5)
-#define SNDRV_PCM_FORMAT_S24_LE ((__force snd_pcm_format_t) 6)
-#define SNDRV_PCM_FORMAT_S24_BE ((__force snd_pcm_format_t) 7)
-#define SNDRV_PCM_FORMAT_U24_LE ((__force snd_pcm_format_t) 8)
-#define SNDRV_PCM_FORMAT_U24_BE ((__force snd_pcm_format_t) 9)
-#define SNDRV_PCM_FORMAT_S32_LE ((__force snd_pcm_format_t) 10)
-#define SNDRV_PCM_FORMAT_S32_BE ((__force snd_pcm_format_t) 11)
-#define SNDRV_PCM_FORMAT_U32_LE ((__force snd_pcm_format_t) 12)
-#define SNDRV_PCM_FORMAT_U32_BE ((__force snd_pcm_format_t) 13)
-#define SNDRV_PCM_FORMAT_FLOAT_LE ((__force snd_pcm_format_t) 14)
-#define SNDRV_PCM_FORMAT_FLOAT_BE ((__force snd_pcm_format_t) 15)
-#define SNDRV_PCM_FORMAT_FLOAT64_LE ((__force snd_pcm_format_t) 16)
-#define SNDRV_PCM_FORMAT_FLOAT64_BE ((__force snd_pcm_format_t) 17)
-#define SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE ((__force snd_pcm_format_t) 18)
-#define SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE ((__force snd_pcm_format_t) 19)
-#define SNDRV_PCM_FORMAT_MU_LAW ((__force snd_pcm_format_t) 20)
-#define SNDRV_PCM_FORMAT_A_LAW ((__force snd_pcm_format_t) 21)
-#define SNDRV_PCM_FORMAT_IMA_ADPCM ((__force snd_pcm_format_t) 22)
-#define SNDRV_PCM_FORMAT_MPEG ((__force snd_pcm_format_t) 23)
-#define SNDRV_PCM_FORMAT_GSM ((__force snd_pcm_format_t) 24)
-#define SNDRV_PCM_FORMAT_SPECIAL ((__force snd_pcm_format_t) 31)
-#define SNDRV_PCM_FORMAT_S24_3LE ((__force snd_pcm_format_t) 32)
-#define SNDRV_PCM_FORMAT_S24_3BE ((__force snd_pcm_format_t) 33)
-#define SNDRV_PCM_FORMAT_U24_3LE ((__force snd_pcm_format_t) 34)
-#define SNDRV_PCM_FORMAT_U24_3BE ((__force snd_pcm_format_t) 35)
-#define SNDRV_PCM_FORMAT_S20_3LE ((__force snd_pcm_format_t) 36)
-#define SNDRV_PCM_FORMAT_S20_3BE ((__force snd_pcm_format_t) 37)
-#define SNDRV_PCM_FORMAT_U20_3LE ((__force snd_pcm_format_t) 38)
-#define SNDRV_PCM_FORMAT_U20_3BE ((__force snd_pcm_format_t) 39)
-#define SNDRV_PCM_FORMAT_S18_3LE ((__force snd_pcm_format_t) 40)
-#define SNDRV_PCM_FORMAT_S18_3BE ((__force snd_pcm_format_t) 41)
-#define SNDRV_PCM_FORMAT_U18_3LE ((__force snd_pcm_format_t) 42)
-#define SNDRV_PCM_FORMAT_U18_3BE ((__force snd_pcm_format_t) 43)
-#define SNDRV_PCM_FORMAT_LAST SNDRV_PCM_FORMAT_U18_3BE
-
-#ifdef SNDRV_LITTLE_ENDIAN
-#define SNDRV_PCM_FORMAT_S16 SNDRV_PCM_FORMAT_S16_LE
-#define SNDRV_PCM_FORMAT_U16 SNDRV_PCM_FORMAT_U16_LE
-#define SNDRV_PCM_FORMAT_S24 SNDRV_PCM_FORMAT_S24_LE
-#define SNDRV_PCM_FORMAT_U24 SNDRV_PCM_FORMAT_U24_LE
-#define SNDRV_PCM_FORMAT_S32 SNDRV_PCM_FORMAT_S32_LE
-#define SNDRV_PCM_FORMAT_U32 SNDRV_PCM_FORMAT_U32_LE
-#define SNDRV_PCM_FORMAT_FLOAT SNDRV_PCM_FORMAT_FLOAT_LE
-#define SNDRV_PCM_FORMAT_FLOAT64 SNDRV_PCM_FORMAT_FLOAT64_LE
-#define SNDRV_PCM_FORMAT_IEC958_SUBFRAME SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE
-#endif
-#ifdef SNDRV_BIG_ENDIAN
-#define SNDRV_PCM_FORMAT_S16 SNDRV_PCM_FORMAT_S16_BE
-#define SNDRV_PCM_FORMAT_U16 SNDRV_PCM_FORMAT_U16_BE
-#define SNDRV_PCM_FORMAT_S24 SNDRV_PCM_FORMAT_S24_BE
-#define SNDRV_PCM_FORMAT_U24 SNDRV_PCM_FORMAT_U24_BE
-#define SNDRV_PCM_FORMAT_S32 SNDRV_PCM_FORMAT_S32_BE
-#define SNDRV_PCM_FORMAT_U32 SNDRV_PCM_FORMAT_U32_BE
-#define SNDRV_PCM_FORMAT_FLOAT SNDRV_PCM_FORMAT_FLOAT_BE
-#define SNDRV_PCM_FORMAT_FLOAT64 SNDRV_PCM_FORMAT_FLOAT64_BE
-#define SNDRV_PCM_FORMAT_IEC958_SUBFRAME SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE
-#endif
-
-typedef int __bitwise snd_pcm_subformat_t;
-#define SNDRV_PCM_SUBFORMAT_STD ((__force snd_pcm_subformat_t) 0)
-#define SNDRV_PCM_SUBFORMAT_LAST SNDRV_PCM_SUBFORMAT_STD
-
-#define SNDRV_PCM_INFO_MMAP 0x00000001
-#define SNDRV_PCM_INFO_MMAP_VALID 0x00000002
-#define SNDRV_PCM_INFO_DOUBLE 0x00000004
-#define SNDRV_PCM_INFO_BATCH 0x00000010
-#define SNDRV_PCM_INFO_INTERLEAVED 0x00000100
-#define SNDRV_PCM_INFO_NONINTERLEAVED 0x00000200
-#define SNDRV_PCM_INFO_COMPLEX 0x00000400
-#define SNDRV_PCM_INFO_BLOCK_TRANSFER 0x00010000
-#define SNDRV_PCM_INFO_OVERRANGE 0x00020000
-#define SNDRV_PCM_INFO_RESUME 0x00040000
-#define SNDRV_PCM_INFO_PAUSE 0x00080000
-#define SNDRV_PCM_INFO_HALF_DUPLEX 0x00100000
-#define SNDRV_PCM_INFO_JOINT_DUPLEX 0x00200000
-#define SNDRV_PCM_INFO_SYNC_START 0x00400000
-#define SNDRV_PCM_INFO_FIFO_IN_FRAMES 0x80000000
-
-typedef int __bitwise snd_pcm_state_t;
-#define SNDRV_PCM_STATE_OPEN ((__force snd_pcm_state_t) 0)
-#define SNDRV_PCM_STATE_SETUP ((__force snd_pcm_state_t) 1)
-#define SNDRV_PCM_STATE_PREPARED ((__force snd_pcm_state_t) 2)
-#define SNDRV_PCM_STATE_RUNNING ((__force snd_pcm_state_t) 3)
-#define SNDRV_PCM_STATE_XRUN ((__force snd_pcm_state_t) 4)
-#define SNDRV_PCM_STATE_DRAINING ((__force snd_pcm_state_t) 5)
-#define SNDRV_PCM_STATE_PAUSED ((__force snd_pcm_state_t) 6)
-#define SNDRV_PCM_STATE_SUSPENDED ((__force snd_pcm_state_t) 7)
-#define SNDRV_PCM_STATE_DISCONNECTED ((__force snd_pcm_state_t) 8)
-#define SNDRV_PCM_STATE_LAST SNDRV_PCM_STATE_DISCONNECTED
-
-enum {
- SNDRV_PCM_MMAP_OFFSET_DATA = 0x00000000,
- SNDRV_PCM_MMAP_OFFSET_STATUS = 0x80000000,
- SNDRV_PCM_MMAP_OFFSET_CONTROL = 0x81000000,
-};
-
-union snd_pcm_sync_id {
- unsigned char id[16];
- unsigned short id16[8];
- unsigned int id32[4];
-};
-
-struct snd_pcm_info {
- unsigned int device;
- unsigned int subdevice;
- int stream;
- int card;
- unsigned char id[64];
- unsigned char name[80];
- unsigned char subname[32];
- int dev_class;
- int dev_subclass;
- unsigned int subdevices_count;
- unsigned int subdevices_avail;
- union snd_pcm_sync_id sync;
- unsigned char reserved[64];
-};
-
-typedef int snd_pcm_hw_param_t;
-#define SNDRV_PCM_HW_PARAM_ACCESS 0
-#define SNDRV_PCM_HW_PARAM_FORMAT 1
-#define SNDRV_PCM_HW_PARAM_SUBFORMAT 2
-#define SNDRV_PCM_HW_PARAM_FIRST_MASK SNDRV_PCM_HW_PARAM_ACCESS
-#define SNDRV_PCM_HW_PARAM_LAST_MASK SNDRV_PCM_HW_PARAM_SUBFORMAT
-
-#define SNDRV_PCM_HW_PARAM_SAMPLE_BITS 8
-#define SNDRV_PCM_HW_PARAM_FRAME_BITS 9
-#define SNDRV_PCM_HW_PARAM_CHANNELS 10
-#define SNDRV_PCM_HW_PARAM_RATE 11
-#define SNDRV_PCM_HW_PARAM_PERIOD_TIME 12
-#define SNDRV_PCM_HW_PARAM_PERIOD_SIZE 13
-#define SNDRV_PCM_HW_PARAM_PERIOD_BYTES 14
-#define SNDRV_PCM_HW_PARAM_PERIODS 15
-#define SNDRV_PCM_HW_PARAM_BUFFER_TIME 16
-#define SNDRV_PCM_HW_PARAM_BUFFER_SIZE 17
-#define SNDRV_PCM_HW_PARAM_BUFFER_BYTES 18
-#define SNDRV_PCM_HW_PARAM_TICK_TIME 19
-#define SNDRV_PCM_HW_PARAM_FIRST_INTERVAL SNDRV_PCM_HW_PARAM_SAMPLE_BITS
-#define SNDRV_PCM_HW_PARAM_LAST_INTERVAL SNDRV_PCM_HW_PARAM_TICK_TIME
-
-#define SNDRV_PCM_HW_PARAMS_NORESAMPLE (1<<0)
-
-struct snd_interval {
- unsigned int min, max;
- unsigned int openmin:1,
- openmax:1,
- integer:1,
- empty:1;
-};
-
-#define SNDRV_MASK_MAX 256
-
-struct snd_mask {
- __u32 bits[(SNDRV_MASK_MAX+31)/32];
-};
-
-struct snd_pcm_hw_params {
- unsigned int flags;
- struct snd_mask masks[SNDRV_PCM_HW_PARAM_LAST_MASK -
- SNDRV_PCM_HW_PARAM_FIRST_MASK + 1];
- struct snd_mask mres[5];
- struct snd_interval intervals[SNDRV_PCM_HW_PARAM_LAST_INTERVAL -
- SNDRV_PCM_HW_PARAM_FIRST_INTERVAL + 1];
- struct snd_interval ires[9];
- unsigned int rmask;
- unsigned int cmask;
- unsigned int info;
- unsigned int msbits;
- unsigned int rate_num;
- unsigned int rate_den;
- snd_pcm_uframes_t fifo_size;
- unsigned char reserved[64];
-};
-
-enum {
- SNDRV_PCM_TSTAMP_NONE = 0,
- SNDRV_PCM_TSTAMP_ENABLE,
- SNDRV_PCM_TSTAMP_LAST = SNDRV_PCM_TSTAMP_ENABLE,
-};
-
-struct snd_pcm_sw_params {
- int tstamp_mode;
- unsigned int period_step;
- unsigned int sleep_min;
- snd_pcm_uframes_t avail_min;
- snd_pcm_uframes_t xfer_align;
- snd_pcm_uframes_t start_threshold;
- snd_pcm_uframes_t stop_threshold;
- snd_pcm_uframes_t silence_threshold;
- snd_pcm_uframes_t silence_size;
- snd_pcm_uframes_t boundary;
- unsigned char reserved[64];
-};
-
-struct snd_pcm_channel_info {
- unsigned int channel;
- __kernel_off_t offset;
- unsigned int first;
- unsigned int step;
-};
-
-struct snd_pcm_status {
- snd_pcm_state_t state;
- struct timespec trigger_tstamp;
- struct timespec tstamp;
- snd_pcm_uframes_t appl_ptr;
- snd_pcm_uframes_t hw_ptr;
- snd_pcm_sframes_t delay;
- snd_pcm_uframes_t avail;
- snd_pcm_uframes_t avail_max;
- snd_pcm_uframes_t overrange;
- snd_pcm_state_t suspended_state;
- unsigned char reserved[60];
-};
-
-struct snd_pcm_mmap_status {
- snd_pcm_state_t state;
- int pad1;
- snd_pcm_uframes_t hw_ptr;
- struct timespec tstamp;
- snd_pcm_state_t suspended_state;
-};
-
-struct snd_pcm_mmap_control {
- snd_pcm_uframes_t appl_ptr;
- snd_pcm_uframes_t avail_min;
-};
-
-#define SNDRV_PCM_SYNC_PTR_HWSYNC (1<<0)
-#define SNDRV_PCM_SYNC_PTR_APPL (1<<1)
-#define SNDRV_PCM_SYNC_PTR_AVAIL_MIN (1<<2)
-
-struct snd_pcm_sync_ptr {
- unsigned int flags;
- union {
- struct snd_pcm_mmap_status status;
- unsigned char reserved[64];
- } s;
- union {
- struct snd_pcm_mmap_control control;
- unsigned char reserved[64];
- } c;
-};
-
-struct snd_xferi {
- snd_pcm_sframes_t result;
- void __user *buf;
- snd_pcm_uframes_t frames;
-};
-
-struct snd_xfern {
- snd_pcm_sframes_t result;
- void __user * __user *bufs;
- snd_pcm_uframes_t frames;
-};
-
-enum {
- SNDRV_PCM_TSTAMP_TYPE_GETTIMEOFDAY = 0,
- SNDRV_PCM_TSTAMP_TYPE_MONOTONIC,
- SNDRV_PCM_TSTAMP_TYPE_LAST = SNDRV_PCM_TSTAMP_TYPE_MONOTONIC,
-};
-
-#define SNDRV_PCM_IOCTL_PVERSION _IOR('A', 0x00, int)
-#define SNDRV_PCM_IOCTL_INFO _IOR('A', 0x01, struct snd_pcm_info)
-#define SNDRV_PCM_IOCTL_TSTAMP _IOW('A', 0x02, int)
-#define SNDRV_PCM_IOCTL_TTSTAMP _IOW('A', 0x03, int)
-#define SNDRV_PCM_IOCTL_HW_REFINE _IOWR('A', 0x10, struct snd_pcm_hw_params)
-#define SNDRV_PCM_IOCTL_HW_PARAMS _IOWR('A', 0x11, struct snd_pcm_hw_params)
-#define SNDRV_PCM_IOCTL_HW_FREE _IO('A', 0x12)
-#define SNDRV_PCM_IOCTL_SW_PARAMS _IOWR('A', 0x13, struct snd_pcm_sw_params)
-#define SNDRV_PCM_IOCTL_STATUS _IOR('A', 0x20, struct snd_pcm_status)
-#define SNDRV_PCM_IOCTL_DELAY _IOR('A', 0x21, snd_pcm_sframes_t)
-#define SNDRV_PCM_IOCTL_HWSYNC _IO('A', 0x22)
-#define SNDRV_PCM_IOCTL_SYNC_PTR _IOWR('A', 0x23, struct snd_pcm_sync_ptr)
-#define SNDRV_PCM_IOCTL_CHANNEL_INFO _IOR('A', 0x32, struct snd_pcm_channel_info)
-#define SNDRV_PCM_IOCTL_PREPARE _IO('A', 0x40)
-#define SNDRV_PCM_IOCTL_RESET _IO('A', 0x41)
-#define SNDRV_PCM_IOCTL_START _IO('A', 0x42)
-#define SNDRV_PCM_IOCTL_DROP _IO('A', 0x43)
-#define SNDRV_PCM_IOCTL_DRAIN _IO('A', 0x44)
-#define SNDRV_PCM_IOCTL_PAUSE _IOW('A', 0x45, int)
-#define SNDRV_PCM_IOCTL_REWIND _IOW('A', 0x46, snd_pcm_uframes_t)
-#define SNDRV_PCM_IOCTL_RESUME _IO('A', 0x47)
-#define SNDRV_PCM_IOCTL_XRUN _IO('A', 0x48)
-#define SNDRV_PCM_IOCTL_FORWARD _IOW('A', 0x49, snd_pcm_uframes_t)
-#define SNDRV_PCM_IOCTL_WRITEI_FRAMES _IOW('A', 0x50, struct snd_xferi)
-#define SNDRV_PCM_IOCTL_READI_FRAMES _IOR('A', 0x51, struct snd_xferi)
-#define SNDRV_PCM_IOCTL_WRITEN_FRAMES _IOW('A', 0x52, struct snd_xfern)
-#define SNDRV_PCM_IOCTL_READN_FRAMES _IOR('A', 0x53, struct snd_xfern)
-#define SNDRV_PCM_IOCTL_LINK _IOW('A', 0x60, int)
-#define SNDRV_PCM_IOCTL_UNLINK _IO('A', 0x61)
-
-#define SNDRV_RAWMIDI_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 0)
-
-enum {
- SNDRV_RAWMIDI_STREAM_OUTPUT = 0,
- SNDRV_RAWMIDI_STREAM_INPUT,
- SNDRV_RAWMIDI_STREAM_LAST = SNDRV_RAWMIDI_STREAM_INPUT,
-};
-
-#define SNDRV_RAWMIDI_INFO_OUTPUT 0x00000001
-#define SNDRV_RAWMIDI_INFO_INPUT 0x00000002
-#define SNDRV_RAWMIDI_INFO_DUPLEX 0x00000004
-
-struct snd_rawmidi_info {
- unsigned int device;
- unsigned int subdevice;
- int stream;
- int card;
- unsigned int flags;
- unsigned char id[64];
- unsigned char name[80];
- unsigned char subname[32];
- unsigned int subdevices_count;
- unsigned int subdevices_avail;
- unsigned char reserved[64];
-};
-
-struct snd_rawmidi_params {
- int stream;
- size_t buffer_size;
- size_t avail_min;
- unsigned int no_active_sensing: 1;
- unsigned char reserved[16];
-};
-
-struct snd_rawmidi_status {
- int stream;
- struct timespec tstamp;
- size_t avail;
- size_t xruns;
- unsigned char reserved[16];
-};
-
-#define SNDRV_RAWMIDI_IOCTL_PVERSION _IOR('W', 0x00, int)
-#define SNDRV_RAWMIDI_IOCTL_INFO _IOR('W', 0x01, struct snd_rawmidi_info)
-#define SNDRV_RAWMIDI_IOCTL_PARAMS _IOWR('W', 0x10, struct snd_rawmidi_params)
-#define SNDRV_RAWMIDI_IOCTL_STATUS _IOWR('W', 0x20, struct snd_rawmidi_status)
-#define SNDRV_RAWMIDI_IOCTL_DROP _IOW('W', 0x30, int)
-#define SNDRV_RAWMIDI_IOCTL_DRAIN _IOW('W', 0x31, int)
-
-#define SNDRV_TIMER_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 6)
-
-enum {
- SNDRV_TIMER_CLASS_NONE = -1,
- SNDRV_TIMER_CLASS_SLAVE = 0,
- SNDRV_TIMER_CLASS_GLOBAL,
- SNDRV_TIMER_CLASS_CARD,
- SNDRV_TIMER_CLASS_PCM,
- SNDRV_TIMER_CLASS_LAST = SNDRV_TIMER_CLASS_PCM,
-};
-
-enum {
- SNDRV_TIMER_SCLASS_NONE = 0,
- SNDRV_TIMER_SCLASS_APPLICATION,
- SNDRV_TIMER_SCLASS_SEQUENCER,
- SNDRV_TIMER_SCLASS_OSS_SEQUENCER,
- SNDRV_TIMER_SCLASS_LAST = SNDRV_TIMER_SCLASS_OSS_SEQUENCER,
-};
-
-#define SNDRV_TIMER_GLOBAL_SYSTEM 0
-#define SNDRV_TIMER_GLOBAL_RTC 1
-#define SNDRV_TIMER_GLOBAL_HPET 2
-#define SNDRV_TIMER_GLOBAL_HRTIMER 3
-
-#define SNDRV_TIMER_FLG_SLAVE (1<<0)
-
-struct snd_timer_id {
- int dev_class;
- int dev_sclass;
- int card;
- int device;
- int subdevice;
-};
-
-struct snd_timer_ginfo {
- struct snd_timer_id tid;
- unsigned int flags;
- int card;
- unsigned char id[64];
- unsigned char name[80];
- unsigned long reserved0;
- unsigned long resolution;
- unsigned long resolution_min;
- unsigned long resolution_max;
- unsigned int clients;
- unsigned char reserved[32];
-};
-
-struct snd_timer_gparams {
- struct snd_timer_id tid;
- unsigned long period_num;
- unsigned long period_den;
- unsigned char reserved[32];
-};
-
-struct snd_timer_gstatus {
- struct snd_timer_id tid;
- unsigned long resolution;
- unsigned long resolution_num;
- unsigned long resolution_den;
- unsigned char reserved[32];
-};
-
-struct snd_timer_select {
- struct snd_timer_id id;
- unsigned char reserved[32];
-};
-
-struct snd_timer_info {
- unsigned int flags;
- int card;
- unsigned char id[64];
- unsigned char name[80];
- unsigned long reserved0;
- unsigned long resolution;
- unsigned char reserved[64];
-};
-
-#define SNDRV_TIMER_PSFLG_AUTO (1<<0)
-#define SNDRV_TIMER_PSFLG_EXCLUSIVE (1<<1)
-#define SNDRV_TIMER_PSFLG_EARLY_EVENT (1<<2)
-
-struct snd_timer_params {
- unsigned int flags;
- unsigned int ticks;
- unsigned int queue_size;
- unsigned int reserved0;
- unsigned int filter;
- unsigned char reserved[60];
-};
-
-struct snd_timer_status {
- struct timespec tstamp;
- unsigned int resolution;
- unsigned int lost;
- unsigned int overrun;
- unsigned int queue;
- unsigned char reserved[64];
-};
-
-#define SNDRV_TIMER_IOCTL_PVERSION _IOR('T', 0x00, int)
-#define SNDRV_TIMER_IOCTL_NEXT_DEVICE _IOWR('T', 0x01, struct snd_timer_id)
-#define SNDRV_TIMER_IOCTL_TREAD _IOW('T', 0x02, int)
-#define SNDRV_TIMER_IOCTL_GINFO _IOWR('T', 0x03, struct snd_timer_ginfo)
-#define SNDRV_TIMER_IOCTL_GPARAMS _IOW('T', 0x04, struct snd_timer_gparams)
-#define SNDRV_TIMER_IOCTL_GSTATUS _IOWR('T', 0x05, struct snd_timer_gstatus)
-#define SNDRV_TIMER_IOCTL_SELECT _IOW('T', 0x10, struct snd_timer_select)
-#define SNDRV_TIMER_IOCTL_INFO _IOR('T', 0x11, struct snd_timer_info)
-#define SNDRV_TIMER_IOCTL_PARAMS _IOW('T', 0x12, struct snd_timer_params)
-#define SNDRV_TIMER_IOCTL_STATUS _IOR('T', 0x14, struct snd_timer_status)
-
-#define SNDRV_TIMER_IOCTL_START _IO('T', 0xa0)
-#define SNDRV_TIMER_IOCTL_STOP _IO('T', 0xa1)
-#define SNDRV_TIMER_IOCTL_CONTINUE _IO('T', 0xa2)
-#define SNDRV_TIMER_IOCTL_PAUSE _IO('T', 0xa3)
-
-struct snd_timer_read {
- unsigned int resolution;
- unsigned int ticks;
-};
-
-enum {
- SNDRV_TIMER_EVENT_RESOLUTION = 0,
- SNDRV_TIMER_EVENT_TICK,
- SNDRV_TIMER_EVENT_START,
- SNDRV_TIMER_EVENT_STOP,
- SNDRV_TIMER_EVENT_CONTINUE,
- SNDRV_TIMER_EVENT_PAUSE,
- SNDRV_TIMER_EVENT_EARLY,
- SNDRV_TIMER_EVENT_SUSPEND,
- SNDRV_TIMER_EVENT_RESUME,
-
- SNDRV_TIMER_EVENT_MSTART = SNDRV_TIMER_EVENT_START + 10,
- SNDRV_TIMER_EVENT_MSTOP = SNDRV_TIMER_EVENT_STOP + 10,
- SNDRV_TIMER_EVENT_MCONTINUE = SNDRV_TIMER_EVENT_CONTINUE + 10,
- SNDRV_TIMER_EVENT_MPAUSE = SNDRV_TIMER_EVENT_PAUSE + 10,
- SNDRV_TIMER_EVENT_MSUSPEND = SNDRV_TIMER_EVENT_SUSPEND + 10,
- SNDRV_TIMER_EVENT_MRESUME = SNDRV_TIMER_EVENT_RESUME + 10,
-};
-
-struct snd_timer_tread {
- int event;
- struct timespec tstamp;
- unsigned int val;
-};
-
-#define SNDRV_CTL_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 6)
-
-struct snd_ctl_card_info {
- int card;
- int pad;
- unsigned char id[16];
- unsigned char driver[16];
- unsigned char name[32];
- unsigned char longname[80];
- unsigned char reserved_[16];
- unsigned char mixername[80];
- unsigned char components[128];
-};
-
-typedef int __bitwise snd_ctl_elem_type_t;
-#define SNDRV_CTL_ELEM_TYPE_NONE ((__force snd_ctl_elem_type_t) 0)
-#define SNDRV_CTL_ELEM_TYPE_BOOLEAN ((__force snd_ctl_elem_type_t) 1)
-#define SNDRV_CTL_ELEM_TYPE_INTEGER ((__force snd_ctl_elem_type_t) 2)
-#define SNDRV_CTL_ELEM_TYPE_ENUMERATED ((__force snd_ctl_elem_type_t) 3)
-#define SNDRV_CTL_ELEM_TYPE_BYTES ((__force snd_ctl_elem_type_t) 4)
-#define SNDRV_CTL_ELEM_TYPE_IEC958 ((__force snd_ctl_elem_type_t) 5)
-#define SNDRV_CTL_ELEM_TYPE_INTEGER64 ((__force snd_ctl_elem_type_t) 6)
-#define SNDRV_CTL_ELEM_TYPE_LAST SNDRV_CTL_ELEM_TYPE_INTEGER64
-
-typedef int __bitwise snd_ctl_elem_iface_t;
-#define SNDRV_CTL_ELEM_IFACE_CARD ((__force snd_ctl_elem_iface_t) 0)
-#define SNDRV_CTL_ELEM_IFACE_HWDEP ((__force snd_ctl_elem_iface_t) 1)
-#define SNDRV_CTL_ELEM_IFACE_MIXER ((__force snd_ctl_elem_iface_t) 2)
-#define SNDRV_CTL_ELEM_IFACE_PCM ((__force snd_ctl_elem_iface_t) 3)
-#define SNDRV_CTL_ELEM_IFACE_RAWMIDI ((__force snd_ctl_elem_iface_t) 4)
-#define SNDRV_CTL_ELEM_IFACE_TIMER ((__force snd_ctl_elem_iface_t) 5)
-#define SNDRV_CTL_ELEM_IFACE_SEQUENCER ((__force snd_ctl_elem_iface_t) 6)
-#define SNDRV_CTL_ELEM_IFACE_LAST SNDRV_CTL_ELEM_IFACE_SEQUENCER
-
-#define SNDRV_CTL_ELEM_ACCESS_READ (1<<0)
-#define SNDRV_CTL_ELEM_ACCESS_WRITE (1<<1)
-#define SNDRV_CTL_ELEM_ACCESS_READWRITE (SNDRV_CTL_ELEM_ACCESS_READ|SNDRV_CTL_ELEM_ACCESS_WRITE)
-#define SNDRV_CTL_ELEM_ACCESS_VOLATILE (1<<2)
-#define SNDRV_CTL_ELEM_ACCESS_TIMESTAMP (1<<3)
-#define SNDRV_CTL_ELEM_ACCESS_TLV_READ (1<<4)
-#define SNDRV_CTL_ELEM_ACCESS_TLV_WRITE (1<<5)
-#define SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE (SNDRV_CTL_ELEM_ACCESS_TLV_READ|SNDRV_CTL_ELEM_ACCESS_TLV_WRITE)
-#define SNDRV_CTL_ELEM_ACCESS_TLV_COMMAND (1<<6)
-#define SNDRV_CTL_ELEM_ACCESS_INACTIVE (1<<8)
-#define SNDRV_CTL_ELEM_ACCESS_LOCK (1<<9)
-#define SNDRV_CTL_ELEM_ACCESS_OWNER (1<<10)
-#define SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK (1<<28)
-#define SNDRV_CTL_ELEM_ACCESS_USER (1<<29)
-
-#define SNDRV_CTL_POWER_D0 0x0000
-#define SNDRV_CTL_POWER_D1 0x0100
-#define SNDRV_CTL_POWER_D2 0x0200
-#define SNDRV_CTL_POWER_D3 0x0300
-#define SNDRV_CTL_POWER_D3hot (SNDRV_CTL_POWER_D3|0x0000)
-#define SNDRV_CTL_POWER_D3cold (SNDRV_CTL_POWER_D3|0x0001)
-
-struct snd_ctl_elem_id {
- unsigned int numid;
- snd_ctl_elem_iface_t iface;
- unsigned int device;
- unsigned int subdevice;
- unsigned char name[44];
- unsigned int index;
-};
-
-struct snd_ctl_elem_list {
- unsigned int offset;
- unsigned int space;
- unsigned int used;
- unsigned int count;
- struct snd_ctl_elem_id __user *pids;
- unsigned char reserved[50];
-};
-
-struct snd_ctl_elem_info {
- struct snd_ctl_elem_id id;
- snd_ctl_elem_type_t type;
- unsigned int access;
- unsigned int count;
- __kernel_pid_t owner;
- union {
- struct {
- long min;
- long max;
- long step;
- } integer;
- struct {
- long long min;
- long long max;
- long long step;
- } integer64;
- struct {
- unsigned int items;
- unsigned int item;
- char name[64];
- } enumerated;
- unsigned char reserved[128];
- } value;
- union {
- unsigned short d[4];
- unsigned short *d_ptr;
- } dimen;
- unsigned char reserved[64-4*sizeof(unsigned short)];
-};
-
-struct snd_ctl_elem_value {
- struct snd_ctl_elem_id id;
- unsigned int indirect: 1;
- union {
- union {
- long value[128];
- long *value_ptr;
- } integer;
- union {
- long long value[64];
- long long *value_ptr;
- } integer64;
- union {
- unsigned int item[128];
- unsigned int *item_ptr;
- } enumerated;
- union {
- unsigned char data[512];
- unsigned char *data_ptr;
- } bytes;
- struct snd_aes_iec958 iec958;
- } value;
- struct timespec tstamp;
- unsigned char reserved[128-sizeof(struct timespec)];
-};
-
-struct snd_ctl_tlv {
- unsigned int numid;
- unsigned int length;
- unsigned int tlv[0];
-};
-
-#define SNDRV_CTL_IOCTL_PVERSION _IOR('U', 0x00, int)
-#define SNDRV_CTL_IOCTL_CARD_INFO _IOR('U', 0x01, struct snd_ctl_card_info)
-#define SNDRV_CTL_IOCTL_ELEM_LIST _IOWR('U', 0x10, struct snd_ctl_elem_list)
-#define SNDRV_CTL_IOCTL_ELEM_INFO _IOWR('U', 0x11, struct snd_ctl_elem_info)
-#define SNDRV_CTL_IOCTL_ELEM_READ _IOWR('U', 0x12, struct snd_ctl_elem_value)
-#define SNDRV_CTL_IOCTL_ELEM_WRITE _IOWR('U', 0x13, struct snd_ctl_elem_value)
-#define SNDRV_CTL_IOCTL_ELEM_LOCK _IOW('U', 0x14, struct snd_ctl_elem_id)
-#define SNDRV_CTL_IOCTL_ELEM_UNLOCK _IOW('U', 0x15, struct snd_ctl_elem_id)
-#define SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS _IOWR('U', 0x16, int)
-#define SNDRV_CTL_IOCTL_ELEM_ADD _IOWR('U', 0x17, struct snd_ctl_elem_info)
-#define SNDRV_CTL_IOCTL_ELEM_REPLACE _IOWR('U', 0x18, struct snd_ctl_elem_info)
-#define SNDRV_CTL_IOCTL_ELEM_REMOVE _IOWR('U', 0x19, struct snd_ctl_elem_id)
-#define SNDRV_CTL_IOCTL_TLV_READ _IOWR('U', 0x1a, struct snd_ctl_tlv)
-#define SNDRV_CTL_IOCTL_TLV_WRITE _IOWR('U', 0x1b, struct snd_ctl_tlv)
-#define SNDRV_CTL_IOCTL_TLV_COMMAND _IOWR('U', 0x1c, struct snd_ctl_tlv)
-#define SNDRV_CTL_IOCTL_HWDEP_NEXT_DEVICE _IOWR('U', 0x20, int)
-#define SNDRV_CTL_IOCTL_HWDEP_INFO _IOR('U', 0x21, struct snd_hwdep_info)
-#define SNDRV_CTL_IOCTL_PCM_NEXT_DEVICE _IOR('U', 0x30, int)
-#define SNDRV_CTL_IOCTL_PCM_INFO _IOWR('U', 0x31, struct snd_pcm_info)
-#define SNDRV_CTL_IOCTL_PCM_PREFER_SUBDEVICE _IOW('U', 0x32, int)
-#define SNDRV_CTL_IOCTL_RAWMIDI_NEXT_DEVICE _IOWR('U', 0x40, int)
-#define SNDRV_CTL_IOCTL_RAWMIDI_INFO _IOWR('U', 0x41, struct snd_rawmidi_info)
-#define SNDRV_CTL_IOCTL_RAWMIDI_PREFER_SUBDEVICE _IOW('U', 0x42, int)
-#define SNDRV_CTL_IOCTL_POWER _IOWR('U', 0xd0, int)
-#define SNDRV_CTL_IOCTL_POWER_STATE _IOR('U', 0xd1, int)
-
-enum sndrv_ctl_event_type {
- SNDRV_CTL_EVENT_ELEM = 0,
- SNDRV_CTL_EVENT_LAST = SNDRV_CTL_EVENT_ELEM,
-};
-
-#define SNDRV_CTL_EVENT_MASK_VALUE (1<<0)
-#define SNDRV_CTL_EVENT_MASK_INFO (1<<1)
-#define SNDRV_CTL_EVENT_MASK_ADD (1<<2)
-#define SNDRV_CTL_EVENT_MASK_TLV (1<<3)
-#define SNDRV_CTL_EVENT_MASK_REMOVE (~0U)
-
-struct snd_ctl_event {
- int type;
- union {
- struct {
- unsigned int mask;
- struct snd_ctl_elem_id id;
- } elem;
- unsigned char data8[60];
- } data;
-};
-
-#define SNDRV_CTL_NAME_NONE ""
-#define SNDRV_CTL_NAME_PLAYBACK "Playback "
-#define SNDRV_CTL_NAME_CAPTURE "Capture "
-
-#define SNDRV_CTL_NAME_IEC958_NONE ""
-#define SNDRV_CTL_NAME_IEC958_SWITCH "Switch"
-#define SNDRV_CTL_NAME_IEC958_VOLUME "Volume"
-#define SNDRV_CTL_NAME_IEC958_DEFAULT "Default"
-#define SNDRV_CTL_NAME_IEC958_MASK "Mask"
-#define SNDRV_CTL_NAME_IEC958_CON_MASK "Con Mask"
-#define SNDRV_CTL_NAME_IEC958_PRO_MASK "Pro Mask"
-#define SNDRV_CTL_NAME_IEC958_PCM_STREAM "PCM Stream"
-#define SNDRV_CTL_NAME_IEC958(expl,direction,what) "IEC958 " expl SNDRV_CTL_NAME_##direction SNDRV_CTL_NAME_IEC958_##what
-
-#endif
-