diff options
author | Pawit Pornkitprasan <p.pawit@gmail.com> | 2011-12-31 10:05:30 +0700 |
---|---|---|
committer | Pawit Pornkitprasan <p.pawit@gmail.com> | 2011-12-31 10:05:30 +0700 |
commit | f0e10ccdb5d65f65017b1c71a68022f63d0c23ef (patch) | |
tree | 2d89e2f58a87b86804ea7691c28b2a14a3e8f712 /libaudio | |
parent | 33d4bf28318157e23ba605cbcb4099aedef638a9 (diff) | |
download | device_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.mk | 74 | ||||
-rw-r--r-- | libaudio/AudioHardware.cpp | 1175 | ||||
-rw-r--r-- | libaudio/AudioHardware.h | 167 | ||||
-rw-r--r-- | libaudio/AudioPolicyManager.cpp | 2 | ||||
-rw-r--r-- | libaudio/alsa_audio.h | 77 | ||||
-rw-r--r-- | libaudio/alsa_mixer.c | 371 | ||||
-rw-r--r-- | libaudio/alsa_pcm.c | 405 | ||||
-rw-r--r-- | libaudio/amix.c | 78 | ||||
-rw-r--r-- | libaudio/aplay.c | 140 | ||||
-rw-r--r-- | libaudio/arec.c | 128 | ||||
-rw-r--r-- | libaudio/asound.h | 814 |
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, + ¶m->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(¶ms); - param_set_mask(¶ms, SNDRV_PCM_HW_PARAM_ACCESS, - SNDRV_PCM_ACCESS_RW_INTERLEAVED); - param_set_mask(¶ms, SNDRV_PCM_HW_PARAM_FORMAT, - SNDRV_PCM_FORMAT_S16_LE); - param_set_mask(¶ms, SNDRV_PCM_HW_PARAM_SUBFORMAT, - SNDRV_PCM_SUBFORMAT_STD); - param_set_min(¶ms, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, period_sz); - param_set_int(¶ms, SNDRV_PCM_HW_PARAM_SAMPLE_BITS, 16); - param_set_int(¶ms, SNDRV_PCM_HW_PARAM_FRAME_BITS, - (flags & PCM_MONO) ? 16 : 32); - param_set_int(¶ms, SNDRV_PCM_HW_PARAM_CHANNELS, - (flags & PCM_MONO) ? 1 : 2); - param_set_int(¶ms, SNDRV_PCM_HW_PARAM_PERIODS, period_cnt); - param_set_int(¶ms, SNDRV_PCM_HW_PARAM_RATE, 44100); - - if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_HW_PARAMS, ¶ms)) { - oops(pcm, errno, "cannot set hw params"); - goto fail; - } - param_dump(¶ms); - - 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 - |