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

Commit 10dbb8e9 authored by Marco Nelissen's avatar Marco Nelissen
Browse files

Music visualizer support hack.

This currently assumes 44k stereo (won't crash on other formats, but won't give the correct results either), and links statically with libspeex to get FFT data, increasing the size of libmedia by about 45kb.
parent defd1bd0
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -43,6 +43,10 @@ public:
    virtual sp<IMemory>         decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, int* pFormat) = 0;
    virtual sp<IMemory>         decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, int* pFormat) = 0;
    virtual sp<IOMX>            createOMX() = 0;

    // Take a peek at currently playing audio, for visualization purposes.
    // This returns a buffer of 16 bit mono PCM data, or NULL if no visualization buffer is currently available.
    virtual sp<IMemory>         snoop() = 0;
};

// ----------------------------------------------------------------------------
+1 −0
Original line number Diff line number Diff line
@@ -153,6 +153,7 @@ public:
            void            notify(int msg, int ext1, int ext2);
    static  sp<IMemory>     decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, int* pFormat);
    static  sp<IMemory>     decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, int* pFormat);
    static  int             snoop(short *data, int len, int kind);
            status_t        invoke(const Parcel& request, Parcel *reply);
            status_t        setMetadataFilter(const Parcel& filter);
            status_t        getMetadata(bool update_only, bool apply_filter, Parcel *metadata);
+7 −3
Original line number Diff line number Diff line
@@ -39,6 +39,10 @@ endif
LOCAL_C_INCLUDES := \
    $(JNI_H_INCLUDE) \
    $(call include-path-for, graphics corecg) \
        $(TOP)/external/opencore/extern_libs_v2/khronos/openmax/include
        $(TOP)/external/opencore/extern_libs_v2/khronos/openmax/include \
        external/speex/include \
        external/speex/libspeex

LOCAL_STATIC_LIBRARIES := libspeex

include $(BUILD_SHARED_LIBRARY)
+15 −0
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@ enum {
    CREATE_MEDIA_RECORDER,
    CREATE_METADATA_RETRIEVER,
    CREATE_OMX,
    SNOOP
};

class BpMediaPlayerService: public BpInterface<IMediaPlayerService>
@@ -114,6 +115,14 @@ public:
        return interface_cast<IMemory>(reply.readStrongBinder());
    }

    virtual sp<IMemory> snoop()
    {
        Parcel data, reply;
        data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
        remote()->transact(SNOOP, data, &reply);
        return interface_cast<IMemory>(reply.readStrongBinder());
    }

    virtual sp<IOMX> createOMX() {
        Parcel data, reply;
        data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
@@ -178,6 +187,12 @@ status_t BnMediaPlayerService::onTransact(
            reply->writeStrongBinder(player->asBinder());
            return NO_ERROR;
        } break;
        case SNOOP: {
            CHECK_INTERFACE(IMediaPlayerService, data, reply);
            sp<IMemory> snooped_audio = snoop();
            reply->writeStrongBinder(snooped_audio->asBinder());
            return NO_ERROR;
        } break;
        case CREATE_MEDIA_RECORDER: {
            CHECK_INTERFACE(IMediaPlayerService, data, reply);
            pid_t pid = data.readInt32();
+57 −0
Original line number Diff line number Diff line
@@ -690,4 +690,61 @@ MediaPlayer::DeathNotifier::~DeathNotifier()

}

extern "C" {
#define FLOATING_POINT 1
#include "fftwrap.h"
}

static void *ffttable = NULL;

// peeks at the audio data and fills 'data' with the requested kind
// (currently kind=0 returns mono 16 bit PCM data, and kind=1 returns
// 256 point FFT data). Return value is number of samples returned,
// which may be 0.
/*static*/ int MediaPlayer::snoop(short* data, int len, int kind) {

    sp<IMemory> p;
    const sp<IMediaPlayerService>& service = getMediaPlayerService();
    if (service != 0) {
        // Take a peek at the waveform. The returned data consists of 16 bit mono PCM data.
        p = service->snoop();

        if (p == NULL) {
            return 0;
        }

        if (kind == 0) { // return waveform data
            int plen = p->size();
            len *= 2; // number of shorts -> number of bytes
            short *src = (short*) p->pointer();
            if (plen > len) {
                plen = len;
            }
            memcpy(data, src, plen);
            return plen / sizeof(short); // return number of samples
        } else if (kind == 1) {
            // TODO: use a more efficient FFT
            // Right now this uses the speex library, which is compiled to do a float FFT
            if (!ffttable) ffttable = spx_fft_init(512);
            short *usrc = (short*) p->pointer();
            float fsrc[512];
            for (int i=0;i<512;i++)
                fsrc[i] = usrc[i];
            float fdst[512];
            spx_fft_float(ffttable, fsrc, fdst);
            if (len > 512) {
                len = 512;
            }
            len /= 2; // only half the output data is valid
            for (int i=0; i < len; i++)
                data[i] = fdst[i];
            return len;
        }

    } else {
        LOGE("Unable to locate media service");
    }
    return 0;
}

}; // namespace android
Loading