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

Commit 3c2bb468 authored by Antti S. Lankila's avatar Antti S. Lankila
Browse files

libcyanogen-dsp for CM9

This commit discards history. Those interested in code archeology
are encouraged to look up the gingerbread branch.

Changes since CM7:

Spurious whitespace has been corrected and all tabs have been replaced
by spaces. Biquads now use 64-bit double for calculation to yield
improved precision of the coefficients.

Some checks for parameter and value sizes have been added, which
corrects CM7's improper usage of the OpenSL command API. These changes
require the new DSPManager to be properly tested (currently unmerged
but available under gerrit).

Change-Id: I62444fe6bdf3800294da46ffe6089879575dc364
parent dca24c77
Loading
Loading
Loading
Loading
+41 −0
Original line number Diff line number Diff line
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

ifneq ($(HAVE_AOSP_DSP), 1)

LOCAL_MODULE := libcyanogen-dsp

LOCAL_MODULE_TAGS := optional

LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/soundfx

LOCAL_PRELINK_MODULE := false

LOCAL_ARM_MODE := arm

LOCAL_SRC_FILES := \
	cyanogen-dsp.cpp \
	Biquad.cpp \
	Delay.cpp \
	Effect.cpp \
	EffectBassBoost.cpp \
	EffectCompression.cpp \
	EffectEqualizer.cpp \
	EffectVirtualizer.cpp \
	FIR16.cpp \
# terminator

LOCAL_C_INCLUDES += \
	frameworks/base/include \
	hardware/libhardware/include \
	system/core/include \
	system/media/audio_effects/include \
# terminator

LOCAL_SHARED_LIBRARIES := \
	libcutils

include $(BUILD_SHARED_LIBRARY)

endif
+150 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2011 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 "Biquad.h"
#include <math.h>

static int64_t toFixedPoint(double in) {
    return int64_t(0.5 + in * (int64_t(1) << 32));
}

Biquad::Biquad()
{
    reset();
    setCoefficients(0, 1, 0, 0, 1, 0, 0);
}

Biquad::~Biquad()
{
}

void Biquad::setCoefficients(int32_t steps, double a0, double a1, double a2, double b0, double b1, double b2)
{
    int64_t A1 = -toFixedPoint(a1/a0);
    int64_t A2 = -toFixedPoint(a2/a0);
    int64_t B0 = toFixedPoint(b0/a0);
    int64_t B1 = toFixedPoint(b1/a0);
    int64_t B2 = toFixedPoint(b2/a0);

    if (steps == 0) {
        mA1 = A1;
        mA2 = A2;
        mB0 = B0;
        mB1 = B1;
        mB2 = B2;
        mInterpolationSteps = 0;
    } else {
        mA1dif = (A1 - mA1) / steps;
        mA2dif = (A2 - mA2) / steps;
        mB0dif = (B0 - mB0) / steps;
        mB1dif = (B1 - mB1) / steps;
        mB2dif = (B2 - mB2) / steps;
        mInterpolationSteps = steps;
    }
}

void Biquad::reset()
{
    mInterpolationSteps = 0;
    mA1 = 0;
    mA2 = 0;
    mB0 = 0;
    mB1 = 0;
    mB2 = 0;
    mX1 = 0;
    mX2 = 0;
    mY1 = 0;
    mY2 = 0;
}

void Biquad::setHighShelf(int32_t steps, double center_frequency, double sampling_frequency, double gainDb, double slope, double overallGainDb)
{
    double w0 = 2 * M_PI * center_frequency / sampling_frequency;
    double A = pow(10, gainDb/40);
    double alpha = sin(w0)/2 * sqrt( (A + 1/A)*(1/slope - 1) + 2 );

    double b0 =    A*( (A+1) + (A-1)*cos(w0) + 2*sqrt(A)*alpha );
    double b1 = -2*A*( (A-1) + (A+1)*cos(w0)                   );
    double b2 =    A*( (A+1) + (A-1)*cos(w0) - 2*sqrt(A)*alpha );
    double a0 =        (A+1) - (A-1)*cos(w0) + 2*sqrt(A)*alpha  ;
    double a1 =    2*( (A-1) - (A+1)*cos(w0)                   );
    double a2 =        (A+1) - (A-1)*cos(w0) - 2*sqrt(A)*alpha  ;

    double overallGain = pow(10, overallGainDb / 20);
    b0 *= overallGain;
    b1 *= overallGain;
    b2 *= overallGain;

    setCoefficients(steps, a0, a1, a2, b0, b1, b2);
}

void Biquad::setBandPass(int32_t steps, double center_frequency, double sampling_frequency, double resonance)
{
    double w0 = 2 * M_PI * center_frequency / sampling_frequency;
    double alpha = sin(w0) / (2*resonance);

    double b0 =   sin(w0)/2;
    double b1 =   0;
    double b2 =  -sin(w0)/2;
    double a0 =   1 + alpha;
    double a1 =  -2*cos(w0);
    double a2 =   1 - alpha;

    setCoefficients(steps, a0, a1, a2, b0, b1, b2);
}

void Biquad::setLowPass(int32_t steps, double center_frequency, double sampling_frequency, double resonance)
{
    double w0 = 2 * M_PI * center_frequency / sampling_frequency;
    double alpha = sin(w0) / (2*resonance);

    double b0 =  (1 - cos(w0))/2;
    double b1 =   1 - cos(w0);
    double b2 =  (1 - cos(w0))/2;
    double a0 =   1 + alpha;
    double a1 =  -2*cos(w0);
    double a2 =   1 - alpha;

    setCoefficients(steps, a0, a1, a2, b0, b1, b2);
}

int32_t Biquad::process(int32_t x0)
{
    int64_t y0 = mB0 * x0
        + mB1 * mX1
        + mB2 * mX2
        + mA1 * mY1
        + mA2 * mY2;
    y0 >>= 32;

    mY2 = mY1;
    mY1 = y0;

    mX2 = mX1;
    mX1 = x0;

    /* Interpolate biquad parameters */
    if (mInterpolationSteps != 0) {
        mInterpolationSteps --;
        mB0 += mB0dif;
        mB1 += mB1dif;
        mB2 += mB2dif;
        mA1 += mA1dif;
        mA2 += mA2dif;
    }

    return y0;
}
+23 −0
Original line number Diff line number Diff line
#pragma once

#include <stdint.h>

class Biquad {
    protected:
    int32_t mX1, mX2;
    int32_t mY1, mY2;
    int64_t mB0, mB1, mB2, mA1, mA2;
    int64_t mB0dif, mB1dif, mB2dif, mA1dif, mA2dif;
    int32_t mInterpolationSteps;

    void setCoefficients(int32_t steps, double a0, double a1, double a2, double b0, double b1, double b2);

    public:
    Biquad();
    virtual ~Biquad();
    void setHighShelf(int32_t steps, double cf, double sf, double gaindB, double slope, double overallGain);
    void setBandPass(int32_t steps, double cf, double sf, double resonance);
    void setLowPass(int32_t steps, double cf, double sf, double resonance);
    int32_t process(int32_t in);
    void reset();
};
+51 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2011 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 "Delay.h"

#include <string.h>

Delay::Delay()
    : mState(0), mIndex(0), mLength(0)
{
}

Delay::~Delay()
{
    if (mState != 0) {
        delete[] mState;
        mState = 0;
    }
}

void Delay::setParameters(float samplingFrequency, float time)
{
    mLength = int32_t(time * samplingFrequency + 0.5f);
    if (mState != 0) {
        delete[] mState;
    }
    mState = new int32_t[mLength];
    memset(mState, 0, mLength * sizeof(int32_t));
    mIndex = 0;
}

int32_t Delay::process(int32_t x0)
{
    int32_t y0 = mState[mIndex];
    mState[mIndex] = x0;
    mIndex = (mIndex + 1) % mLength;
    return y0;
}
+15 −0
Original line number Diff line number Diff line
#pragma once

#include <stdint.h>

class Delay {
    int32_t* mState;
    int32_t mIndex;
    int32_t mLength;

    public:
    Delay();
    ~Delay();
    void setParameters(float rate, float time);
    int32_t process(int32_t x0);
};
Loading