FileDocCategorySizeDatePackage
Visualizer.javaAPI DocAndroid 5.1 API30097Thu Mar 12 22:22:30 GMT 2015android.media.audiofx

Visualizer

public class Visualizer extends Object
The Visualizer class enables application to retrieve part of the currently playing audio for visualization purpose. It is not an audio recording interface and only returns partial and low quality audio content. However, to protect privacy of certain audio data (e.g voice mail) the use of the visualizer requires the permission android.permission.RECORD_AUDIO.

The audio session ID passed to the constructor indicates which audio content should be visualized:

  • If the session is 0, the audio output mix is visualized
  • If the session is not 0, the audio from a particular {@link android.media.MediaPlayer} or {@link android.media.AudioTrack} using this audio session is visualized

Two types of representation of audio content can be captured:

  • Waveform data: consecutive 8-bit (unsigned) mono samples by using the {@link #getWaveForm(byte[])} method
  • Frequency data: 8-bit magnitude FFT by using the {@link #getFft(byte[])} method

The length of the capture can be retrieved or specified by calling respectively {@link #getCaptureSize()} and {@link #setCaptureSize(int)} methods. The capture size must be a power of 2 in the range returned by {@link #getCaptureSizeRange()}.

In addition to the polling capture mode described above with {@link #getWaveForm(byte[])} and {@link #getFft(byte[])} methods, a callback mode is also available by installing a listener by use of the {@link #setDataCaptureListener(OnDataCaptureListener, int, boolean, boolean)} method. The rate at which the listener capture method is called as well as the type of data returned is specified.

Before capturing data, the Visualizer must be enabled by calling the {@link #setEnabled(boolean)} method. When data capture is not needed any more, the Visualizer should be disabled.

It is good practice to call the {@link #release()} method when the Visualizer is not used anymore to free up native resources associated to the Visualizer instance.

Creating a Visualizer on the output mix (audio session 0) requires permission {@link android.Manifest.permission#MODIFY_AUDIO_SETTINGS}

The Visualizer class can also be used to perform measurements on the audio being played back. The measurements to perform are defined by setting a mask of the requested measurement modes with {@link #setMeasurementMode(int)}. Supported values are {@link #MEASUREMENT_MODE_NONE} to cancel any measurement, and {@link #MEASUREMENT_MODE_PEAK_RMS} for peak and RMS monitoring. Measurements can be retrieved through {@link #getMeasurementPeakRms(MeasurementPeakRms)}.

Fields Summary
private static final String
TAG
public static final int
STATE_UNINITIALIZED
State of a Visualizer object that was not successfully initialized upon creation
public static final int
STATE_INITIALIZED
State of a Visualizer object that is ready to be used.
public static final int
STATE_ENABLED
State of a Visualizer object that is active.
public static final int
SCALING_MODE_NORMALIZED
Defines a capture mode where amplification is applied based on the content of the captured data. This is the default Visualizer mode, and is suitable for music visualization.
public static final int
SCALING_MODE_AS_PLAYED
Defines a capture mode where the playback volume will affect (scale) the range of the captured data. A low playback volume will lead to low sample and fft values, and vice-versa.
public static final int
MEASUREMENT_MODE_NONE
Defines a measurement mode in which no measurements are performed.
public static final int
MEASUREMENT_MODE_PEAK_RMS
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 #getMeasurementPeakRms(MeasurementPeakRms)}.
private static final int
NATIVE_EVENT_PCM_CAPTURE
private static final int
NATIVE_EVENT_FFT_CAPTURE
private static final int
NATIVE_EVENT_SERVER_DIED
public static final int
SUCCESS
Successful operation.
public static final int
ERROR
Unspecified error.
public static final int
ALREADY_EXISTS
Internal operation status. Not returned by any method.
public static final int
ERROR_NO_INIT
Operation failed due to bad object initialization.
public static final int
ERROR_BAD_VALUE
Operation failed due to bad parameter value.
public static final int
ERROR_INVALID_OPERATION
Operation failed because it was requested in wrong state.
public static final int
ERROR_NO_MEMORY
Operation failed due to lack of memory.
public static final int
ERROR_DEAD_OBJECT
Operation failed due to dead remote object.
private int
mState
Indicates the state of the Visualizer instance
private final Object
mStateLock
Lock to synchronize access to mState
private int
mId
System wide unique Identifier of the visualizer engine used by this Visualizer instance
private final Object
mListenerLock
Lock to protect listeners updates against event notifications
private NativeEventHandler
mNativeEventHandler
Handler for events coming from the native code
private OnDataCaptureListener
mCaptureListener
PCM and FFT capture listener registered by client
private OnServerDiedListener
mServerDiedListener
Server Died listener registered by client
private long
mNativeVisualizer
private long
mJniData
Constructors Summary
public Visualizer(int audioSession)
Class constructor.

param
audioSession system wide unique audio session identifier. If audioSession is not 0, the visualizer will be attached to the MediaPlayer or AudioTrack in the same audio session. Otherwise, the Visualizer will apply to the output mix.
throws
java.lang.UnsupportedOperationException
throws
java.lang.RuntimeException


    //--------------------------------------------------------------------------
    // Constructor, Finalize
    //--------------------
                                                      

      
       
        int[] id = new int[1];

        synchronized (mStateLock) {
            mState = STATE_UNINITIALIZED;
            // native initialization
            int result = native_setup(new WeakReference<Visualizer>(this), audioSession, id);
            if (result != SUCCESS && result != ALREADY_EXISTS) {
                Log.e(TAG, "Error code "+result+" when initializing Visualizer.");
                switch (result) {
                case ERROR_INVALID_OPERATION:
                    throw (new UnsupportedOperationException("Effect library not loaded"));
                default:
                    throw (new RuntimeException("Cannot initialize Visualizer engine, error: "
                            +result));
                }
            }
            mId = id[0];
            if (native_getEnabled()) {
                mState = STATE_ENABLED;
            } else {
                mState = STATE_INITIALIZED;
            }
        }
    
Methods Summary
protected voidfinalize()

        native_finalize();
    
public intgetCaptureSize()
Returns current capture size.

return
the capture size in bytes.

        synchronized (mStateLock) {
            if (mState == STATE_UNINITIALIZED) {
                throw(new IllegalStateException("getCaptureSize() called in wrong state: "+mState));
            }
            return native_getCaptureSize();
        }
    
public static native int[]getCaptureSizeRange()
Returns the capture size range.

return
the mininum capture size is returned in first array element and the maximum in second array element.

public booleangetEnabled()
Get current activation state of the visualizer.

return
true if the visualizer is active, false otherwise

        synchronized (mStateLock) {
            if (mState == STATE_UNINITIALIZED) {
                throw(new IllegalStateException("getEnabled() called in wrong state: "+mState));
            }
            return native_getEnabled();
        }
    
public intgetFft(byte[] fft)
Returns a frequency capture of currently playing audio content.

This method must be called when the Visualizer is enabled.

The capture is an 8-bit magnitude FFT, the frequency range covered being 0 (DC) to half of the sampling rate returned by {@link #getSamplingRate()}. The capture returns the real and imaginary parts of a number of frequency points equal to half of the capture size plus one.

Note: only the real part is returned for the first point (DC) and the last point (sampling frequency / 2).

The layout in the returned byte array is as follows:

  • n is the capture size returned by getCaptureSize()
  • Rfk, Ifk are respectively the real and imaginary parts of the kth frequency component
  • If Fs is the sampling frequency retuned by getSamplingRate() the kth frequency is: (k*Fs)/(n/2)
Index

0

1

2

3

4

5

...

n - 2

n - 1

Data

Rf0

Rf(n/2)

Rf1

If1

Rf2

If2

...

Rf(n-1)/2

If(n-1)/2

param
fft array of bytes where the FFT should be returned
return
{@link #SUCCESS} in case of success, {@link #ERROR_NO_MEMORY}, {@link #ERROR_INVALID_OPERATION} or {@link #ERROR_DEAD_OBJECT} in case of failure.
throws
IllegalStateException

        synchronized (mStateLock) {
            if (mState != STATE_ENABLED) {
                throw(new IllegalStateException("getFft() called in wrong state: "+mState));
            }
            return native_getFft(fft);
        }
    
public static native intgetMaxCaptureRate()
Returns the maximum capture rate for the callback capture method. This is the maximum value for the rate parameter of the {@link #setDataCaptureListener(OnDataCaptureListener, int, boolean, boolean)} method.

return
the maximum capture rate expressed in milliHertz

public intgetMeasurementMode()
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

        synchronized (mStateLock) {
            if (mState == STATE_UNINITIALIZED) {
                throw(new IllegalStateException("getMeasurementMode() called in wrong state: "
                        + mState));
            }
            return native_getMeasurementMode();
        }
    
public intgetMeasurementPeakRms(android.media.audiofx.Visualizer$MeasurementPeakRms measurement)
Retrieves the latest peak and RMS measurement. Sets the peak and RMS fields of the supplied {@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.

        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);
        }
    
public intgetSamplingRate()
Returns the sampling rate of the captured audio.

return
the sampling rate in milliHertz.

        synchronized (mStateLock) {
            if (mState == STATE_UNINITIALIZED) {
                throw(new IllegalStateException("getSamplingRate() called in wrong state: "+mState));
            }
            return native_getSamplingRate();
        }
    
public intgetScalingMode()
Returns the current scaling mode on the captured visualization data.

return
the scaling mode, see {@link #SCALING_MODE_NORMALIZED} and {@link #SCALING_MODE_AS_PLAYED}.
throws
IllegalStateException

        synchronized (mStateLock) {
            if (mState == STATE_UNINITIALIZED) {
                throw(new IllegalStateException("getScalingMode() called in wrong state: "
                        + mState));
            }
            return native_getScalingMode();
        }
    
public intgetWaveForm(byte[] waveform)
Returns a waveform capture of currently playing audio content. The capture consists in a number of consecutive 8-bit (unsigned) mono PCM samples equal to the capture size returned by {@link #getCaptureSize()}.

This method must be called when the Visualizer is enabled.

param
waveform array of bytes where the waveform should be returned
return
{@link #SUCCESS} in case of success, {@link #ERROR_NO_MEMORY}, {@link #ERROR_INVALID_OPERATION} or {@link #ERROR_DEAD_OBJECT} in case of failure.
throws
IllegalStateException

        synchronized (mStateLock) {
            if (mState != STATE_ENABLED) {
                throw(new IllegalStateException("getWaveForm() called in wrong state: "+mState));
            }
            return native_getWaveForm(waveform);
        }
    
private final native voidnative_finalize()

private final native intnative_getCaptureSize()

private final native booleannative_getEnabled()

private final native intnative_getFft(byte[] fft)

private final native intnative_getMeasurementMode()

private final native intnative_getPeakRms(android.media.audiofx.Visualizer$MeasurementPeakRms measurement)

private final native intnative_getSamplingRate()

private final native intnative_getScalingMode()

private final native intnative_getWaveForm(byte[] waveform)

private static final native voidnative_init()

private final native voidnative_release()

private final native intnative_setCaptureSize(int size)

private final native intnative_setEnabled(boolean enabled)

private final native intnative_setMeasurementMode(int mode)

private final native intnative_setPeriodicCapture(int rate, boolean waveForm, boolean fft)

private final native intnative_setScalingMode(int mode)

private final native intnative_setup(java.lang.Object audioeffect_this, int audioSession, int[] id)

private static voidpostEventFromNative(java.lang.Object effect_ref, int what, int arg1, int arg2, java.lang.Object obj)

        Visualizer visu = (Visualizer)((WeakReference)effect_ref).get();
        if (visu == null) {
            return;
        }

        if (visu.mNativeEventHandler != null) {
            Message m = visu.mNativeEventHandler.obtainMessage(what, arg1, arg2, obj);
            visu.mNativeEventHandler.sendMessage(m);
        }

    
public voidrelease()
Releases the native Visualizer resources. It is a good practice to release the visualization engine when not in use.

        synchronized (mStateLock) {
            native_release();
            mState = STATE_UNINITIALIZED;
        }
    
public intsetCaptureSize(int size)
Sets the capture size, i.e. the number of bytes returned by {@link #getWaveForm(byte[])} and {@link #getFft(byte[])} methods. The capture size must be a power of 2 in the range returned by {@link #getCaptureSizeRange()}. This method must not be called when the Visualizer is enabled.

param
size requested capture size
return
{@link #SUCCESS} in case of success, {@link #ERROR_BAD_VALUE} in case of failure.
throws
IllegalStateException

        synchronized (mStateLock) {
            if (mState != STATE_INITIALIZED) {
                throw(new IllegalStateException("setCaptureSize() called in wrong state: "+mState));
            }
            return native_setCaptureSize(size);
        }
    
public intsetDataCaptureListener(android.media.audiofx.Visualizer$OnDataCaptureListener listener, int rate, boolean waveform, boolean fft)
Registers an OnDataCaptureListener interface and specifies the rate at which the capture should be updated as well as the type of capture requested.

Call this method with a null listener to stop receiving the capture updates.

param
listener OnDataCaptureListener registered
param
rate rate in milliHertz at which the capture should be updated
param
waveform true if a waveform capture is requested: the onWaveFormDataCapture() method will be called on the OnDataCaptureListener interface.
param
fft true if a frequency capture is requested: the onFftDataCapture() method will be called on the OnDataCaptureListener interface.
return
{@link #SUCCESS} in case of success, {@link #ERROR_NO_INIT} or {@link #ERROR_BAD_VALUE} in case of failure.

        synchronized (mListenerLock) {
            mCaptureListener = listener;
        }
        if (listener == null) {
            // make sure capture callback is stopped in native code
            waveform = false;
            fft = false;
        }
        int status = native_setPeriodicCapture(rate, waveform, fft);
        if (status == SUCCESS) {
            if ((listener != null) && (mNativeEventHandler == null)) {
                Looper looper;
                if ((looper = Looper.myLooper()) != null) {
                    mNativeEventHandler = new NativeEventHandler(this, looper);
                } else if ((looper = Looper.getMainLooper()) != null) {
                    mNativeEventHandler = new NativeEventHandler(this, looper);
                } else {
                    mNativeEventHandler = null;
                    status = ERROR_NO_INIT;
                }
            }
        }
        return status;
    
public intsetEnabled(boolean enabled)
Enable or disable the visualization engine.

param
enabled requested enable state
return
{@link #SUCCESS} in case of success, {@link #ERROR_INVALID_OPERATION} or {@link #ERROR_DEAD_OBJECT} in case of failure.
throws
IllegalStateException

        synchronized (mStateLock) {
            if (mState == STATE_UNINITIALIZED) {
                throw(new IllegalStateException("setEnabled() called in wrong state: "+mState));
            }
            int status = SUCCESS;
            if ((enabled && (mState == STATE_INITIALIZED)) ||
                    (!enabled && (mState == STATE_ENABLED))) {
                status = native_setEnabled(enabled);
                if (status == SUCCESS) {
                    mState = enabled ? STATE_ENABLED : STATE_INITIALIZED;
                }
            }
            return status;
        }
    
public intsetMeasurementMode(int mode)
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

        synchronized (mStateLock) {
            if (mState == STATE_UNINITIALIZED) {
                throw(new IllegalStateException("setMeasurementMode() called in wrong state: "
                        + mState));
            }
            return native_setMeasurementMode(mode);
        }
    
public intsetScalingMode(int mode)
Set the type of scaling applied on the captured visualization data.

param
mode see {@link #SCALING_MODE_NORMALIZED} and {@link #SCALING_MODE_AS_PLAYED}
return
{@link #SUCCESS} in case of success, {@link #ERROR_BAD_VALUE} in case of failure.
throws
IllegalStateException

        synchronized (mStateLock) {
            if (mState == STATE_UNINITIALIZED) {
                throw(new IllegalStateException("setScalingMode() called in wrong state: "
                        + mState));
            }
            return native_setScalingMode(mode);
        }
    
public intsetServerDiedListener(android.media.audiofx.Visualizer$OnServerDiedListener listener)

hide
Registers an OnServerDiedListener interface.

Call this method with a null listener to stop receiving server death notifications.

return
{@link #SUCCESS} in case of success,

        synchronized (mListenerLock) {
            mServerDiedListener = listener;
        }
        return SUCCESS;