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

Commit 30231077 authored by Jean-Michel Trivi's avatar Jean-Michel Trivi Committed by Android Git Automerger
Browse files

am b25f2640: am e9b0dd89: Merge "Add audio level monitoring capabilities in...

am b25f2640: am e9b0dd89: Merge "Add audio level monitoring capabilities in Visualizer effect" into klp-dev

* commit 'b25f2640':
  Add audio level monitoring capabilities in Visualizer effect
parents e1cf0f6a b25f2640
Loading
Loading
Loading
Loading
+110 −0
Original line number Diff line number Diff line
@@ -93,6 +93,24 @@ public class Visualizer {
     */
    public static final int SCALING_MODE_AS_PLAYED = 1;

    /**
     * @hide
     * CANDIDATE FOR PUBLIC API
     * Defines a measurement mode with no requested measurement.
     */
    public static final int MEASUREMENT_MODE_NONE = 0;

    /**
     * @hide
     * CANDIDATE FOR PUBLIC API
     * Defines a measurement mode which computes the peak and RMS value in mB, where 0mB is the
     * maximum sample value, and -9600mB is the minimum value.
     * Values for peak and RMS can be retrieved with {@link #getIntMeasurements(int, int[])}, where
     * the array holds the peak value at index {@link #MEASUREMENT_INDEX_PEAK} in the measurement
     * array, and the RMS value at index {@link #MEASUREMENT_INDEX_RMS}.
     */
    public static final int MEASUREMENT_MODE_PEAK_RMS = 1 << 0;

    // to keep in sync with frameworks/base/media/jni/audioeffect/android_media_Visualizer.cpp
    private static final int NATIVE_EVENT_PCM_CAPTURE = 0;
    private static final int NATIVE_EVENT_FFT_CAPTURE = 1;
@@ -349,6 +367,47 @@ public class Visualizer {
        }
    }

    /**
     * @hide
     * CANDIDATE FOR PUBLIC API
     * Sets the combination of measurement modes to be performed by this audio effect.
     * @param mode a mask of the measurements to perform. The valid values are
     *     {@link #MEASUREMENT_MODE_NONE} (to cancel any measurement)
     *     or {@link #MEASUREMENT_MODE_PEAK_RMS}.
     * @return {@link #SUCCESS} in case of success, {@link #ERROR_BAD_VALUE} in case of failure.
     * @throws IllegalStateException
     */
    public int setMeasurementMode(int mode)
            throws IllegalStateException {
        synchronized (mStateLock) {
            if (mState == STATE_UNINITIALIZED) {
                throw(new IllegalStateException("setMeasurementMode() called in wrong state: "
                        + mState));
            }
            return native_setMeasurementMode(mode);
        }
    }

    /**
     * @hide
     * CANDIDATE FOR PUBLIC API
     * Returns the current measurement modes performed by this audio effect
     * @return the mask of the measurements,
     *     {@link #MEASUREMENT_MODE_NONE} (when no measurements are performed)
     *     or {@link #MEASUREMENT_MODE_PEAK_RMS}.
     * @throws IllegalStateException
     */
    public int getMeasurementMode()
            throws IllegalStateException {
        synchronized (mStateLock) {
            if (mState == STATE_UNINITIALIZED) {
                throw(new IllegalStateException("getMeasurementMode() called in wrong state: "
                        + mState));
            }
            return native_getMeasurementMode();
        }
    }

    /**
     * Returns the sampling rate of the captured audio.
     * @return the sampling rate in milliHertz.
@@ -437,6 +496,51 @@ public class Visualizer {
        }
    }

    /**
     * @hide
     * CANDIDATE FOR PUBLIC API
     * A class to store peak and RMS values.
     * Peak and RMS are expressed in mB, as described in the
     * {@link Visualizer#MEASUREMENT_MODE_PEAK_RMS} measurement mode.
     */
    public static final class MeasurementPeakRms {
        /**
         * @hide
         * CANDIDATE FOR PUBLIC API
         */
        public int mPeak;
        /**
         * @hide
         * CANDIDATE FOR PUBLIC API
         */
        public int mRms;
    }

    /**
     * @hide
     * Retrieves the latest peak and RMS measurement.
     * Sets the peak and RMS fields of the {@link Visualizer.MeasurementPeakRms} to the latest
     * measured values.
     * @param measurement a non-null {@link Visualizer.MeasurementPeakRms} instance to store
     *    the measurement values.
     * @return {@link #SUCCESS} in case of success, {@link #ERROR_BAD_VALUE},
     *    {@link #ERROR_NO_MEMORY}, {@link #ERROR_INVALID_OPERATION} or {@link #ERROR_DEAD_OBJECT}
     *    in case of failure.
     */
    public int getMeasurementPeakRms(MeasurementPeakRms measurement) {
        if (measurement == null) {
            Log.e(TAG, "Cannot store measurements in a null object");
            return ERROR_BAD_VALUE;
        }
        synchronized (mStateLock) {
            if (mState != STATE_ENABLED) {
                throw (new IllegalStateException("getMeasurementPeakRms() called in wrong state: "
                        + mState));
            }
            return native_getPeakRms(measurement);
        }
    }

    //---------------------------------------------------------
    // Interface definitions
    //--------------------
@@ -640,12 +744,18 @@ public class Visualizer {

    private native final int native_getScalingMode();

    private native final int native_setMeasurementMode(int mode);

    private native final int native_getMeasurementMode();

    private native final int native_getSamplingRate();

    private native final int native_getWaveForm(byte[] waveform);

    private native final int native_getFft(byte[] fft);

    private native final int native_getPeakRms(MeasurementPeakRms measurement);

    private native final int native_setPeriodicCapture(int rate, boolean waveForm, boolean fft);

    //---------------------------------------------------------
+72 −0
Original line number Diff line number Diff line
@@ -43,6 +43,8 @@ using namespace android;

// ----------------------------------------------------------------------------
static const char* const kClassPathName = "android/media/audiofx/Visualizer";
static const char* const kClassPeakRmsPathName =
        "android/media/audiofx/Visualizer$MeasurementPeakRms";

struct fields_t {
    // these fields provide access from C++ to the...
@@ -50,6 +52,8 @@ struct fields_t {
    jmethodID midPostNativeEvent;   // event post callback method
    jfieldID  fidNativeVisualizer; // stores in Java the native Visualizer object
    jfieldID  fidJniData;           // stores in Java additional resources used by the native Visualizer
    jfieldID  fidPeak; // to access Visualizer.MeasurementPeakRms.mPeak
    jfieldID  fidRms;  // to access Visualizer.MeasurementPeakRms.mRms
};
static fields_t fields;

@@ -257,6 +261,14 @@ android_media_visualizer_native_init(JNIEnv *env)

    fields.clazzEffect = (jclass)env->NewGlobalRef(clazz);

    // Get the Visualizer.MeasurementPeakRms class
    clazz = env->FindClass(kClassPeakRmsPathName);
    if (clazz == NULL) {
        ALOGE("Can't find %s", kClassPeakRmsPathName);
        return;
    }
    jclass clazzMeasurementPeakRms = (jclass)env->NewGlobalRef(clazz);

    // Get the postEvent method
    fields.midPostNativeEvent = env->GetStaticMethodID(
            fields.clazzEffect,
@@ -283,7 +295,24 @@ android_media_visualizer_native_init(JNIEnv *env)
        ALOGE("Can't find Visualizer.%s", "mJniData");
        return;
    }
    //      fidPeak
    fields.fidPeak = env->GetFieldID(
            clazzMeasurementPeakRms,
            "mPeak", "I");
    if (fields.fidPeak == NULL) {
        ALOGE("Can't find Visualizer.MeasurementPeakRms.%s", "mPeak");
        return;
    }
    //      fidRms
    fields.fidRms = env->GetFieldID(
            clazzMeasurementPeakRms,
            "mRms", "I");
    if (fields.fidRms == NULL) {
        ALOGE("Can't find Visualizer.MeasurementPeakRms.%s", "mPeak");
        return;
    }

    env->DeleteGlobalRef(clazzMeasurementPeakRms);
}

static void android_media_visualizer_effect_callback(int32_t event,
@@ -512,6 +541,26 @@ android_media_visualizer_native_getScalingMode(JNIEnv *env, jobject thiz)
    return lpVisualizer->getScalingMode();
}

static jint
android_media_visualizer_native_setMeasurementMode(JNIEnv *env, jobject thiz, jint mode)
{
    Visualizer* lpVisualizer = getVisualizer(env, thiz);
    if (lpVisualizer == NULL) {
        return VISUALIZER_ERROR_NO_INIT;
    }
    return translateError(lpVisualizer->setMeasurementMode(mode));
}

static jint
android_media_visualizer_native_getMeasurementMode(JNIEnv *env, jobject thiz)
{
    Visualizer* lpVisualizer = getVisualizer(env, thiz);
    if (lpVisualizer == NULL) {
        return MEASUREMENT_MODE_NONE;
    }
    return lpVisualizer->getMeasurementMode();
}

static jint
android_media_visualizer_native_getSamplingRate(JNIEnv *env, jobject thiz)
{
@@ -559,6 +608,25 @@ android_media_visualizer_native_getFft(JNIEnv *env, jobject thiz, jbyteArray jFf
    return status;
}

static jint
android_media_visualizer_native_getPeakRms(JNIEnv *env, jobject thiz, jobject jPeakRmsObj)
{
    Visualizer* lpVisualizer = getVisualizer(env, thiz);
    if (lpVisualizer == NULL) {
        return VISUALIZER_ERROR_NO_INIT;
    }
    int32_t measurements[2];
    jint status = translateError(
                lpVisualizer->getIntMeasurements(MEASUREMENT_MODE_PEAK_RMS,
                        2, measurements));
    if (status == VISUALIZER_SUCCESS) {
        // measurement worked, write the values to the java object
        env->SetIntField(jPeakRmsObj, fields.fidPeak, measurements[MEASUREMENT_IDX_PEAK]);
        env->SetIntField(jPeakRmsObj, fields.fidRms, measurements[MEASUREMENT_IDX_RMS]);
    }
    return status;
}

static jint
android_media_setPeriodicCapture(JNIEnv *env, jobject thiz, jint rate, jboolean jWaveform, jboolean jFft)
{
@@ -606,9 +674,13 @@ static JNINativeMethod gMethods[] = {
    {"native_getCaptureSize",    "()I",   (void *)android_media_visualizer_native_getCaptureSize},
    {"native_setScalingMode",    "(I)I",  (void *)android_media_visualizer_native_setScalingMode},
    {"native_getScalingMode",    "()I",   (void *)android_media_visualizer_native_getScalingMode},
    {"native_setMeasurementMode","(I)I",  (void *)android_media_visualizer_native_setMeasurementMode},
    {"native_getMeasurementMode","()I",   (void *)android_media_visualizer_native_getMeasurementMode},
    {"native_getSamplingRate",   "()I",   (void *)android_media_visualizer_native_getSamplingRate},
    {"native_getWaveForm",       "([B)I", (void *)android_media_visualizer_native_getWaveForm},
    {"native_getFft",            "([B)I", (void *)android_media_visualizer_native_getFft},
    {"native_getPeakRms",      "(Landroid/media/audiofx/Visualizer$MeasurementPeakRms;)I",
                                          (void *)android_media_visualizer_native_getPeakRms},
    {"native_setPeriodicCapture","(IZZ)I",(void *)android_media_setPeriodicCapture},
};