diff options
Diffstat (limited to 'libs/audioflinger')
21 files changed, 0 insertions, 7258 deletions
diff --git a/libs/audioflinger/A2dpAudioInterface.cpp b/libs/audioflinger/A2dpAudioInterface.cpp deleted file mode 100644 index d1b7af3..0000000 --- a/libs/audioflinger/A2dpAudioInterface.cpp +++ /dev/null @@ -1,243 +0,0 @@ -/* - * Copyright (C) 2008 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 <math.h> - -#define LOG_NDEBUG 0 -#define LOG_TAG "A2dpAudioInterface" -#include <utils/Log.h> -#include <utils/String8.h> - -#include "A2dpAudioInterface.h" -#include "audio/liba2dp.h" - - -namespace android { - -// ---------------------------------------------------------------------------- - -A2dpAudioInterface::A2dpAudioInterface() : - mOutput(0) -{ -} - -A2dpAudioInterface::~A2dpAudioInterface() -{ - delete mOutput; -} - -status_t A2dpAudioInterface::initCheck() -{ - return 0; -} - -AudioStreamOut* A2dpAudioInterface::openOutputStream( - int format, int channelCount, uint32_t sampleRate, status_t *status) -{ - LOGD("A2dpAudioInterface::openOutputStream %d, %d, %d\n", format, channelCount, sampleRate); - Mutex::Autolock lock(mLock); - status_t err = 0; - - // only one output stream allowed - if (mOutput) { - if (status) - *status = -1; - return NULL; - } - - // create new output stream - A2dpAudioStreamOut* out = new A2dpAudioStreamOut(); - if ((err = out->set(format, channelCount, sampleRate)) == NO_ERROR) { - mOutput = out; - } else { - delete out; - } - - if (status) - *status = err; - return mOutput; -} - -AudioStreamIn* A2dpAudioInterface::openInputStream( - int format, int channelCount, uint32_t sampleRate, status_t *status, - AudioSystem::audio_in_acoustics acoustics) -{ - if (status) - *status = -1; - return NULL; -} - -status_t A2dpAudioInterface::setMicMute(bool state) -{ - return 0; -} - -status_t A2dpAudioInterface::getMicMute(bool* state) -{ - return 0; -} - -status_t A2dpAudioInterface::setParameter(const char *key, const char *value) -{ - LOGD("setParameter %s,%s\n", key, value); - - if (!key || !value) - return -EINVAL; - - if (strcmp(key, "a2dp_sink_address") == 0) { - return mOutput->setAddress(value); - } - if (strcmp(key, "bluetooth_enabled") == 0 && - strcmp(value, "false") == 0) { - return mOutput->close(); - } - - return 0; -} - -status_t A2dpAudioInterface::setVoiceVolume(float v) -{ - return 0; -} - -status_t A2dpAudioInterface::setMasterVolume(float v) -{ - return 0; -} - -status_t A2dpAudioInterface::doRouting() -{ - return 0; -} - -status_t A2dpAudioInterface::dump(int fd, const Vector<String16>& args) -{ - return 0; -} - -// ---------------------------------------------------------------------------- - -A2dpAudioInterface::A2dpAudioStreamOut::A2dpAudioStreamOut() : - mFd(-1), mStandby(true), mStartCount(0), mRetryCount(0), mData(NULL), - mInitialized(false) -{ - // use any address by default - strncpy(mA2dpAddress, "00:00:00:00:00:00", sizeof(mA2dpAddress)); -} - -status_t A2dpAudioInterface::A2dpAudioStreamOut::set( - int format, int channels, uint32_t rate) -{ - LOGD("A2dpAudioStreamOut::set %d, %d, %d\n", format, channels, rate); - - // fix up defaults - if (format == 0) format = AudioSystem::PCM_16_BIT; - if (channels == 0) channels = channelCount(); - if (rate == 0) rate = sampleRate(); - - // check values - if ((format != AudioSystem::PCM_16_BIT) || - (channels != channelCount()) || - (rate != sampleRate())) - return BAD_VALUE; - - return NO_ERROR; -} - -A2dpAudioInterface::A2dpAudioStreamOut::~A2dpAudioStreamOut() -{ - close(); -} - -ssize_t A2dpAudioInterface::A2dpAudioStreamOut::write(const void* buffer, size_t bytes) -{ - status_t status = NO_INIT; - size_t remaining = bytes; - - if (!mInitialized) { - status = a2dp_init(mA2dpAddress, 44100, 2, &mData); - if (status < 0) { - LOGE("a2dp_init failed err: %d\n", status); - goto Error; - } - mInitialized = true; - } - - while (remaining > 0) { - status = a2dp_write(mData, buffer, remaining); - if (status <= 0) { - LOGE("a2dp_write failed err: %d\n", status); - goto Error; - } - remaining -= status; - buffer = ((char *)buffer) + status; - } - - mStandby = false; - - return bytes; - -Error: - close(); - // Simulate audio output timing in case of error - usleep(bytes * 1000000 / frameSize() / sampleRate()); - - return status; -} - -status_t A2dpAudioInterface::A2dpAudioStreamOut::standby() -{ - int result = 0; - - if (!mStandby) { - result = a2dp_stop(mData); - if (result == 0) - mStandby = true; - } - - return result; -} - -status_t A2dpAudioInterface::A2dpAudioStreamOut::setAddress(const char* address) -{ - if (strlen(address) < sizeof(mA2dpAddress)) - return -EINVAL; - - if (strcmp(address, mA2dpAddress)) { - strcpy(mA2dpAddress, address); - close(); - } - - return NO_ERROR; -} - -status_t A2dpAudioInterface::A2dpAudioStreamOut::close() -{ - if (mData) { - a2dp_cleanup(mData); - mData = NULL; - mInitialized = false; - } - return NO_ERROR; -} - -status_t A2dpAudioInterface::A2dpAudioStreamOut::dump(int fd, const Vector<String16>& args) -{ - return NO_ERROR; -} - - -}; // namespace android diff --git a/libs/audioflinger/A2dpAudioInterface.h b/libs/audioflinger/A2dpAudioInterface.h deleted file mode 100644 index 5bef5da..0000000 --- a/libs/audioflinger/A2dpAudioInterface.h +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright (C) 2008 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 A2DP_AUDIO_HARDWARE_H -#define A2DP_AUDIO_HARDWARE_H - -#include <stdint.h> -#include <sys/types.h> - -#include <utils/threads.h> - -#include <hardware_legacy/AudioHardwareBase.h> - - -namespace android { - -class A2dpAudioInterface : public AudioHardwareBase -{ - class A2dpAudioStreamOut; - -public: - A2dpAudioInterface(); - virtual ~A2dpAudioInterface(); - virtual status_t initCheck(); - - virtual status_t setVoiceVolume(float volume); - virtual status_t setMasterVolume(float volume); - - // mic mute - virtual status_t setMicMute(bool state); - virtual status_t getMicMute(bool* state); - - // Temporary interface, do not use - // TODO: Replace with a more generic key:value get/set mechanism - virtual status_t setParameter(const char *key, const char *value); - - // create I/O streams - virtual AudioStreamOut* openOutputStream( - int format=0, - int channelCount=0, - uint32_t sampleRate=0, - status_t *status=0); - - virtual AudioStreamIn* openInputStream( - int format, - int channelCount, - uint32_t sampleRate, - status_t *status, - AudioSystem::audio_in_acoustics acoustics); - -protected: - virtual status_t doRouting(); - virtual status_t dump(int fd, const Vector<String16>& args); - -private: - class A2dpAudioStreamOut : public AudioStreamOut { - public: - A2dpAudioStreamOut(); - virtual ~A2dpAudioStreamOut(); - status_t set(int format, - int channelCount, - uint32_t sampleRate); - virtual uint32_t sampleRate() const { return 44100; } - // SBC codec wants a multiple of 512 - virtual size_t bufferSize() const { return 512 * 20; } - virtual int channelCount() const { return 2; } - virtual int format() const { return AudioSystem::PCM_16_BIT; } - virtual uint32_t latency() const { return ((1000*bufferSize())/frameSize())/sampleRate() + 200; } - virtual status_t setVolume(float volume) { return INVALID_OPERATION; } - virtual ssize_t write(const void* buffer, size_t bytes); - status_t standby(); - status_t close(); - virtual status_t dump(int fd, const Vector<String16>& args); - - private: - friend class A2dpAudioInterface; - status_t setAddress(const char* address); - - private: - int mFd; - bool mStandby; - int mStartCount; - int mRetryCount; - char mA2dpAddress[20]; - void* mData; - bool mInitialized; - }; - - Mutex mLock; - A2dpAudioStreamOut* mOutput; -}; - -// ---------------------------------------------------------------------------- - -}; // namespace android - -#endif // A2DP_AUDIO_HARDWARE_H diff --git a/libs/audioflinger/Android.mk b/libs/audioflinger/Android.mk deleted file mode 100644 index 50d516b..0000000 --- a/libs/audioflinger/Android.mk +++ /dev/null @@ -1,56 +0,0 @@ -LOCAL_PATH:= $(call my-dir) - -include $(CLEAR_VARS) - -LOCAL_SRC_FILES:= \ - AudioHardwareGeneric.cpp \ - AudioHardwareStub.cpp \ - AudioDumpInterface.cpp \ - AudioHardwareInterface.cpp - -LOCAL_SHARED_LIBRARIES := \ - libcutils \ - libutils \ - libmedia \ - libhardware_legacy - -ifeq ($(strip $(BOARD_USES_GENERIC_AUDIO)),true) - LOCAL_CFLAGS += -DGENERIC_AUDIO -endif - -LOCAL_MODULE:= libaudiointerface - -include $(BUILD_STATIC_LIBRARY) - -include $(CLEAR_VARS) - -LOCAL_SRC_FILES:= \ - AudioFlinger.cpp \ - AudioMixer.cpp.arm \ - AudioResampler.cpp.arm \ - AudioResamplerSinc.cpp.arm \ - AudioResamplerCubic.cpp.arm - -LOCAL_SHARED_LIBRARIES := \ - libcutils \ - libutils \ - libmedia \ - libhardware_legacy - -ifeq ($(strip $(BOARD_USES_GENERIC_AUDIO)),true) - LOCAL_STATIC_LIBRARIES += libaudiointerface -else - LOCAL_SHARED_LIBRARIES += libaudio -endif - -LOCAL_MODULE:= libaudioflinger - -ifeq ($(BOARD_HAVE_BLUETOOTH),true) - LOCAL_SRC_FILES += A2dpAudioInterface.cpp - LOCAL_SHARED_LIBRARIES += liba2dp - LOCAL_CFLAGS += -DWITH_BLUETOOTH -DWITH_A2DP - LOCAL_C_INCLUDES += $(call include-path-for, bluez-libs) - LOCAL_C_INCLUDES += $(call include-path-for, bluez-utils) -endif - -include $(BUILD_SHARED_LIBRARY) diff --git a/libs/audioflinger/AudioBufferProvider.h b/libs/audioflinger/AudioBufferProvider.h deleted file mode 100644 index 1a467c7..0000000 --- a/libs/audioflinger/AudioBufferProvider.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2007 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 ANDROID_AUDIO_BUFFER_PROVIDER_H -#define ANDROID_AUDIO_BUFFER_PROVIDER_H - -#include <stdint.h> -#include <sys/types.h> -#include <utils/Errors.h> - -namespace android { -// ---------------------------------------------------------------------------- - -class AudioBufferProvider -{ -public: - - struct Buffer { - union { - void* raw; - short* i16; - int8_t* i8; - }; - size_t frameCount; - }; - - virtual status_t getNextBuffer(Buffer* buffer) = 0; - virtual void releaseBuffer(Buffer* buffer) = 0; -}; - -// ---------------------------------------------------------------------------- -}; // namespace android - -#endif // ANDROID_AUDIO_BUFFER_PROVIDER_H diff --git a/libs/audioflinger/AudioDumpInterface.cpp b/libs/audioflinger/AudioDumpInterface.cpp deleted file mode 100644 index b4940cb..0000000 --- a/libs/audioflinger/AudioDumpInterface.cpp +++ /dev/null @@ -1,117 +0,0 @@ -/* //device/servers/AudioFlinger/AudioDumpInterface.cpp -** -** Copyright 2008, 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 "AudioFlingerDump" - -#include <stdint.h> -#include <sys/types.h> -#include <utils/Log.h> - -#include <stdlib.h> -#include <unistd.h> - -#include "AudioDumpInterface.h" - -namespace android { - -bool gFirst = true; // true if first write after a standby - -// ---------------------------------------------------------------------------- - -AudioDumpInterface::AudioDumpInterface(AudioHardwareInterface* hw) -{ - if(hw == 0) { - LOGE("Dump construct hw = 0"); - } - mFinalInterface = hw; - mStreamOut = 0; -} - - -AudioDumpInterface::~AudioDumpInterface() -{ - if(mFinalInterface) delete mFinalInterface; - if(mStreamOut) delete mStreamOut; -} - - -AudioStreamOut* AudioDumpInterface::openOutputStream( - int format, int channelCount, uint32_t sampleRate, status_t *status) -{ - AudioStreamOut* outFinal = mFinalInterface->openOutputStream(format, channelCount, sampleRate, status); - - if(outFinal) { - mStreamOut = new AudioStreamOutDump(outFinal); - return mStreamOut; - } else { - LOGE("Dump outFinal=0"); - return 0; - } -} - -// ---------------------------------------------------------------------------- - -AudioStreamOutDump::AudioStreamOutDump( AudioStreamOut* finalStream) -{ - mFinalStream = finalStream; - mOutFile = 0; -} - - -AudioStreamOutDump::~AudioStreamOutDump() -{ - Close(); - delete mFinalStream; -} - -ssize_t AudioStreamOutDump::write(const void* buffer, size_t bytes) -{ - ssize_t ret; - - ret = mFinalStream->write(buffer, bytes); - if(!mOutFile && gFirst) { - gFirst = false; - // check if dump file exist - mOutFile = fopen(FLINGER_DUMP_NAME, "r"); - if(mOutFile) { - fclose(mOutFile); - mOutFile = fopen(FLINGER_DUMP_NAME, "ab"); - } - } - if (mOutFile) { - fwrite(buffer, bytes, 1, mOutFile); - } - return ret; -} - -status_t AudioStreamOutDump::standby() -{ - Close(); - gFirst = true; - return mFinalStream->standby(); -} - - -void AudioStreamOutDump::Close(void) -{ - if(mOutFile) { - fclose(mOutFile); - mOutFile = 0; - } -} - -}; // namespace android diff --git a/libs/audioflinger/AudioDumpInterface.h b/libs/audioflinger/AudioDumpInterface.h deleted file mode 100644 index 9a94102..0000000 --- a/libs/audioflinger/AudioDumpInterface.h +++ /dev/null @@ -1,97 +0,0 @@ -/* //device/servers/AudioFlinger/AudioDumpInterface.h -** -** Copyright 2008, 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 ANDROID_AUDIO_DUMP_INTERFACE_H -#define ANDROID_AUDIO_DUMP_INTERFACE_H - -#include <stdint.h> -#include <sys/types.h> - -#include <hardware_legacy/AudioHardwareBase.h> - -namespace android { - -#define FLINGER_DUMP_NAME "/data/FlingerOut.pcm" // name of file used for dump - -class AudioStreamOutDump : public AudioStreamOut { -public: - AudioStreamOutDump( AudioStreamOut* FinalStream); - ~AudioStreamOutDump(); - virtual ssize_t write(const void* buffer, size_t bytes); - - virtual uint32_t sampleRate() const { return mFinalStream->sampleRate(); } - virtual size_t bufferSize() const { return mFinalStream->bufferSize(); } - virtual int channelCount() const { return mFinalStream->channelCount(); } - virtual int format() const { return mFinalStream->format(); } - virtual uint32_t latency() const { return mFinalStream->latency(); } - virtual status_t setVolume(float volume) - { return mFinalStream->setVolume(volume); } - virtual status_t standby(); - virtual status_t dump(int fd, const Vector<String16>& args) { return mFinalStream->dump(fd, args); } - void Close(void); - -private: - AudioStreamOut *mFinalStream; - FILE *mOutFile; // output file -}; - - -class AudioDumpInterface : public AudioHardwareBase -{ - -public: - AudioDumpInterface(AudioHardwareInterface* hw); - virtual AudioStreamOut* openOutputStream( - int format=0, - int channelCount=0, - uint32_t sampleRate=0, - status_t *status=0); - virtual ~AudioDumpInterface(); - - virtual status_t initCheck() - {return mFinalInterface->initCheck();} - virtual status_t setVoiceVolume(float volume) - {return mFinalInterface->setVoiceVolume(volume);} - virtual status_t setMasterVolume(float volume) - {return mFinalInterface->setMasterVolume(volume);} - - // mic mute - virtual status_t setMicMute(bool state) - {return mFinalInterface->setMicMute(state);} - virtual status_t getMicMute(bool* state) - {return mFinalInterface->getMicMute(state);} - - virtual status_t setParameter(const char* key, const char* value) - {return mFinalInterface->setParameter(key, value);} - - virtual AudioStreamIn* openInputStream( int format, int channelCount, uint32_t sampleRate, status_t *status, - AudioSystem::audio_in_acoustics acoustics) - {return mFinalInterface->openInputStream( format, channelCount, sampleRate, status, acoustics);} - - virtual status_t dump(int fd, const Vector<String16>& args) { return mFinalInterface->dumpState(fd, args); } - -protected: - virtual status_t doRouting() {return mFinalInterface->setRouting(mMode, mRoutes[mMode]);} - - AudioHardwareInterface *mFinalInterface; - AudioStreamOutDump *mStreamOut; - -}; - -}; // namespace android - -#endif // ANDROID_AUDIO_DUMP_INTERFACE_H diff --git a/libs/audioflinger/AudioFlinger.cpp b/libs/audioflinger/AudioFlinger.cpp deleted file mode 100644 index 557d93b..0000000 --- a/libs/audioflinger/AudioFlinger.cpp +++ /dev/null @@ -1,2471 +0,0 @@ -/* //device/include/server/AudioFlinger/AudioFlinger.cpp -** -** Copyright 2007, 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 "AudioFlinger" -//#define LOG_NDEBUG 0 - -#include <math.h> -#include <signal.h> -#include <sys/time.h> -#include <sys/resource.h> - -#include <utils/IServiceManager.h> -#include <utils/Log.h> -#include <utils/Parcel.h> -#include <utils/IPCThreadState.h> -#include <utils/String16.h> -#include <utils/threads.h> - -#include <cutils/properties.h> - -#include <media/AudioTrack.h> -#include <media/AudioRecord.h> - -#include <private/media/AudioTrackShared.h> - -#include <hardware_legacy/AudioHardwareInterface.h> - -#include "AudioMixer.h" -#include "AudioFlinger.h" - -#ifdef WITH_A2DP -#include "A2dpAudioInterface.h" -#endif - -// ---------------------------------------------------------------------------- -// the sim build doesn't have gettid - -#ifndef HAVE_GETTID -# define gettid getpid -#endif - -// ---------------------------------------------------------------------------- - -namespace android { - -//static const nsecs_t kStandbyTimeInNsecs = seconds(3); -static const unsigned long kBufferRecoveryInUsecs = 2000; -static const unsigned long kMaxBufferRecoveryInUsecs = 20000; -static const float MAX_GAIN = 4096.0f; - -// retry counts for buffer fill timeout -// 50 * ~20msecs = 1 second -static const int8_t kMaxTrackRetries = 50; -static const int8_t kMaxTrackStartupRetries = 50; - -static const int kStartSleepTime = 30000; -static const int kStopSleepTime = 30000; - -// Maximum number of pending buffers allocated by OutputTrack::write() -static const uint8_t kMaxOutputTrackBuffers = 5; - - -#define AUDIOFLINGER_SECURITY_ENABLED 1 - -// ---------------------------------------------------------------------------- - -static bool recordingAllowed() { -#ifndef HAVE_ANDROID_OS - return true; -#endif -#if AUDIOFLINGER_SECURITY_ENABLED - if (getpid() == IPCThreadState::self()->getCallingPid()) return true; - bool ok = checkCallingPermission(String16("android.permission.RECORD_AUDIO")); - if (!ok) LOGE("Request requires android.permission.RECORD_AUDIO"); - return ok; -#else - if (!checkCallingPermission(String16("android.permission.RECORD_AUDIO"))) - LOGW("WARNING: Need to add android.permission.RECORD_AUDIO to manifest"); - return true; -#endif -} - -static bool settingsAllowed() { -#ifndef HAVE_ANDROID_OS - return true; -#endif -#if AUDIOFLINGER_SECURITY_ENABLED - if (getpid() == IPCThreadState::self()->getCallingPid()) return true; - bool ok = checkCallingPermission(String16("android.permission.MODIFY_AUDIO_SETTINGS")); - if (!ok) LOGE("Request requires android.permission.MODIFY_AUDIO_SETTINGS"); - return ok; -#else - if (!checkCallingPermission(String16("android.permission.MODIFY_AUDIO_SETTINGS"))) - LOGW("WARNING: Need to add android.permission.MODIFY_AUDIO_SETTINGS to manifest"); - return true; -#endif -} - -// ---------------------------------------------------------------------------- - -AudioFlinger::AudioFlinger() - : BnAudioFlinger(), - mAudioHardware(0), mA2dpAudioInterface(0), - mA2dpEnabled(false), mA2dpEnabledReq(false), - mForcedSpeakerCount(0), mForcedRoute(0), mRouteRestoreTime(0), mMusicMuteSaved(false) -{ - mHardwareStatus = AUDIO_HW_IDLE; - mAudioHardware = AudioHardwareInterface::create(); - mHardwareStatus = AUDIO_HW_INIT; - if (mAudioHardware->initCheck() == NO_ERROR) { - // open 16-bit output stream for s/w mixer - mHardwareStatus = AUDIO_HW_OUTPUT_OPEN; - status_t status; - AudioStreamOut *hwOutput = mAudioHardware->openOutputStream(AudioSystem::PCM_16_BIT, 0, 0, &status); - mHardwareStatus = AUDIO_HW_IDLE; - if (hwOutput) { - mHardwareMixerThread = new MixerThread(this, hwOutput, AudioSystem::AUDIO_OUTPUT_HARDWARE); - } else { - LOGE("Failed to initialize hardware output stream, status: %d", status); - } - -#ifdef WITH_A2DP - // Create A2DP interface - mA2dpAudioInterface = new A2dpAudioInterface(); - AudioStreamOut *a2dpOutput = mA2dpAudioInterface->openOutputStream(AudioSystem::PCM_16_BIT, 0, 0, &status); - if (a2dpOutput) { - mA2dpMixerThread = new MixerThread(this, a2dpOutput, AudioSystem::AUDIO_OUTPUT_A2DP); - if (hwOutput) { - uint32_t frameCount = ((a2dpOutput->bufferSize()/a2dpOutput->frameSize()) * hwOutput->sampleRate()) / a2dpOutput->sampleRate(); - MixerThread::OutputTrack *a2dpOutTrack = new MixerThread::OutputTrack(mA2dpMixerThread, - hwOutput->sampleRate(), - AudioSystem::PCM_16_BIT, - hwOutput->channelCount(), - frameCount); - mHardwareMixerThread->setOuputTrack(a2dpOutTrack); - } - } else { - LOGE("Failed to initialize A2DP output stream, status: %d", status); - } -#endif - - // FIXME - this should come from settings - setRouting(AudioSystem::MODE_NORMAL, AudioSystem::ROUTE_SPEAKER, AudioSystem::ROUTE_ALL); - setRouting(AudioSystem::MODE_RINGTONE, AudioSystem::ROUTE_SPEAKER, AudioSystem::ROUTE_ALL); - setRouting(AudioSystem::MODE_IN_CALL, AudioSystem::ROUTE_EARPIECE, AudioSystem::ROUTE_ALL); - setMode(AudioSystem::MODE_NORMAL); - - setMasterVolume(1.0f); - setMasterMute(false); - - // Start record thread - mAudioRecordThread = new AudioRecordThread(mAudioHardware); - if (mAudioRecordThread != 0) { - mAudioRecordThread->run("AudioRecordThread", PRIORITY_URGENT_AUDIO); - } - } else { - LOGE("Couldn't even initialize the stubbed audio hardware!"); - } - - char value[PROPERTY_VALUE_MAX]; - property_get("ro.audio.silent", value, "0"); - if (atoi(value)) { - LOGD("Silence is golden"); - setMasterMute(true); - } -} - -AudioFlinger::~AudioFlinger() -{ - if (mAudioRecordThread != 0) { - mAudioRecordThread->exit(); - mAudioRecordThread.clear(); - } - mHardwareMixerThread.clear(); - delete mAudioHardware; - // deleting mA2dpAudioInterface also deletes mA2dpOutput; -#ifdef WITH_A2DP - mA2dpMixerThread.clear(); - delete mA2dpAudioInterface; -#endif -} - - -#ifdef WITH_A2DP -void AudioFlinger::setA2dpEnabled(bool enable) -{ - LOGV_IF(enable, "set output to A2DP\n"); - LOGV_IF(!enable, "set output to hardware audio\n"); - - mA2dpEnabledReq = enable; - mA2dpMixerThread->wakeUp(); -} -#endif // WITH_A2DP - -bool AudioFlinger::streamForcedToSpeaker(int streamType) -{ - // NOTE that streams listed here must not be routed to A2DP by default: - // AudioSystem::routedToA2dpOutput(streamType) == false - return (streamType == AudioSystem::RING || - streamType == AudioSystem::ALARM || - streamType == AudioSystem::NOTIFICATION); -} - -status_t AudioFlinger::dumpClients(int fd, const Vector<String16>& args) -{ - const size_t SIZE = 256; - char buffer[SIZE]; - String8 result; - - result.append("Clients:\n"); - for (size_t i = 0; i < mClients.size(); ++i) { - wp<Client> wClient = mClients.valueAt(i); - if (wClient != 0) { - sp<Client> client = wClient.promote(); - if (client != 0) { - snprintf(buffer, SIZE, " pid: %d\n", client->pid()); - result.append(buffer); - } - } - } - write(fd, result.string(), result.size()); - return NO_ERROR; -} - - -status_t AudioFlinger::dumpInternals(int fd, const Vector<String16>& args) -{ - const size_t SIZE = 256; - char buffer[SIZE]; - String8 result; - - snprintf(buffer, SIZE, "Hardware status: %d\n", mHardwareStatus); - result.append(buffer); - write(fd, result.string(), result.size()); - return NO_ERROR; -} - -status_t AudioFlinger::dumpPermissionDenial(int fd, const Vector<String16>& args) -{ - const size_t SIZE = 256; - char buffer[SIZE]; - String8 result; - snprintf(buffer, SIZE, "Permission Denial: " - "can't dump AudioFlinger from pid=%d, uid=%d\n", - IPCThreadState::self()->getCallingPid(), - IPCThreadState::self()->getCallingUid()); - result.append(buffer); - write(fd, result.string(), result.size()); - return NO_ERROR; -} - -status_t AudioFlinger::dump(int fd, const Vector<String16>& args) -{ - if (checkCallingPermission(String16("android.permission.DUMP")) == false) { - dumpPermissionDenial(fd, args); - } else { - AutoMutex lock(&mLock); - - dumpClients(fd, args); - dumpInternals(fd, args); - mHardwareMixerThread->dump(fd, args); -#ifdef WITH_A2DP - mA2dpMixerThread->dump(fd, args); -#endif - - // dump record client - if (mAudioRecordThread != 0) mAudioRecordThread->dump(fd, args); - - if (mAudioHardware) { - mAudioHardware->dumpState(fd, args); - } - } - return NO_ERROR; -} - -// IAudioFlinger interface - - -sp<IAudioTrack> AudioFlinger::createTrack( - pid_t pid, - int streamType, - uint32_t sampleRate, - int format, - int channelCount, - int frameCount, - uint32_t flags, - const sp<IMemory>& sharedBuffer, - status_t *status) -{ - sp<MixerThread::Track> track; - sp<TrackHandle> trackHandle; - sp<Client> client; - wp<Client> wclient; - status_t lStatus; - - if (streamType >= AudioSystem::NUM_STREAM_TYPES) { - LOGE("invalid stream type"); - lStatus = BAD_VALUE; - goto Exit; - } - - { - Mutex::Autolock _l(mLock); - - wclient = mClients.valueFor(pid); - - if (wclient != NULL) { - client = wclient.promote(); - } else { - client = new Client(this, pid); - mClients.add(pid, client); - } -#ifdef WITH_A2DP - if (isA2dpEnabled() && AudioSystem::routedToA2dpOutput(streamType)) { - track = mA2dpMixerThread->createTrack(client, streamType, sampleRate, format, - channelCount, frameCount, sharedBuffer, &lStatus); - } else -#endif - { - track = mHardwareMixerThread->createTrack(client, streamType, sampleRate, format, - channelCount, frameCount, sharedBuffer, &lStatus); - } - if (track != NULL) { - trackHandle = new TrackHandle(track); - lStatus = NO_ERROR; - } - } - -Exit: - if(status) { - *status = lStatus; - } - return trackHandle; -} - -uint32_t AudioFlinger::sampleRate(int output) const -{ -#ifdef WITH_A2DP - if (output == AudioSystem::AUDIO_OUTPUT_A2DP) { - return mA2dpMixerThread->sampleRate(); - } -#endif - return mHardwareMixerThread->sampleRate(); -} - -int AudioFlinger::channelCount(int output) const -{ -#ifdef WITH_A2DP - if (output == AudioSystem::AUDIO_OUTPUT_A2DP) { - return mA2dpMixerThread->channelCount(); - } -#endif - return mHardwareMixerThread->channelCount(); -} - -int AudioFlinger::format(int output) const -{ -#ifdef WITH_A2DP - if (output == AudioSystem::AUDIO_OUTPUT_A2DP) { - return mA2dpMixerThread->format(); - } -#endif - return mHardwareMixerThread->format(); -} - -size_t AudioFlinger::frameCount(int output) const -{ -#ifdef WITH_A2DP - if (output == AudioSystem::AUDIO_OUTPUT_A2DP) { - return mA2dpMixerThread->frameCount(); - } -#endif - return mHardwareMixerThread->frameCount(); -} - -uint32_t AudioFlinger::latency(int output) const -{ -#ifdef WITH_A2DP - if (output == AudioSystem::AUDIO_OUTPUT_A2DP) { - return mA2dpMixerThread->latency(); - } -#endif - return mHardwareMixerThread->latency(); -} - -status_t AudioFlinger::setMasterVolume(float value) -{ - // check calling permissions - if (!settingsAllowed()) { - return PERMISSION_DENIED; - } - - // when hw supports master volume, don't scale in sw mixer - AutoMutex lock(mHardwareLock); - mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME; - if (mAudioHardware->setMasterVolume(value) == NO_ERROR) { - value = 1.0f; - } - mHardwareStatus = AUDIO_HW_IDLE; - mHardwareMixerThread->setMasterVolume(value); -#ifdef WITH_A2DP - mA2dpMixerThread->setMasterVolume(value); -#endif - - return NO_ERROR; -} - -status_t AudioFlinger::setRouting(int mode, uint32_t routes, uint32_t mask) -{ - status_t err = NO_ERROR; - - // check calling permissions - if (!settingsAllowed()) { - return PERMISSION_DENIED; - } - if ((mode < AudioSystem::MODE_CURRENT) || (mode >= AudioSystem::NUM_MODES)) { - LOGW("Illegal value: setRouting(%d, %u, %u)", mode, routes, mask); - return BAD_VALUE; - } - -#ifdef WITH_A2DP - LOGD("setRouting %d %d %d, tid %d, calling tid %d\n", mode, routes, mask, gettid(), IPCThreadState::self()->getCallingPid()); - if (mode == AudioSystem::MODE_NORMAL && - (mask & AudioSystem::ROUTE_BLUETOOTH_A2DP)) { - AutoMutex lock(&mLock); - - bool enableA2dp = false; - if (routes & AudioSystem::ROUTE_BLUETOOTH_A2DP) { - enableA2dp = true; - } - setA2dpEnabled(enableA2dp); - LOGV("setOutput done\n"); - } -#endif - - // do nothing if only A2DP routing is affected - mask &= ~AudioSystem::ROUTE_BLUETOOTH_A2DP; - if (mask) { - AutoMutex lock(mHardwareLock); - mHardwareStatus = AUDIO_HW_GET_ROUTING; - uint32_t r; - err = mAudioHardware->getRouting(mode, &r); - if (err == NO_ERROR) { - r = (r & ~mask) | (routes & mask); - if (mode == AudioSystem::MODE_NORMAL || - (mode == AudioSystem::MODE_CURRENT && getMode() == AudioSystem::MODE_NORMAL)) { - mSavedRoute = r; - r |= mForcedRoute; - LOGV("setRouting mSavedRoute %08x mForcedRoute %08x\n", mSavedRoute, mForcedRoute); - } - mHardwareStatus = AUDIO_HW_SET_ROUTING; - err = mAudioHardware->setRouting(mode, r); - } - mHardwareStatus = AUDIO_HW_IDLE; - } - return err; -} - -uint32_t AudioFlinger::getRouting(int mode) const -{ - uint32_t routes = 0; - if ((mode >= AudioSystem::MODE_CURRENT) && (mode < AudioSystem::NUM_MODES)) { - if (mode == AudioSystem::MODE_NORMAL || - (mode == AudioSystem::MODE_CURRENT && getMode() == AudioSystem::MODE_NORMAL)) { - routes = mSavedRoute; - } else { - mHardwareStatus = AUDIO_HW_GET_ROUTING; - mAudioHardware->getRouting(mode, &routes); - mHardwareStatus = AUDIO_HW_IDLE; - } - } else { - LOGW("Illegal value: getRouting(%d)", mode); - } - return routes; -} - -status_t AudioFlinger::setMode(int mode) -{ - // check calling permissions - if (!settingsAllowed()) { - return PERMISSION_DENIED; - } - if ((mode < 0) || (mode >= AudioSystem::NUM_MODES)) { - LOGW("Illegal value: setMode(%d)", mode); - return BAD_VALUE; - } - - AutoMutex lock(mHardwareLock); - mHardwareStatus = AUDIO_HW_SET_MODE; - status_t ret = mAudioHardware->setMode(mode); - mHardwareStatus = AUDIO_HW_IDLE; - return ret; -} - -int AudioFlinger::getMode() const -{ - int mode = AudioSystem::MODE_INVALID; - mHardwareStatus = AUDIO_HW_SET_MODE; - mAudioHardware->getMode(&mode); - mHardwareStatus = AUDIO_HW_IDLE; - return mode; -} - -status_t AudioFlinger::setMicMute(bool state) -{ - // check calling permissions - if (!settingsAllowed()) { - return PERMISSION_DENIED; - } - - AutoMutex lock(mHardwareLock); - mHardwareStatus = AUDIO_HW_SET_MIC_MUTE; - status_t ret = mAudioHardware->setMicMute(state); - mHardwareStatus = AUDIO_HW_IDLE; - return ret; -} - -bool AudioFlinger::getMicMute() const -{ - bool state = AudioSystem::MODE_INVALID; - mHardwareStatus = AUDIO_HW_GET_MIC_MUTE; - mAudioHardware->getMicMute(&state); - mHardwareStatus = AUDIO_HW_IDLE; - return state; -} - -status_t AudioFlinger::setMasterMute(bool muted) -{ - // check calling permissions - if (!settingsAllowed()) { - return PERMISSION_DENIED; - } - mHardwareMixerThread->setMasterMute(muted); -#ifdef WITH_A2DP - mA2dpMixerThread->setMasterMute(muted); -#endif - return NO_ERROR; -} - -float AudioFlinger::masterVolume() const -{ - return mHardwareMixerThread->masterVolume(); -} - -bool AudioFlinger::masterMute() const -{ - return mHardwareMixerThread->masterMute(); -} - -status_t AudioFlinger::setStreamVolume(int stream, float value) -{ - // check calling permissions - if (!settingsAllowed()) { - return PERMISSION_DENIED; - } - - if (uint32_t(stream) >= AudioSystem::NUM_STREAM_TYPES) { - return BAD_VALUE; - } - - mHardwareMixerThread->setStreamVolume(stream, value); -#ifdef WITH_A2DP - mA2dpMixerThread->setStreamVolume(stream, value); -#endif - - status_t ret = NO_ERROR; - if (stream == AudioSystem::VOICE_CALL || - stream == AudioSystem::BLUETOOTH_SCO) { - - if (stream == AudioSystem::VOICE_CALL) { - value = (float)AudioSystem::logToLinear(value)/100.0f; - } else { // (type == AudioSystem::BLUETOOTH_SCO) - value = 1.0f; - } - - AutoMutex lock(mHardwareLock); - mHardwareStatus = AUDIO_SET_VOICE_VOLUME; - ret = mAudioHardware->setVoiceVolume(value); - mHardwareStatus = AUDIO_HW_IDLE; - } - - return ret; -} - -status_t AudioFlinger::setStreamMute(int stream, bool muted) -{ - // check calling permissions - if (!settingsAllowed()) { - return PERMISSION_DENIED; - } - - if (uint32_t(stream) >= AudioSystem::NUM_STREAM_TYPES) { - return BAD_VALUE; - } - -#ifdef WITH_A2DP - mA2dpMixerThread->setStreamMute(stream, muted); -#endif - if (stream == AudioSystem::MUSIC) - { - AutoMutex lock(&mHardwareLock); - if (mForcedRoute != 0) - mMusicMuteSaved = muted; - else - mHardwareMixerThread->setStreamMute(stream, muted); - } else { - mHardwareMixerThread->setStreamMute(stream, muted); - } - - - - return NO_ERROR; -} - -float AudioFlinger::streamVolume(int stream) const -{ - if (uint32_t(stream) >= AudioSystem::NUM_STREAM_TYPES) { - return 0.0f; - } - return mHardwareMixerThread->streamVolume(stream); -} - -bool AudioFlinger::streamMute(int stream) const -{ - if (uint32_t(stream) >= AudioSystem::NUM_STREAM_TYPES) { - return true; - } - - if (stream == AudioSystem::MUSIC && mForcedRoute != 0) - { - return mMusicMuteSaved; - } - return mHardwareMixerThread->streamMute(stream); -} - -bool AudioFlinger::isMusicActive() const -{ - #ifdef WITH_A2DP - if (isA2dpEnabled()) { - return mA2dpMixerThread->isMusicActive(); - } - #endif - return mHardwareMixerThread->isMusicActive(); -} - -status_t AudioFlinger::setParameter(const char* key, const char* value) -{ - status_t result, result2; - AutoMutex lock(mHardwareLock); - mHardwareStatus = AUDIO_SET_PARAMETER; - - LOGV("setParameter() key %s, value %s, tid %d, calling tid %d", key, value, gettid(), IPCThreadState::self()->getCallingPid()); - result = mAudioHardware->setParameter(key, value); - if (mA2dpAudioInterface) { - result2 = mA2dpAudioInterface->setParameter(key, value); - if (result2) - result = result2; - } - mHardwareStatus = AUDIO_HW_IDLE; - return result; -} - -size_t AudioFlinger::getInputBufferSize(uint32_t sampleRate, int format, int channelCount) -{ - return mAudioHardware->getInputBufferSize(sampleRate, format, channelCount); -} - -void AudioFlinger::registerClient(const sp<IAudioFlingerClient>& client) -{ - - LOGV("registerClient() %p, tid %d, calling tid %d", client.get(), gettid(), IPCThreadState::self()->getCallingPid()); - Mutex::Autolock _l(mLock); - - sp<IBinder> binder = client->asBinder(); - if (mNotificationClients.indexOf(binder) < 0) { - LOGV("Adding notification client %p", binder.get()); - binder->linkToDeath(this); - mNotificationClients.add(binder); - client->a2dpEnabledChanged(isA2dpEnabled()); - } -} - -void AudioFlinger::binderDied(const wp<IBinder>& who) { - - LOGV("binderDied() %p, tid %d, calling tid %d", who.unsafe_get(), gettid(), IPCThreadState::self()->getCallingPid()); - Mutex::Autolock _l(mLock); - - IBinder *binder = who.unsafe_get(); - - if (binder != NULL) { - int index = mNotificationClients.indexOf(binder); - if (index >= 0) { - LOGV("Removing notification client %p", binder); - mNotificationClients.removeAt(index); - } - } -} - -void AudioFlinger::handleOutputSwitch() -{ - if (mA2dpEnabled != mA2dpEnabledReq) - { - Mutex::Autolock _l(mLock); - - if (mA2dpEnabled != mA2dpEnabledReq) - { - mA2dpEnabled = mA2dpEnabledReq; - SortedVector < sp<MixerThread::Track> > tracks; - SortedVector < wp<MixerThread::Track> > activeTracks; - - // We hold mA2dpMixerThread mLock already - Mutex::Autolock _l(mHardwareMixerThread->mLock); - - // Transfer tracks playing on MUSIC stream from one mixer to the other - if (mA2dpEnabled) { - mHardwareMixerThread->getTracks(tracks, activeTracks); - mA2dpMixerThread->putTracks(tracks, activeTracks); - } else { - mA2dpMixerThread->getTracks(tracks, activeTracks); - mHardwareMixerThread->putTracks(tracks, activeTracks); - } - - // Notify AudioSystem of the A2DP activation/deactivation - size_t size = mNotificationClients.size(); - for (size_t i = 0; i < size; i++) { - sp<IBinder> binder = mNotificationClients.itemAt(i).promote(); - if (binder != NULL) { - LOGV("Notifying output change to client %p", binder.get()); - sp<IAudioFlingerClient> client = interface_cast<IAudioFlingerClient> (binder); - client->a2dpEnabledChanged(mA2dpEnabled); - } - } - - mHardwareMixerThread->wakeUp(); - } - } -} - -void AudioFlinger::removeClient(pid_t pid) -{ - LOGV("removeClient() pid %d, tid %d, calling tid %d", pid, gettid(), IPCThreadState::self()->getCallingPid()); - Mutex::Autolock _l(mLock); - mClients.removeItem(pid); -} - -void AudioFlinger::wakeUp() -{ - mHardwareMixerThread->wakeUp(); -#ifdef WITH_A2DP - mA2dpMixerThread->wakeUp(); -#endif // WITH_A2DP -} - -bool AudioFlinger::isA2dpEnabled() const -{ - return mA2dpEnabledReq; -} - -void AudioFlinger::handleForcedSpeakerRoute(int command) -{ - switch(command) { - case ACTIVE_TRACK_ADDED: - { - AutoMutex lock(mHardwareLock); - if (mForcedSpeakerCount++ == 0) { - mRouteRestoreTime = 0; - mMusicMuteSaved = mHardwareMixerThread->streamMute(AudioSystem::MUSIC); - if (mForcedRoute == 0 && !(mSavedRoute & AudioSystem::ROUTE_SPEAKER)) { - LOGV("Route forced to Speaker ON %08x", mSavedRoute | AudioSystem::ROUTE_SPEAKER); - mHardwareMixerThread->setStreamMute(AudioSystem::MUSIC, true); - mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME; - mAudioHardware->setMasterVolume(0); - usleep(mHardwareMixerThread->latency()*1000); - mHardwareStatus = AUDIO_HW_SET_ROUTING; - mAudioHardware->setRouting(AudioSystem::MODE_NORMAL, mSavedRoute | AudioSystem::ROUTE_SPEAKER); - mHardwareStatus = AUDIO_HW_IDLE; - // delay track start so that audio hardware has time to siwtch routes - usleep(kStartSleepTime); - mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME; - mAudioHardware->setMasterVolume(mHardwareMixerThread->masterVolume()); - mHardwareStatus = AUDIO_HW_IDLE; - } - mForcedRoute = AudioSystem::ROUTE_SPEAKER; - } - LOGV("mForcedSpeakerCount incremented to %d", mForcedSpeakerCount); - } - break; - case ACTIVE_TRACK_REMOVED: - { - AutoMutex lock(mHardwareLock); - if (mForcedSpeakerCount > 0){ - if (--mForcedSpeakerCount == 0) { - mRouteRestoreTime = systemTime() + milliseconds(kStopSleepTime/1000); - } - LOGV("mForcedSpeakerCount decremented to %d", mForcedSpeakerCount); - } else { - LOGE("mForcedSpeakerCount is already zero"); - } - } - break; - case CHECK_ROUTE_RESTORE_TIME: - case FORCE_ROUTE_RESTORE: - if (mRouteRestoreTime) { - AutoMutex lock(mHardwareLock); - if (mRouteRestoreTime && - (systemTime() > mRouteRestoreTime || command == FORCE_ROUTE_RESTORE)) { - mHardwareMixerThread->setStreamMute(AudioSystem::MUSIC, mMusicMuteSaved); - mForcedRoute = 0; - if (!(mSavedRoute & AudioSystem::ROUTE_SPEAKER)) { - mHardwareStatus = AUDIO_HW_SET_ROUTING; - mAudioHardware->setRouting(AudioSystem::MODE_NORMAL, mSavedRoute); - mHardwareStatus = AUDIO_HW_IDLE; - LOGV("Route forced to Speaker OFF %08x", mSavedRoute); - } - mRouteRestoreTime = 0; - } - } - break; - } -} - - -// ---------------------------------------------------------------------------- - -AudioFlinger::MixerThread::MixerThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int outputType) - : Thread(false), - mAudioFlinger(audioFlinger), mAudioMixer(0), mOutput(output), mOutputType(outputType), - mSampleRate(0), mFrameCount(0), mChannelCount(0), mFormat(0), mMixBuffer(0), - mLastWriteTime(0), mNumWrites(0), mNumDelayedWrites(0), mStandby(false), - mInWrite(false) -{ - mSampleRate = output->sampleRate(); - mChannelCount = output->channelCount(); - - // FIXME - Current mixer implementation only supports stereo output - if (mChannelCount == 1) { - LOGE("Invalid audio hardware channel count"); - } - - mFormat = output->format(); - mFrameCount = output->bufferSize() / output->channelCount() / sizeof(int16_t); - mAudioMixer = new AudioMixer(mFrameCount, output->sampleRate()); - - // FIXME - Current mixer implementation only supports stereo output: Always - // Allocate a stereo buffer even if HW output is mono. - mMixBuffer = new int16_t[mFrameCount * 2]; - memset(mMixBuffer, 0, mFrameCount * 2 * sizeof(int16_t)); -} - -AudioFlinger::MixerThread::~MixerThread() -{ - delete [] mMixBuffer; - delete mAudioMixer; -} - -status_t AudioFlinger::MixerThread::dump(int fd, const Vector<String16>& args) -{ - dumpInternals(fd, args); - dumpTracks(fd, args); - return NO_ERROR; -} - -status_t AudioFlinger::MixerThread::dumpTracks(int fd, const Vector<String16>& args) -{ - const size_t SIZE = 256; - char buffer[SIZE]; - String8 result; - - snprintf(buffer, SIZE, "Output %d mixer thread tracks\n", mOutputType); - result.append(buffer); - result.append(" Name Clien Typ Fmt Chn Buf S M F SRate LeftV RighV Serv User\n"); - for (size_t i = 0; i < mTracks.size(); ++i) { - wp<Track> wTrack = mTracks[i]; - if (wTrack != 0) { - sp<Track> track = wTrack.promote(); - if (track != 0) { - track->dump(buffer, SIZE); - result.append(buffer); - } - } - } - - snprintf(buffer, SIZE, "Output %d mixer thread active tracks\n", mOutputType); - result.append(buffer); - result.append(" Name Clien Typ Fmt Chn Buf S M F SRate LeftV RighV Serv User\n"); - for (size_t i = 0; i < mActiveTracks.size(); ++i) { - wp<Track> wTrack = mTracks[i]; - if (wTrack != 0) { - sp<Track> track = wTrack.promote(); - if (track != 0) { - track->dump(buffer, SIZE); - result.append(buffer); - } - } - } - write(fd, result.string(), result.size()); - return NO_ERROR; -} - -status_t AudioFlinger::MixerThread::dumpInternals(int fd, const Vector<String16>& args) -{ - const size_t SIZE = 256; - char buffer[SIZE]; - String8 result; - - snprintf(buffer, SIZE, "Output %d mixer thread internals\n", mOutputType); - result.append(buffer); - snprintf(buffer, SIZE, "AudioMixer tracks: %08x\n", mAudioMixer->trackNames()); - result.append(buffer); - snprintf(buffer, SIZE, "last write occurred (msecs): %llu\n", ns2ms(systemTime() - mLastWriteTime)); - result.append(buffer); - snprintf(buffer, SIZE, "total writes: %d\n", mNumWrites); - result.append(buffer); - snprintf(buffer, SIZE, "delayed writes: %d\n", mNumDelayedWrites); - result.append(buffer); - snprintf(buffer, SIZE, "blocked in write: %d\n", mInWrite); - result.append(buffer); - snprintf(buffer, SIZE, "standby: %d\n", mStandby); - result.append(buffer); - write(fd, result.string(), result.size()); - return NO_ERROR; -} - -// Thread virtuals -bool AudioFlinger::MixerThread::threadLoop() -{ - unsigned long sleepTime = kBufferRecoveryInUsecs; - int16_t* curBuf = mMixBuffer; - Vector< sp<Track> > tracksToRemove; - size_t enabledTracks = 0; - nsecs_t standbyTime = systemTime(); - size_t mixBufferSize = mFrameCount*mChannelCount*sizeof(int16_t); - nsecs_t maxPeriod = seconds(mFrameCount) / mSampleRate * 2; - -#ifdef WITH_A2DP - bool outputTrackActive = false; -#endif - - do { - enabledTracks = 0; - { // scope for the mLock - - Mutex::Autolock _l(mLock); - -#ifdef WITH_A2DP - if (mOutputType == AudioSystem::AUDIO_OUTPUT_A2DP) { - mAudioFlinger->handleOutputSwitch(); - } - if (mOutputTrack != NULL && !mAudioFlinger->isA2dpEnabled()) { - if (outputTrackActive) { - mOutputTrack->stop(); - outputTrackActive = false; - } - } -#endif - - const SortedVector< wp<Track> >& activeTracks = mActiveTracks; - - // put audio hardware into standby after short delay - if UNLIKELY(!activeTracks.size() && systemTime() > standbyTime) { - // wait until we have something to do... - LOGV("Audio hardware entering standby, output %d\n", mOutputType); -// mAudioFlinger->mHardwareStatus = AUDIO_HW_STANDBY; - if (!mStandby) { - mOutput->standby(); - mStandby = true; - } - -#ifdef WITH_A2DP - if (outputTrackActive) { - mOutputTrack->stop(); - outputTrackActive = false; - } -#endif - if (mOutputType == AudioSystem::AUDIO_OUTPUT_HARDWARE) { - mAudioFlinger->handleForcedSpeakerRoute(FORCE_ROUTE_RESTORE); - } -// mHardwareStatus = AUDIO_HW_IDLE; - // we're about to wait, flush the binder command buffer - IPCThreadState::self()->flushCommands(); - mWaitWorkCV.wait(mLock); - LOGV("Audio hardware exiting standby, output %d\n", mOutputType); - standbyTime = systemTime() + kStandbyTimeInNsecs; - continue; - } - - // Forced route to speaker is handled by hardware mixer thread - if (mOutputType == AudioSystem::AUDIO_OUTPUT_HARDWARE) { - mAudioFlinger->handleForcedSpeakerRoute(CHECK_ROUTE_RESTORE_TIME); - } - - // find out which tracks need to be processed - size_t count = activeTracks.size(); - for (size_t i=0 ; i<count ; i++) { - sp<Track> t = activeTracks[i].promote(); - if (t == 0) continue; - - Track* const track = t.get(); - audio_track_cblk_t* cblk = track->cblk(); - - // The first time a track is added we wait - // for all its buffers to be filled before processing it - mAudioMixer->setActiveTrack(track->name()); - if (cblk->framesReady() && (track->isReady() || track->isStopped()) && - !track->isPaused()) - { - //LOGV("track %d u=%08x, s=%08x [OK]", track->name(), cblk->user, cblk->server); - - // compute volume for this track - int16_t left, right; - if (track->isMuted() || mMasterMute || track->isPausing()) { - left = right = 0; - if (track->isPausing()) { - LOGV("paused(%d)", track->name()); - track->setPaused(); - } - } else { - float typeVolume = mStreamTypes[track->type()].volume; - float v = mMasterVolume * typeVolume; - float v_clamped = v * cblk->volume[0]; - if (v_clamped > MAX_GAIN) v_clamped = MAX_GAIN; - left = int16_t(v_clamped); - v_clamped = v * cblk->volume[1]; - if (v_clamped > MAX_GAIN) v_clamped = MAX_GAIN; - right = int16_t(v_clamped); - } - - // XXX: these things DON'T need to be done each time - mAudioMixer->setBufferProvider(track); - mAudioMixer->enable(AudioMixer::MIXING); - - int param; - if ( track->mFillingUpStatus == Track::FS_FILLED) { - // no ramp for the first volume setting - track->mFillingUpStatus = Track::FS_ACTIVE; - if (track->mState == TrackBase::RESUMING) { - track->mState = TrackBase::ACTIVE; - param = AudioMixer::RAMP_VOLUME; - } else { - param = AudioMixer::VOLUME; - } - } else { - param = AudioMixer::RAMP_VOLUME; - } - mAudioMixer->setParameter(param, AudioMixer::VOLUME0, left); - mAudioMixer->setParameter(param, AudioMixer::VOLUME1, right); - mAudioMixer->setParameter( - AudioMixer::TRACK, - AudioMixer::FORMAT, track->format()); - mAudioMixer->setParameter( - AudioMixer::TRACK, - AudioMixer::CHANNEL_COUNT, track->channelCount()); - mAudioMixer->setParameter( - AudioMixer::RESAMPLE, - AudioMixer::SAMPLE_RATE, - int(cblk->sampleRate)); - - // reset retry count - track->mRetryCount = kMaxTrackRetries; - enabledTracks++; - } else { - //LOGV("track %d u=%08x, s=%08x [NOT READY]", track->name(), cblk->user, cblk->server); - if (track->isStopped()) { - track->reset(); - } - if (track->isTerminated() || track->isStopped() || track->isPaused()) { - // We have consumed all the buffers of this track. - // Remove it from the list of active tracks. - LOGV("remove(%d) from active list", track->name()); - tracksToRemove.add(track); - } else { - // No buffers for this track. Give it a few chances to - // fill a buffer, then remove it from active list. - if (--(track->mRetryCount) <= 0) { - LOGV("BUFFER TIMEOUT: remove(%d) from active list", track->name()); - tracksToRemove.add(track); - } - } - // LOGV("disable(%d)", track->name()); - mAudioMixer->disable(AudioMixer::MIXING); - } - } - - // remove all the tracks that need to be... - count = tracksToRemove.size(); - if (UNLIKELY(count)) { - for (size_t i=0 ; i<count ; i++) { - const sp<Track>& track = tracksToRemove[i]; - removeActiveTrack(track); - if (track->isTerminated()) { - mTracks.remove(track); - deleteTrackName(track->mName); - } - } - } - } - - if (LIKELY(enabledTracks)) { - // mix buffers... - mAudioMixer->process(curBuf); - -#ifdef WITH_A2DP - if (mOutputTrack != NULL && mAudioFlinger->isA2dpEnabled()) { - if (!outputTrackActive) { - LOGV("starting output track in mixer for output %d", mOutputType); - mOutputTrack->start(); - outputTrackActive = true; - } - mOutputTrack->write(curBuf, mFrameCount); - } -#endif - - // output audio to hardware - mLastWriteTime = systemTime(); - mInWrite = true; - mOutput->write(curBuf, mixBufferSize); - mNumWrites++; - mInWrite = false; - mStandby = false; - nsecs_t temp = systemTime(); - standbyTime = temp + kStandbyTimeInNsecs; - nsecs_t delta = temp - mLastWriteTime; - if (delta > maxPeriod) { - LOGW("write blocked for %llu msecs", ns2ms(delta)); - mNumDelayedWrites++; - } - sleepTime = kBufferRecoveryInUsecs; - } else { -#ifdef WITH_A2DP - if (mOutputTrack != NULL && mAudioFlinger->isA2dpEnabled()) { - if (outputTrackActive) { - mOutputTrack->write(curBuf, 0); - if (mOutputTrack->bufferQueueEmpty()) { - mOutputTrack->stop(); - outputTrackActive = false; - } else { - standbyTime = systemTime() + kStandbyTimeInNsecs; - } - } - } -#endif - // There was nothing to mix this round, which means all - // active tracks were late. Sleep a little bit to give - // them another chance. If we're too late, the audio - // hardware will zero-fill for us. - //LOGV("no buffers - usleep(%lu)", sleepTime); - usleep(sleepTime); - if (sleepTime < kMaxBufferRecoveryInUsecs) { - sleepTime += kBufferRecoveryInUsecs; - } - } - - // finally let go of all our tracks, without the lock held - // since we can't guarantee the destructors won't acquire that - // same lock. - tracksToRemove.clear(); - } while (true); - - return false; -} - -status_t AudioFlinger::MixerThread::readyToRun() -{ - if (mSampleRate == 0) { - LOGE("No working audio driver found."); - return NO_INIT; - } - LOGI("AudioFlinger's thread ready to run for output %d", mOutputType); - return NO_ERROR; -} - -void AudioFlinger::MixerThread::onFirstRef() -{ - const size_t SIZE = 256; - char buffer[SIZE]; - - snprintf(buffer, SIZE, "Mixer Thread for output %d", mOutputType); - - run(buffer, ANDROID_PRIORITY_URGENT_AUDIO); -} - - -sp<AudioFlinger::MixerThread::Track> AudioFlinger::MixerThread::createTrack( - const sp<AudioFlinger::Client>& client, - int streamType, - uint32_t sampleRate, - int format, - int channelCount, - int frameCount, - const sp<IMemory>& sharedBuffer, - status_t *status) -{ - sp<Track> track; - status_t lStatus; - - // Resampler implementation limits input sampling rate to 2 x output sampling rate. - if (sampleRate > MAX_SAMPLE_RATE || sampleRate > mSampleRate*2) { - LOGE("Sample rate out of range: %d mSampleRate %d", sampleRate, mSampleRate); - lStatus = BAD_VALUE; - goto Exit; - } - - { - Mutex::Autolock _l(mLock); - - if (mSampleRate == 0) { - LOGE("Audio driver not initialized."); - lStatus = NO_INIT; - goto Exit; - } - - track = new Track(this, client, streamType, sampleRate, format, - channelCount, frameCount, sharedBuffer); - if (track->getCblk() == NULL) { - track.clear(); - lStatus = NO_MEMORY; - goto Exit; - } - mTracks.add(track); - lStatus = NO_ERROR; - } - -Exit: - if(status) { - *status = lStatus; - } - return track; -} - -void AudioFlinger::MixerThread::getTracks( - SortedVector < sp<Track> >& tracks, - SortedVector < wp<Track> >& activeTracks) -{ - size_t size = mTracks.size(); - LOGV ("MixerThread::getTracks() for output %d, mTracks.size %d, mActiveTracks.size %d", mOutputType, mTracks.size(), mActiveTracks.size()); - for (size_t i = 0; i < size; i++) { - sp<Track> t = mTracks[i]; - if (AudioSystem::routedToA2dpOutput(t->mStreamType)) { - tracks.add(t); - int j = mActiveTracks.indexOf(t); - if (j >= 0) { - t = mActiveTracks[j].promote(); - if (t != NULL) { - activeTracks.add(t); - } - } - } - } - - size = activeTracks.size(); - for (size_t i = 0; i < size; i++) { - removeActiveTrack(activeTracks[i]); - } - - size = tracks.size(); - for (size_t i = 0; i < size; i++) { - sp<Track> t = tracks[i]; - mTracks.remove(t); - deleteTrackName(t->name()); - } -} - -void AudioFlinger::MixerThread::putTracks( - SortedVector < sp<Track> >& tracks, - SortedVector < wp<Track> >& activeTracks) -{ - - LOGV ("MixerThread::putTracks() for output %d, tracks.size %d, activeTracks.size %d", mOutputType, tracks.size(), activeTracks.size()); - - size_t size = tracks.size(); - for (size_t i = 0; i < size ; i++) { - sp<Track> t = tracks[i]; - int name = getTrackName(); - - if (name < 0) return; - - t->mName = name; - t->mMixerThread = this; - mTracks.add(t); - - int j = activeTracks.indexOf(t); - if (j >= 0) { - addActiveTrack(t); - } - } -} - -uint32_t AudioFlinger::MixerThread::sampleRate() const -{ - return mSampleRate; -} - -int AudioFlinger::MixerThread::channelCount() const -{ - return mChannelCount; -} - -int AudioFlinger::MixerThread::format() const -{ - return mFormat; -} - -size_t AudioFlinger::MixerThread::frameCount() const -{ - return mFrameCount; -} - -uint32_t AudioFlinger::MixerThread::latency() const -{ - if (mOutput) { - return mOutput->latency(); - } - else { - return 0; - } -} - -status_t AudioFlinger::MixerThread::setMasterVolume(float value) -{ - mMasterVolume = value; - return NO_ERROR; -} - -status_t AudioFlinger::MixerThread::setMasterMute(bool muted) -{ - mMasterMute = muted; - return NO_ERROR; -} - -float AudioFlinger::MixerThread::masterVolume() const -{ - return mMasterVolume; -} - -bool AudioFlinger::MixerThread::masterMute() const -{ - return mMasterMute; -} - -status_t AudioFlinger::MixerThread::setStreamVolume(int stream, float value) -{ - mStreamTypes[stream].volume = value; - return NO_ERROR; -} - -status_t AudioFlinger::MixerThread::setStreamMute(int stream, bool muted) -{ - mStreamTypes[stream].mute = muted; - return NO_ERROR; -} - -float AudioFlinger::MixerThread::streamVolume(int stream) const -{ - return mStreamTypes[stream].volume; -} - -bool AudioFlinger::MixerThread::streamMute(int stream) const -{ - return mStreamTypes[stream].mute; -} - -bool AudioFlinger::MixerThread::isMusicActive() const -{ - size_t count = mActiveTracks.size(); - for (size_t i = 0 ; i < count ; ++i) { - sp<Track> t = mActiveTracks[i].promote(); - if (t == 0) continue; - Track* const track = t.get(); - if (t->mStreamType == AudioSystem::MUSIC) - return true; - } - return false; -} - -status_t AudioFlinger::MixerThread::addTrack(const sp<Track>& track) -{ - status_t status = ALREADY_EXISTS; - Mutex::Autolock _l(mLock); - - // here the track could be either new, or restarted - // in both cases "unstop" the track - if (track->isPaused()) { - track->mState = TrackBase::RESUMING; - LOGV("PAUSED => RESUMING (%d)", track->name()); - } else { - track->mState = TrackBase::ACTIVE; - LOGV("? => ACTIVE (%d)", track->name()); - } - // set retry count for buffer fill - track->mRetryCount = kMaxTrackStartupRetries; - if (mActiveTracks.indexOf(track) < 0) { - // the track is newly added, make sure it fills up all its - // buffers before playing. This is to ensure the client will - // effectively get the latency it requested. - track->mFillingUpStatus = Track::FS_FILLING; - track->mResetDone = false; - addActiveTrack(track); - status = NO_ERROR; - } - - LOGV("mWaitWorkCV.broadcast"); - mWaitWorkCV.broadcast(); - - return status; -} - -void AudioFlinger::MixerThread::removeTrack(wp<Track> track, int name) -{ - Mutex::Autolock _l(mLock); - sp<Track> t = track.promote(); - if (t!=NULL && (t->mState <= TrackBase::STOPPED)) { - remove_track_l(track, name); - } -} - -void AudioFlinger::MixerThread::remove_track_l(wp<Track> track, int name) -{ - sp<Track> t = track.promote(); - if (t!=NULL) { - t->reset(); - } - deleteTrackName(name); - removeActiveTrack(track); - mWaitWorkCV.broadcast(); -} - -void AudioFlinger::MixerThread::destroyTrack(const sp<Track>& track) -{ - // NOTE: We're acquiring a strong reference on the track before - // acquiring the lock, this is to make sure removing it from - // mTracks won't cause the destructor to be called while the lock is - // held (note that technically, 'track' could be a reference to an item - // in mTracks, which is why we need to do this). - sp<Track> keep(track); - Mutex::Autolock _l(mLock); - track->mState = TrackBase::TERMINATED; - if (mActiveTracks.indexOf(track) < 0) { - LOGV("remove track (%d) and delete from mixer", track->name()); - mTracks.remove(track); - deleteTrackName(keep->name()); - } -} - - -void AudioFlinger::MixerThread::addActiveTrack(const wp<Track>& t) -{ - mActiveTracks.add(t); - - // Force routing to speaker for certain stream types - // The forced routing to speaker is managed by hardware mixer - if (mOutputType == AudioSystem::AUDIO_OUTPUT_HARDWARE) { - sp<Track> track = t.promote(); - if (track == NULL) return; - - if (streamForcedToSpeaker(track->type())) { - mAudioFlinger->handleForcedSpeakerRoute(ACTIVE_TRACK_ADDED); - } - } -} - -void AudioFlinger::MixerThread::removeActiveTrack(const wp<Track>& t) -{ - mActiveTracks.remove(t); - - // Force routing to speaker for certain stream types - // The forced routing to speaker is managed by hardware mixer - if (mOutputType == AudioSystem::AUDIO_OUTPUT_HARDWARE) { - sp<Track> track = t.promote(); - if (track == NULL) return; - - if (streamForcedToSpeaker(track->type())) { - mAudioFlinger->handleForcedSpeakerRoute(ACTIVE_TRACK_REMOVED); - } - } -} - -int AudioFlinger::MixerThread::getTrackName() -{ - return mAudioMixer->getTrackName(); -} - -void AudioFlinger::MixerThread::deleteTrackName(int name) -{ - mAudioMixer->deleteTrackName(name); -} - -size_t AudioFlinger::MixerThread::getOutputFrameCount() -{ - return mOutput->bufferSize() / mOutput->channelCount() / sizeof(int16_t); -} - -// ---------------------------------------------------------------------------- - -AudioFlinger::MixerThread::TrackBase::TrackBase( - const sp<MixerThread>& mixerThread, - const sp<Client>& client, - int streamType, - uint32_t sampleRate, - int format, - int channelCount, - int frameCount, - uint32_t flags, - const sp<IMemory>& sharedBuffer) - : RefBase(), - mMixerThread(mixerThread), - mClient(client), - mStreamType(streamType), - mFrameCount(0), - mState(IDLE), - mClientTid(-1), - mFormat(format), - mFlags(flags & ~SYSTEM_FLAGS_MASK) -{ - mName = mixerThread->getTrackName(); - LOGV("TrackBase contructor name %d, calling thread %d", mName, IPCThreadState::self()->getCallingPid()); - if (mName < 0) { - LOGE("no more track names availlable"); - return; - } - - LOGV_IF(sharedBuffer != 0, "sharedBuffer: %p, size: %d", sharedBuffer->pointer(), sharedBuffer->size()); - - // LOGD("Creating track with %d buffers @ %d bytes", bufferCount, bufferSize); - size_t size = sizeof(audio_track_cblk_t); - size_t bufferSize = frameCount*channelCount*sizeof(int16_t); - if (sharedBuffer == 0) { - size += bufferSize; - } - - if (client != NULL) { - mCblkMemory = client->heap()->allocate(size); - if (mCblkMemory != 0) { - mCblk = static_cast<audio_track_cblk_t *>(mCblkMemory->pointer()); - if (mCblk) { // construct the shared structure in-place. - new(mCblk) audio_track_cblk_t(); - // clear all buffers - mCblk->frameCount = frameCount; - mCblk->sampleRate = sampleRate; - mCblk->channels = channelCount; - if (sharedBuffer == 0) { - mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t); - memset(mBuffer, 0, frameCount*channelCount*sizeof(int16_t)); - // Force underrun condition to avoid false underrun callback until first data is - // written to buffer - mCblk->flowControlFlag = 1; - } else { - mBuffer = sharedBuffer->pointer(); - } - mBufferEnd = (uint8_t *)mBuffer + bufferSize; - } - } else { - LOGE("not enough memory for AudioTrack size=%u", size); - client->heap()->dump("AudioTrack"); - return; - } - } else { - mCblk = (audio_track_cblk_t *)(new uint8_t[size]); - if (mCblk) { // construct the shared structure in-place. - new(mCblk) audio_track_cblk_t(); - // clear all buffers - mCblk->frameCount = frameCount; - mCblk->sampleRate = sampleRate; - mCblk->channels = channelCount; - mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t); - memset(mBuffer, 0, frameCount*channelCount*sizeof(int16_t)); - // Force underrun condition to avoid false underrun callback until first data is - // written to buffer - mCblk->flowControlFlag = 1; - mBufferEnd = (uint8_t *)mBuffer + bufferSize; - } - } -} - -AudioFlinger::MixerThread::TrackBase::~TrackBase() -{ - if (mCblk) { - mCblk->~audio_track_cblk_t(); // destroy our shared-structure. - } - mCblkMemory.clear(); // and free the shared memory - mClient.clear(); -} - -void AudioFlinger::MixerThread::TrackBase::releaseBuffer(AudioBufferProvider::Buffer* buffer) -{ - buffer->raw = 0; - mFrameCount = buffer->frameCount; - step(); - buffer->frameCount = 0; -} - -bool AudioFlinger::MixerThread::TrackBase::step() { - bool result; - audio_track_cblk_t* cblk = this->cblk(); - - result = cblk->stepServer(mFrameCount); - if (!result) { - LOGV("stepServer failed acquiring cblk mutex"); - mFlags |= STEPSERVER_FAILED; - } - return result; -} - -void AudioFlinger::MixerThread::TrackBase::reset() { - audio_track_cblk_t* cblk = this->cblk(); - - cblk->user = 0; - cblk->server = 0; - cblk->userBase = 0; - cblk->serverBase = 0; - mFlags &= (uint32_t)(~SYSTEM_FLAGS_MASK); - LOGV("TrackBase::reset"); -} - -sp<IMemory> AudioFlinger::MixerThread::TrackBase::getCblk() const -{ - return mCblkMemory; -} - -int AudioFlinger::MixerThread::TrackBase::sampleRate() const { - return mCblk->sampleRate; -} - -int AudioFlinger::MixerThread::TrackBase::channelCount() const { - return mCblk->channels; -} - -void* AudioFlinger::MixerThread::TrackBase::getBuffer(uint32_t offset, uint32_t frames) const { - audio_track_cblk_t* cblk = this->cblk(); - int16_t *bufferStart = (int16_t *)mBuffer + (offset-cblk->serverBase)*cblk->channels; - int16_t *bufferEnd = bufferStart + frames * cblk->channels; - - // Check validity of returned pointer in case the track control block would have been corrupted. - if (bufferStart < mBuffer || bufferStart > bufferEnd || bufferEnd > mBufferEnd) { - LOGW("TrackBase::getBuffer buffer out of range:\n start: %p, end %p , mBuffer %p mBufferEnd %p\n \ - server %d, serverBase %d, user %d, userBase %d", - bufferStart, bufferEnd, mBuffer, mBufferEnd, - cblk->server, cblk->serverBase, cblk->user, cblk->userBase); - return 0; - } - - return bufferStart; -} - -// ---------------------------------------------------------------------------- - -AudioFlinger::MixerThread::Track::Track( - const sp<MixerThread>& mixerThread, - const sp<Client>& client, - int streamType, - uint32_t sampleRate, - int format, - int channelCount, - int frameCount, - const sp<IMemory>& sharedBuffer) - : TrackBase(mixerThread, client, streamType, sampleRate, format, channelCount, frameCount, 0, sharedBuffer) -{ - mVolume[0] = 1.0f; - mVolume[1] = 1.0f; - mMute = false; - mSharedBuffer = sharedBuffer; -} - -AudioFlinger::MixerThread::Track::~Track() -{ - wp<Track> weak(this); // never create a strong ref from the dtor - mState = TERMINATED; - mMixerThread->removeTrack(weak, mName); -} - -void AudioFlinger::MixerThread::Track::destroy() -{ - mMixerThread->destroyTrack(this); -} - -void AudioFlinger::MixerThread::Track::dump(char* buffer, size_t size) -{ - snprintf(buffer, size, " %5d %5d %3u %3u %3u %3u %1d %1d %1d %5u %5u %5u %04x %04x\n", - mName - AudioMixer::TRACK0, - (mClient == NULL) ? getpid() : mClient->pid(), - mStreamType, - mFormat, - mCblk->channels, - mFrameCount, - mState, - mMute, - mFillingUpStatus, - mCblk->sampleRate, - mCblk->volume[0], - mCblk->volume[1], - mCblk->server, - mCblk->user); -} - -status_t AudioFlinger::MixerThread::Track::getNextBuffer(AudioBufferProvider::Buffer* buffer) -{ - audio_track_cblk_t* cblk = this->cblk(); - uint32_t framesReady; - uint32_t framesReq = buffer->frameCount; - - // Check if last stepServer failed, try to step now - if (mFlags & TrackBase::STEPSERVER_FAILED) { - if (!step()) goto getNextBuffer_exit; - LOGV("stepServer recovered"); - mFlags &= ~TrackBase::STEPSERVER_FAILED; - } - - framesReady = cblk->framesReady(); - - if (LIKELY(framesReady)) { - uint32_t s = cblk->server; - uint32_t bufferEnd = cblk->serverBase + cblk->frameCount; - - bufferEnd = (cblk->loopEnd < bufferEnd) ? cblk->loopEnd : bufferEnd; - if (framesReq > framesReady) { - framesReq = framesReady; - } - if (s + framesReq > bufferEnd) { - framesReq = bufferEnd - s; - } - - buffer->raw = getBuffer(s, framesReq); - if (buffer->raw == 0) goto getNextBuffer_exit; - - buffer->frameCount = framesReq; - return NO_ERROR; - } - -getNextBuffer_exit: - buffer->raw = 0; - buffer->frameCount = 0; - return NOT_ENOUGH_DATA; -} - -bool AudioFlinger::MixerThread::Track::isReady() const { - if (mFillingUpStatus != FS_FILLING) return true; - - if (mCblk->framesReady() >= mCblk->frameCount || - mCblk->forceReady) { - mFillingUpStatus = FS_FILLED; - mCblk->forceReady = 0; - LOGV("Track::isReady() track %d for output %d", mName, mMixerThread->mOutputType); - return true; - } - return false; -} - -status_t AudioFlinger::MixerThread::Track::start() -{ - LOGV("start(%d), calling thread %d for output %d", mName, IPCThreadState::self()->getCallingPid(), mMixerThread->mOutputType); - mMixerThread->addTrack(this); - return NO_ERROR; -} - -void AudioFlinger::MixerThread::Track::stop() -{ - LOGV("stop(%d), calling thread %d for output %d", mName, IPCThreadState::self()->getCallingPid(), mMixerThread->mOutputType); - Mutex::Autolock _l(mMixerThread->mLock); - if (mState > STOPPED) { - mState = STOPPED; - // If the track is not active (PAUSED and buffers full), flush buffers - if (mMixerThread->mActiveTracks.indexOf(this) < 0) { - reset(); - } - LOGV("(> STOPPED) => STOPPED (%d)", mName); - } -} - -void AudioFlinger::MixerThread::Track::pause() -{ - LOGV("pause(%d), calling thread %d", mName, IPCThreadState::self()->getCallingPid()); - Mutex::Autolock _l(mMixerThread->mLock); - if (mState == ACTIVE || mState == RESUMING) { - mState = PAUSING; - LOGV("ACTIVE/RESUMING => PAUSING (%d)", mName); - } -} - -void AudioFlinger::MixerThread::Track::flush() -{ - LOGV("flush(%d)", mName); - Mutex::Autolock _l(mMixerThread->mLock); - if (mState != STOPPED && mState != PAUSED && mState != PAUSING) { - return; - } - // No point remaining in PAUSED state after a flush => go to - // STOPPED state - mState = STOPPED; - - // NOTE: reset() will reset cblk->user and cblk->server with - // the risk that at the same time, the AudioMixer is trying to read - // data. In this case, getNextBuffer() would return a NULL pointer - // as audio buffer => the AudioMixer code MUST always test that pointer - // returned by getNextBuffer() is not NULL! - reset(); -} - -void AudioFlinger::MixerThread::Track::reset() -{ - // Do not reset twice to avoid discarding data written just after a flush and before - // the audioflinger thread detects the track is stopped. - if (!mResetDone) { - TrackBase::reset(); - // Force underrun condition to avoid false underrun callback until first data is - // written to buffer - mCblk->flowControlFlag = 1; - mCblk->forceReady = 0; - mFillingUpStatus = FS_FILLING; - mResetDone = true; - } -} - -void AudioFlinger::MixerThread::Track::mute(bool muted) -{ - mMute = muted; -} - -void AudioFlinger::MixerThread::Track::setVolume(float left, float right) -{ - mVolume[0] = left; - mVolume[1] = right; -} - -// ---------------------------------------------------------------------------- - -AudioFlinger::MixerThread::RecordTrack::RecordTrack( - const sp<MixerThread>& mixerThread, - const sp<Client>& client, - int streamType, - uint32_t sampleRate, - int format, - int channelCount, - int frameCount, - uint32_t flags) - : TrackBase(mixerThread, client, streamType, sampleRate, format, - channelCount, frameCount, flags, 0), - mOverflow(false) -{ -} - -AudioFlinger::MixerThread::RecordTrack::~RecordTrack() -{ - mMixerThread->deleteTrackName(mName); -} - -status_t AudioFlinger::MixerThread::RecordTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer) -{ - audio_track_cblk_t* cblk = this->cblk(); - uint32_t framesAvail; - uint32_t framesReq = buffer->frameCount; - - // Check if last stepServer failed, try to step now - if (mFlags & TrackBase::STEPSERVER_FAILED) { - if (!step()) goto getNextBuffer_exit; - LOGV("stepServer recovered"); - mFlags &= ~TrackBase::STEPSERVER_FAILED; - } - - framesAvail = cblk->framesAvailable_l(); - - if (LIKELY(framesAvail)) { - uint32_t s = cblk->server; - uint32_t bufferEnd = cblk->serverBase + cblk->frameCount; - - if (framesReq > framesAvail) { - framesReq = framesAvail; - } - if (s + framesReq > bufferEnd) { - framesReq = bufferEnd - s; - } - - buffer->raw = getBuffer(s, framesReq); - if (buffer->raw == 0) goto getNextBuffer_exit; - - buffer->frameCount = framesReq; - return NO_ERROR; - } - -getNextBuffer_exit: - buffer->raw = 0; - buffer->frameCount = 0; - return NOT_ENOUGH_DATA; -} - -status_t AudioFlinger::MixerThread::RecordTrack::start() -{ - return mMixerThread->mAudioFlinger->startRecord(this); -} - -void AudioFlinger::MixerThread::RecordTrack::stop() -{ - mMixerThread->mAudioFlinger->stopRecord(this); - TrackBase::reset(); - // Force overerrun condition to avoid false overrun callback until first data is - // read from buffer - mCblk->flowControlFlag = 1; -} - - -// ---------------------------------------------------------------------------- - -AudioFlinger::MixerThread::OutputTrack::OutputTrack( - const sp<MixerThread>& mixerThread, - uint32_t sampleRate, - int format, - int channelCount, - int frameCount) - : Track(mixerThread, NULL, AudioSystem::SYSTEM, sampleRate, format, channelCount, frameCount, NULL), - mOutputMixerThread(mixerThread) -{ - - mCblk->out = 1; - mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t); - mCblk->volume[0] = mCblk->volume[1] = 0x1000; - mOutBuffer.frameCount = 0; - mCblk->bufferTimeoutMs = 10; - - LOGV("OutputTrack constructor mCblk %p, mBuffer %p, mCblk->buffers %p, mCblk->frameCount %d, mCblk->sampleRate %d, mCblk->channels %d mBufferEnd %p", - mCblk, mBuffer, mCblk->buffers, mCblk->frameCount, mCblk->sampleRate, mCblk->channels, mBufferEnd); - -} - -AudioFlinger::MixerThread::OutputTrack::~OutputTrack() -{ - stop(); -} - -status_t AudioFlinger::MixerThread::OutputTrack::start() -{ - status_t status = Track::start(); - - mRetryCount = 127; - return status; -} - -void AudioFlinger::MixerThread::OutputTrack::stop() -{ - Track::stop(); - clearBufferQueue(); - mOutBuffer.frameCount = 0; -} - -void AudioFlinger::MixerThread::OutputTrack::write(int16_t* data, uint32_t frames) -{ - Buffer *pInBuffer; - Buffer inBuffer; - uint32_t channels = mCblk->channels; - - inBuffer.frameCount = frames; - inBuffer.i16 = data; - - if (mCblk->user == 0) { - if (mOutputMixerThread->isMusicActive()) { - mCblk->forceReady = 1; - LOGV("OutputTrack::start() force ready"); - } else if (mCblk->frameCount > frames){ - if (mBufferQueue.size() < kMaxOutputTrackBuffers) { - uint32_t startFrames = (mCblk->frameCount - frames); - LOGV("OutputTrack::start() write %d frames", startFrames); - pInBuffer = new Buffer; - pInBuffer->mBuffer = new int16_t[startFrames * channels]; - pInBuffer->frameCount = startFrames; - pInBuffer->i16 = pInBuffer->mBuffer; - memset(pInBuffer->raw, 0, startFrames * channels * sizeof(int16_t)); - mBufferQueue.add(pInBuffer); - } else { - LOGW ("OutputTrack::write() no more buffers"); - } - } - } - - while (1) { - // First write pending buffers, then new data - if (mBufferQueue.size()) { - pInBuffer = mBufferQueue.itemAt(0); - } else { - pInBuffer = &inBuffer; - } - - if (pInBuffer->frameCount == 0) { - break; - } - - if (mOutBuffer.frameCount == 0) { - mOutBuffer.frameCount = pInBuffer->frameCount; - if (obtainBuffer(&mOutBuffer) == (status_t)AudioTrack::NO_MORE_BUFFERS) { - break; - } - } - - uint32_t outFrames = pInBuffer->frameCount > mOutBuffer.frameCount ? mOutBuffer.frameCount : pInBuffer->frameCount; - memcpy(mOutBuffer.raw, pInBuffer->raw, outFrames * channels * sizeof(int16_t)); - mCblk->stepUser(outFrames); - pInBuffer->frameCount -= outFrames; - pInBuffer->i16 += outFrames * channels; - mOutBuffer.frameCount -= outFrames; - mOutBuffer.i16 += outFrames * channels; - - if (pInBuffer->frameCount == 0) { - if (mBufferQueue.size()) { - mBufferQueue.removeAt(0); - delete [] pInBuffer->mBuffer; - delete pInBuffer; - } else { - break; - } - } - } - - // If we could not write all frames, allocate a buffer and queue it for next time. - if (inBuffer.frameCount) { - if (mBufferQueue.size() < kMaxOutputTrackBuffers) { - pInBuffer = new Buffer; - pInBuffer->mBuffer = new int16_t[inBuffer.frameCount * channels]; - pInBuffer->frameCount = inBuffer.frameCount; - pInBuffer->i16 = pInBuffer->mBuffer; - memcpy(pInBuffer->raw, inBuffer.raw, inBuffer.frameCount * channels * sizeof(int16_t)); - mBufferQueue.add(pInBuffer); - } else { - LOGW("OutputTrack::write() no more buffers"); - } - } - - // Calling write() with a 0 length buffer, means that no more data will be written: - // If no more buffers are pending, fill output track buffer to make sure it is started - // by output mixer. - if (frames == 0 && mBufferQueue.size() == 0 && mCblk->user < mCblk->frameCount) { - frames = mCblk->frameCount - mCblk->user; - pInBuffer = new Buffer; - pInBuffer->mBuffer = new int16_t[frames * channels]; - pInBuffer->frameCount = frames; - pInBuffer->i16 = pInBuffer->mBuffer; - memset(pInBuffer->raw, 0, frames * channels * sizeof(int16_t)); - mBufferQueue.add(pInBuffer); - } - -} - -status_t AudioFlinger::MixerThread::OutputTrack::obtainBuffer(AudioBufferProvider::Buffer* buffer) -{ - int active; - int timeout = 0; - status_t result; - audio_track_cblk_t* cblk = mCblk; - uint32_t framesReq = buffer->frameCount; - - LOGV("OutputTrack::obtainBuffer user %d, server %d", cblk->user, cblk->server); - buffer->frameCount = 0; - - uint32_t framesAvail = cblk->framesAvailable(); - - if (framesAvail == 0) { - return AudioTrack::NO_MORE_BUFFERS; - } - - if (framesReq > framesAvail) { - framesReq = framesAvail; - } - - uint32_t u = cblk->user; - uint32_t bufferEnd = cblk->userBase + cblk->frameCount; - - if (u + framesReq > bufferEnd) { - framesReq = bufferEnd - u; - } - - buffer->frameCount = framesReq; - buffer->raw = (void *)cblk->buffer(u); - return NO_ERROR; -} - - -void AudioFlinger::MixerThread::OutputTrack::clearBufferQueue() -{ - size_t size = mBufferQueue.size(); - Buffer *pBuffer; - - for (size_t i = 0; i < size; i++) { - pBuffer = mBufferQueue.itemAt(i); - delete [] pBuffer->mBuffer; - delete pBuffer; - } - mBufferQueue.clear(); -} - -// ---------------------------------------------------------------------------- - -AudioFlinger::Client::Client(const sp<AudioFlinger>& audioFlinger, pid_t pid) - : RefBase(), - mAudioFlinger(audioFlinger), - mMemoryDealer(new MemoryDealer(1024*1024)), - mPid(pid) -{ - // 1 MB of address space is good for 32 tracks, 8 buffers each, 4 KB/buffer -} - -AudioFlinger::Client::~Client() -{ - mAudioFlinger->removeClient(mPid); -} - -const sp<MemoryDealer>& AudioFlinger::Client::heap() const -{ - return mMemoryDealer; -} - -// ---------------------------------------------------------------------------- - -AudioFlinger::TrackHandle::TrackHandle(const sp<AudioFlinger::MixerThread::Track>& track) - : BnAudioTrack(), - mTrack(track) -{ -} - -AudioFlinger::TrackHandle::~TrackHandle() { - // just stop the track on deletion, associated resources - // will be freed from the main thread once all pending buffers have - // been played. Unless it's not in the active track list, in which - // case we free everything now... - mTrack->destroy(); -} - -status_t AudioFlinger::TrackHandle::start() { - return mTrack->start(); -} - -void AudioFlinger::TrackHandle::stop() { - mTrack->stop(); -} - -void AudioFlinger::TrackHandle::flush() { - mTrack->flush(); -} - -void AudioFlinger::TrackHandle::mute(bool e) { - mTrack->mute(e); -} - -void AudioFlinger::TrackHandle::pause() { - mTrack->pause(); -} - -void AudioFlinger::TrackHandle::setVolume(float left, float right) { - mTrack->setVolume(left, right); -} - -sp<IMemory> AudioFlinger::TrackHandle::getCblk() const { - return mTrack->getCblk(); -} - -status_t AudioFlinger::TrackHandle::onTransact( - uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) -{ - return BnAudioTrack::onTransact(code, data, reply, flags); -} - -// ---------------------------------------------------------------------------- - -sp<IAudioRecord> AudioFlinger::openRecord( - pid_t pid, - int streamType, - uint32_t sampleRate, - int format, - int channelCount, - int frameCount, - uint32_t flags, - status_t *status) -{ - sp<AudioRecordThread> thread; - sp<MixerThread::RecordTrack> recordTrack; - sp<RecordHandle> recordHandle; - sp<Client> client; - wp<Client> wclient; - AudioStreamIn* input = 0; - int inFrameCount; - size_t inputBufferSize; - status_t lStatus; - - // check calling permissions - if (!recordingAllowed()) { - lStatus = PERMISSION_DENIED; - goto Exit; - } - - if (uint32_t(streamType) >= AudioRecord::NUM_STREAM_TYPES) { - LOGE("invalid stream type"); - lStatus = BAD_VALUE; - goto Exit; - } - - if (sampleRate > MAX_SAMPLE_RATE) { - LOGE("Sample rate out of range"); - lStatus = BAD_VALUE; - goto Exit; - } - - if (mAudioRecordThread == 0) { - LOGE("Audio record thread not started"); - lStatus = NO_INIT; - goto Exit; - } - - - // Check that audio input stream accepts requested audio parameters - inputBufferSize = mAudioHardware->getInputBufferSize(sampleRate, format, channelCount); - if (inputBufferSize == 0) { - lStatus = BAD_VALUE; - LOGE("Bad audio input parameters: sampling rate %u, format %d, channels %d", sampleRate, format, channelCount); - goto Exit; - } - - // add client to list - { - Mutex::Autolock _l(mLock); - wclient = mClients.valueFor(pid); - if (wclient != NULL) { - client = wclient.promote(); - } else { - client = new Client(this, pid); - mClients.add(pid, client); - } - } - - // frameCount must be a multiple of input buffer size - inFrameCount = inputBufferSize/channelCount/sizeof(short); - frameCount = ((frameCount - 1)/inFrameCount + 1) * inFrameCount; - - // create new record track and pass to record thread - recordTrack = new MixerThread::RecordTrack(mHardwareMixerThread, client, streamType, sampleRate, - format, channelCount, frameCount, flags); - if (recordTrack->getCblk() == NULL) { - recordTrack.clear(); - lStatus = NO_MEMORY; - goto Exit; - } - - // return to handle to client - recordHandle = new RecordHandle(recordTrack); - lStatus = NO_ERROR; - -Exit: - if (status) { - *status = lStatus; - } - return recordHandle; -} - -status_t AudioFlinger::startRecord(MixerThread::RecordTrack* recordTrack) { - if (mAudioRecordThread != 0) { - return mAudioRecordThread->start(recordTrack); - } - return NO_INIT; -} - -void AudioFlinger::stopRecord(MixerThread::RecordTrack* recordTrack) { - if (mAudioRecordThread != 0) { - mAudioRecordThread->stop(recordTrack); - } -} - -// ---------------------------------------------------------------------------- - -AudioFlinger::RecordHandle::RecordHandle(const sp<AudioFlinger::MixerThread::RecordTrack>& recordTrack) - : BnAudioRecord(), - mRecordTrack(recordTrack) -{ -} - -AudioFlinger::RecordHandle::~RecordHandle() { - stop(); -} - -status_t AudioFlinger::RecordHandle::start() { - LOGV("RecordHandle::start()"); - return mRecordTrack->start(); -} - -void AudioFlinger::RecordHandle::stop() { - LOGV("RecordHandle::stop()"); - mRecordTrack->stop(); -} - -sp<IMemory> AudioFlinger::RecordHandle::getCblk() const { - return mRecordTrack->getCblk(); -} - -status_t AudioFlinger::RecordHandle::onTransact( - uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) -{ - return BnAudioRecord::onTransact(code, data, reply, flags); -} - -// ---------------------------------------------------------------------------- - -AudioFlinger::AudioRecordThread::AudioRecordThread(AudioHardwareInterface* audioHardware) : - mAudioHardware(audioHardware), - mActive(false) -{ -} - -AudioFlinger::AudioRecordThread::~AudioRecordThread() -{ -} - -bool AudioFlinger::AudioRecordThread::threadLoop() -{ - LOGV("AudioRecordThread: start record loop"); - AudioBufferProvider::Buffer buffer; - int inBufferSize = 0; - int inFrameCount = 0; - AudioStreamIn* input = 0; - - mActive = 0; - - // start recording - while (!exitPending()) { - if (!mActive) { - mLock.lock(); - if (!mActive && !exitPending()) { - LOGV("AudioRecordThread: loop stopping"); - if (input) { - delete input; - input = 0; - } - mRecordTrack.clear(); - mStopped.signal(); - - mWaitWorkCV.wait(mLock); - - LOGV("AudioRecordThread: loop starting"); - if (mRecordTrack != 0) { - input = mAudioHardware->openInputStream(mRecordTrack->format(), - mRecordTrack->channelCount(), - mRecordTrack->sampleRate(), - &mStartStatus, - (AudioSystem::audio_in_acoustics)(mRecordTrack->mFlags >> 16)); - if (input != 0) { - inBufferSize = input->bufferSize(); - inFrameCount = inBufferSize/input->frameSize(); - } - } else { - mStartStatus = NO_INIT; - } - if (mStartStatus !=NO_ERROR) { - LOGW("record start failed, status %d", mStartStatus); - mActive = false; - mRecordTrack.clear(); - } - mWaitWorkCV.signal(); - } - mLock.unlock(); - } else if (mRecordTrack != 0) { - - buffer.frameCount = inFrameCount; - if (LIKELY(mRecordTrack->getNextBuffer(&buffer) == NO_ERROR)) { - LOGV("AudioRecordThread read: %d frames", buffer.frameCount); - ssize_t bytesRead = input->read(buffer.raw, inBufferSize); - if (bytesRead < 0) { - LOGE("Error reading audio input"); - sleep(1); - } - mRecordTrack->releaseBuffer(&buffer); - mRecordTrack->overflow(); - } - - // client isn't retrieving buffers fast enough - else { - if (!mRecordTrack->setOverflow()) - LOGW("AudioRecordThread: buffer overflow"); - // Release the processor for a while before asking for a new buffer. - // This will give the application more chance to read from the buffer and - // clear the overflow. - usleep(5000); - } - } - } - - - if (input) { - delete input; - } - mRecordTrack.clear(); - - return false; -} - -status_t AudioFlinger::AudioRecordThread::start(MixerThread::RecordTrack* recordTrack) -{ - LOGV("AudioRecordThread::start"); - AutoMutex lock(&mLock); - mActive = true; - // If starting the active track, just reset mActive in case a stop - // was pending and exit - if (recordTrack == mRecordTrack.get()) return NO_ERROR; - - if (mRecordTrack != 0) return -EBUSY; - - mRecordTrack = recordTrack; - - // signal thread to start - LOGV("Signal record thread"); - mWaitWorkCV.signal(); - mWaitWorkCV.wait(mLock); - LOGV("Record started, status %d", mStartStatus); - return mStartStatus; -} - -void AudioFlinger::AudioRecordThread::stop(MixerThread::RecordTrack* recordTrack) { - LOGV("AudioRecordThread::stop"); - AutoMutex lock(&mLock); - if (mActive && (recordTrack == mRecordTrack.get())) { - mActive = false; - mStopped.wait(mLock); - } -} - -void AudioFlinger::AudioRecordThread::exit() -{ - LOGV("AudioRecordThread::exit"); - { - AutoMutex lock(&mLock); - requestExit(); - mWaitWorkCV.signal(); - } - requestExitAndWait(); -} - -status_t AudioFlinger::AudioRecordThread::dump(int fd, const Vector<String16>& args) -{ - const size_t SIZE = 256; - char buffer[SIZE]; - String8 result; - pid_t pid = 0; - - if (mRecordTrack != 0 && mRecordTrack->mClient != 0) { - snprintf(buffer, SIZE, "Record client pid: %d\n", mRecordTrack->mClient->pid()); - result.append(buffer); - } else { - result.append("No record client\n"); - } - write(fd, result.string(), result.size()); - return NO_ERROR; -} - -status_t AudioFlinger::onTransact( - uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) -{ - return BnAudioFlinger::onTransact(code, data, reply, flags); -} - -// ---------------------------------------------------------------------------- -void AudioFlinger::instantiate() { - defaultServiceManager()->addService( - String16("media.audio_flinger"), new AudioFlinger()); -} - -}; // namespace android diff --git a/libs/audioflinger/AudioFlinger.h b/libs/audioflinger/AudioFlinger.h deleted file mode 100644 index dfbb1e9..0000000 --- a/libs/audioflinger/AudioFlinger.h +++ /dev/null @@ -1,640 +0,0 @@ -/* //device/include/server/AudioFlinger/AudioFlinger.h -** -** Copyright 2007, 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 ANDROID_AUDIO_FLINGER_H -#define ANDROID_AUDIO_FLINGER_H - -#include <stdint.h> -#include <sys/types.h> - -#include <media/IAudioFlinger.h> -#include <media/IAudioFlingerClient.h> -#include <media/IAudioTrack.h> -#include <media/IAudioRecord.h> -#include <media/AudioTrack.h> - -#include <utils/Atomic.h> -#include <utils/Errors.h> -#include <utils/threads.h> -#include <utils/MemoryDealer.h> -#include <utils/KeyedVector.h> -#include <utils/SortedVector.h> -#include <utils/Vector.h> - -#include <hardware_legacy/AudioHardwareInterface.h> - -#include "AudioBufferProvider.h" - -namespace android { - -class audio_track_cblk_t; -class AudioMixer; -class AudioBuffer; - - -// ---------------------------------------------------------------------------- - -#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true )) -#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false )) - - -// ---------------------------------------------------------------------------- - -static const nsecs_t kStandbyTimeInNsecs = seconds(3); - -class AudioFlinger : public BnAudioFlinger, public IBinder::DeathRecipient -{ -public: - static void instantiate(); - - virtual status_t dump(int fd, const Vector<String16>& args); - - // IAudioFlinger interface - virtual sp<IAudioTrack> createTrack( - pid_t pid, - int streamType, - uint32_t sampleRate, - int format, - int channelCount, - int frameCount, - uint32_t flags, - const sp<IMemory>& sharedBuffer, - status_t *status); - - virtual uint32_t sampleRate(int output) const; - virtual int channelCount(int output) const; - virtual int format(int output) const; - virtual size_t frameCount(int output) const; - virtual uint32_t latency(int output) const; - - virtual status_t setMasterVolume(float value); - virtual status_t setMasterMute(bool muted); - - virtual float masterVolume() const; - virtual bool masterMute() const; - - virtual status_t setStreamVolume(int stream, float value); - virtual status_t setStreamMute(int stream, bool muted); - - virtual float streamVolume(int stream) const; - virtual bool streamMute(int stream) const; - - virtual status_t setRouting(int mode, uint32_t routes, uint32_t mask); - virtual uint32_t getRouting(int mode) const; - - virtual status_t setMode(int mode); - virtual int getMode() const; - - virtual status_t setMicMute(bool state); - virtual bool getMicMute() const; - - virtual bool isMusicActive() const; - - virtual bool isA2dpEnabled() const; - - virtual status_t setParameter(const char* key, const char* value); - - virtual void registerClient(const sp<IAudioFlingerClient>& client); - - virtual size_t getInputBufferSize(uint32_t sampleRate, int format, int channelCount); - - virtual void wakeUp(); - - // IBinder::DeathRecipient - virtual void binderDied(const wp<IBinder>& who); - - enum hardware_call_state { - AUDIO_HW_IDLE = 0, - AUDIO_HW_INIT, - AUDIO_HW_OUTPUT_OPEN, - AUDIO_HW_OUTPUT_CLOSE, - AUDIO_HW_INPUT_OPEN, - AUDIO_HW_INPUT_CLOSE, - AUDIO_HW_STANDBY, - AUDIO_HW_SET_MASTER_VOLUME, - AUDIO_HW_GET_ROUTING, - AUDIO_HW_SET_ROUTING, - AUDIO_HW_GET_MODE, - AUDIO_HW_SET_MODE, - AUDIO_HW_GET_MIC_MUTE, - AUDIO_HW_SET_MIC_MUTE, - AUDIO_SET_VOICE_VOLUME, - AUDIO_SET_PARAMETER, - }; - - // record interface - virtual sp<IAudioRecord> openRecord( - pid_t pid, - int streamType, - uint32_t sampleRate, - int format, - int channelCount, - int frameCount, - uint32_t flags, - status_t *status); - - virtual status_t onTransact( - uint32_t code, - const Parcel& data, - Parcel* reply, - uint32_t flags); - -private: - AudioFlinger(); - virtual ~AudioFlinger(); - - void setOutput(int outputType); - void doSetOutput(int outputType); - -#ifdef WITH_A2DP - void setA2dpEnabled(bool enable); -#endif - static bool streamForcedToSpeaker(int streamType); - - // Management of forced route to speaker for certain track types. - enum force_speaker_command { - ACTIVE_TRACK_ADDED = 0, - ACTIVE_TRACK_REMOVED, - CHECK_ROUTE_RESTORE_TIME, - FORCE_ROUTE_RESTORE - }; - void handleForcedSpeakerRoute(int command); - - // Internal dump utilites. - status_t dumpPermissionDenial(int fd, const Vector<String16>& args); - status_t dumpClients(int fd, const Vector<String16>& args); - status_t dumpInternals(int fd, const Vector<String16>& args); - - // --- Client --- - class Client : public RefBase { - public: - Client(const sp<AudioFlinger>& audioFlinger, pid_t pid); - virtual ~Client(); - const sp<MemoryDealer>& heap() const; - pid_t pid() const { return mPid; } - private: - Client(const Client&); - Client& operator = (const Client&); - sp<AudioFlinger> mAudioFlinger; - sp<MemoryDealer> mMemoryDealer; - pid_t mPid; - }; - - - class TrackHandle; - class RecordHandle; - class AudioRecordThread; - - - // --- MixerThread --- - class MixerThread : public Thread { - public: - - // --- Track --- - - // base for record and playback - class TrackBase : public AudioBufferProvider, public RefBase { - - public: - enum track_state { - IDLE, - TERMINATED, - STOPPED, - RESUMING, - ACTIVE, - PAUSING, - PAUSED - }; - - enum track_flags { - STEPSERVER_FAILED = 0x01, // StepServer could not acquire cblk->lock mutex - SYSTEM_FLAGS_MASK = 0x0000ffffUL, - - AUDIO_IN_AGC_ENABLE = AudioSystem::AGC_ENABLE << 16, - AUDIO_IN_NS_ENABLE = AudioSystem::NS_ENABLE << 16, - AUDIO_IN_IIR_ENABLE = AudioSystem::TX_IIR_ENABLE << 16 - }; - - TrackBase(const sp<MixerThread>& mixerThread, - const sp<Client>& client, - int streamType, - uint32_t sampleRate, - int format, - int channelCount, - int frameCount, - uint32_t flags, - const sp<IMemory>& sharedBuffer); - ~TrackBase(); - - virtual status_t start() = 0; - virtual void stop() = 0; - sp<IMemory> getCblk() const; - - protected: - friend class MixerThread; - friend class RecordHandle; - friend class AudioRecordThread; - - TrackBase(const TrackBase&); - TrackBase& operator = (const TrackBase&); - - virtual status_t getNextBuffer(AudioBufferProvider::Buffer* buffer) = 0; - virtual void releaseBuffer(AudioBufferProvider::Buffer* buffer); - - audio_track_cblk_t* cblk() const { - return mCblk; - } - - int type() const { - return mStreamType; - } - - int format() const { - return mFormat; - } - - int channelCount() const ; - - int sampleRate() const; - - void* getBuffer(uint32_t offset, uint32_t frames) const; - - int name() const { - return mName; - } - - bool isStopped() const { - return mState == STOPPED; - } - - bool isTerminated() const { - return mState == TERMINATED; - } - - bool step(); - void reset(); - - sp<MixerThread> mMixerThread; - sp<Client> mClient; - sp<IMemory> mCblkMemory; - audio_track_cblk_t* mCblk; - int mStreamType; - void* mBuffer; - void* mBufferEnd; - uint32_t mFrameCount; - int mName; - // we don't really need a lock for these - int mState; - int mClientTid; - uint8_t mFormat; - uint32_t mFlags; - }; - - // playback track - class Track : public TrackBase { - public: - Track( const sp<MixerThread>& mixerThread, - const sp<Client>& client, - int streamType, - uint32_t sampleRate, - int format, - int channelCount, - int frameCount, - const sp<IMemory>& sharedBuffer); - ~Track(); - - void dump(char* buffer, size_t size); - virtual status_t start(); - virtual void stop(); - void pause(); - - void flush(); - void destroy(); - void mute(bool); - void setVolume(float left, float right); - - protected: - friend class MixerThread; - friend class AudioFlinger; - friend class AudioFlinger::TrackHandle; - - Track(const Track&); - Track& operator = (const Track&); - - virtual status_t getNextBuffer(AudioBufferProvider::Buffer* buffer); - - bool isMuted() const { - return (mMute || mMixerThread->mStreamTypes[mStreamType].mute); - } - - bool isPausing() const { - return mState == PAUSING; - } - - bool isPaused() const { - return mState == PAUSED; - } - - bool isReady() const; - - void setPaused() { mState = PAUSED; } - void reset(); - - // we don't really need a lock for these - float mVolume[2]; - volatile bool mMute; - // FILLED state is used for suppressing volume ramp at begin of playing - enum {FS_FILLING, FS_FILLED, FS_ACTIVE}; - mutable uint8_t mFillingUpStatus; - int8_t mRetryCount; - sp<IMemory> mSharedBuffer; - bool mResetDone; - }; // end of Track - - // record track - class RecordTrack : public TrackBase { - public: - RecordTrack(const sp<MixerThread>& mixerThread, - const sp<Client>& client, - int streamType, - uint32_t sampleRate, - int format, - int channelCount, - int frameCount, - uint32_t flags); - ~RecordTrack(); - - virtual status_t start(); - virtual void stop(); - - bool overflow() { bool tmp = mOverflow; mOverflow = false; return tmp; } - bool setOverflow() { bool tmp = mOverflow; mOverflow = true; return tmp; } - - private: - friend class AudioFlinger; - friend class AudioFlinger::RecordHandle; - friend class AudioFlinger::AudioRecordThread; - friend class MixerThread; - - RecordTrack(const Track&); - RecordTrack& operator = (const Track&); - - virtual status_t getNextBuffer(AudioBufferProvider::Buffer* buffer); - - bool mOverflow; - }; - - // playback track - class OutputTrack : public Track { - public: - - class Buffer: public AudioBufferProvider::Buffer { - public: - int16_t *mBuffer; - }; - - OutputTrack( const sp<MixerThread>& mixerThread, - uint32_t sampleRate, - int format, - int channelCount, - int frameCount); - ~OutputTrack(); - - virtual status_t start(); - virtual void stop(); - void write(int16_t* data, uint32_t frames); - bool bufferQueueEmpty() { return (mBufferQueue.size() == 0) ? true : false; } - - private: - - status_t obtainBuffer(AudioBufferProvider::Buffer* buffer); - void clearBufferQueue(); - - sp<MixerThread> mOutputMixerThread; - Vector < Buffer* > mBufferQueue; - AudioBufferProvider::Buffer mOutBuffer; - uint32_t mFramesWritten; - - }; // end of OutputTrack - - MixerThread (const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int outputType); - virtual ~MixerThread(); - - virtual status_t dump(int fd, const Vector<String16>& args); - - // Thread virtuals - virtual bool threadLoop(); - virtual status_t readyToRun(); - virtual void onFirstRef(); - - virtual uint32_t sampleRate() const; - virtual int channelCount() const; - virtual int format() const; - virtual size_t frameCount() const; - virtual uint32_t latency() const; - - virtual status_t setMasterVolume(float value); - virtual status_t setMasterMute(bool muted); - - virtual float masterVolume() const; - virtual bool masterMute() const; - - virtual status_t setStreamVolume(int stream, float value); - virtual status_t setStreamMute(int stream, bool muted); - - virtual float streamVolume(int stream) const; - virtual bool streamMute(int stream) const; - - bool isMusicActive() const; - - - sp<Track> createTrack( - const sp<AudioFlinger::Client>& client, - int streamType, - uint32_t sampleRate, - int format, - int channelCount, - int frameCount, - const sp<IMemory>& sharedBuffer, - status_t *status); - - void wakeUp() { mWaitWorkCV.broadcast(); } - - void getTracks(SortedVector < sp<Track> >& tracks, - SortedVector < wp<Track> >& activeTracks); - void putTracks(SortedVector < sp<Track> >& tracks, - SortedVector < wp<Track> >& activeTracks); - void setOuputTrack(OutputTrack *track) { mOutputTrack = track; } - - struct stream_type_t { - stream_type_t() - : volume(1.0f), - mute(false) - { - } - float volume; - bool mute; - }; - - private: - - - friend class AudioFlinger; - friend class Track; - friend class TrackBase; - friend class RecordTrack; - - MixerThread(const Client&); - MixerThread& operator = (const MixerThread&); - - status_t addTrack(const sp<Track>& track); - void removeTrack(wp<Track> track, int name); - void remove_track_l(wp<Track> track, int name); - void destroyTrack(const sp<Track>& track); - int getTrackName(); - void deleteTrackName(int name); - void addActiveTrack(const wp<Track>& t); - void removeActiveTrack(const wp<Track>& t); - size_t getOutputFrameCount(); - - status_t dumpInternals(int fd, const Vector<String16>& args); - status_t dumpTracks(int fd, const Vector<String16>& args); - - sp<AudioFlinger> mAudioFlinger; - mutable Mutex mLock; - mutable Condition mWaitWorkCV; - SortedVector< wp<Track> > mActiveTracks; - SortedVector< sp<Track> > mTracks; - stream_type_t mStreamTypes[AudioSystem::NUM_STREAM_TYPES]; - AudioMixer* mAudioMixer; - AudioStreamOut* mOutput; - int mOutputType; - uint32_t mSampleRate; - size_t mFrameCount; - int mChannelCount; - int mFormat; - int16_t* mMixBuffer; - float mMasterVolume; - bool mMasterMute; - nsecs_t mLastWriteTime; - int mNumWrites; - int mNumDelayedWrites; - bool mStandby; - bool mInWrite; - sp <OutputTrack> mOutputTrack; - }; - - - friend class AudioBuffer; - - class TrackHandle : public android::BnAudioTrack { - public: - TrackHandle(const sp<MixerThread::Track>& track); - virtual ~TrackHandle(); - virtual status_t start(); - virtual void stop(); - virtual void flush(); - virtual void mute(bool); - virtual void pause(); - virtual void setVolume(float left, float right); - virtual sp<IMemory> getCblk() const; - virtual status_t onTransact( - uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags); - private: - sp<MixerThread::Track> mTrack; - }; - - friend class Client; - friend class MixerThread::Track; - - - void removeClient(pid_t pid); - - - - class RecordHandle : public android::BnAudioRecord { - public: - RecordHandle(const sp<MixerThread::RecordTrack>& recordTrack); - virtual ~RecordHandle(); - virtual status_t start(); - virtual void stop(); - virtual sp<IMemory> getCblk() const; - virtual status_t onTransact( - uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags); - private: - sp<MixerThread::RecordTrack> mRecordTrack; - }; - - // record thread - class AudioRecordThread : public Thread - { - public: - AudioRecordThread(AudioHardwareInterface* audioHardware); - virtual ~AudioRecordThread(); - virtual bool threadLoop(); - virtual status_t readyToRun() { return NO_ERROR; } - virtual void onFirstRef() {} - - status_t start(MixerThread::RecordTrack* recordTrack); - void stop(MixerThread::RecordTrack* recordTrack); - void exit(); - status_t dump(int fd, const Vector<String16>& args); - - private: - AudioRecordThread(); - AudioHardwareInterface *mAudioHardware; - sp<MixerThread::RecordTrack> mRecordTrack; - Mutex mLock; - Condition mWaitWorkCV; - Condition mStopped; - volatile bool mActive; - status_t mStartStatus; - }; - - friend class AudioRecordThread; - friend class MixerThread; - - status_t startRecord(MixerThread::RecordTrack* recordTrack); - void stopRecord(MixerThread::RecordTrack* recordTrack); - - void handleOutputSwitch(); - - mutable Mutex mHardwareLock; - mutable Mutex mLock; - DefaultKeyedVector< pid_t, wp<Client> > mClients; - - sp<MixerThread> mA2dpMixerThread; - sp<MixerThread> mHardwareMixerThread; - AudioHardwareInterface* mAudioHardware; - AudioHardwareInterface* mA2dpAudioInterface; - sp<AudioRecordThread> mAudioRecordThread; - bool mA2dpEnabled; - bool mA2dpEnabledReq; - mutable int mHardwareStatus; - SortedVector< wp<IBinder> > mNotificationClients; - int mForcedSpeakerCount; - uint32_t mSavedRoute; - uint32_t mForcedRoute; - nsecs_t mRouteRestoreTime; - bool mMusicMuteSaved; -}; - -// ---------------------------------------------------------------------------- - -}; // namespace android - -#endif // ANDROID_AUDIO_FLINGER_H diff --git a/libs/audioflinger/AudioHardwareGeneric.cpp b/libs/audioflinger/AudioHardwareGeneric.cpp deleted file mode 100644 index 62beada..0000000 --- a/libs/audioflinger/AudioHardwareGeneric.cpp +++ /dev/null @@ -1,313 +0,0 @@ -/* -** -** Copyright 2007, 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 <stdint.h> -#include <sys/types.h> - -#include <stdlib.h> -#include <stdio.h> -#include <unistd.h> -#include <sched.h> -#include <fcntl.h> -#include <sys/ioctl.h> - -#define LOG_TAG "AudioHardware" -#include <utils/Log.h> -#include <utils/String8.h> - -#include "AudioHardwareGeneric.h" - -namespace android { - -// ---------------------------------------------------------------------------- - -static char const * const kAudioDeviceName = "/dev/eac"; - -// ---------------------------------------------------------------------------- - -AudioHardwareGeneric::AudioHardwareGeneric() - : mOutput(0), mInput(0), mFd(-1), mMicMute(false) -{ - mFd = ::open(kAudioDeviceName, O_RDWR); -} - -AudioHardwareGeneric::~AudioHardwareGeneric() -{ - if (mFd >= 0) ::close(mFd); - delete mOutput; - delete mInput; -} - -status_t AudioHardwareGeneric::initCheck() -{ - if (mFd >= 0) { - if (::access(kAudioDeviceName, O_RDWR) == NO_ERROR) - return NO_ERROR; - } - return NO_INIT; -} - -AudioStreamOut* AudioHardwareGeneric::openOutputStream( - int format, int channelCount, uint32_t sampleRate, status_t *status) -{ - AutoMutex lock(mLock); - - // only one output stream allowed - if (mOutput) { - if (status) { - *status = INVALID_OPERATION; - } - return 0; - } - - // create new output stream - AudioStreamOutGeneric* out = new AudioStreamOutGeneric(); - status_t lStatus = out->set(this, mFd, format, channelCount, sampleRate); - if (status) { - *status = lStatus; - } - if (lStatus == NO_ERROR) { - mOutput = out; - } else { - delete out; - } - return mOutput; -} - -void AudioHardwareGeneric::closeOutputStream(AudioStreamOutGeneric* out) { - if (out == mOutput) mOutput = 0; -} - -AudioStreamIn* AudioHardwareGeneric::openInputStream( - int format, int channelCount, uint32_t sampleRate, status_t *status, - AudioSystem::audio_in_acoustics acoustics) -{ - AutoMutex lock(mLock); - - // only one input stream allowed - if (mInput) { - if (status) { - *status = INVALID_OPERATION; - } - return 0; - } - - // create new output stream - AudioStreamInGeneric* in = new AudioStreamInGeneric(); - status_t lStatus = in->set(this, mFd, format, channelCount, sampleRate, acoustics); - if (status) { - *status = lStatus; - } - if (lStatus == NO_ERROR) { - mInput = in; - } else { - delete in; - } - return mInput; -} - -void AudioHardwareGeneric::closeInputStream(AudioStreamInGeneric* in) { - if (in == mInput) mInput = 0; -} - -status_t AudioHardwareGeneric::setVoiceVolume(float v) -{ - // Implement: set voice volume - return NO_ERROR; -} - -status_t AudioHardwareGeneric::setMasterVolume(float v) -{ - // Implement: set master volume - // return error - software mixer will handle it - return INVALID_OPERATION; -} - -status_t AudioHardwareGeneric::setMicMute(bool state) -{ - mMicMute = state; - return NO_ERROR; -} - -status_t AudioHardwareGeneric::getMicMute(bool* state) -{ - *state = mMicMute; - return NO_ERROR; -} - -status_t AudioHardwareGeneric::dumpInternals(int fd, const Vector<String16>& args) -{ - const size_t SIZE = 256; - char buffer[SIZE]; - String8 result; - result.append("AudioHardwareGeneric::dumpInternals\n"); - snprintf(buffer, SIZE, "\tmFd: %d mMicMute: %s\n", mFd, mMicMute? "true": "false"); - result.append(buffer); - ::write(fd, result.string(), result.size()); - return NO_ERROR; -} - -status_t AudioHardwareGeneric::dump(int fd, const Vector<String16>& args) -{ - dumpInternals(fd, args); - if (mInput) { - mInput->dump(fd, args); - } - if (mOutput) { - mOutput->dump(fd, args); - } - return NO_ERROR; -} - -// ---------------------------------------------------------------------------- - -status_t AudioStreamOutGeneric::set( - AudioHardwareGeneric *hw, - int fd, - int format, - int channels, - uint32_t rate) -{ - // fix up defaults - if (format == 0) format = AudioSystem::PCM_16_BIT; - if (channels == 0) channels = channelCount(); - if (rate == 0) rate = sampleRate(); - - // check values - if ((format != AudioSystem::PCM_16_BIT) || - (channels != channelCount()) || - (rate != sampleRate())) - return BAD_VALUE; - - mAudioHardware = hw; - mFd = fd; - return NO_ERROR; -} - -AudioStreamOutGeneric::~AudioStreamOutGeneric() -{ - if (mAudioHardware) - mAudioHardware->closeOutputStream(this); -} - -ssize_t AudioStreamOutGeneric::write(const void* buffer, size_t bytes) -{ - Mutex::Autolock _l(mLock); - return ssize_t(::write(mFd, buffer, bytes)); -} - -status_t AudioStreamOutGeneric::standby() -{ - // Implement: audio hardware to standby mode - return NO_ERROR; -} - -status_t AudioStreamOutGeneric::dump(int fd, const Vector<String16>& args) -{ - const size_t SIZE = 256; - char buffer[SIZE]; - String8 result; - snprintf(buffer, SIZE, "AudioStreamOutGeneric::dump\n"); - result.append(buffer); - snprintf(buffer, SIZE, "\tsample rate: %d\n", sampleRate()); - result.append(buffer); - snprintf(buffer, SIZE, "\tbuffer size: %d\n", bufferSize()); - result.append(buffer); - snprintf(buffer, SIZE, "\tchannel count: %d\n", channelCount()); - result.append(buffer); - snprintf(buffer, SIZE, "\tformat: %d\n", format()); - result.append(buffer); - snprintf(buffer, SIZE, "\tmAudioHardware: %p\n", mAudioHardware); - result.append(buffer); - snprintf(buffer, SIZE, "\tmFd: %d\n", mFd); - result.append(buffer); - ::write(fd, result.string(), result.size()); - return NO_ERROR; -} - -// ---------------------------------------------------------------------------- - -// record functions -status_t AudioStreamInGeneric::set( - AudioHardwareGeneric *hw, - int fd, - int format, - int channels, - uint32_t rate, - AudioSystem::audio_in_acoustics acoustics) -{ - // FIXME: remove logging - LOGD("AudioStreamInGeneric::set(%p, %d, %d, %d, %u)", hw, fd, format, channels, rate); - // check values - if ((format != AudioSystem::PCM_16_BIT) || - (channels != channelCount()) || - (rate != sampleRate())) { - LOGE("Error opening input channel"); - return BAD_VALUE; - } - - mAudioHardware = hw; - mFd = fd; - return NO_ERROR; -} - -AudioStreamInGeneric::~AudioStreamInGeneric() -{ - // FIXME: remove logging - LOGD("AudioStreamInGeneric destructor"); - if (mAudioHardware) - mAudioHardware->closeInputStream(this); -} - -ssize_t AudioStreamInGeneric::read(void* buffer, ssize_t bytes) -{ - // FIXME: remove logging - LOGD("AudioStreamInGeneric::read(%p, %d) from fd %d", buffer, bytes, mFd); - AutoMutex lock(mLock); - if (mFd < 0) { - LOGE("Attempt to read from unopened device"); - return NO_INIT; - } - return ::read(mFd, buffer, bytes); -} - -status_t AudioStreamInGeneric::dump(int fd, const Vector<String16>& args) -{ - const size_t SIZE = 256; - char buffer[SIZE]; - String8 result; - snprintf(buffer, SIZE, "AudioStreamInGeneric::dump\n"); - result.append(buffer); - snprintf(buffer, SIZE, "\tsample rate: %d\n", sampleRate()); - result.append(buffer); - snprintf(buffer, SIZE, "\tbuffer size: %d\n", bufferSize()); - result.append(buffer); - snprintf(buffer, SIZE, "\tchannel count: %d\n", channelCount()); - result.append(buffer); - snprintf(buffer, SIZE, "\tformat: %d\n", format()); - result.append(buffer); - snprintf(buffer, SIZE, "\tmAudioHardware: %p\n", mAudioHardware); - result.append(buffer); - snprintf(buffer, SIZE, "\tmFd: %d\n", mFd); - result.append(buffer); - ::write(fd, result.string(), result.size()); - return NO_ERROR; -} - -// ---------------------------------------------------------------------------- - -}; // namespace android diff --git a/libs/audioflinger/AudioHardwareGeneric.h b/libs/audioflinger/AudioHardwareGeneric.h deleted file mode 100644 index 1d58389..0000000 --- a/libs/audioflinger/AudioHardwareGeneric.h +++ /dev/null @@ -1,141 +0,0 @@ -/* -** -** Copyright 2007, 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 ANDROID_AUDIO_HARDWARE_GENERIC_H -#define ANDROID_AUDIO_HARDWARE_GENERIC_H - -#include <stdint.h> -#include <sys/types.h> - -#include <utils/threads.h> - -#include <hardware_legacy/AudioHardwareBase.h> - -namespace android { - -// ---------------------------------------------------------------------------- - -class AudioHardwareGeneric; - -class AudioStreamOutGeneric : public AudioStreamOut { -public: - AudioStreamOutGeneric() : mAudioHardware(0), mFd(-1) {} - virtual ~AudioStreamOutGeneric(); - - virtual status_t set( - AudioHardwareGeneric *hw, - int mFd, - int format, - int channelCount, - uint32_t sampleRate); - - virtual uint32_t sampleRate() const { return 44100; } - virtual size_t bufferSize() const { return 4096; } - virtual int channelCount() const { return 2; } - virtual int format() const { return AudioSystem::PCM_16_BIT; } - virtual uint32_t latency() const { return 0; } - virtual status_t setVolume(float volume) { return INVALID_OPERATION; } - virtual ssize_t write(const void* buffer, size_t bytes); - virtual status_t standby(); - virtual status_t dump(int fd, const Vector<String16>& args); - -private: - AudioHardwareGeneric *mAudioHardware; - Mutex mLock; - int mFd; -}; - -class AudioStreamInGeneric : public AudioStreamIn { -public: - AudioStreamInGeneric() : mAudioHardware(0), mFd(-1) {} - virtual ~AudioStreamInGeneric(); - - virtual status_t set( - AudioHardwareGeneric *hw, - int mFd, - int format, - int channelCount, - uint32_t sampleRate, - AudioSystem::audio_in_acoustics acoustics); - - uint32_t sampleRate() const { return 8000; } - virtual size_t bufferSize() const { return 320; } - virtual int channelCount() const { return 1; } - virtual int format() const { return AudioSystem::PCM_16_BIT; } - virtual status_t setGain(float gain) { return INVALID_OPERATION; } - virtual ssize_t read(void* buffer, ssize_t bytes); - virtual status_t dump(int fd, const Vector<String16>& args); - virtual status_t standby() { return NO_ERROR; } - -private: - AudioHardwareGeneric *mAudioHardware; - Mutex mLock; - int mFd; -}; - - -class AudioHardwareGeneric : public AudioHardwareBase -{ -public: - AudioHardwareGeneric(); - virtual ~AudioHardwareGeneric(); - virtual status_t initCheck(); - virtual status_t setVoiceVolume(float volume); - virtual status_t setMasterVolume(float volume); - - // mic mute - virtual status_t setMicMute(bool state); - virtual status_t getMicMute(bool* state); - - virtual status_t setParameter(const char* key, const char* value) - { return NO_ERROR; } - - // create I/O streams - virtual AudioStreamOut* openOutputStream( - int format=0, - int channelCount=0, - uint32_t sampleRate=0, - status_t *status=0); - - virtual AudioStreamIn* openInputStream( - int format, - int channelCount, - uint32_t sampleRate, - status_t *status, - AudioSystem::audio_in_acoustics acoustics); - - void closeOutputStream(AudioStreamOutGeneric* out); - void closeInputStream(AudioStreamInGeneric* in); -protected: - virtual status_t doRouting() { return NO_ERROR; } - virtual status_t dump(int fd, const Vector<String16>& args); - -private: - status_t dumpInternals(int fd, const Vector<String16>& args); - - Mutex mLock; - AudioStreamOutGeneric *mOutput; - AudioStreamInGeneric *mInput; - int mFd; - bool mMicMute; -}; - -// ---------------------------------------------------------------------------- - -}; // namespace android - -#endif // ANDROID_AUDIO_HARDWARE_GENERIC_H diff --git a/libs/audioflinger/AudioHardwareInterface.cpp b/libs/audioflinger/AudioHardwareInterface.cpp deleted file mode 100644 index ac76a19..0000000 --- a/libs/audioflinger/AudioHardwareInterface.cpp +++ /dev/null @@ -1,247 +0,0 @@ -/* -** -** Copyright 2007, 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 <cutils/properties.h> -#include <string.h> -#include <unistd.h> - -#define LOG_TAG "AudioHardwareInterface" -#include <utils/Log.h> -#include <utils/String8.h> - -#include "AudioHardwareStub.h" -#include "AudioHardwareGeneric.h" - -//#define DUMP_FLINGER_OUT // if defined allows recording samples in a file -#ifdef DUMP_FLINGER_OUT -#include "AudioDumpInterface.h" -#endif - - -// change to 1 to log routing calls -#define LOG_ROUTING_CALLS 0 - -namespace android { - -#if LOG_ROUTING_CALLS -static const char* routingModeStrings[] = -{ - "OUT OF RANGE", - "INVALID", - "CURRENT", - "NORMAL", - "RINGTONE", - "IN_CALL" -}; - -static const char* routeStrings[] = -{ - "EARPIECE ", - "SPEAKER ", - "BLUETOOTH ", - "HEADSET " - "BLUETOOTH_A2DP " -}; -static const char* routeNone = "NONE"; - -static const char* displayMode(int mode) -{ - if ((mode < -2) || (mode > 2)) - return routingModeStrings[0]; - return routingModeStrings[mode+3]; -} - -static const char* displayRoutes(uint32_t routes) -{ - static char routeStr[80]; - if (routes == 0) - return routeNone; - routeStr[0] = 0; - int bitMask = 1; - for (int i = 0; i < 4; ++i, bitMask <<= 1) { - if (routes & bitMask) { - strcat(routeStr, routeStrings[i]); - } - } - routeStr[strlen(routeStr)-1] = 0; - return routeStr; -} -#endif - -// ---------------------------------------------------------------------------- - -AudioHardwareInterface* AudioHardwareInterface::create() -{ - /* - * FIXME: This code needs to instantiate the correct audio device - * interface. For now - we use compile-time switches. - */ - AudioHardwareInterface* hw = 0; - char value[PROPERTY_VALUE_MAX]; - -#ifdef GENERIC_AUDIO - hw = new AudioHardwareGeneric(); -#else - // if running in emulation - use the emulator driver - if (property_get("ro.kernel.qemu", value, 0)) { - LOGD("Running in emulation - using generic audio driver"); - hw = new AudioHardwareGeneric(); - } - else { - LOGV("Creating Vendor Specific AudioHardware"); - hw = createAudioHardware(); - } -#endif - if (hw->initCheck() != NO_ERROR) { - LOGW("Using stubbed audio hardware. No sound will be produced."); - delete hw; - hw = new AudioHardwareStub(); - } - -#ifdef DUMP_FLINGER_OUT - // This code adds a record of buffers in a file to write calls made by AudioFlinger. - // It replaces the current AudioHardwareInterface object by an intermediate one which - // will record buffers in a file (after sending them to hardware) for testing purpose. - // This feature is enabled by defining symbol DUMP_FLINGER_OUT. - // The output file is FLINGER_DUMP_NAME. Pause are not recorded in the file. - - hw = new AudioDumpInterface(hw); // replace interface -#endif - return hw; -} - -AudioStreamOut::~AudioStreamOut() -{ -} - -AudioStreamIn::~AudioStreamIn() {} - -AudioHardwareBase::AudioHardwareBase() -{ - // force a routing update on initialization - memset(&mRoutes, 0, sizeof(mRoutes)); - mMode = 0; -} - -// generics for audio routing - the real work is done in doRouting -status_t AudioHardwareBase::setRouting(int mode, uint32_t routes) -{ -#if LOG_ROUTING_CALLS - LOGD("setRouting: mode=%s, routes=[%s]", displayMode(mode), displayRoutes(routes)); -#endif - if (mode == AudioSystem::MODE_CURRENT) - mode = mMode; - if ((mode < 0) || (mode >= AudioSystem::NUM_MODES)) - return BAD_VALUE; - uint32_t old = mRoutes[mode]; - mRoutes[mode] = routes; - if ((mode != mMode) || (old == routes)) - return NO_ERROR; -#if LOG_ROUTING_CALLS - const char* oldRouteStr = strdup(displayRoutes(old)); - LOGD("doRouting: mode=%s, old route=[%s], new route=[%s]", - displayMode(mode), oldRouteStr, displayRoutes(routes)); - delete oldRouteStr; -#endif - return doRouting(); -} - -status_t AudioHardwareBase::getRouting(int mode, uint32_t* routes) -{ - if (mode == AudioSystem::MODE_CURRENT) - mode = mMode; - if ((mode < 0) || (mode >= AudioSystem::NUM_MODES)) - return BAD_VALUE; - *routes = mRoutes[mode]; -#if LOG_ROUTING_CALLS - LOGD("getRouting: mode=%s, routes=[%s]", - displayMode(mode), displayRoutes(*routes)); -#endif - return NO_ERROR; -} - -status_t AudioHardwareBase::setMode(int mode) -{ -#if LOG_ROUTING_CALLS - LOGD("setMode(%s)", displayMode(mode)); -#endif - if ((mode < 0) || (mode >= AudioSystem::NUM_MODES)) - return BAD_VALUE; - if (mMode == mode) - return NO_ERROR; -#if LOG_ROUTING_CALLS - LOGD("doRouting: old mode=%s, new mode=%s route=[%s]", - displayMode(mMode), displayMode(mode), displayRoutes(mRoutes[mode])); -#endif - mMode = mode; - return doRouting(); -} - -status_t AudioHardwareBase::getMode(int* mode) -{ - // Implement: set audio routing - *mode = mMode; - return NO_ERROR; -} - -status_t AudioHardwareBase::setParameter(const char* key, const char* value) -{ - // default implementation is to ignore - return NO_ERROR; -} - - -// default implementation -size_t AudioHardwareBase::getInputBufferSize(uint32_t sampleRate, int format, int channelCount) -{ - if (sampleRate != 8000) { - LOGW("getInputBufferSize bad sampling rate: %d", sampleRate); - return 0; - } - if (format != AudioSystem::PCM_16_BIT) { - LOGW("getInputBufferSize bad format: %d", format); - return 0; - } - if (channelCount != 1) { - LOGW("getInputBufferSize bad channel count: %d", channelCount); - return 0; - } - - return 320; -} - -status_t AudioHardwareBase::dumpState(int fd, const Vector<String16>& args) -{ - const size_t SIZE = 256; - char buffer[SIZE]; - String8 result; - snprintf(buffer, SIZE, "AudioHardwareBase::dumpState\n"); - result.append(buffer); - snprintf(buffer, SIZE, "\tmMode: %d\n", mMode); - result.append(buffer); - for (int i = 0, n = AudioSystem::NUM_MODES; i < n; ++i) { - snprintf(buffer, SIZE, "\tmRoutes[%d]: %d\n", i, mRoutes[i]); - result.append(buffer); - } - ::write(fd, result.string(), result.size()); - dump(fd, args); // Dump the state of the concrete child. - return NO_ERROR; -} - -// ---------------------------------------------------------------------------- - -}; // namespace android diff --git a/libs/audioflinger/AudioHardwareStub.cpp b/libs/audioflinger/AudioHardwareStub.cpp deleted file mode 100644 index b13cb1c..0000000 --- a/libs/audioflinger/AudioHardwareStub.cpp +++ /dev/null @@ -1,185 +0,0 @@ -/* //device/servers/AudioFlinger/AudioHardwareStub.cpp -** -** Copyright 2007, 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 <stdint.h> -#include <sys/types.h> - -#include <stdlib.h> -#include <unistd.h> -#include <utils/String8.h> - -#include "AudioHardwareStub.h" - -namespace android { - -// ---------------------------------------------------------------------------- - -AudioHardwareStub::AudioHardwareStub() : mMicMute(false) -{ -} - -AudioHardwareStub::~AudioHardwareStub() -{ -} - -status_t AudioHardwareStub::initCheck() -{ - return NO_ERROR; -} - -AudioStreamOut* AudioHardwareStub::openOutputStream( - int format, int channelCount, uint32_t sampleRate, status_t *status) -{ - AudioStreamOutStub* out = new AudioStreamOutStub(); - status_t lStatus = out->set(format, channelCount, sampleRate); - if (status) { - *status = lStatus; - } - if (lStatus == NO_ERROR) - return out; - delete out; - return 0; -} - -AudioStreamIn* AudioHardwareStub::openInputStream( - int format, int channelCount, uint32_t sampleRate, - status_t *status, AudioSystem::audio_in_acoustics acoustics) -{ - AudioStreamInStub* in = new AudioStreamInStub(); - status_t lStatus = in->set(format, channelCount, sampleRate, acoustics); - if (status) { - *status = lStatus; - } - if (lStatus == NO_ERROR) - return in; - delete in; - return 0; -} - -status_t AudioHardwareStub::setVoiceVolume(float volume) -{ - return NO_ERROR; -} - -status_t AudioHardwareStub::setMasterVolume(float volume) -{ - return NO_ERROR; -} - -status_t AudioHardwareStub::dumpInternals(int fd, const Vector<String16>& args) -{ - const size_t SIZE = 256; - char buffer[SIZE]; - String8 result; - result.append("AudioHardwareStub::dumpInternals\n"); - snprintf(buffer, SIZE, "\tmMicMute: %s\n", mMicMute? "true": "false"); - result.append(buffer); - ::write(fd, result.string(), result.size()); - return NO_ERROR; -} - -status_t AudioHardwareStub::dump(int fd, const Vector<String16>& args) -{ - dumpInternals(fd, args); - return NO_ERROR; -} - -// ---------------------------------------------------------------------------- - -status_t AudioStreamOutStub::set(int format, int channels, uint32_t rate) -{ - // fix up defaults - if (format == 0) format = AudioSystem::PCM_16_BIT; - if (channels == 0) channels = channelCount(); - if (rate == 0) rate = sampleRate(); - - if ((format == AudioSystem::PCM_16_BIT) && - (channels == channelCount()) && - (rate == sampleRate())) - return NO_ERROR; - return BAD_VALUE; -} - -ssize_t AudioStreamOutStub::write(const void* buffer, size_t bytes) -{ - // fake timing for audio output - usleep(bytes * 1000000 / sizeof(int16_t) / channelCount() / sampleRate()); - return bytes; -} - -status_t AudioStreamOutStub::standby() -{ - return NO_ERROR; -} - -status_t AudioStreamOutStub::dump(int fd, const Vector<String16>& args) -{ - const size_t SIZE = 256; - char buffer[SIZE]; - String8 result; - snprintf(buffer, SIZE, "AudioStreamOutStub::dump\n"); - snprintf(buffer, SIZE, "\tsample rate: %d\n", sampleRate()); - snprintf(buffer, SIZE, "\tbuffer size: %d\n", bufferSize()); - snprintf(buffer, SIZE, "\tchannel count: %d\n", channelCount()); - snprintf(buffer, SIZE, "\tformat: %d\n", format()); - result.append(buffer); - ::write(fd, result.string(), result.size()); - return NO_ERROR; -} - -// ---------------------------------------------------------------------------- - -status_t AudioStreamInStub::set(int format, int channels, uint32_t rate, - AudioSystem::audio_in_acoustics acoustics) -{ - if ((format == AudioSystem::PCM_16_BIT) && - (channels == channelCount()) && - (rate == sampleRate())) - return NO_ERROR; - return BAD_VALUE; -} - -ssize_t AudioStreamInStub::read(void* buffer, ssize_t bytes) -{ - // fake timing for audio input - usleep(bytes * 1000000 / sizeof(int16_t) / channelCount() / sampleRate()); - memset(buffer, 0, bytes); - return bytes; -} - -status_t AudioStreamInStub::dump(int fd, const Vector<String16>& args) -{ - const size_t SIZE = 256; - char buffer[SIZE]; - String8 result; - snprintf(buffer, SIZE, "AudioStreamInStub::dump\n"); - result.append(buffer); - snprintf(buffer, SIZE, "\tsample rate: %d\n", sampleRate()); - result.append(buffer); - snprintf(buffer, SIZE, "\tbuffer size: %d\n", bufferSize()); - result.append(buffer); - snprintf(buffer, SIZE, "\tchannel count: %d\n", channelCount()); - result.append(buffer); - snprintf(buffer, SIZE, "\tformat: %d\n", format()); - result.append(buffer); - ::write(fd, result.string(), result.size()); - return NO_ERROR; -} - -// ---------------------------------------------------------------------------- - -}; // namespace android diff --git a/libs/audioflinger/AudioHardwareStub.h b/libs/audioflinger/AudioHardwareStub.h deleted file mode 100644 index d406424..0000000 --- a/libs/audioflinger/AudioHardwareStub.h +++ /dev/null @@ -1,100 +0,0 @@ -/* //device/servers/AudioFlinger/AudioHardwareStub.h -** -** Copyright 2007, 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 ANDROID_AUDIO_HARDWARE_STUB_H -#define ANDROID_AUDIO_HARDWARE_STUB_H - -#include <stdint.h> -#include <sys/types.h> - -#include <hardware_legacy/AudioHardwareBase.h> - -namespace android { - -// ---------------------------------------------------------------------------- - -class AudioStreamOutStub : public AudioStreamOut { -public: - virtual status_t set(int format, int channelCount, uint32_t sampleRate); - virtual uint32_t sampleRate() const { return 44100; } - virtual size_t bufferSize() const { return 4096; } - virtual int channelCount() const { return 2; } - virtual int format() const { return AudioSystem::PCM_16_BIT; } - virtual uint32_t latency() const { return 0; } - virtual status_t setVolume(float volume) { return NO_ERROR; } - virtual ssize_t write(const void* buffer, size_t bytes); - virtual status_t standby(); - virtual status_t dump(int fd, const Vector<String16>& args); -}; - -class AudioStreamInStub : public AudioStreamIn { -public: - virtual status_t set(int format, int channelCount, uint32_t sampleRate, AudioSystem::audio_in_acoustics acoustics); - virtual uint32_t sampleRate() const { return 8000; } - virtual size_t bufferSize() const { return 320; } - virtual int channelCount() const { return 1; } - virtual int format() const { return AudioSystem::PCM_16_BIT; } - virtual status_t setGain(float gain) { return NO_ERROR; } - virtual ssize_t read(void* buffer, ssize_t bytes); - virtual status_t dump(int fd, const Vector<String16>& args); - virtual status_t standby() { return NO_ERROR; } -}; - -class AudioHardwareStub : public AudioHardwareBase -{ -public: - AudioHardwareStub(); - virtual ~AudioHardwareStub(); - virtual status_t initCheck(); - virtual status_t setVoiceVolume(float volume); - virtual status_t setMasterVolume(float volume); - - // mic mute - virtual status_t setMicMute(bool state) { mMicMute = state; return NO_ERROR; } - virtual status_t getMicMute(bool* state) { *state = mMicMute ; return NO_ERROR; } - - virtual status_t setParameter(const char* key, const char* value) - { return NO_ERROR; } - - // create I/O streams - virtual AudioStreamOut* openOutputStream( - int format=0, - int channelCount=0, - uint32_t sampleRate=0, - status_t *status=0); - - virtual AudioStreamIn* openInputStream( - int format, - int channelCount, - uint32_t sampleRate, - status_t *status, - AudioSystem::audio_in_acoustics acoustics); - -protected: - virtual status_t doRouting() { return NO_ERROR; } - virtual status_t dump(int fd, const Vector<String16>& args); - - bool mMicMute; -private: - status_t dumpInternals(int fd, const Vector<String16>& args); -}; - -// ---------------------------------------------------------------------------- - -}; // namespace android - -#endif // ANDROID_AUDIO_HARDWARE_STUB_H diff --git a/libs/audioflinger/AudioMixer.cpp b/libs/audioflinger/AudioMixer.cpp deleted file mode 100644 index b03467f..0000000 --- a/libs/audioflinger/AudioMixer.cpp +++ /dev/null @@ -1,913 +0,0 @@ -/* //device/include/server/AudioFlinger/AudioMixer.cpp -** -** Copyright 2007, 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 "AudioMixer" - -#include <stdint.h> -#include <string.h> -#include <stdlib.h> -#include <sys/types.h> - -#include <utils/Errors.h> -#include <utils/Log.h> - -#include "AudioMixer.h" - -namespace android { -// ---------------------------------------------------------------------------- - -static inline int16_t clamp16(int32_t sample) -{ - if ((sample>>15) ^ (sample>>31)) - sample = 0x7FFF ^ (sample>>31); - return sample; -} - -// ---------------------------------------------------------------------------- - -AudioMixer::AudioMixer(size_t frameCount, uint32_t sampleRate) - : mActiveTrack(0), mTrackNames(0), mSampleRate(sampleRate) -{ - mState.enabledTracks= 0; - mState.needsChanged = 0; - mState.frameCount = frameCount; - mState.outputTemp = 0; - mState.resampleTemp = 0; - mState.hook = process__nop; - track_t* t = mState.tracks; - for (int i=0 ; i<32 ; i++) { - t->needs = 0; - t->volume[0] = UNITY_GAIN; - t->volume[1] = UNITY_GAIN; - t->volumeInc[0] = 0; - t->volumeInc[1] = 0; - t->channelCount = 2; - t->enabled = 0; - t->format = 16; - t->buffer.raw = 0; - t->bufferProvider = 0; - t->hook = 0; - t->resampler = 0; - t->sampleRate = mSampleRate; - t->in = 0; - t++; - } -} - - AudioMixer::~AudioMixer() - { - track_t* t = mState.tracks; - for (int i=0 ; i<32 ; i++) { - delete t->resampler; - t++; - } - delete [] mState.outputTemp; - delete [] mState.resampleTemp; - } - - int AudioMixer::getTrackName() - { - uint32_t names = mTrackNames; - uint32_t mask = 1; - int n = 0; - while (names & mask) { - mask <<= 1; - n++; - } - if (mask) { - LOGV("add track (%d)", n); - mTrackNames |= mask; - return TRACK0 + n; - } - return -1; - } - - void AudioMixer::invalidateState(uint32_t mask) - { - if (mask) { - mState.needsChanged |= mask; - mState.hook = process__validate; - } - } - - void AudioMixer::deleteTrackName(int name) - { - name -= TRACK0; - if (uint32_t(name) < MAX_NUM_TRACKS) { - LOGV("deleteTrackName(%d)", name); - track_t& track(mState.tracks[ name ]); - if (track.enabled != 0) { - track.enabled = 0; - invalidateState(1<<name); - } - if (track.resampler) { - // delete the resampler - delete track.resampler; - track.resampler = 0; - track.sampleRate = mSampleRate; - invalidateState(1<<name); - } - track.volumeInc[0] = 0; - track.volumeInc[1] = 0; - mTrackNames &= ~(1<<name); - } - } - -status_t AudioMixer::enable(int name) -{ - switch (name) { - case MIXING: { - if (mState.tracks[ mActiveTrack ].enabled != 1) { - mState.tracks[ mActiveTrack ].enabled = 1; - LOGV("enable(%d)", mActiveTrack); - invalidateState(1<<mActiveTrack); - } - } break; - default: - return NAME_NOT_FOUND; - } - return NO_ERROR; -} - -status_t AudioMixer::disable(int name) -{ - switch (name) { - case MIXING: { - if (mState.tracks[ mActiveTrack ].enabled != 0) { - mState.tracks[ mActiveTrack ].enabled = 0; - LOGV("disable(%d)", mActiveTrack); - invalidateState(1<<mActiveTrack); - } - } break; - default: - return NAME_NOT_FOUND; - } - return NO_ERROR; -} - -status_t AudioMixer::setActiveTrack(int track) -{ - if (uint32_t(track-TRACK0) >= MAX_NUM_TRACKS) { - return BAD_VALUE; - } - mActiveTrack = track - TRACK0; - return NO_ERROR; -} - -status_t AudioMixer::setParameter(int target, int name, int value) -{ - switch (target) { - case TRACK: - if (name == CHANNEL_COUNT) { - if ((uint32_t(value) <= MAX_NUM_CHANNELS) && (value)) { - if (mState.tracks[ mActiveTrack ].channelCount != value) { - mState.tracks[ mActiveTrack ].channelCount = value; - LOGV("setParameter(TRACK, CHANNEL_COUNT, %d)", value); - invalidateState(1<<mActiveTrack); - } - return NO_ERROR; - } - } - break; - case RESAMPLE: - if (name == SAMPLE_RATE) { - if (value > 0) { - track_t& track = mState.tracks[ mActiveTrack ]; - if (track.setResampler(uint32_t(value), mSampleRate)) { - LOGV("setParameter(RESAMPLE, SAMPLE_RATE, %u)", - uint32_t(value)); - invalidateState(1<<mActiveTrack); - } - return NO_ERROR; - } - } - break; - case RAMP_VOLUME: - case VOLUME: - if ((uint32_t(name-VOLUME0) < MAX_NUM_CHANNELS)) { - track_t& track = mState.tracks[ mActiveTrack ]; - if (track.volume[name-VOLUME0] != value) { - track.prevVolume[name-VOLUME0] = track.volume[name-VOLUME0] << 16; - track.volume[name-VOLUME0] = value; - if (target == VOLUME) { - track.prevVolume[name-VOLUME0] = value << 16; - track.volumeInc[name-VOLUME0] = 0; - } else { - int32_t d = (value<<16) - track.prevVolume[name-VOLUME0]; - int32_t volInc = d / int32_t(mState.frameCount); - track.volumeInc[name-VOLUME0] = volInc; - if (volInc == 0) { - track.prevVolume[name-VOLUME0] = value << 16; - } - } - invalidateState(1<<mActiveTrack); - } - return NO_ERROR; - } - break; - } - return BAD_VALUE; -} - -bool AudioMixer::track_t::setResampler(uint32_t value, uint32_t devSampleRate) -{ - if (value!=devSampleRate || resampler) { - if (sampleRate != value) { - sampleRate = value; - if (resampler == 0) { - resampler = AudioResampler::create( - format, channelCount, devSampleRate); - } - return true; - } - } - return false; -} - -bool AudioMixer::track_t::doesResample() const -{ - return resampler != 0; -} - -inline -void AudioMixer::track_t::adjustVolumeRamp() -{ - for (int i=0 ; i<2 ; i++) { - if (((volumeInc[i]>0) && (((prevVolume[i]+volumeInc[i])>>16) >= volume[i])) || - ((volumeInc[i]<0) && (((prevVolume[i]+volumeInc[i])>>16) <= volume[i]))) { - volumeInc[i] = 0; - prevVolume[i] = volume[i]<<16; - } - } -} - - -status_t AudioMixer::setBufferProvider(AudioBufferProvider* buffer) -{ - mState.tracks[ mActiveTrack ].bufferProvider = buffer; - return NO_ERROR; -} - - - -void AudioMixer::process(void* output) -{ - mState.hook(&mState, output); -} - - -void AudioMixer::process__validate(state_t* state, void* output) -{ - LOGW_IF(!state->needsChanged, - "in process__validate() but nothing's invalid"); - - uint32_t changed = state->needsChanged; - state->needsChanged = 0; // clear the validation flag - - // recompute which tracks are enabled / disabled - uint32_t enabled = 0; - uint32_t disabled = 0; - while (changed) { - const int i = 31 - __builtin_clz(changed); - const uint32_t mask = 1<<i; - changed &= ~mask; - track_t& t = state->tracks[i]; - (t.enabled ? enabled : disabled) |= mask; - } - state->enabledTracks &= ~disabled; - state->enabledTracks |= enabled; - - // compute everything we need... - int countActiveTracks = 0; - int all16BitsStereoNoResample = 1; - int resampling = 0; - int volumeRamp = 0; - uint32_t en = state->enabledTracks; - while (en) { - const int i = 31 - __builtin_clz(en); - en &= ~(1<<i); - - countActiveTracks++; - track_t& t = state->tracks[i]; - uint32_t n = 0; - n |= NEEDS_CHANNEL_1 + t.channelCount - 1; - n |= NEEDS_FORMAT_16; - n |= t.doesResample() ? NEEDS_RESAMPLE_ENABLED : NEEDS_RESAMPLE_DISABLED; - - if (t.volumeInc[0]|t.volumeInc[1]) { - volumeRamp = 1; - } else if (!t.doesResample() && t.volumeRL == 0) { - n |= NEEDS_MUTE_ENABLED; - } - t.needs = n; - - if ((n & NEEDS_MUTE__MASK) == NEEDS_MUTE_ENABLED) { - t.hook = track__nop; - } else { - if ((n & NEEDS_RESAMPLE__MASK) == NEEDS_RESAMPLE_ENABLED) { - all16BitsStereoNoResample = 0; - resampling = 1; - t.hook = track__genericResample; - } else { - if ((n & NEEDS_CHANNEL_COUNT__MASK) == NEEDS_CHANNEL_1){ - t.hook = track__16BitsMono; - all16BitsStereoNoResample = 0; - } - if ((n & NEEDS_CHANNEL_COUNT__MASK) == NEEDS_CHANNEL_2){ - t.hook = track__16BitsStereo; - } - } - } - } - - // select the processing hooks - state->hook = process__nop; - if (countActiveTracks) { - if (resampling) { - if (!state->outputTemp) { - state->outputTemp = new int32_t[MAX_NUM_CHANNELS * state->frameCount]; - } - if (!state->resampleTemp) { - state->resampleTemp = new int32_t[MAX_NUM_CHANNELS * state->frameCount]; - } - state->hook = process__genericResampling; - } else { - if (state->outputTemp) { - delete [] state->outputTemp; - state->outputTemp = 0; - } - if (state->resampleTemp) { - delete [] state->resampleTemp; - state->resampleTemp = 0; - } - state->hook = process__genericNoResampling; - if (all16BitsStereoNoResample && !volumeRamp) { - if (countActiveTracks == 1) { - state->hook = process__OneTrack16BitsStereoNoResampling; - } - } - } - } - - LOGV("mixer configuration change: %d activeTracks (%08x) " - "all16BitsStereoNoResample=%d, resampling=%d, volumeRamp=%d", - countActiveTracks, state->enabledTracks, - all16BitsStereoNoResample, resampling, volumeRamp); - - state->hook(state, output); - - // Now that the volume ramp has been done, set optimal state and - // track hooks for subsequent mixer process - if (countActiveTracks) { - int allMuted = 1; - uint32_t en = state->enabledTracks; - while (en) { - const int i = 31 - __builtin_clz(en); - en &= ~(1<<i); - track_t& t = state->tracks[i]; - if (!t.doesResample() && t.volumeRL == 0) - { - t.needs |= NEEDS_MUTE_ENABLED; - t.hook = track__nop; - } else { - allMuted = 0; - } - } - if (allMuted) { - state->hook = process__nop; - } else if (!resampling && all16BitsStereoNoResample) { - if (countActiveTracks == 1) { - state->hook = process__OneTrack16BitsStereoNoResampling; - } - } - } -} - -static inline -int32_t mulAdd(int16_t in, int16_t v, int32_t a) -{ -#if defined(__arm__) && !defined(__thumb__) - int32_t out; - asm( "smlabb %[out], %[in], %[v], %[a] \n" - : [out]"=r"(out) - : [in]"%r"(in), [v]"r"(v), [a]"r"(a) - : ); - return out; -#else - return a + in * int32_t(v); -#endif -} - -static inline -int32_t mul(int16_t in, int16_t v) -{ -#if defined(__arm__) && !defined(__thumb__) - int32_t out; - asm( "smulbb %[out], %[in], %[v] \n" - : [out]"=r"(out) - : [in]"%r"(in), [v]"r"(v) - : ); - return out; -#else - return in * int32_t(v); -#endif -} - -static inline -int32_t mulAddRL(int left, uint32_t inRL, uint32_t vRL, int32_t a) -{ -#if defined(__arm__) && !defined(__thumb__) - int32_t out; - if (left) { - asm( "smlabb %[out], %[inRL], %[vRL], %[a] \n" - : [out]"=r"(out) - : [inRL]"%r"(inRL), [vRL]"r"(vRL), [a]"r"(a) - : ); - } else { - asm( "smlatt %[out], %[inRL], %[vRL], %[a] \n" - : [out]"=r"(out) - : [inRL]"%r"(inRL), [vRL]"r"(vRL), [a]"r"(a) - : ); - } - return out; -#else - if (left) { - return a + int16_t(inRL&0xFFFF) * int16_t(vRL&0xFFFF); - } else { - return a + int16_t(inRL>>16) * int16_t(vRL>>16); - } -#endif -} - -static inline -int32_t mulRL(int left, uint32_t inRL, uint32_t vRL) -{ -#if defined(__arm__) && !defined(__thumb__) - int32_t out; - if (left) { - asm( "smulbb %[out], %[inRL], %[vRL] \n" - : [out]"=r"(out) - : [inRL]"%r"(inRL), [vRL]"r"(vRL) - : ); - } else { - asm( "smultt %[out], %[inRL], %[vRL] \n" - : [out]"=r"(out) - : [inRL]"%r"(inRL), [vRL]"r"(vRL) - : ); - } - return out; -#else - if (left) { - return int16_t(inRL&0xFFFF) * int16_t(vRL&0xFFFF); - } else { - return int16_t(inRL>>16) * int16_t(vRL>>16); - } -#endif -} - - -void AudioMixer::track__genericResample(track_t* t, int32_t* out, size_t outFrameCount, int32_t* temp) -{ - t->resampler->setSampleRate(t->sampleRate); - - // ramp gain - resample to temp buffer and scale/mix in 2nd step - if UNLIKELY(t->volumeInc[0]|t->volumeInc[1]) { - t->resampler->setVolume(UNITY_GAIN, UNITY_GAIN); - memset(temp, 0, outFrameCount * MAX_NUM_CHANNELS * sizeof(int32_t)); - t->resampler->resample(temp, outFrameCount, t->bufferProvider); - volumeRampStereo(t, out, outFrameCount, temp); - } - - // constant gain - else { - t->resampler->setVolume(t->volume[0], t->volume[1]); - t->resampler->resample(out, outFrameCount, t->bufferProvider); - } -} - -void AudioMixer::track__nop(track_t* t, int32_t* out, size_t outFrameCount, int32_t* temp) -{ -} - -void AudioMixer::volumeRampStereo(track_t* t, int32_t* out, size_t frameCount, int32_t* temp) -{ - int32_t vl = t->prevVolume[0]; - int32_t vr = t->prevVolume[1]; - const int32_t vlInc = t->volumeInc[0]; - const int32_t vrInc = t->volumeInc[1]; - - //LOGD("[0] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d", - // t, vlInc/65536.0f, vl/65536.0f, t->volume[0], - // (vl + vlInc*frameCount)/65536.0f, frameCount); - - // ramp volume - do { - *out++ += (vl >> 16) * (*temp++ >> 12); - *out++ += (vr >> 16) * (*temp++ >> 12); - vl += vlInc; - vr += vrInc; - } while (--frameCount); - - t->prevVolume[0] = vl; - t->prevVolume[1] = vr; - t->adjustVolumeRamp(); -} - -void AudioMixer::track__16BitsStereo(track_t* t, int32_t* out, size_t frameCount, int32_t* temp) -{ - int16_t const *in = static_cast<int16_t const *>(t->in); - - // ramp gain - if UNLIKELY(t->volumeInc[0]|t->volumeInc[1]) { - int32_t vl = t->prevVolume[0]; - int32_t vr = t->prevVolume[1]; - const int32_t vlInc = t->volumeInc[0]; - const int32_t vrInc = t->volumeInc[1]; - - // LOGD("[1] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d", - // t, vlInc/65536.0f, vl/65536.0f, t->volume[0], - // (vl + vlInc*frameCount)/65536.0f, frameCount); - - do { - *out++ += (vl >> 16) * (int32_t) *in++; - *out++ += (vr >> 16) * (int32_t) *in++; - vl += vlInc; - vr += vrInc; - } while (--frameCount); - - t->prevVolume[0] = vl; - t->prevVolume[1] = vr; - t->adjustVolumeRamp(); - } - - // constant gain - else { - const uint32_t vrl = t->volumeRL; - do { - uint32_t rl = *reinterpret_cast<uint32_t const *>(in); - in += 2; - out[0] = mulAddRL(1, rl, vrl, out[0]); - out[1] = mulAddRL(0, rl, vrl, out[1]); - out += 2; - } while (--frameCount); - } - t->in = in; -} - -void AudioMixer::track__16BitsMono(track_t* t, int32_t* out, size_t frameCount, int32_t* temp) -{ - int16_t const *in = static_cast<int16_t const *>(t->in); - - // ramp gain - if UNLIKELY(t->volumeInc[0]|t->volumeInc[1]) { - int32_t vl = t->prevVolume[0]; - int32_t vr = t->prevVolume[1]; - const int32_t vlInc = t->volumeInc[0]; - const int32_t vrInc = t->volumeInc[1]; - - // LOGD("[2] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d", - // t, vlInc/65536.0f, vl/65536.0f, t->volume[0], - // (vl + vlInc*frameCount)/65536.0f, frameCount); - - do { - int32_t l = *in++; - *out++ += (vl >> 16) * l; - *out++ += (vr >> 16) * l; - vl += vlInc; - vr += vrInc; - } while (--frameCount); - - t->prevVolume[0] = vl; - t->prevVolume[1] = vr; - t->adjustVolumeRamp(); - } - // constant gain - else { - const int16_t vl = t->volume[0]; - const int16_t vr = t->volume[1]; - do { - int16_t l = *in++; - out[0] = mulAdd(l, vl, out[0]); - out[1] = mulAdd(l, vr, out[1]); - out += 2; - } while (--frameCount); - } - t->in = in; -} - -inline -void AudioMixer::ditherAndClamp(int32_t* out, int32_t const *sums, size_t c) -{ - for (size_t i=0 ; i<c ; i++) { - int32_t l = *sums++; - int32_t r = *sums++; - int32_t nl = l >> 12; - int32_t nr = r >> 12; - l = clamp16(nl); - r = clamp16(nr); - *out++ = (r<<16) | (l & 0xFFFF); - } -} - -// no-op case -void AudioMixer::process__nop(state_t* state, void* output) -{ - // this assumes output 16 bits stereo, no resampling - memset(output, 0, state->frameCount*4); - uint32_t en = state->enabledTracks; - while (en) { - const int i = 31 - __builtin_clz(en); - en &= ~(1<<i); - track_t& t = state->tracks[i]; - size_t outFrames = state->frameCount; - while (outFrames) { - t.buffer.frameCount = outFrames; - t.bufferProvider->getNextBuffer(&t.buffer); - if (!t.buffer.raw) break; - outFrames -= t.buffer.frameCount; - t.bufferProvider->releaseBuffer(&t.buffer); - } - } -} - -// generic code without resampling -void AudioMixer::process__genericNoResampling(state_t* state, void* output) -{ - int32_t outTemp[BLOCKSIZE * MAX_NUM_CHANNELS] __attribute__((aligned(32))); - - // acquire each track's buffer - uint32_t enabledTracks = state->enabledTracks; - uint32_t en = enabledTracks; - while (en) { - const int i = 31 - __builtin_clz(en); - en &= ~(1<<i); - track_t& t = state->tracks[i]; - t.buffer.frameCount = state->frameCount; - t.bufferProvider->getNextBuffer(&t.buffer); - t.frameCount = t.buffer.frameCount; - t.in = t.buffer.raw; - // t.in == NULL can happen if the track was flushed just after having - // been enabled for mixing. - if (t.in == NULL) - enabledTracks &= ~(1<<i); - } - - // this assumes output 16 bits stereo, no resampling - int32_t* out = static_cast<int32_t*>(output); - size_t numFrames = state->frameCount; - do { - memset(outTemp, 0, sizeof(outTemp)); - - en = enabledTracks; - while (en) { - const int i = 31 - __builtin_clz(en); - en &= ~(1<<i); - track_t& t = state->tracks[i]; - size_t outFrames = BLOCKSIZE; - - while (outFrames) { - size_t inFrames = (t.frameCount > outFrames)?outFrames:t.frameCount; - if (inFrames) { - (t.hook)(&t, outTemp + (BLOCKSIZE-outFrames)*MAX_NUM_CHANNELS, inFrames, state->resampleTemp); - t.frameCount -= inFrames; - outFrames -= inFrames; - } - if (t.frameCount == 0 && outFrames) { - t.bufferProvider->releaseBuffer(&t.buffer); - t.buffer.frameCount = numFrames - (BLOCKSIZE - outFrames); - t.bufferProvider->getNextBuffer(&t.buffer); - t.in = t.buffer.raw; - if (t.in == NULL) { - enabledTracks &= ~(1<<i); - break; - } - t.frameCount = t.buffer.frameCount; - } - } - } - - ditherAndClamp(out, outTemp, BLOCKSIZE); - out += BLOCKSIZE; - numFrames -= BLOCKSIZE; - } while (numFrames); - - - // release each track's buffer - en = enabledTracks; - while (en) { - const int i = 31 - __builtin_clz(en); - en &= ~(1<<i); - track_t& t = state->tracks[i]; - t.bufferProvider->releaseBuffer(&t.buffer); - } -} - -// generic code with resampling -void AudioMixer::process__genericResampling(state_t* state, void* output) -{ - int32_t* const outTemp = state->outputTemp; - const size_t size = sizeof(int32_t) * MAX_NUM_CHANNELS * state->frameCount; - memset(outTemp, 0, size); - - int32_t* out = static_cast<int32_t*>(output); - size_t numFrames = state->frameCount; - - uint32_t en = state->enabledTracks; - while (en) { - const int i = 31 - __builtin_clz(en); - en &= ~(1<<i); - track_t& t = state->tracks[i]; - - // this is a little goofy, on the resampling case we don't - // acquire/release the buffers because it's done by - // the resampler. - if ((t.needs & NEEDS_RESAMPLE__MASK) == NEEDS_RESAMPLE_ENABLED) { - (t.hook)(&t, outTemp, numFrames, state->resampleTemp); - } else { - - size_t outFrames = numFrames; - - while (outFrames) { - t.buffer.frameCount = outFrames; - t.bufferProvider->getNextBuffer(&t.buffer); - t.in = t.buffer.raw; - // t.in == NULL can happen if the track was flushed just after having - // been enabled for mixing. - if (t.in == NULL) break; - - (t.hook)(&t, outTemp + (numFrames-outFrames)*MAX_NUM_CHANNELS, t.buffer.frameCount, state->resampleTemp); - outFrames -= t.buffer.frameCount; - t.bufferProvider->releaseBuffer(&t.buffer); - } - } - } - - ditherAndClamp(out, outTemp, numFrames); -} - -// one track, 16 bits stereo without resampling is the most common case -void AudioMixer::process__OneTrack16BitsStereoNoResampling(state_t* state, void* output) -{ - const int i = 31 - __builtin_clz(state->enabledTracks); - const track_t& t = state->tracks[i]; - - AudioBufferProvider::Buffer& b(t.buffer); - - int32_t* out = static_cast<int32_t*>(output); - size_t numFrames = state->frameCount; - - const int16_t vl = t.volume[0]; - const int16_t vr = t.volume[1]; - const uint32_t vrl = t.volumeRL; - while (numFrames) { - b.frameCount = numFrames; - t.bufferProvider->getNextBuffer(&b); - int16_t const *in = b.i16; - - // in == NULL can happen if the track was flushed just after having - // been enabled for mixing. - if (in == NULL) { - memset(out, 0, numFrames*MAX_NUM_CHANNELS*sizeof(int16_t)); - return; - } - size_t outFrames = b.frameCount; - - if (UNLIKELY(uint32_t(vl) > UNITY_GAIN || uint32_t(vr) > UNITY_GAIN)) { - // volume is boosted, so we might need to clamp even though - // we process only one track. - do { - uint32_t rl = *reinterpret_cast<uint32_t const *>(in); - in += 2; - int32_t l = mulRL(1, rl, vrl) >> 12; - int32_t r = mulRL(0, rl, vrl) >> 12; - // clamping... - l = clamp16(l); - r = clamp16(r); - *out++ = (r<<16) | (l & 0xFFFF); - } while (--outFrames); - } else { - do { - uint32_t rl = *reinterpret_cast<uint32_t const *>(in); - in += 2; - int32_t l = mulRL(1, rl, vrl) >> 12; - int32_t r = mulRL(0, rl, vrl) >> 12; - *out++ = (r<<16) | (l & 0xFFFF); - } while (--outFrames); - } - numFrames -= b.frameCount; - t.bufferProvider->releaseBuffer(&b); - } -} - -// 2 tracks is also a common case -void AudioMixer::process__TwoTracks16BitsStereoNoResampling(state_t* state, void* output) -{ - int i; - uint32_t en = state->enabledTracks; - - i = 31 - __builtin_clz(en); - const track_t& t0 = state->tracks[i]; - AudioBufferProvider::Buffer& b0(t0.buffer); - - en &= ~(1<<i); - i = 31 - __builtin_clz(en); - const track_t& t1 = state->tracks[i]; - AudioBufferProvider::Buffer& b1(t1.buffer); - - int16_t const *in0; - const int16_t vl0 = t0.volume[0]; - const int16_t vr0 = t0.volume[1]; - size_t frameCount0 = 0; - - int16_t const *in1; - const int16_t vl1 = t1.volume[0]; - const int16_t vr1 = t1.volume[1]; - size_t frameCount1 = 0; - - int32_t* out = static_cast<int32_t*>(output); - size_t numFrames = state->frameCount; - int16_t const *buff = NULL; - - - while (numFrames) { - - if (frameCount0 == 0) { - b0.frameCount = numFrames; - t0.bufferProvider->getNextBuffer(&b0); - if (b0.i16 == NULL) { - if (buff == NULL) { - buff = new int16_t[MAX_NUM_CHANNELS * state->frameCount]; - } - in0 = buff; - b0.frameCount = numFrames; - } else { - in0 = b0.i16; - } - frameCount0 = b0.frameCount; - } - if (frameCount1 == 0) { - b1.frameCount = numFrames; - t1.bufferProvider->getNextBuffer(&b1); - if (b1.i16 == NULL) { - if (buff == NULL) { - buff = new int16_t[MAX_NUM_CHANNELS * state->frameCount]; - } - in1 = buff; - b1.frameCount = numFrames; - } else { - in1 = b1.i16; - } - frameCount1 = b1.frameCount; - } - - size_t outFrames = frameCount0 < frameCount1?frameCount0:frameCount1; - - numFrames -= outFrames; - frameCount0 -= outFrames; - frameCount1 -= outFrames; - - do { - int32_t l0 = *in0++; - int32_t r0 = *in0++; - l0 = mul(l0, vl0); - r0 = mul(r0, vr0); - int32_t l = *in1++; - int32_t r = *in1++; - l = mulAdd(l, vl1, l0) >> 12; - r = mulAdd(r, vr1, r0) >> 12; - // clamping... - l = clamp16(l); - r = clamp16(r); - *out++ = (r<<16) | (l & 0xFFFF); - } while (--outFrames); - - if (frameCount0 == 0) { - t0.bufferProvider->releaseBuffer(&b0); - } - if (frameCount1 == 0) { - t1.bufferProvider->releaseBuffer(&b1); - } - } - - if (buff != NULL) { - delete [] buff; - } -} - -// ---------------------------------------------------------------------------- -}; // namespace android - diff --git a/libs/audioflinger/AudioMixer.h b/libs/audioflinger/AudioMixer.h deleted file mode 100644 index 72ca28a..0000000 --- a/libs/audioflinger/AudioMixer.h +++ /dev/null @@ -1,192 +0,0 @@ -/* //device/include/server/AudioFlinger/AudioMixer.h -** -** Copyright 2007, 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 ANDROID_AUDIO_MIXER_H -#define ANDROID_AUDIO_MIXER_H - -#include <stdint.h> -#include <sys/types.h> - -#include "AudioBufferProvider.h" -#include "AudioResampler.h" - -namespace android { - -// ---------------------------------------------------------------------------- - -#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true )) -#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false )) - -// ---------------------------------------------------------------------------- - -class AudioMixer -{ -public: - AudioMixer(size_t frameCount, uint32_t sampleRate); - - ~AudioMixer(); - - static const uint32_t MAX_NUM_TRACKS = 32; - static const uint32_t MAX_NUM_CHANNELS = 2; - - static const uint16_t UNITY_GAIN = 0x1000; - - enum { // names - - // track units (32 units) - TRACK0 = 0x1000, - - // enable/disable - MIXING = 0x2000, - - // setParameter targets - TRACK = 0x3000, - RESAMPLE = 0x3001, - RAMP_VOLUME = 0x3002, // ramp to new volume - VOLUME = 0x3003, // don't ramp - - // set Parameter names - // for target TRACK - CHANNEL_COUNT = 0x4000, - FORMAT = 0x4001, - // for TARGET RESAMPLE - SAMPLE_RATE = 0x4100, - // for TARGET VOLUME (8 channels max) - VOLUME0 = 0x4200, - VOLUME1 = 0x4201, - }; - - - int getTrackName(); - void deleteTrackName(int name); - - status_t enable(int name); - status_t disable(int name); - - status_t setActiveTrack(int track); - status_t setParameter(int target, int name, int value); - - status_t setBufferProvider(AudioBufferProvider* bufferProvider); - void process(void* output); - - uint32_t trackNames() const { return mTrackNames; } - -private: - - enum { - NEEDS_CHANNEL_COUNT__MASK = 0x00000003, - NEEDS_FORMAT__MASK = 0x000000F0, - NEEDS_MUTE__MASK = 0x00000100, - NEEDS_RESAMPLE__MASK = 0x00001000, - }; - - enum { - NEEDS_CHANNEL_1 = 0x00000000, - NEEDS_CHANNEL_2 = 0x00000001, - - NEEDS_FORMAT_16 = 0x00000010, - - NEEDS_MUTE_DISABLED = 0x00000000, - NEEDS_MUTE_ENABLED = 0x00000100, - - NEEDS_RESAMPLE_DISABLED = 0x00000000, - NEEDS_RESAMPLE_ENABLED = 0x00001000, - }; - - static inline int32_t applyVolume(int32_t in, int32_t v) { - return in * v; - } - - - struct state_t; - - typedef void (*mix_t)(state_t* state, void* output); - - static const int BLOCKSIZE = 16; // 4 cache lines - - struct track_t { - uint32_t needs; - - union { - int16_t volume[2]; // [0]3.12 fixed point - int32_t volumeRL; - }; - - int32_t prevVolume[2]; - - int32_t volumeInc[2]; - - uint16_t frameCount; - - uint8_t channelCount : 4; - uint8_t enabled : 1; - uint8_t reserved0 : 3; - uint8_t format; - - AudioBufferProvider* bufferProvider; - mutable AudioBufferProvider::Buffer buffer; - - void (*hook)(track_t* t, int32_t* output, size_t numOutFrames, int32_t* temp); - void const* in; // current location in buffer - - AudioResampler* resampler; - uint32_t sampleRate; - - bool setResampler(uint32_t sampleRate, uint32_t devSampleRate); - bool doesResample() const; - void adjustVolumeRamp(); - }; - - // pad to 32-bytes to fill cache line - struct state_t { - uint32_t enabledTracks; - uint32_t needsChanged; - size_t frameCount; - mix_t hook; - int32_t *outputTemp; - int32_t *resampleTemp; - int32_t reserved[2]; - track_t tracks[32]; __attribute__((aligned(32))); - }; - - int mActiveTrack; - uint32_t mTrackNames; - const uint32_t mSampleRate; - - state_t mState __attribute__((aligned(32))); - - void invalidateState(uint32_t mask); - - static void track__genericResample(track_t* t, int32_t* out, size_t numFrames, int32_t* temp); - static void track__nop(track_t* t, int32_t* out, size_t numFrames, int32_t* temp); - static void volumeRampStereo(track_t* t, int32_t* out, size_t frameCount, int32_t* temp); - static void track__16BitsStereo(track_t* t, int32_t* out, size_t numFrames, int32_t* temp); - static void track__16BitsMono(track_t* t, int32_t* out, size_t numFrames, int32_t* temp); - static void ditherAndClamp(int32_t* out, int32_t const *sums, size_t c); - - static void process__validate(state_t* state, void* output); - static void process__nop(state_t* state, void* output); - static void process__genericNoResampling(state_t* state, void* output); - static void process__genericResampling(state_t* state, void* output); - static void process__OneTrack16BitsStereoNoResampling(state_t* state, void* output); - static void process__TwoTracks16BitsStereoNoResampling(state_t* state, void* output); -}; - -// ---------------------------------------------------------------------------- -}; // namespace android - -#endif // ANDROID_AUDIO_MIXER_H diff --git a/libs/audioflinger/AudioResampler.cpp b/libs/audioflinger/AudioResampler.cpp deleted file mode 100644 index 5dabacb..0000000 --- a/libs/audioflinger/AudioResampler.cpp +++ /dev/null @@ -1,595 +0,0 @@ -/* - * Copyright (C) 2007 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 "AudioResampler" -//#define LOG_NDEBUG 0 - -#include <stdint.h> -#include <stdlib.h> -#include <sys/types.h> -#include <cutils/log.h> -#include <cutils/properties.h> -#include "AudioResampler.h" -#include "AudioResamplerSinc.h" -#include "AudioResamplerCubic.h" - -namespace android { - -#ifdef __ARM_ARCH_5E__ // optimized asm option - #define ASM_ARM_RESAMP1 // enable asm optimisation for ResamplerOrder1 -#endif // __ARM_ARCH_5E__ -// ---------------------------------------------------------------------------- - -class AudioResamplerOrder1 : public AudioResampler { -public: - AudioResamplerOrder1(int bitDepth, int inChannelCount, int32_t sampleRate) : - AudioResampler(bitDepth, inChannelCount, sampleRate), mX0L(0), mX0R(0) { - } - virtual void resample(int32_t* out, size_t outFrameCount, - AudioBufferProvider* provider); -private: - // number of bits used in interpolation multiply - 15 bits avoids overflow - static const int kNumInterpBits = 15; - - // bits to shift the phase fraction down to avoid overflow - static const int kPreInterpShift = kNumPhaseBits - kNumInterpBits; - - void init() {} - void resampleMono16(int32_t* out, size_t outFrameCount, - AudioBufferProvider* provider); - void resampleStereo16(int32_t* out, size_t outFrameCount, - AudioBufferProvider* provider); -#ifdef ASM_ARM_RESAMP1 // asm optimisation for ResamplerOrder1 - void AsmMono16Loop(int16_t *in, int32_t* maxOutPt, int32_t maxInIdx, - size_t &outputIndex, int32_t* out, size_t &inputIndex, int32_t vl, int32_t vr, - uint32_t &phaseFraction, uint32_t phaseIncrement); - void AsmStereo16Loop(int16_t *in, int32_t* maxOutPt, int32_t maxInIdx, - size_t &outputIndex, int32_t* out, size_t &inputIndex, int32_t vl, int32_t vr, - uint32_t &phaseFraction, uint32_t phaseIncrement); -#endif // ASM_ARM_RESAMP1 - - static inline int32_t Interp(int32_t x0, int32_t x1, uint32_t f) { - return x0 + (((x1 - x0) * (int32_t)(f >> kPreInterpShift)) >> kNumInterpBits); - } - static inline void Advance(size_t* index, uint32_t* frac, uint32_t inc) { - *frac += inc; - *index += (size_t)(*frac >> kNumPhaseBits); - *frac &= kPhaseMask; - } - int mX0L; - int mX0R; -}; - -// ---------------------------------------------------------------------------- -AudioResampler* AudioResampler::create(int bitDepth, int inChannelCount, - int32_t sampleRate, int quality) { - - // can only create low quality resample now - AudioResampler* resampler; - - char value[PROPERTY_VALUE_MAX]; - if (property_get("af.resampler.quality", value, 0)) { - quality = atoi(value); - LOGD("forcing AudioResampler quality to %d", quality); - } - - if (quality == DEFAULT) - quality = LOW_QUALITY; - - switch (quality) { - default: - case LOW_QUALITY: - LOGV("Create linear Resampler"); - resampler = new AudioResamplerOrder1(bitDepth, inChannelCount, sampleRate); - break; - case MED_QUALITY: - LOGV("Create cubic Resampler"); - resampler = new AudioResamplerCubic(bitDepth, inChannelCount, sampleRate); - break; - case HIGH_QUALITY: - LOGV("Create sinc Resampler"); - resampler = new AudioResamplerSinc(bitDepth, inChannelCount, sampleRate); - break; - } - - // initialize resampler - resampler->init(); - return resampler; -} - -AudioResampler::AudioResampler(int bitDepth, int inChannelCount, - int32_t sampleRate) : - mBitDepth(bitDepth), mChannelCount(inChannelCount), - mSampleRate(sampleRate), mInSampleRate(sampleRate), mInputIndex(0), - mPhaseFraction(0) { - // sanity check on format - if ((bitDepth != 16) ||(inChannelCount < 1) || (inChannelCount > 2)) { - LOGE("Unsupported sample format, %d bits, %d channels", bitDepth, - inChannelCount); - // LOG_ASSERT(0); - } - - // initialize common members - mVolume[0] = mVolume[1] = 0; - mBuffer.frameCount = 0; - - // save format for quick lookup - if (inChannelCount == 1) { - mFormat = MONO_16_BIT; - } else { - mFormat = STEREO_16_BIT; - } -} - -AudioResampler::~AudioResampler() { -} - -void AudioResampler::setSampleRate(int32_t inSampleRate) { - mInSampleRate = inSampleRate; - mPhaseIncrement = (uint32_t)((kPhaseMultiplier * inSampleRate) / mSampleRate); -} - -void AudioResampler::setVolume(int16_t left, int16_t right) { - // TODO: Implement anti-zipper filter - mVolume[0] = left; - mVolume[1] = right; -} - -// ---------------------------------------------------------------------------- - -void AudioResamplerOrder1::resample(int32_t* out, size_t outFrameCount, - AudioBufferProvider* provider) { - - // should never happen, but we overflow if it does - // LOG_ASSERT(outFrameCount < 32767); - - // select the appropriate resampler - switch (mChannelCount) { - case 1: - resampleMono16(out, outFrameCount, provider); - break; - case 2: - resampleStereo16(out, outFrameCount, provider); - break; - } -} - -void AudioResamplerOrder1::resampleStereo16(int32_t* out, size_t outFrameCount, - AudioBufferProvider* provider) { - - int32_t vl = mVolume[0]; - int32_t vr = mVolume[1]; - - size_t inputIndex = mInputIndex; - uint32_t phaseFraction = mPhaseFraction; - uint32_t phaseIncrement = mPhaseIncrement; - size_t outputIndex = 0; - size_t outputSampleCount = outFrameCount * 2; - size_t inFrameCount = (outFrameCount*mInSampleRate)/mSampleRate; - - // LOGE("starting resample %d frames, inputIndex=%d, phaseFraction=%d, phaseIncrement=%d\n", - // outFrameCount, inputIndex, phaseFraction, phaseIncrement); - - while (outputIndex < outputSampleCount) { - - // buffer is empty, fetch a new one - while (mBuffer.frameCount == 0) { - mBuffer.frameCount = inFrameCount; - provider->getNextBuffer(&mBuffer); - if (mBuffer.raw == NULL) { - goto resampleStereo16_exit; - } - - // LOGE("New buffer fetched: %d frames\n", mBuffer.frameCount); - if (mBuffer.frameCount > inputIndex) break; - - inputIndex -= mBuffer.frameCount; - mX0L = mBuffer.i16[mBuffer.frameCount*2-2]; - mX0R = mBuffer.i16[mBuffer.frameCount*2-1]; - provider->releaseBuffer(&mBuffer); - // mBuffer.frameCount == 0 now so we reload a new buffer - } - - int16_t *in = mBuffer.i16; - - // handle boundary case - while (inputIndex == 0) { - // LOGE("boundary case\n"); - out[outputIndex++] += vl * Interp(mX0L, in[0], phaseFraction); - out[outputIndex++] += vr * Interp(mX0R, in[1], phaseFraction); - Advance(&inputIndex, &phaseFraction, phaseIncrement); - if (outputIndex == outputSampleCount) - break; - } - - // process input samples - // LOGE("general case\n"); - -#ifdef ASM_ARM_RESAMP1 // asm optimisation for ResamplerOrder1 - if (inputIndex + 2 < mBuffer.frameCount) { - int32_t* maxOutPt; - int32_t maxInIdx; - - maxOutPt = out + (outputSampleCount - 2); // 2 because 2 frames per loop - maxInIdx = mBuffer.frameCount - 2; - AsmStereo16Loop(in, maxOutPt, maxInIdx, outputIndex, out, inputIndex, vl, vr, - phaseFraction, phaseIncrement); - } -#endif // ASM_ARM_RESAMP1 - - while (outputIndex < outputSampleCount && inputIndex < mBuffer.frameCount) { - out[outputIndex++] += vl * Interp(in[inputIndex*2-2], - in[inputIndex*2], phaseFraction); - out[outputIndex++] += vr * Interp(in[inputIndex*2-1], - in[inputIndex*2+1], phaseFraction); - Advance(&inputIndex, &phaseFraction, phaseIncrement); - } - - // LOGE("loop done - outputIndex=%d, inputIndex=%d\n", outputIndex, inputIndex); - - // if done with buffer, save samples - if (inputIndex >= mBuffer.frameCount) { - inputIndex -= mBuffer.frameCount; - - // LOGE("buffer done, new input index %d", inputIndex); - - mX0L = mBuffer.i16[mBuffer.frameCount*2-2]; - mX0R = mBuffer.i16[mBuffer.frameCount*2-1]; - provider->releaseBuffer(&mBuffer); - - // verify that the releaseBuffer resets the buffer frameCount - // LOG_ASSERT(mBuffer.frameCount == 0); - } - } - - // LOGE("output buffer full - outputIndex=%d, inputIndex=%d\n", outputIndex, inputIndex); - -resampleStereo16_exit: - // save state - mInputIndex = inputIndex; - mPhaseFraction = phaseFraction; -} - -void AudioResamplerOrder1::resampleMono16(int32_t* out, size_t outFrameCount, - AudioBufferProvider* provider) { - - int32_t vl = mVolume[0]; - int32_t vr = mVolume[1]; - - size_t inputIndex = mInputIndex; - uint32_t phaseFraction = mPhaseFraction; - uint32_t phaseIncrement = mPhaseIncrement; - size_t outputIndex = 0; - size_t outputSampleCount = outFrameCount * 2; - size_t inFrameCount = (outFrameCount*mInSampleRate)/mSampleRate; - - // LOGE("starting resample %d frames, inputIndex=%d, phaseFraction=%d, phaseIncrement=%d\n", - // outFrameCount, inputIndex, phaseFraction, phaseIncrement); - while (outputIndex < outputSampleCount) { - // buffer is empty, fetch a new one - while (mBuffer.frameCount == 0) { - mBuffer.frameCount = inFrameCount; - provider->getNextBuffer(&mBuffer); - if (mBuffer.raw == NULL) { - mInputIndex = inputIndex; - mPhaseFraction = phaseFraction; - goto resampleMono16_exit; - } - // LOGE("New buffer fetched: %d frames\n", mBuffer.frameCount); - if (mBuffer.frameCount > inputIndex) break; - - inputIndex -= mBuffer.frameCount; - mX0L = mBuffer.i16[mBuffer.frameCount-1]; - provider->releaseBuffer(&mBuffer); - // mBuffer.frameCount == 0 now so we reload a new buffer - } - int16_t *in = mBuffer.i16; - - // handle boundary case - while (inputIndex == 0) { - // LOGE("boundary case\n"); - int32_t sample = Interp(mX0L, in[0], phaseFraction); - out[outputIndex++] += vl * sample; - out[outputIndex++] += vr * sample; - Advance(&inputIndex, &phaseFraction, phaseIncrement); - if (outputIndex == outputSampleCount) - break; - } - - // process input samples - // LOGE("general case\n"); - -#ifdef ASM_ARM_RESAMP1 // asm optimisation for ResamplerOrder1 - if (inputIndex + 2 < mBuffer.frameCount) { - int32_t* maxOutPt; - int32_t maxInIdx; - - maxOutPt = out + (outputSampleCount - 2); - maxInIdx = (int32_t)mBuffer.frameCount - 2; - AsmMono16Loop(in, maxOutPt, maxInIdx, outputIndex, out, inputIndex, vl, vr, - phaseFraction, phaseIncrement); - } -#endif // ASM_ARM_RESAMP1 - - while (outputIndex < outputSampleCount && inputIndex < mBuffer.frameCount) { - int32_t sample = Interp(in[inputIndex-1], in[inputIndex], - phaseFraction); - out[outputIndex++] += vl * sample; - out[outputIndex++] += vr * sample; - Advance(&inputIndex, &phaseFraction, phaseIncrement); - } - - - // LOGE("loop done - outputIndex=%d, inputIndex=%d\n", outputIndex, inputIndex); - - // if done with buffer, save samples - if (inputIndex >= mBuffer.frameCount) { - inputIndex -= mBuffer.frameCount; - - // LOGE("buffer done, new input index %d", inputIndex); - - mX0L = mBuffer.i16[mBuffer.frameCount-1]; - provider->releaseBuffer(&mBuffer); - - // verify that the releaseBuffer resets the buffer frameCount - // LOG_ASSERT(mBuffer.frameCount == 0); - } - } - - // LOGE("output buffer full - outputIndex=%d, inputIndex=%d\n", outputIndex, inputIndex); - -resampleMono16_exit: - // save state - mInputIndex = inputIndex; - mPhaseFraction = phaseFraction; -} - -#ifdef ASM_ARM_RESAMP1 // asm optimisation for ResamplerOrder1 - -/******************************************************************* -* -* AsmMono16Loop -* asm optimized monotonic loop version; one loop is 2 frames -* Input: -* in : pointer on input samples -* maxOutPt : pointer on first not filled -* maxInIdx : index on first not used -* outputIndex : pointer on current output index -* out : pointer on output buffer -* inputIndex : pointer on current input index -* vl, vr : left and right gain -* phaseFraction : pointer on current phase fraction -* phaseIncrement -* Ouput: -* outputIndex : -* out : updated buffer -* inputIndex : index of next to use -* phaseFraction : phase fraction for next interpolation -* -*******************************************************************/ -void AudioResamplerOrder1::AsmMono16Loop(int16_t *in, int32_t* maxOutPt, int32_t maxInIdx, - size_t &outputIndex, int32_t* out, size_t &inputIndex, int32_t vl, int32_t vr, - uint32_t &phaseFraction, uint32_t phaseIncrement) -{ -#define MO_PARAM5 "36" // offset of parameter 5 (outputIndex) - - asm( - "stmfd sp!, {r4, r5, r6, r7, r8, r9, r10, r11, lr}\n" - // get parameters - " ldr r6, [sp, #" MO_PARAM5 " + 20]\n" // &phaseFraction - " ldr r6, [r6]\n" // phaseFraction - " ldr r7, [sp, #" MO_PARAM5 " + 8]\n" // &inputIndex - " ldr r7, [r7]\n" // inputIndex - " ldr r8, [sp, #" MO_PARAM5 " + 4]\n" // out - " ldr r0, [sp, #" MO_PARAM5 " + 0]\n" // &outputIndex - " ldr r0, [r0]\n" // outputIndex - " add r8, r0, asl #2\n" // curOut - " ldr r9, [sp, #" MO_PARAM5 " + 24]\n" // phaseIncrement - " ldr r10, [sp, #" MO_PARAM5 " + 12]\n" // vl - " ldr r11, [sp, #" MO_PARAM5 " + 16]\n" // vr - - // r0 pin, x0, Samp - - // r1 in - // r2 maxOutPt - // r3 maxInIdx - - // r4 x1, i1, i3, Out1 - // r5 out0 - - // r6 frac - // r7 inputIndex - // r8 curOut - - // r9 inc - // r10 vl - // r11 vr - - // r12 - // r13 sp - // r14 - - // the following loop works on 2 frames - - ".Y4L01:\n" - " cmp r8, r2\n" // curOut - maxCurOut - " bcs .Y4L02\n" - -#define MO_ONE_FRAME \ - " add r0, r1, r7, asl #1\n" /* in + inputIndex */\ - " ldrsh r4, [r0]\n" /* in[inputIndex] */\ - " ldr r5, [r8]\n" /* out[outputIndex] */\ - " ldrsh r0, [r0, #-2]\n" /* in[inputIndex-1] */\ - " bic r6, r6, #0xC0000000\n" /* phaseFraction & ... */\ - " sub r4, r4, r0\n" /* in[inputIndex] - in[inputIndex-1] */\ - " mov r4, r4, lsl #2\n" /* <<2 */\ - " smulwt r4, r4, r6\n" /* (x1-x0)*.. */\ - " add r6, r6, r9\n" /* phaseFraction + phaseIncrement */\ - " add r0, r0, r4\n" /* x0 - (..) */\ - " mla r5, r0, r10, r5\n" /* vl*interp + out[] */\ - " ldr r4, [r8, #4]\n" /* out[outputIndex+1] */\ - " str r5, [r8], #4\n" /* out[outputIndex++] = ... */\ - " mla r4, r0, r11, r4\n" /* vr*interp + out[] */\ - " add r7, r7, r6, lsr #30\n" /* inputIndex + phaseFraction>>30 */\ - " str r4, [r8], #4\n" /* out[outputIndex++] = ... */ - - MO_ONE_FRAME // frame 1 - MO_ONE_FRAME // frame 2 - - " cmp r7, r3\n" // inputIndex - maxInIdx - " bcc .Y4L01\n" - ".Y4L02:\n" - - " bic r6, r6, #0xC0000000\n" // phaseFraction & ... - // save modified values - " ldr r0, [sp, #" MO_PARAM5 " + 20]\n" // &phaseFraction - " str r6, [r0]\n" // phaseFraction - " ldr r0, [sp, #" MO_PARAM5 " + 8]\n" // &inputIndex - " str r7, [r0]\n" // inputIndex - " ldr r0, [sp, #" MO_PARAM5 " + 4]\n" // out - " sub r8, r0\n" // curOut - out - " asr r8, #2\n" // new outputIndex - " ldr r0, [sp, #" MO_PARAM5 " + 0]\n" // &outputIndex - " str r8, [r0]\n" // save outputIndex - - " ldmfd sp!, {r4, r5, r6, r7, r8, r9, r10, r11, pc}\n" - ); -} - -/******************************************************************* -* -* AsmStereo16Loop -* asm optimized stereo loop version; one loop is 2 frames -* Input: -* in : pointer on input samples -* maxOutPt : pointer on first not filled -* maxInIdx : index on first not used -* outputIndex : pointer on current output index -* out : pointer on output buffer -* inputIndex : pointer on current input index -* vl, vr : left and right gain -* phaseFraction : pointer on current phase fraction -* phaseIncrement -* Ouput: -* outputIndex : -* out : updated buffer -* inputIndex : index of next to use -* phaseFraction : phase fraction for next interpolation -* -*******************************************************************/ -void AudioResamplerOrder1::AsmStereo16Loop(int16_t *in, int32_t* maxOutPt, int32_t maxInIdx, - size_t &outputIndex, int32_t* out, size_t &inputIndex, int32_t vl, int32_t vr, - uint32_t &phaseFraction, uint32_t phaseIncrement) -{ -#define ST_PARAM5 "40" // offset of parameter 5 (outputIndex) - asm( - "stmfd sp!, {r4, r5, r6, r7, r8, r9, r10, r11, r12, lr}\n" - // get parameters - " ldr r6, [sp, #" ST_PARAM5 " + 20]\n" // &phaseFraction - " ldr r6, [r6]\n" // phaseFraction - " ldr r7, [sp, #" ST_PARAM5 " + 8]\n" // &inputIndex - " ldr r7, [r7]\n" // inputIndex - " ldr r8, [sp, #" ST_PARAM5 " + 4]\n" // out - " ldr r0, [sp, #" ST_PARAM5 " + 0]\n" // &outputIndex - " ldr r0, [r0]\n" // outputIndex - " add r8, r0, asl #2\n" // curOut - " ldr r9, [sp, #" ST_PARAM5 " + 24]\n" // phaseIncrement - " ldr r10, [sp, #" ST_PARAM5 " + 12]\n" // vl - " ldr r11, [sp, #" ST_PARAM5 " + 16]\n" // vr - - // r0 pin, x0, Samp - - // r1 in - // r2 maxOutPt - // r3 maxInIdx - - // r4 x1, i1, i3, out1 - // r5 out0 - - // r6 frac - // r7 inputIndex - // r8 curOut - - // r9 inc - // r10 vl - // r11 vr - - // r12 temporary - // r13 sp - // r14 - - ".Y5L01:\n" - " cmp r8, r2\n" // curOut - maxCurOut - " bcs .Y5L02\n" - -#define ST_ONE_FRAME \ - " bic r6, r6, #0xC0000000\n" /* phaseFraction & ... */\ -\ - " add r0, r1, r7, asl #2\n" /* in + 2*inputIndex */\ -\ - " ldrsh r4, [r0]\n" /* in[2*inputIndex] */\ - " ldr r5, [r8]\n" /* out[outputIndex] */\ - " ldrsh r12, [r0, #-4]\n" /* in[2*inputIndex-2] */\ - " sub r4, r4, r12\n" /* in[2*InputIndex] - in[2*InputIndex-2] */\ - " mov r4, r4, lsl #2\n" /* <<2 */\ - " smulwt r4, r4, r6\n" /* (x1-x0)*.. */\ - " add r12, r12, r4\n" /* x0 - (..) */\ - " mla r5, r12, r10, r5\n" /* vl*interp + out[] */\ - " ldr r4, [r8, #4]\n" /* out[outputIndex+1] */\ - " str r5, [r8], #4\n" /* out[outputIndex++] = ... */\ -\ - " ldrsh r12, [r0, #+2]\n" /* in[2*inputIndex+1] */\ - " ldrsh r0, [r0, #-2]\n" /* in[2*inputIndex-1] */\ - " sub r12, r12, r0\n" /* in[2*InputIndex] - in[2*InputIndex-2] */\ - " mov r12, r12, lsl #2\n" /* <<2 */\ - " smulwt r12, r12, r6\n" /* (x1-x0)*.. */\ - " add r12, r0, r12\n" /* x0 - (..) */\ - " mla r4, r12, r11, r4\n" /* vr*interp + out[] */\ - " str r4, [r8], #4\n" /* out[outputIndex++] = ... */\ -\ - " add r6, r6, r9\n" /* phaseFraction + phaseIncrement */\ - " add r7, r7, r6, lsr #30\n" /* inputIndex + phaseFraction>>30 */ - - ST_ONE_FRAME // frame 1 - ST_ONE_FRAME // frame 1 - - " cmp r7, r3\n" // inputIndex - maxInIdx - " bcc .Y5L01\n" - ".Y5L02:\n" - - " bic r6, r6, #0xC0000000\n" // phaseFraction & ... - // save modified values - " ldr r0, [sp, #" ST_PARAM5 " + 20]\n" // &phaseFraction - " str r6, [r0]\n" // phaseFraction - " ldr r0, [sp, #" ST_PARAM5 " + 8]\n" // &inputIndex - " str r7, [r0]\n" // inputIndex - " ldr r0, [sp, #" ST_PARAM5 " + 4]\n" // out - " sub r8, r0\n" // curOut - out - " asr r8, #2\n" // new outputIndex - " ldr r0, [sp, #" ST_PARAM5 " + 0]\n" // &outputIndex - " str r8, [r0]\n" // save outputIndex - - " ldmfd sp!, {r4, r5, r6, r7, r8, r9, r10, r11, r12, pc}\n" - ); -} - -#endif // ASM_ARM_RESAMP1 - - -// ---------------------------------------------------------------------------- -} -; // namespace android - diff --git a/libs/audioflinger/AudioResampler.h b/libs/audioflinger/AudioResampler.h deleted file mode 100644 index 39656c0..0000000 --- a/libs/audioflinger/AudioResampler.h +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (C) 2007 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 ANDROID_AUDIO_RESAMPLER_H -#define ANDROID_AUDIO_RESAMPLER_H - -#include <stdint.h> -#include <sys/types.h> - -#include "AudioBufferProvider.h" - -namespace android { -// ---------------------------------------------------------------------------- - -class AudioResampler { -public: - // Determines quality of SRC. - // LOW_QUALITY: linear interpolator (1st order) - // MED_QUALITY: cubic interpolator (3rd order) - // HIGH_QUALITY: fixed multi-tap FIR (e.g. 48KHz->44.1KHz) - // NOTE: high quality SRC will only be supported for - // certain fixed rate conversions. Sample rate cannot be - // changed dynamically. - enum src_quality { - DEFAULT=0, - LOW_QUALITY=1, - MED_QUALITY=2, - HIGH_QUALITY=3 - }; - - static AudioResampler* create(int bitDepth, int inChannelCount, - int32_t sampleRate, int quality=DEFAULT); - - virtual ~AudioResampler(); - - virtual void init() = 0; - virtual void setSampleRate(int32_t inSampleRate); - virtual void setVolume(int16_t left, int16_t right); - - virtual void resample(int32_t* out, size_t outFrameCount, - AudioBufferProvider* provider) = 0; - -protected: - // number of bits for phase fraction - 30 bits allows nearly 2x downsampling - static const int kNumPhaseBits = 30; - - // phase mask for fraction - static const uint32_t kPhaseMask = (1LU<<kNumPhaseBits)-1; - - // multiplier to calculate fixed point phase increment - static const double kPhaseMultiplier = 1L << kNumPhaseBits; - - enum format {MONO_16_BIT, STEREO_16_BIT}; - AudioResampler(int bitDepth, int inChannelCount, int32_t sampleRate); - - // prevent copying - AudioResampler(const AudioResampler&); - AudioResampler& operator=(const AudioResampler&); - - int32_t mBitDepth; - int32_t mChannelCount; - int32_t mSampleRate; - int32_t mInSampleRate; - AudioBufferProvider::Buffer mBuffer; - union { - int16_t mVolume[2]; - uint32_t mVolumeRL; - }; - int16_t mTargetVolume[2]; - format mFormat; - size_t mInputIndex; - int32_t mPhaseIncrement; - uint32_t mPhaseFraction; -}; - -// ---------------------------------------------------------------------------- -} -; // namespace android - -#endif // ANDROID_AUDIO_RESAMPLER_H diff --git a/libs/audioflinger/AudioResamplerCubic.cpp b/libs/audioflinger/AudioResamplerCubic.cpp deleted file mode 100644 index 1d247bd..0000000 --- a/libs/audioflinger/AudioResamplerCubic.cpp +++ /dev/null @@ -1,184 +0,0 @@ -/* - * Copyright (C) 2007 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 <stdint.h> -#include <string.h> -#include <sys/types.h> -#include <cutils/log.h> - -#include "AudioResampler.h" -#include "AudioResamplerCubic.h" - -#define LOG_TAG "AudioSRC" - -namespace android { -// ---------------------------------------------------------------------------- - -void AudioResamplerCubic::init() { - memset(&left, 0, sizeof(state)); - memset(&right, 0, sizeof(state)); -} - -void AudioResamplerCubic::resample(int32_t* out, size_t outFrameCount, - AudioBufferProvider* provider) { - - // should never happen, but we overflow if it does - // LOG_ASSERT(outFrameCount < 32767); - - // select the appropriate resampler - switch (mChannelCount) { - case 1: - resampleMono16(out, outFrameCount, provider); - break; - case 2: - resampleStereo16(out, outFrameCount, provider); - break; - } -} - -void AudioResamplerCubic::resampleStereo16(int32_t* out, size_t outFrameCount, - AudioBufferProvider* provider) { - - int32_t vl = mVolume[0]; - int32_t vr = mVolume[1]; - - size_t inputIndex = mInputIndex; - uint32_t phaseFraction = mPhaseFraction; - uint32_t phaseIncrement = mPhaseIncrement; - size_t outputIndex = 0; - size_t outputSampleCount = outFrameCount * 2; - size_t inFrameCount = (outFrameCount*mInSampleRate)/mSampleRate; - - // fetch first buffer - if (mBuffer.frameCount == 0) { - mBuffer.frameCount = inFrameCount; - provider->getNextBuffer(&mBuffer); - if (mBuffer.raw == NULL) - return; - // LOGW("New buffer: offset=%p, frames=%dn", mBuffer.raw, mBuffer.frameCount); - } - int16_t *in = mBuffer.i16; - - while (outputIndex < outputSampleCount) { - int32_t sample; - int32_t x; - - // calculate output sample - x = phaseFraction >> kPreInterpShift; - out[outputIndex++] += vl * interp(&left, x); - out[outputIndex++] += vr * interp(&right, x); - // out[outputIndex++] += vr * in[inputIndex*2]; - - // increment phase - phaseFraction += phaseIncrement; - uint32_t indexIncrement = (phaseFraction >> kNumPhaseBits); - phaseFraction &= kPhaseMask; - - // time to fetch another sample - while (indexIncrement--) { - - inputIndex++; - if (inputIndex == mBuffer.frameCount) { - inputIndex = 0; - provider->releaseBuffer(&mBuffer); - mBuffer.frameCount = inFrameCount; - provider->getNextBuffer(&mBuffer); - if (mBuffer.raw == NULL) - goto save_state; // ugly, but efficient - in = mBuffer.i16; - // LOGW("New buffer: offset=%p, frames=%d\n", mBuffer.raw, mBuffer.frameCount); - } - - // advance sample state - advance(&left, in[inputIndex*2]); - advance(&right, in[inputIndex*2+1]); - } - } - -save_state: - // LOGW("Done: index=%d, fraction=%u", inputIndex, phaseFraction); - mInputIndex = inputIndex; - mPhaseFraction = phaseFraction; -} - -void AudioResamplerCubic::resampleMono16(int32_t* out, size_t outFrameCount, - AudioBufferProvider* provider) { - - int32_t vl = mVolume[0]; - int32_t vr = mVolume[1]; - - size_t inputIndex = mInputIndex; - uint32_t phaseFraction = mPhaseFraction; - uint32_t phaseIncrement = mPhaseIncrement; - size_t outputIndex = 0; - size_t outputSampleCount = outFrameCount * 2; - size_t inFrameCount = (outFrameCount*mInSampleRate)/mSampleRate; - - // fetch first buffer - if (mBuffer.frameCount == 0) { - mBuffer.frameCount = inFrameCount; - provider->getNextBuffer(&mBuffer); - if (mBuffer.raw == NULL) - return; - // LOGW("New buffer: offset=%p, frames=%d\n", mBuffer.raw, mBuffer.frameCount); - } - int16_t *in = mBuffer.i16; - - while (outputIndex < outputSampleCount) { - int32_t sample; - int32_t x; - - // calculate output sample - x = phaseFraction >> kPreInterpShift; - sample = interp(&left, x); - out[outputIndex++] += vl * sample; - out[outputIndex++] += vr * sample; - - // increment phase - phaseFraction += phaseIncrement; - uint32_t indexIncrement = (phaseFraction >> kNumPhaseBits); - phaseFraction &= kPhaseMask; - - // time to fetch another sample - while (indexIncrement--) { - - inputIndex++; - if (inputIndex == mBuffer.frameCount) { - inputIndex = 0; - provider->releaseBuffer(&mBuffer); - mBuffer.frameCount = inFrameCount; - provider->getNextBuffer(&mBuffer); - if (mBuffer.raw == NULL) - goto save_state; // ugly, but efficient - // LOGW("New buffer: offset=%p, frames=%dn", mBuffer.raw, mBuffer.frameCount); - in = mBuffer.i16; - } - - // advance sample state - advance(&left, in[inputIndex]); - } - } - -save_state: - // LOGW("Done: index=%d, fraction=%u", inputIndex, phaseFraction); - mInputIndex = inputIndex; - mPhaseFraction = phaseFraction; -} - -// ---------------------------------------------------------------------------- -} -; // namespace android - diff --git a/libs/audioflinger/AudioResamplerCubic.h b/libs/audioflinger/AudioResamplerCubic.h deleted file mode 100644 index b72b62a..0000000 --- a/libs/audioflinger/AudioResamplerCubic.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (C) 2007 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 ANDROID_AUDIO_RESAMPLER_CUBIC_H -#define ANDROID_AUDIO_RESAMPLER_CUBIC_H - -#include <stdint.h> -#include <sys/types.h> -#include <cutils/log.h> - -#include "AudioResampler.h" - -namespace android { -// ---------------------------------------------------------------------------- - -class AudioResamplerCubic : public AudioResampler { -public: - AudioResamplerCubic(int bitDepth, int inChannelCount, int32_t sampleRate) : - AudioResampler(bitDepth, inChannelCount, sampleRate) { - } - virtual void resample(int32_t* out, size_t outFrameCount, - AudioBufferProvider* provider); -private: - // number of bits used in interpolation multiply - 14 bits avoids overflow - static const int kNumInterpBits = 14; - - // bits to shift the phase fraction down to avoid overflow - static const int kPreInterpShift = kNumPhaseBits - kNumInterpBits; - typedef struct { - int32_t a, b, c, y0, y1, y2, y3; - } state; - void init(); - void resampleMono16(int32_t* out, size_t outFrameCount, - AudioBufferProvider* provider); - void resampleStereo16(int32_t* out, size_t outFrameCount, - AudioBufferProvider* provider); - static inline int32_t interp(state* p, int32_t x) { - return (((((p->a * x >> 14) + p->b) * x >> 14) + p->c) * x >> 14) + p->y1; - } - static inline void advance(state* p, int16_t in) { - p->y0 = p->y1; - p->y1 = p->y2; - p->y2 = p->y3; - p->y3 = in; - p->a = (3 * (p->y1 - p->y2) - p->y0 + p->y3) >> 1; - p->b = (p->y2 << 1) + p->y0 - (((5 * p->y1 + p->y3)) >> 1); - p->c = (p->y2 - p->y0) >> 1; - } - state left, right; -}; - -// ---------------------------------------------------------------------------- -}; // namespace android - -#endif /*ANDROID_AUDIO_RESAMPLER_CUBIC_H*/ diff --git a/libs/audioflinger/AudioResamplerSinc.cpp b/libs/audioflinger/AudioResamplerSinc.cpp deleted file mode 100644 index 9e5e254..0000000 --- a/libs/audioflinger/AudioResamplerSinc.cpp +++ /dev/null @@ -1,358 +0,0 @@ -/* - * Copyright (C) 2007 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 <string.h> -#include "AudioResamplerSinc.h" - -namespace android { -// ---------------------------------------------------------------------------- - - -/* - * These coeficients are computed with the "fir" utility found in - * tools/resampler_tools - * TODO: A good optimization would be to transpose this matrix, to take - * better advantage of the data-cache. - */ -const int32_t AudioResamplerSinc::mFirCoefsUp[] = { - 0x7fffffff, 0x7f15d078, 0x7c5e0da6, 0x77ecd867, 0x71e2e251, 0x6a6c304a, 0x61be7269, 0x58170412, 0x4db8ab05, 0x42e92ea6, 0x37eee214, 0x2d0e3bb1, 0x22879366, 0x18951e95, 0x0f693d0d, 0x072d2621, - 0x00000000, 0xf9f66655, 0xf51a5fd7, 0xf16bbd84, 0xeee0d9ac, 0xed67a922, 0xece70de6, 0xed405897, 0xee50e505, 0xeff3be30, 0xf203370f, 0xf45a6741, 0xf6d67d53, 0xf957db66, 0xfbc2f647, 0xfe00f2b9, - 0x00000000, 0x01b37218, 0x0313a0c6, 0x041d930d, 0x04d28057, 0x053731b0, 0x05534dff, 0x05309bfd, 0x04da440d, 0x045c1aee, 0x03c1fcdd, 0x03173ef5, 0x02663ae8, 0x01b7f736, 0x0113ec79, 0x007fe6a9, - 0x00000000, 0xff96b229, 0xff44f99f, 0xff0a86be, 0xfee5f803, 0xfed518fd, 0xfed521fd, 0xfee2f4fd, 0xfefb54f8, 0xff1b159b, 0xff3f4203, 0xff6539e0, 0xff8ac502, 0xffae1ddd, 0xffcdf3f9, 0xffe96798, - 0x00000000, 0x00119de6, 0x001e6b7e, 0x0026cb7a, 0x002b4830, 0x002c83d6, 0x002b2a82, 0x0027e67a, 0x002356f9, 0x001e098e, 0x001875e4, 0x0012fbbe, 0x000de2d1, 0x00095c10, 0x00058414, 0x00026636, - 0x00000000, 0xfffe44a9, 0xfffd206d, 0xfffc7b7f, 0xfffc3c8f, 0xfffc4ac2, 0xfffc8f2b, 0xfffcf5c4, 0xfffd6df3, 0xfffdeab2, 0xfffe6275, 0xfffececf, 0xffff2c07, 0xffff788c, 0xffffb471, 0xffffe0f2, - 0x00000000, 0x000013e6, 0x00001f03, 0x00002396, 0x00002399, 0x000020b6, 0x00001c3c, 0x00001722, 0x00001216, 0x00000d81, 0x0000099c, 0x0000067c, 0x00000419, 0x0000025f, 0x00000131, 0x00000070, - 0x00000000, 0xffffffc7, 0xffffffb3, 0xffffffb3, 0xffffffbe, 0xffffffcd, 0xffffffdb, 0xffffffe7, 0xfffffff0, 0xfffffff7, 0xfffffffb, 0xfffffffe, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, - 0x00000000 // this one is needed for lerping the last coefficient -}; - -/* - * These coefficients are optimized for 48KHz -> 44.1KHz (stop-band at 22.050KHz) - * It's possible to use the above coefficient for any down-sampling - * at the expense of a slower processing loop (we can interpolate - * these coefficient from the above by "Stretching" them in time). - */ -const int32_t AudioResamplerSinc::mFirCoefsDown[] = { - 0x7fffffff, 0x7f55e46d, 0x7d5b4c60, 0x7a1b4b98, 0x75a7fb14, 0x7019f0bd, 0x698f875a, 0x622bfd59, 0x5a167256, 0x5178cc54, 0x487e8e6c, 0x3f53aae8, 0x36235ad4, 0x2d17047b, 0x245539ab, 0x1c00d540, - 0x14383e57, 0x0d14d5ca, 0x06aa910b, 0x0107c38b, 0xfc351654, 0xf835abae, 0xf5076b45, 0xf2a37202, 0xf0fe9faa, 0xf00a3bbd, 0xefb4aa81, 0xefea2b05, 0xf0959716, 0xf1a11e83, 0xf2f6f7a0, 0xf481fff4, - 0xf62e48ce, 0xf7e98ca5, 0xf9a38b4c, 0xfb4e4bfa, 0xfcde456f, 0xfe4a6d30, 0xff8c2fdf, 0x009f5555, 0x0181d393, 0x0233940f, 0x02b62f06, 0x030ca07d, 0x033afa62, 0x03461725, 0x03334f83, 0x030835fa, - 0x02ca59cc, 0x027f12d1, 0x022b570d, 0x01d39a49, 0x017bb78f, 0x0126e414, 0x00d7aaaf, 0x008feec7, 0x0050f584, 0x001b73e3, 0xffefa063, 0xffcd46ed, 0xffb3ddcd, 0xffa29aaa, 0xff988691, 0xff949066, - 0xff959d24, 0xff9a959e, 0xffa27195, 0xffac4011, 0xffb72d2b, 0xffc28569, 0xffcdb706, 0xffd85171, 0xffe20364, 0xffea97e9, 0xfff1f2b2, 0xfff80c06, 0xfffcec92, 0x0000a955, 0x00035fd8, 0x000532cf, - 0x00064735, 0x0006c1f9, 0x0006c62d, 0x000673ba, 0x0005e68f, 0x00053630, 0x000475a3, 0x0003b397, 0x0002fac1, 0x00025257, 0x0001be9e, 0x0001417a, 0x0000dafd, 0x000089eb, 0x00004c28, 0x00001f1d, - 0x00000000, 0xffffec10, 0xffffe0be, 0xffffdbc5, 0xffffdb39, 0xffffdd8b, 0xffffe182, 0xffffe638, 0xffffeb0a, 0xffffef8f, 0xfffff38b, 0xfffff6e3, 0xfffff993, 0xfffffba6, 0xfffffd30, 0xfffffe4a, - 0xffffff09, 0xffffff85, 0xffffffd1, 0xfffffffb, 0x0000000f, 0x00000016, 0x00000015, 0x00000012, 0x0000000d, 0x00000009, 0x00000006, 0x00000003, 0x00000002, 0x00000001, 0x00000000, 0x00000000, - 0x00000000 // this one is needed for lerping the last coefficient -}; - -// ---------------------------------------------------------------------------- - -static inline -int32_t mulRL(int left, int32_t in, uint32_t vRL) -{ -#if defined(__arm__) && !defined(__thumb__) - int32_t out; - if (left) { - asm( "smultb %[out], %[in], %[vRL] \n" - : [out]"=r"(out) - : [in]"%r"(in), [vRL]"r"(vRL) - : ); - } else { - asm( "smultt %[out], %[in], %[vRL] \n" - : [out]"=r"(out) - : [in]"%r"(in), [vRL]"r"(vRL) - : ); - } - return out; -#else - if (left) { - return int16_t(in>>16) * int16_t(vRL&0xFFFF); - } else { - return int16_t(in>>16) * int16_t(vRL>>16); - } -#endif -} - -static inline -int32_t mulAdd(int16_t in, int32_t v, int32_t a) -{ -#if defined(__arm__) && !defined(__thumb__) - int32_t out; - asm( "smlawb %[out], %[v], %[in], %[a] \n" - : [out]"=r"(out) - : [in]"%r"(in), [v]"r"(v), [a]"r"(a) - : ); - return out; -#else - return a + in * (v>>16); - // improved precision - // return a + in * (v>>16) + ((in * (v & 0xffff)) >> 16); -#endif -} - -static inline -int32_t mulAddRL(int left, uint32_t inRL, int32_t v, int32_t a) -{ -#if defined(__arm__) && !defined(__thumb__) - int32_t out; - if (left) { - asm( "smlawb %[out], %[v], %[inRL], %[a] \n" - : [out]"=r"(out) - : [inRL]"%r"(inRL), [v]"r"(v), [a]"r"(a) - : ); - } else { - asm( "smlawt %[out], %[v], %[inRL], %[a] \n" - : [out]"=r"(out) - : [inRL]"%r"(inRL), [v]"r"(v), [a]"r"(a) - : ); - } - return out; -#else - if (left) { - return a + (int16_t(inRL&0xFFFF) * (v>>16)); - //improved precision - // return a + (int16_t(inRL&0xFFFF) * (v>>16)) + ((int16_t(inRL&0xFFFF) * (v & 0xffff)) >> 16); - } else { - return a + (int16_t(inRL>>16) * (v>>16)); - } -#endif -} - -// ---------------------------------------------------------------------------- - -AudioResamplerSinc::AudioResamplerSinc(int bitDepth, - int inChannelCount, int32_t sampleRate) - : AudioResampler(bitDepth, inChannelCount, sampleRate), - mState(0) -{ - /* - * Layout of the state buffer for 32 tap: - * - * "present" sample beginning of 2nd buffer - * v v - * 0 01 2 23 3 - * 0 F0 0 F0 F - * [pppppppppppppppInnnnnnnnnnnnnnnnpppppppppppppppInnnnnnnnnnnnnnnn] - * ^ ^ head - * - * p = past samples, convoluted with the (p)ositive side of sinc() - * n = future samples, convoluted with the (n)egative side of sinc() - * r = extra space for implementing the ring buffer - * - */ - - const size_t numCoefs = 2*halfNumCoefs; - const size_t stateSize = numCoefs * inChannelCount * 2; - mState = new int16_t[stateSize]; - memset(mState, 0, sizeof(int16_t)*stateSize); - mImpulse = mState + (halfNumCoefs-1)*inChannelCount; - mRingFull = mImpulse + (numCoefs+1)*inChannelCount; -} - -AudioResamplerSinc::~AudioResamplerSinc() -{ - delete [] mState; -} - -void AudioResamplerSinc::init() { -} - -void AudioResamplerSinc::resample(int32_t* out, size_t outFrameCount, - AudioBufferProvider* provider) -{ - mFirCoefs = (mInSampleRate <= mSampleRate) ? mFirCoefsUp : mFirCoefsDown; - - // select the appropriate resampler - switch (mChannelCount) { - case 1: - resample<1>(out, outFrameCount, provider); - break; - case 2: - resample<2>(out, outFrameCount, provider); - break; - } -} - - -template<int CHANNELS> -void AudioResamplerSinc::resample(int32_t* out, size_t outFrameCount, - AudioBufferProvider* provider) -{ - int16_t* impulse = mImpulse; - uint32_t vRL = mVolumeRL; - size_t inputIndex = mInputIndex; - uint32_t phaseFraction = mPhaseFraction; - uint32_t phaseIncrement = mPhaseIncrement; - size_t outputIndex = 0; - size_t outputSampleCount = outFrameCount * 2; - size_t inFrameCount = (outFrameCount*mInSampleRate)/mSampleRate; - - AudioBufferProvider::Buffer& buffer(mBuffer); - while (outputIndex < outputSampleCount) { - // buffer is empty, fetch a new one - while (buffer.frameCount == 0) { - buffer.frameCount = inFrameCount; - provider->getNextBuffer(&buffer); - if (buffer.raw == NULL) { - goto resample_exit; - } - const uint32_t phaseIndex = phaseFraction >> kNumPhaseBits; - if (phaseIndex == 1) { - // read one frame - read<CHANNELS>(impulse, phaseFraction, buffer.i16, inputIndex); - } else if (phaseIndex == 2) { - // read 2 frames - read<CHANNELS>(impulse, phaseFraction, buffer.i16, inputIndex); - inputIndex++; - if (inputIndex >= mBuffer.frameCount) { - inputIndex -= mBuffer.frameCount; - provider->releaseBuffer(&buffer); - } else { - read<CHANNELS>(impulse, phaseFraction, buffer.i16, inputIndex); - } - } - } - int16_t *in = buffer.i16; - const size_t frameCount = buffer.frameCount; - - // Always read-in the first samples from the input buffer - int16_t* head = impulse + halfNumCoefs*CHANNELS; - head[0] = in[inputIndex*CHANNELS + 0]; - if (CHANNELS == 2) - head[1] = in[inputIndex*CHANNELS + 1]; - - // handle boundary case - int32_t l, r; - while (outputIndex < outputSampleCount) { - filterCoefficient<CHANNELS>(l, r, phaseFraction, impulse); - out[outputIndex++] += 2 * mulRL(1, l, vRL); - out[outputIndex++] += 2 * mulRL(0, r, vRL); - - phaseFraction += phaseIncrement; - const uint32_t phaseIndex = phaseFraction >> kNumPhaseBits; - if (phaseIndex == 1) { - inputIndex++; - if (inputIndex >= frameCount) - break; // need a new buffer - read<CHANNELS>(impulse, phaseFraction, in, inputIndex); - } else if(phaseIndex == 2) { // maximum value - inputIndex++; - if (inputIndex >= frameCount) - break; // 0 frame available, 2 frames needed - // read first frame - read<CHANNELS>(impulse, phaseFraction, in, inputIndex); - inputIndex++; - if (inputIndex >= frameCount) - break; // 0 frame available, 1 frame needed - // read second frame - read<CHANNELS>(impulse, phaseFraction, in, inputIndex); - } - } - - // if done with buffer, save samples - if (inputIndex >= frameCount) { - inputIndex -= frameCount; - provider->releaseBuffer(&buffer); - } - } - -resample_exit: - mImpulse = impulse; - mInputIndex = inputIndex; - mPhaseFraction = phaseFraction; -} - -template<int CHANNELS> -/*** -* read() -* -* This function reads only one frame from input buffer and writes it in -* state buffer -* -**/ -void AudioResamplerSinc::read( - int16_t*& impulse, uint32_t& phaseFraction, - int16_t const* in, size_t inputIndex) -{ - const uint32_t phaseIndex = phaseFraction >> kNumPhaseBits; - impulse += CHANNELS; - phaseFraction -= 1LU<<kNumPhaseBits; - if (impulse >= mRingFull) { - const size_t stateSize = (halfNumCoefs*2)*CHANNELS; - memcpy(mState, mState+stateSize, sizeof(int16_t)*stateSize); - impulse -= stateSize; - } - int16_t* head = impulse + halfNumCoefs*CHANNELS; - head[0] = in[inputIndex*CHANNELS + 0]; - if (CHANNELS == 2) - head[1] = in[inputIndex*CHANNELS + 1]; -} - -template<int CHANNELS> -void AudioResamplerSinc::filterCoefficient( - int32_t& l, int32_t& r, uint32_t phase, int16_t const *samples) -{ - // compute the index of the coefficient on the positive side and - // negative side - uint32_t indexP = (phase & cMask) >> cShift; - uint16_t lerpP = (phase & pMask) >> pShift; - uint32_t indexN = (-phase & cMask) >> cShift; - uint16_t lerpN = (-phase & pMask) >> pShift; - if ((indexP == 0) && (lerpP == 0)) { - indexN = cMask >> cShift; - lerpN = pMask >> pShift; - } - - l = 0; - r = 0; - int32_t const* coefs = mFirCoefs; - int16_t const *sP = samples; - int16_t const *sN = samples+CHANNELS; - for (unsigned int i=0 ; i<halfNumCoefs/4 ; i++) { - interpolate<CHANNELS>(l, r, coefs+indexP, lerpP, sP); - interpolate<CHANNELS>(l, r, coefs+indexN, lerpN, sN); - sP -= CHANNELS; sN += CHANNELS; coefs += 1<<coefsBits; - interpolate<CHANNELS>(l, r, coefs+indexP, lerpP, sP); - interpolate<CHANNELS>(l, r, coefs+indexN, lerpN, sN); - sP -= CHANNELS; sN += CHANNELS; coefs += 1<<coefsBits; - interpolate<CHANNELS>(l, r, coefs+indexP, lerpP, sP); - interpolate<CHANNELS>(l, r, coefs+indexN, lerpN, sN); - sP -= CHANNELS; sN += CHANNELS; coefs += 1<<coefsBits; - interpolate<CHANNELS>(l, r, coefs+indexP, lerpP, sP); - interpolate<CHANNELS>(l, r, coefs+indexN, lerpN, sN); - sP -= CHANNELS; sN += CHANNELS; coefs += 1<<coefsBits; - } -} - -template<int CHANNELS> -void AudioResamplerSinc::interpolate( - int32_t& l, int32_t& r, - int32_t const* coefs, int16_t lerp, int16_t const* samples) -{ - int32_t c0 = coefs[0]; - int32_t c1 = coefs[1]; - int32_t sinc = mulAdd(lerp, (c1-c0)<<1, c0); - if (CHANNELS == 2) { - uint32_t rl = *reinterpret_cast<uint32_t const*>(samples); - l = mulAddRL(1, rl, sinc, l); - r = mulAddRL(0, rl, sinc, r); - } else { - r = l = mulAdd(samples[0], sinc, l); - } -} - -// ---------------------------------------------------------------------------- -}; // namespace android - diff --git a/libs/audioflinger/AudioResamplerSinc.h b/libs/audioflinger/AudioResamplerSinc.h deleted file mode 100644 index e6cb90b..0000000 --- a/libs/audioflinger/AudioResamplerSinc.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (C) 2007 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 ANDROID_AUDIO_RESAMPLER_SINC_H -#define ANDROID_AUDIO_RESAMPLER_SINC_H - -#include <stdint.h> -#include <sys/types.h> -#include <cutils/log.h> - -#include "AudioResampler.h" - -namespace android { - -// ---------------------------------------------------------------------------- - -class AudioResamplerSinc : public AudioResampler { -public: - AudioResamplerSinc(int bitDepth, int inChannelCount, int32_t sampleRate); - - ~AudioResamplerSinc(); - - virtual void resample(int32_t* out, size_t outFrameCount, - AudioBufferProvider* provider); -private: - void init(); - - template<int CHANNELS> - void resample(int32_t* out, size_t outFrameCount, - AudioBufferProvider* provider); - - template<int CHANNELS> - inline void filterCoefficient( - int32_t& l, int32_t& r, uint32_t phase, int16_t const *samples); - - template<int CHANNELS> - inline void interpolate( - int32_t& l, int32_t& r, - int32_t const* coefs, int16_t lerp, int16_t const* samples); - - template<int CHANNELS> - inline void read(int16_t*& impulse, uint32_t& phaseFraction, - int16_t const* in, size_t inputIndex); - - int16_t *mState; - int16_t *mImpulse; - int16_t *mRingFull; - - int32_t const * mFirCoefs; - static const int32_t mFirCoefsDown[]; - static const int32_t mFirCoefsUp[]; - - // ---------------------------------------------------------------------------- - static const int32_t RESAMPLE_FIR_NUM_COEF = 8; - static const int32_t RESAMPLE_FIR_LERP_INT_BITS = 4; - - // we have 16 coefs samples per zero-crossing - static const int coefsBits = RESAMPLE_FIR_LERP_INT_BITS; // 4 - static const int cShift = kNumPhaseBits - coefsBits; // 26 - static const uint32_t cMask = ((1<<coefsBits)-1) << cShift; // 0xf<<26 = 3c00 0000 - - // and we use 15 bits to interpolate between these samples - // this cannot change because the mul below rely on it. - static const int pLerpBits = 15; - static const int pShift = kNumPhaseBits - coefsBits - pLerpBits; // 11 - static const uint32_t pMask = ((1<<pLerpBits)-1) << pShift; // 0x7fff << 11 - - // number of zero-crossing on each side - static const unsigned int halfNumCoefs = RESAMPLE_FIR_NUM_COEF; -}; - -// ---------------------------------------------------------------------------- -}; // namespace android - -#endif /*ANDROID_AUDIO_RESAMPLER_SINC_H*/ |