Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 15d5d7c1 authored by Yamit Mehta's avatar Yamit Mehta Committed by Linux Build Service Account
Browse files

audio: Audio resampler support for 192Khz playback

Add support for QTI audio resampler

audio: Audio resampler support for 192Khz playback
Change-Id: Ia8f24a0874ebf6e16ef7bd1f2759a14f47149875

audio: Add audio mixing support for qti resampler
Change-Id: Ib657aa12b2a72323564148c302ff8891e1bb7433

AudioMixer: Extend use of QTI resampler for 44.1Khz sampling rate
Change-Id: I2a819dbc9f1e3e280cb4fa79328e331883a3e981

AudioMixer: fill 0s at right place when no more buffers available
Change-Id: I50504c5a02eb0c69abfc9b047792b0f6f85b9ce8

audioflinger: add channel count check to use QTI resampler
Change-Id: I8f76dd82b72a0dd8b77343e77e0d0545e1be2114

audio: QTI resampler supports for 32 bit input format
Change-Id: I7e1b8582cd6bb106ab0bd25f9bc1bd9e4092318b

Change-Id: Ia8f24a0874ebf6e16ef7bd1f2759a14f47149875
parent 97071e78
Loading
Loading
Loading
Loading
+21 −1
Original line number Diff line number Diff line
@@ -64,6 +64,14 @@ LOCAL_STATIC_LIBRARIES := \

LOCAL_MULTILIB := $(AUDIOSERVER_MULTILIB)

#QTI Resampler
ifeq ($(call is-vendor-board-platform,QCOM), true)
ifeq ($(strip $(AUDIO_FEATURE_ENABLED_EXTN_RESAMPLER)), true)
LOCAL_CFLAGS += -DQTI_RESAMPLER
endif
endif
#QTI Resampler

LOCAL_MODULE:= libaudioflinger

LOCAL_SRC_FILES += \
@@ -130,7 +138,19 @@ LOCAL_C_INCLUDES := \
LOCAL_SHARED_LIBRARIES := \
    libcutils \
    libdl \
    liblog
    liblog \
    libaudioutils

#QTI Resampler
ifeq ($(call is-vendor-board-platform,QCOM), true)
ifeq ($(strip $(AUDIO_FEATURE_ENABLED_EXTN_RESAMPLER)), true)
LOCAL_SRC_FILES_$(TARGET_2ND_ARCH) += AudioResamplerQTI.cpp.arm
LOCAL_C_INCLUDES_$(TARGET_2ND_ARCH) += $(TARGET_OUT_HEADERS)/mm-audio/audio-src
LOCAL_SHARED_LIBRARIES_$(TARGET_2ND_ARCH) += libqct_resampler
LOCAL_CFLAGS_$(TARGET_2ND_ARCH) += -DQTI_RESAMPLER
endif
endif
#QTI Resampler

LOCAL_MODULE := libaudioresampler

+14 −0
Original line number Diff line number Diff line
@@ -83,6 +83,9 @@ static const bool kUseFloat = true;
// Set to default copy buffer size in frames for input processing.
static const size_t kCopyBufferFrameCount = 256;

#ifdef QTI_RESAMPLER
#define QTI_RESAMPLER_MAX_SAMPLERATE 192000
#endif
namespace android {

// ----------------------------------------------------------------------------
@@ -777,6 +780,14 @@ bool AudioMixer::track_t::setResampler(uint32_t trackSampleRate, uint32_t devSam
                // but if none exists, it is the channel count (1 for mono).
                const int resamplerChannelCount = downmixerBufferProvider != NULL
                        ? mMixerChannelCount : channelCount;
#ifdef QTI_RESAMPLER
                if ((trackSampleRate <= QTI_RESAMPLER_MAX_SAMPLERATE) &&
                       (trackSampleRate > devSampleRate * 2) &&
                       ((devSampleRate == 48000)||(devSampleRate == 44100)) &&
                       (resamplerChannelCount <= 2)) {
                    quality = AudioResampler::QTI_QUALITY;
                }
#endif
                ALOGVV("Creating resampler:"
                        " format(%#x) channels(%d) devSampleRate(%u) quality(%d)\n",
                        mMixerInFormat, resamplerChannelCount, devSampleRate, quality);
@@ -1633,6 +1644,9 @@ void AudioMixer::process__OneTrack16BitsStereoNoResampling(state_t* state)
                // Note: In case of later int16_t sink output,
                // conversion and clamping is done by memcpy_to_i16_from_float().
            } while (--outFrames);
            //assign fout to out, when no more frames are available, so that 0s
            //can be filled at the right place
            out = (int32_t *)fout;
            break;
        case AUDIO_FORMAT_PCM_16_BIT:
            if (CC_UNLIKELY(uint32_t(vl) > UNITY_GAIN_INT || uint32_t(vr) > UNITY_GAIN_INT)) {
+25 −0
Original line number Diff line number Diff line
@@ -28,6 +28,10 @@
#include "AudioResamplerCubic.h"
#include "AudioResamplerDyn.h"

#ifdef QTI_RESAMPLER
#include "AudioResamplerQTI.h"
#endif

#ifdef __arm__
    // bug 13102576
    //#define ASM_ARM_RESAMP1 // enable asm optimisation for ResamplerOrder1
@@ -91,6 +95,9 @@ bool AudioResampler::qualityIsSupported(src_quality quality)
    case DYN_LOW_QUALITY:
    case DYN_MED_QUALITY:
    case DYN_HIGH_QUALITY:
#ifdef QTI_RESAMPLER
    case QTI_QUALITY:
#endif
        return true;
    default:
        return false;
@@ -111,7 +118,11 @@ void AudioResampler::init_routine()
        if (*endptr == '\0') {
            defaultQuality = (src_quality) l;
            ALOGD("forcing AudioResampler quality to %d", defaultQuality);
#ifdef QTI_RESAMPLER
            if (defaultQuality < DEFAULT_QUALITY || defaultQuality > QTI_QUALITY) {
#else
            if (defaultQuality < DEFAULT_QUALITY || defaultQuality > DYN_HIGH_QUALITY) {
#endif
                defaultQuality = DEFAULT_QUALITY;
            }
        }
@@ -130,6 +141,9 @@ uint32_t AudioResampler::qualityMHz(src_quality quality)
    case HIGH_QUALITY:
        return 20;
    case VERY_HIGH_QUALITY:
#ifdef QTI_RESAMPLER
    case QTI_QUALITY: //for QTI_QUALITY, currently assuming same as VHQ
#endif
        return 34;
    case DYN_LOW_QUALITY:
        return 4;
@@ -205,6 +219,11 @@ AudioResampler* AudioResampler::create(audio_format_t format, int inChannelCount
        case DYN_HIGH_QUALITY:
            quality = DYN_MED_QUALITY;
            break;
#ifdef QTI_RESAMPLER
        case QTI_QUALITY:
            quality = DYN_HIGH_QUALITY;
            break;
#endif
        }
    }
    pthread_mutex_unlock(&mutex);
@@ -251,6 +270,12 @@ AudioResampler* AudioResampler::create(audio_format_t format, int inChannelCount
            }
        }
        break;
#ifdef QTI_RESAMPLER
    case QTI_QUALITY:
        ALOGV("Create QTI_QUALITY Resampler = %d",quality);
        resampler = new AudioResamplerQTI(format, inChannelCount, sampleRate);
        break;
#endif
    }

    // initialize resampler
+3 −0
Original line number Diff line number Diff line
@@ -47,6 +47,9 @@ public:
        DYN_LOW_QUALITY=5,
        DYN_MED_QUALITY=6,
        DYN_HIGH_QUALITY=7,
#ifdef QTI_RESAMPLER
        QTI_QUALITY=8,
#endif
    };

    static const CONSTEXPR float UNITY_GAIN_FLOAT = 1.0f;
+173 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2014, The Linux Foundation. All rights reserved.
 * Not a Contribution.
 * 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 "AudioResamplerQTI.h"
#include "QCT_Resampler.h"
#include <sys/time.h>
#include <audio_utils/primitives.h>

namespace android {
AudioResamplerQTI::AudioResamplerQTI(int format,
        int inChannelCount, int32_t sampleRate)
    :AudioResampler(inChannelCount, sampleRate, QTI_QUALITY),
     mTmpBuf(0), mResamplerOutBuf(0), mFrameIndex(0),mOutFrameCount(0)
{
    stateSize = QCT_Resampler::MemAlloc(format, inChannelCount, sampleRate, sampleRate);
    mState = new int16_t[stateSize];
    mVolume[0] = mVolume[1] = 0;
    mBuffer.frameCount = 0;
}

AudioResamplerQTI::~AudioResamplerQTI()
{
    if (mState) {
        delete [] mState;
    }
    if (mTmpBuf) {
        delete [] mTmpBuf;
    }
    if(mResamplerOutBuf) {
        delete [] mResamplerOutBuf;
    }
}

size_t AudioResamplerQTI::resample(int32_t* out, size_t outFrameCount,
            AudioBufferProvider* provider)
{
    int16_t vl = mVolume[0];
    int16_t vr = mVolume[1];
    int32_t *pBuf;

    int64_t tempL, tempR;
    size_t inFrameRequest;
    size_t inFrameCount = getNumInSample(outFrameCount);
    size_t index = 0;
    size_t frameIndex = mFrameIndex;
    size_t out_count = outFrameCount * 2;
    float *fout = reinterpret_cast<float *>(out);

    if (mChannelCount == 1) {
        inFrameRequest = inFrameCount;
    } else {
        inFrameRequest = inFrameCount * 2;
    }

    if (mOutFrameCount < outFrameCount) {
        mOutFrameCount = outFrameCount;
        if (mTmpBuf) {
            delete [] mTmpBuf;
        }
        if(mResamplerOutBuf) {
            delete [] mResamplerOutBuf;
        }
        mTmpBuf = new int32_t[inFrameRequest + 16];
        mResamplerOutBuf = new int32_t[out_count];
    }

    if (mChannelCount == 1) {
        // buffer is empty, fetch a new one
        while (index < inFrameCount) {
            if (!mBuffer.frameCount) {
                mBuffer.frameCount = inFrameCount;
                provider->getNextBuffer(&mBuffer);
                frameIndex = 0;
            }

            if (mBuffer.raw == NULL) {
                while (index < inFrameCount) {
                    mTmpBuf[index++] = 0;
                }
                QCT_Resampler::Resample90dB(mState, mTmpBuf, mResamplerOutBuf, inFrameCount, outFrameCount);
                goto resample_exit;
            }

            mTmpBuf[index++] = clampq4_27_from_float(*((float *)mBuffer.raw + frameIndex++));

            if (frameIndex >= mBuffer.frameCount) {
                provider->releaseBuffer(&mBuffer);
            }
        }

        QCT_Resampler::Resample90dB(mState, mTmpBuf, mResamplerOutBuf, inFrameCount, outFrameCount);
    } else {
        pBuf = &mTmpBuf[inFrameCount];
        // buffer is empty, fetch a new one
        while (index < inFrameCount) {
            if (!mBuffer.frameCount) {
                mBuffer.frameCount = inFrameCount;
                provider->getNextBuffer(&mBuffer);
                frameIndex = 0;
            }
            if (mBuffer.raw == NULL) {
                while (index < inFrameCount) {
                    mTmpBuf[index] = 0;
                    pBuf[index++] = 0;
                }
                QCT_Resampler::Resample90dB(mState, mTmpBuf, mResamplerOutBuf, inFrameCount, outFrameCount);
                goto resample_exit;
            }

            mTmpBuf[index] = clampq4_27_from_float(*((float *)mBuffer.raw + frameIndex++));
            pBuf[index++] = clampq4_27_from_float(*((float *)mBuffer.raw + frameIndex++));
            if (frameIndex >= mBuffer.frameCount * 2) {
                provider->releaseBuffer(&mBuffer);
            }
       }

       QCT_Resampler::Resample90dB(mState, mTmpBuf, mResamplerOutBuf, inFrameCount, outFrameCount);
    }

resample_exit:
    for (uint32_t i = 0; i < out_count; i += 2) {
        // Multiplying q4.27 data with u4.12 gain could result in 39 fractional bit data(27+12)
        // To get back the 27 fractional bit format output data, do right shift by 12
        tempL = (int64_t)mResamplerOutBuf[i] * vl;
        tempR = (int64_t)mResamplerOutBuf[i+1] * vr;
        fout[i] += float_from_q4_27((int32_t)(tempL>>12));
        fout[i+1] += float_from_q4_27((int32_t)(tempR>>12));
    }

    mFrameIndex = frameIndex;
    return index;
}

void AudioResamplerQTI::setSampleRate(int32_t inSampleRate)
{
    if (mInSampleRate != inSampleRate) {
        mInSampleRate = inSampleRate;
        init();
    }
}

void AudioResamplerQTI::init()
{
    QCT_Resampler::Init(mState, mChannelCount, mInSampleRate, mSampleRate, 1/*32bit in*/);
}

size_t AudioResamplerQTI::getNumInSample(size_t outFrameCount)
{
    size_t size = (size_t)QCT_Resampler::GetNumInSamp(mState, outFrameCount);
    return size;
}

void AudioResamplerQTI::reset()
{
    AudioResampler::reset();
}

}; // namespace android
Loading