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

Commit 0d20832f authored by Eric Laurent's avatar Eric Laurent Committed by Android Git Automerger
Browse files

am 030a1553: am 2ea200c5: Merge "Issue 2667801: [Audio Effect Framework]...

am 030a1553: am 2ea200c5: Merge "Issue 2667801: [Audio Effect Framework] AudioFlinger, AudioMixer AudioTrack modifications." into kraken
parents 526213cf bf0ce275
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -87,7 +87,8 @@ LOCAL_SHARED_LIBRARIES := \
    libutils \
    libbinder \
    libmedia \
    libhardware_legacy
    libhardware_legacy \
    libeffects

ifeq ($(strip $(BOARD_USES_GENERIC_AUDIO)),true)
  LOCAL_STATIC_LIBRARIES += libaudiointerface libaudiopolicybase
+1979 −95

File changed.

Preview size limit exceeded, changes collapsed.

+296 −9
Original line number Diff line number Diff line
@@ -42,6 +42,7 @@
namespace android {

class audio_track_cblk_t;
class effect_param_cblk_t;
class AudioMixer;
class AudioBuffer;
class AudioResampler;
@@ -75,6 +76,7 @@ public:
                                uint32_t flags,
                                const sp<IMemory>& sharedBuffer,
                                int output,
                                int *sessionId,
                                status_t *status);

    virtual     uint32_t    sampleRate(int output) const;
@@ -139,6 +141,28 @@ public:

    virtual status_t getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames, int output);

    virtual int newAudioSessionId();

    virtual status_t loadEffectLibrary(const char *libPath, int *handle);

    virtual status_t unloadEffectLibrary(int handle);

    virtual status_t queryNumberEffects(uint32_t *numEffects);

    virtual status_t queryNextEffect(effect_descriptor_t *descriptor);

    virtual status_t getEffectDescriptor(effect_uuid_t *pUuid, effect_descriptor_t *descriptor);

    virtual sp<IEffect> createEffect(pid_t pid,
                        effect_descriptor_t *pDesc,
                        const sp<IEffectClient>& effectClient,
                        int32_t priority,
                        int output,
                        int sessionId,
                        status_t *status,
                        int *id,
                        int *enabled);

    enum hardware_call_state {
        AUDIO_HW_IDLE = 0,
        AUDIO_HW_INIT,
@@ -167,6 +191,7 @@ public:
                                int channelCount,
                                int frameCount,
                                uint32_t flags,
                                int *sessionId,
                                status_t *status);

    virtual     status_t    onTransact(
@@ -233,6 +258,9 @@ private:
    class DuplicatingThread;
    class Track;
    class RecordTrack;
    class EffectModule;
    class EffectHandle;
    class EffectChain;

    class ThreadBase : public Thread {
    public:
@@ -268,13 +296,15 @@ private:
                                        int channelCount,
                                        int frameCount,
                                        uint32_t flags,
                                        const sp<IMemory>& sharedBuffer);
                                        const sp<IMemory>& sharedBuffer,
                                        int sessionId);
                                ~TrackBase();

            virtual status_t    start() = 0;
            virtual void        stop() = 0;
                    sp<IMemory> getCblk() const;
                    audio_track_cblk_t* cblk() const { return mCblk; }
                    int         sessionId() { return mSessionId; }

        protected:
            friend class ThreadBase;
@@ -323,6 +353,7 @@ private:
            int                 mClientTid;
            uint8_t             mFormat;
            uint32_t            mFlags;
            int                 mSessionId;
        };

        class ConfigEvent {
@@ -405,7 +436,8 @@ private:
                                        int format,
                                        int channelCount,
                                        int frameCount,
                                        const sp<IMemory>& sharedBuffer);
                                        const sp<IMemory>& sharedBuffer,
                                        int sessionId);
                                ~Track();

                    void        dump(char* buffer, size_t size);
@@ -424,6 +456,12 @@ private:
                    int type() const {
                        return mStreamType;
                    }
                    status_t    attachAuxEffect(int EffectId);
                    void        setAuxBuffer(int EffectId, int32_t *buffer);
                    int32_t     *auxBuffer() { return mAuxBuffer; }
                    void        setMainBuffer(int16_t *buffer) { mMainBuffer = buffer; }
                    int16_t     *mainBuffer() { return mMainBuffer; }
                    int         auxEffectId() { return mAuxEffectId; }


        protected:
@@ -464,6 +502,9 @@ private:
            bool                mResetDone;
            int                 mStreamType;
            int                 mName;
            int16_t             *mMainBuffer;
            int32_t             *mAuxBuffer;
            int                 mAuxEffectId;
        };  // end of Track


@@ -505,7 +546,7 @@ private:
            DuplicatingThread*          mSourceThread;
        };  // end of OutputTrack

        PlaybackThread (const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id);
        PlaybackThread (const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id, uint32_t device);
        virtual             ~PlaybackThread();

        virtual     status_t    dump(int fd, const Vector<String16>& args);
@@ -538,6 +579,7 @@ private:
                                    int channelCount,
                                    int frameCount,
                                    const sp<IMemory>& sharedBuffer,
                                    int sessionId,
                                    status_t *status);

                    AudioStreamOut* getOutput() { return mOutput; }
@@ -549,6 +591,29 @@ private:
        virtual     String8     getParameters(const String8& keys);
        virtual     void        audioConfigChanged_l(int event, int param = 0);
        virtual     status_t    getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames);
                    int16_t     *mixBuffer() { return mMixBuffer; };

                    sp<EffectHandle> createEffect_l(
                                        const sp<AudioFlinger::Client>& client,
                                        const sp<IEffectClient>& effectClient,
                                        int32_t priority,
                                        int sessionId,
                                        effect_descriptor_t *desc,
                                        int *enabled,
                                        status_t *status);

                    bool hasAudioSession(int sessionId);
                    sp<EffectChain> getEffectChain(int sessionId);
                    sp<EffectChain> getEffectChain_l(int sessionId);
                    status_t addEffectChain_l(const sp<EffectChain>& chain);
                    size_t removeEffectChain_l(const sp<EffectChain>& chain);
                    void lockEffectChains_l();
                    void unlockEffectChains();

                    sp<AudioFlinger::EffectModule> getEffect_l(int sessionId, int effectId);
                    void detachAuxEffect_l(int effectId);
                    status_t attachAuxEffect(const sp<AudioFlinger::PlaybackThread::Track> track, int EffectId);
                    status_t attachAuxEffect_l(const sp<AudioFlinger::PlaybackThread::Track> track, int EffectId);

        struct  stream_type_t {
            stream_type_t()
@@ -591,8 +656,11 @@ private:

        void        readOutputParameters();

        uint32_t    device() { return mDevice; }

        virtual status_t    dumpInternals(int fd, const Vector<String16>& args);
        status_t    dumpTracks(int fd, const Vector<String16>& args);
        status_t    dumpEffectChains(int fd, const Vector<String16>& args);

        SortedVector< sp<Track> >       mTracks;
        // mStreamTypes[] uses 1 additionnal stream type internally for the OutputTrack used by DuplicatingThread
@@ -603,11 +671,13 @@ private:
        int                             mNumWrites;
        int                             mNumDelayedWrites;
        bool                            mInWrite;
        Vector< sp<EffectChain> >       mEffectChains;
        uint32_t                        mDevice;
    };

    class MixerThread : public PlaybackThread {
    public:
        MixerThread (const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id);
        MixerThread (const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id, uint32_t device);
        virtual             ~MixerThread();

        // Thread virtuals
@@ -630,7 +700,7 @@ private:
    class DirectOutputThread : public PlaybackThread {
    public:

        DirectOutputThread (const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id);
        DirectOutputThread (const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id, uint32_t device);
        ~DirectOutputThread();

        // Thread virtuals
@@ -645,8 +715,12 @@ private:
        virtual     uint32_t    idleSleepTimeUs();

    private:
        float mLeftVolume;
        float mRightVolume;
        void applyVolume(uint16_t leftVol, uint16_t rightVol, bool ramp);

        float mLeftVolFloat;
        float mRightVolFloat;
        uint16_t mLeftVolShort;
        uint16_t mRightVolShort;
    };

    class DuplicatingThread : public MixerThread {
@@ -676,6 +750,8 @@ private:
              float streamVolumeInternal(int stream) const { return mStreamTypes[stream].volume; }
              void audioConfigChanged_l(int event, int ioHandle, void *param2);

              int  nextUniqueId();

    friend class AudioBuffer;

    class TrackHandle : public android::BnAudioTrack {
@@ -689,6 +765,7 @@ private:
        virtual void        pause();
        virtual void        setVolume(float left, float right);
        virtual sp<IMemory> getCblk() const;
        virtual status_t    attachAuxEffect(int effectId);
        virtual status_t onTransact(
            uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags);
    private:
@@ -717,7 +794,8 @@ private:
                                        int format,
                                        int channelCount,
                                        int frameCount,
                                        uint32_t flags);
                                        uint32_t flags,
                                        int sessionId);
                                ~RecordTrack();

            virtual status_t    start();
@@ -792,6 +870,215 @@ private:
        sp<RecordThread::RecordTrack> mRecordTrack;
    };

    //--- Audio Effect Management

    // EffectModule and EffectChain classes both have their own mutex to protect
    // state changes or resource modifications. Always respect the following order
    // if multiple mutexes must be acquired to avoid cross deadlock:
    // AudioFlinger -> ThreadBase -> EffectChain -> EffectModule

    // The EffectModule class is a wrapper object controlling the effect engine implementation
    // in the effect library. It prevents concurrent calls to process() and command() functions
    // from different client threads. It keeps a list of EffectHandle objects corresponding
    // to all client applications using this effect and notifies applications of effect state,
    // control or parameter changes. It manages the activation state machine to send appropriate
    // reset, enable, disable commands to effect engine and provide volume
    // ramping when effects are activated/deactivated.
    // When controlling an auxiliary effect, the EffectModule also provides an input buffer used by
    // the attached track(s) to accumulate their auxiliary channel.
    class EffectModule: public RefBase {
    public:
        EffectModule(const wp<ThreadBase>& wThread,
                        const wp<AudioFlinger::EffectChain>& chain,
                        effect_descriptor_t *desc,
                        int id,
                        int sessionId);
        ~EffectModule();

        enum effect_state {
            IDLE,
            RESET,
            STARTING,
            ACTIVE,
            STOPPING,
            STOPPED
        };

        int         id() { return mId; }
        void process();
        status_t command(int cmdCode, int cmdSize, void *pCmdData, int *replySize, void *pReplyData);

        void reset();
        status_t configure();
        status_t init();
        uint32_t state() {
            return mState;
        }
        uint32_t status() {
            return mStatus;
        }
        status_t    setEnabled(bool enabled);
        bool isEnabled();

        void        setInBuffer(int16_t *buffer) { mConfig.inputCfg.buffer.s16 = buffer; }
        int16_t     *inBuffer() { return mConfig.inputCfg.buffer.s16; }
        void        setOutBuffer(int16_t *buffer) { mConfig.outputCfg.buffer.s16 = buffer; }
        int16_t     *outBuffer() { return mConfig.outputCfg.buffer.s16; }

        status_t addHandle(sp<EffectHandle>& handle);
        void disconnect(const wp<EffectHandle>& handle);
        size_t removeHandle (const wp<EffectHandle>& handle);

        effect_descriptor_t& desc() { return mDescriptor; }

        status_t         setDevice(uint32_t device);
        status_t         setVolume(uint32_t *left, uint32_t *right, bool controller);

        status_t         dump(int fd, const Vector<String16>& args);

    protected:

        EffectModule(const EffectModule&);
        EffectModule& operator = (const EffectModule&);

        status_t start();
        status_t stop();

        Mutex               mLock;      // mutex for process, commands and handles list protection
        wp<ThreadBase>      mThread;    // parent thread
        wp<EffectChain>     mChain;     // parent effect chain
        int                 mId;        // this instance unique ID
        int                 mSessionId; // audio session ID
        effect_descriptor_t mDescriptor;// effect descriptor received from effect engine
        effect_config_t     mConfig;    // input and output audio configuration
        effect_interface_t  mEffectInterface; // Effect module C API
        status_t mStatus;               // initialization status
        uint32_t mState;                // current activation state (effect_state)
        Vector< wp<EffectHandle> > mHandles;    // list of client handles
    };

    // The EffectHandle class implements the IEffect interface. It provides resources
    // to receive parameter updates, keeps track of effect control
    // ownership and state and has a pointer to the EffectModule object it is controlling.
    // There is one EffectHandle object for each application controlling (or using)
    // an effect module.
    // The EffectHandle is obtained by calling AudioFlinger::createEffect().
    class EffectHandle: public android::BnEffect {
    public:

        EffectHandle(const sp<EffectModule>& effect,
                const sp<AudioFlinger::Client>& client,
                const sp<IEffectClient>& effectClient,
                int32_t priority);
        virtual ~EffectHandle();

        // IEffect
        virtual status_t enable();
        virtual status_t disable();
        virtual status_t command(int cmdCode, int cmdSize, void *pCmdData, int *replySize, void *pReplyData);
        virtual void disconnect();
        virtual sp<IMemory> getCblk() const;
        virtual status_t onTransact(uint32_t code, const Parcel& data,
                Parcel* reply, uint32_t flags);


        // Give or take control of effect module
        void setControl(bool hasControl, bool signal);
        void commandExecuted(int cmdCode, int cmdSize, void *pCmdData, int replySize, void *pReplyData);
        void setEnabled(bool enabled);

        // Getters
        int id() { return mEffect->id(); }
        int priority() { return mPriority; }
        bool hasControl() { return mHasControl; }
        sp<EffectModule> effect() { return mEffect; }

        void dump(char* buffer, size_t size);

    protected:

        EffectHandle(const EffectHandle&);
        EffectHandle& operator =(const EffectHandle&);

        sp<EffectModule> mEffect;           // pointer to controlled EffectModule
        sp<IEffectClient> mEffectClient;    // callback interface for client notifications
        sp<Client>          mClient;        // client for shared memory allocation
        sp<IMemory>         mCblkMemory;    // shared memory for control block
        effect_param_cblk_t* mCblk;         // control block for deferred parameter setting via shared memory
        uint8_t*            mBuffer;        // pointer to parameter area in shared memory
        int mPriority;                      // client application priority to control the effect
        bool mHasControl;                   // true if this handle is controlling the effect
    };

    // the EffectChain class represents a group of effects associated to one audio session.
    // There can be any number of EffectChain objects per output mixer thread (PlaybackThread).
    // The EffecChain with session ID 0 contains global effects applied to the output mix.
    // Effects in this chain can be insert or auxiliary. Effects in other chains (attached to tracks)
    // are insert only. The EffectChain maintains an ordered list of effect module, the order corresponding
    // in the effect process order. When attached to a track (session ID != 0), it also provide it's own
    // input buffer used by the track as accumulation buffer.
    class EffectChain: public RefBase {
    public:
        EffectChain(const wp<ThreadBase>& wThread, int sessionId);
        ~EffectChain();

        void process_l();

        void lock() {
            mLock.lock();
        }
        void unlock() {
            mLock.unlock();
        }

        status_t addEffect(sp<EffectModule>& handle);
        size_t removeEffect(const sp<EffectModule>& handle);

        int sessionId() {
            return mSessionId;
        }
        sp<EffectModule> getEffectFromDesc(effect_descriptor_t *descriptor);
        sp<EffectModule> getEffectFromId(int id);
        sp<EffectModule> getVolumeController();
        bool setVolume(uint32_t *left, uint32_t *right);
        void setDevice(uint32_t device);

        void setInBuffer(int16_t *buffer, bool ownsBuffer = false) {
            mInBuffer = buffer;
            mOwnInBuffer = ownsBuffer;
        }
        int16_t *inBuffer() {
            return mInBuffer;
        }
        void setOutBuffer(int16_t *buffer) {
            mOutBuffer = buffer;
        }
        int16_t *outBuffer() {
            return mOutBuffer;
        }

        void startTrack() {mActiveTrackCnt++;}
        void stopTrack() {mActiveTrackCnt--;}
        int activeTracks() { return mActiveTrackCnt;}

        status_t dump(int fd, const Vector<String16>& args);

    protected:

        EffectChain(const EffectChain&);
        EffectChain& operator =(const EffectChain&);

        wp<ThreadBase> mThread;     // parent mixer thread
        Mutex mLock;                // mutex protecting effect list
        Vector<sp<EffectModule> > mEffects; // list of effect modules
        int mSessionId;             // audio session ID
        int16_t *mInBuffer;         // chain input buffer
        int16_t *mOutBuffer;        // chain output buffer
        int mVolumeCtrlIdx;         // index of insert effect having control over volume
        int mActiveTrackCnt;        // number of active tracks connected
        bool mOwnInBuffer;          // true if the chain owns its input buffer
    };

    friend class RecordThread;
    friend class PlaybackThread;

@@ -813,7 +1100,7 @@ private:
                DefaultKeyedVector< int, sp<RecordThread> >    mRecordThreads;

                DefaultKeyedVector< pid_t, sp<NotificationClient> >    mNotificationClients;
                int                                 mNextThreadId;
                volatile int32_t                    mNextUniqueId;
#ifdef LVMX
                int mLifeVibesClientPid;
#endif
+487 −207

File changed.

Preview size limit exceeded, changes collapsed.

+32 −18
Original line number Diff line number Diff line
@@ -63,11 +63,14 @@ public:
        // for target TRACK
        CHANNEL_COUNT   = 0x4000,
        FORMAT          = 0x4001,
        MAIN_BUFFER     = 0x4002,
        AUX_BUFFER      = 0x4003,
        // for TARGET RESAMPLE
        SAMPLE_RATE     = 0x4100,
        // for TARGET VOLUME (8 channels max)
        VOLUME0         = 0x4200,
        VOLUME1         = 0x4201,
        AUXLEVEL        = 0x4210,
    };


@@ -78,10 +81,10 @@ public:
    status_t    disable(int name);

    status_t    setActiveTrack(int track);
    status_t    setParameter(int target, int name, int value);
    status_t    setParameter(int target, int name, void *value);

    status_t    setBufferProvider(AudioBufferProvider* bufferProvider);
    void        process(void* output);
    void        process();

    uint32_t    trackNames() const { return mTrackNames; }

@@ -94,6 +97,7 @@ private:
        NEEDS_FORMAT__MASK          = 0x000000F0,
        NEEDS_MUTE__MASK            = 0x00000100,
        NEEDS_RESAMPLE__MASK        = 0x00001000,
        NEEDS_AUX__MASK             = 0x00010000,
    };

    enum {
@@ -107,6 +111,9 @@ private:

        NEEDS_RESAMPLE_DISABLED     = 0x00000000,
        NEEDS_RESAMPLE_ENABLED      = 0x00001000,

        NEEDS_AUX_DISABLED     = 0x00000000,
        NEEDS_AUX_ENABLED      = 0x00010000,
    };

    static inline int32_t applyVolume(int32_t in, int32_t v) {
@@ -115,9 +122,10 @@ private:


    struct state_t;
    struct track_t;

    typedef void (*mix_t)(state_t* state, void* output);

    typedef void (*mix_t)(state_t* state);
    typedef void (*hook_t)(track_t* t, int32_t* output, size_t numOutFrames, int32_t* temp, int32_t* aux);
    static const int BLOCKSIZE = 16; // 4 cache lines

    struct track_t {
@@ -131,6 +139,9 @@ private:
        int32_t     prevVolume[2];

        int32_t     volumeInc[2];
        int32_t     auxLevel;
        int32_t     auxInc;
        int32_t     prevAuxLevel;

        uint16_t    frameCount;

@@ -142,15 +153,17 @@ private:
        AudioBufferProvider*                bufferProvider;
        mutable AudioBufferProvider::Buffer buffer;

        void (*hook)(track_t* t, int32_t* output, size_t numOutFrames, int32_t* temp);
        hook_t      hook;
        void const* in;             // current location in buffer

        AudioResampler*     resampler;
        uint32_t            sampleRate;
        int32_t*           mainBuffer;
        int32_t*           auxBuffer;

        bool        setResampler(uint32_t sampleRate, uint32_t devSampleRate);
        bool        doesResample() const;
        void        adjustVolumeRamp();
        void        adjustVolumeRamp(bool aux);
    };

    // pad to 32-bytes to fill cache line
@@ -173,18 +186,19 @@ private:

    void invalidateState(uint32_t mask);

    static void track__genericResample(track_t* t, int32_t* out, size_t numFrames, int32_t* temp);
    static void track__nop(track_t* t, int32_t* out, size_t numFrames, int32_t* temp);
    static void volumeRampStereo(track_t* t, int32_t* out, size_t frameCount, int32_t* temp);
    static void track__16BitsStereo(track_t* t, int32_t* out, size_t numFrames, int32_t* temp);
    static void track__16BitsMono(track_t* t, int32_t* out, size_t numFrames, int32_t* temp);

    static void process__validate(state_t* state, void* output);
    static void process__nop(state_t* state, void* output);
    static void process__genericNoResampling(state_t* state, void* output);
    static void process__genericResampling(state_t* state, void* output);
    static void process__OneTrack16BitsStereoNoResampling(state_t* state, void* output);
    static void process__TwoTracks16BitsStereoNoResampling(state_t* state, void* output);
    static void track__genericResample(track_t* t, int32_t* out, size_t numFrames, int32_t* temp, int32_t* aux);
    static void track__nop(track_t* t, int32_t* out, size_t numFrames, int32_t* temp, int32_t* aux);
    static void track__16BitsStereo(track_t* t, int32_t* out, size_t numFrames, int32_t* temp, int32_t* aux);
    static void track__16BitsMono(track_t* t, int32_t* out, size_t numFrames, int32_t* temp, int32_t* aux);
    static void volumeRampStereo(track_t* t, int32_t* out, size_t frameCount, int32_t* temp, int32_t* aux);
    static void volumeStereo(track_t* t, int32_t* out, size_t frameCount, int32_t* temp, int32_t* aux);

    static void process__validate(state_t* state);
    static void process__nop(state_t* state);
    static void process__genericNoResampling(state_t* state);
    static void process__genericResampling(state_t* state);
    static void process__OneTrack16BitsStereoNoResampling(state_t* state);
    static void process__TwoTracks16BitsStereoNoResampling(state_t* state);
};

// ----------------------------------------------------------------------------