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

Commit 9c56d4ae authored by Glenn Kasten's avatar Glenn Kasten
Browse files

Remove the notion of "active track" from mixer

This is a first step towards making the mixer more object-oriented.

Change-Id: Ifd445d0e471023a7f5c82e934736ffc95ba1b05b
parent bbaf8673
Loading
Loading
Loading
Loading
+19 −13
Original line number Diff line number Diff line
@@ -2101,12 +2101,13 @@ uint32_t AudioFlinger::MixerThread::prepareTracks_l(const SortedVector< wp<Track
        sp<Track> t = activeTracks[i].promote();
        if (t == 0) continue;

        // this const just means the local variable doesn't change
        Track* const track = t.get();
        audio_track_cblk_t* cblk = track->cblk();

        // The first time a track is added we wait
        // for all its buffers to be filled before processing it
        mAudioMixer->setActiveTrack(track->name());
        int name = track->name();
        // make sure that we have enough frames to mix one full buffer.
        // enforce this condition only once to enable draining the buffer in case the client
        // app does not call stop() and relies on underrun to stop:
@@ -2124,7 +2125,7 @@ uint32_t AudioFlinger::MixerThread::prepareTracks_l(const SortedVector< wp<Track
        if ((cblk->framesReady() >= minFrames) && track->isReady() &&
                !track->isPaused() && !track->isTerminated())
        {
            //ALOGV("track %d u=%08x, s=%08x [OK] on thread %p", track->name(), cblk->user, cblk->server, this);
            //ALOGV("track %d u=%08x, s=%08x [OK] on thread %p", name, cblk->user, cblk->server, this);

            mixedTracks++;

@@ -2137,8 +2138,8 @@ uint32_t AudioFlinger::MixerThread::prepareTracks_l(const SortedVector< wp<Track
                if (chain != 0) {
                    tracksWithEffect++;
                } else {
                    LOGW("prepareTracks_l(): track %08x attached to effect but no chain found on session %d",
                            track->name(), track->sessionId());
                    LOGW("prepareTracks_l(): track %d attached to effect but no chain found on session %d",
                            name, track->sessionId());
                }
            }

@@ -2151,7 +2152,7 @@ uint32_t AudioFlinger::MixerThread::prepareTracks_l(const SortedVector< wp<Track
                    track->mState = TrackBase::ACTIVE;
                    param = AudioMixer::RAMP_VOLUME;
                }
                mAudioMixer->setParameter(AudioMixer::RESAMPLE, AudioMixer::RESET, NULL);
                mAudioMixer->setParameter(name, AudioMixer::RESAMPLE, AudioMixer::RESET, NULL);
            } else if (cblk->server != 0) {
                // If the track is stopped before the first frame was mixed,
                // do not apply ramp
@@ -2203,26 +2204,31 @@ uint32_t AudioFlinger::MixerThread::prepareTracks_l(const SortedVector< wp<Track
            aux = int16_t(va);

            // XXX: these things DON'T need to be done each time
            mAudioMixer->setBufferProvider(track);
            mAudioMixer->enable();
            mAudioMixer->setBufferProvider(name, track);
            mAudioMixer->enable(name);

            mAudioMixer->setParameter(param, AudioMixer::VOLUME0, (void *)left);
            mAudioMixer->setParameter(param, AudioMixer::VOLUME1, (void *)right);
            mAudioMixer->setParameter(param, AudioMixer::AUXLEVEL, (void *)aux);
            mAudioMixer->setParameter(name, param, AudioMixer::VOLUME0, (void *)left);
            mAudioMixer->setParameter(name, param, AudioMixer::VOLUME1, (void *)right);
            mAudioMixer->setParameter(name, param, AudioMixer::AUXLEVEL, (void *)aux);
            mAudioMixer->setParameter(
                name,
                AudioMixer::TRACK,
                AudioMixer::FORMAT, (void *)track->format());
            mAudioMixer->setParameter(
                name,
                AudioMixer::TRACK,
                AudioMixer::CHANNEL_MASK, (void *)track->channelMask());
            mAudioMixer->setParameter(
                name,
                AudioMixer::RESAMPLE,
                AudioMixer::SAMPLE_RATE,
                (void *)(cblk->sampleRate));
            mAudioMixer->setParameter(
                name,
                AudioMixer::TRACK,
                AudioMixer::MAIN_BUFFER, (void *)track->mainBuffer());
            mAudioMixer->setParameter(
                name,
                AudioMixer::TRACK,
                AudioMixer::AUX_BUFFER, (void *)track->auxBuffer());

@@ -2230,7 +2236,7 @@ uint32_t AudioFlinger::MixerThread::prepareTracks_l(const SortedVector< wp<Track
            track->mRetryCount = kMaxTrackRetries;
            mixerStatus = MIXER_TRACKS_READY;
        } else {
            //ALOGV("track %d u=%08x, s=%08x [NOT READY] on thread %p", track->name(), cblk->user, cblk->server, this);
            //ALOGV("track %d u=%08x, s=%08x [NOT READY] on thread %p", name, cblk->user, cblk->server, this);
            if (track->isStopped()) {
                track->reset();
            }
@@ -2242,7 +2248,7 @@ uint32_t AudioFlinger::MixerThread::prepareTracks_l(const SortedVector< wp<Track
                // No buffers for this track. Give it a few chances to
                // fill a buffer, then remove it from active list.
                if (--(track->mRetryCount) <= 0) {
                    ALOGV("BUFFER TIMEOUT: remove(%d) from active list on thread %p", track->name(), this);
                    ALOGV("BUFFER TIMEOUT: remove(%d) from active list on thread %p", name, this);
                    tracksToRemove->add(track);
                    // indicate to client process that the track was disabled because of underrun
                    android_atomic_or(CBLK_DISABLED_ON, &cblk->flags);
@@ -2250,7 +2256,7 @@ uint32_t AudioFlinger::MixerThread::prepareTracks_l(const SortedVector< wp<Track
                    mixerStatus = MIXER_TRACKS_ENABLED;
                }
            }
            mAudioMixer->disable();
            mAudioMixer->disable(name);
        }
    }

+63 −61
Original line number Diff line number Diff line
@@ -40,7 +40,7 @@ namespace android {
// ----------------------------------------------------------------------------

AudioMixer::AudioMixer(size_t frameCount, uint32_t sampleRate)
    :   mActiveTrack(0), mTrackNames(0), mSampleRate(sampleRate)
    :   mTrackNames(0), mSampleRate(sampleRate)
{
    // AudioMixer is not yet capable of multi-channel beyond stereo
    assert(2 == MAX_NUM_CHANNELS);
@@ -139,120 +139,120 @@ void AudioMixer::deleteTrackName(int name)
    mTrackNames &= ~(1<<name);
}

void AudioMixer::enable()
void AudioMixer::enable(int name)
{
    if (mState.tracks[ mActiveTrack ].enabled != 1) {
        mState.tracks[ mActiveTrack ].enabled = 1;
        ALOGV("enable(%d)", mActiveTrack);
        invalidateState(1<<mActiveTrack);
    name -= TRACK0;
    assert(uint32_t(name) < MAX_NUM_TRACKS);
    track_t& track = mState.tracks[name];

    if (track.enabled != 1) {
        track.enabled = 1;
        ALOGV("enable(%d)", name);
        invalidateState(1 << name);
    }
}

void AudioMixer::disable()
void AudioMixer::disable(int name)
{
    if (mState.tracks[ mActiveTrack ].enabled != 0) {
        mState.tracks[ mActiveTrack ].enabled = 0;
        ALOGV("disable(%d)", mActiveTrack);
        invalidateState(1<<mActiveTrack);
    name -= TRACK0;
    assert(uint32_t(name) < MAX_NUM_TRACKS);
    track_t& track = mState.tracks[name];

    if (track.enabled != 0) {
        track.enabled = 0;
        ALOGV("disable(%d)", name);
        invalidateState(1 << name);
    }
}

void AudioMixer::setActiveTrack(int track)
void AudioMixer::setParameter(int name, int target, int param, void *value)
{
    // this also catches track < TRACK0
    track -= TRACK0;
    assert(uint32_t(track) < MAX_NUM_TRACKS);
    mActiveTrack = track;
}
    name -= TRACK0;
    assert(uint32_t(name) < MAX_NUM_TRACKS);
    track_t& track = mState.tracks[name];

void AudioMixer::setParameter(int target, int name, void *value)
{
    int valueInt = (int)value;
    int32_t *valueBuf = (int32_t *)value;

    switch (target) {

    case TRACK:
        switch (name) {
        switch (param) {
        case CHANNEL_MASK: {
            uint32_t mask = (uint32_t)value;
            if (mState.tracks[ mActiveTrack ].channelMask != mask) {
            if (track.channelMask != mask) {
                uint8_t channelCount = popcount(mask);
                assert((channelCount <= MAX_NUM_CHANNELS) && (channelCount));
                mState.tracks[ mActiveTrack ].channelMask = mask;
                mState.tracks[ mActiveTrack ].channelCount = channelCount;
                track.channelMask = mask;
                track.channelCount = channelCount;
                ALOGV("setParameter(TRACK, CHANNEL_MASK, %x)", mask);
                invalidateState(1<<mActiveTrack);
                invalidateState(1 << name);
            }
            } break;
        case MAIN_BUFFER:
            if (mState.tracks[ mActiveTrack ].mainBuffer != valueBuf) {
                mState.tracks[ mActiveTrack ].mainBuffer = valueBuf;
            if (track.mainBuffer != valueBuf) {
                track.mainBuffer = valueBuf;
                ALOGV("setParameter(TRACK, MAIN_BUFFER, %p)", valueBuf);
                invalidateState(1<<mActiveTrack);
                invalidateState(1 << name);
            }
            break;
        case AUX_BUFFER:
            if (mState.tracks[ mActiveTrack ].auxBuffer != valueBuf) {
                mState.tracks[ mActiveTrack ].auxBuffer = valueBuf;
            if (track.auxBuffer != valueBuf) {
                track.auxBuffer = valueBuf;
                ALOGV("setParameter(TRACK, AUX_BUFFER, %p)", valueBuf);
                invalidateState(1<<mActiveTrack);
                invalidateState(1 << name);
            }
            break;
        default:
            // bad name
            // bad param
            assert(false);
        }
        break;

    case RESAMPLE:
        switch (name) {
        case SAMPLE_RATE: {
        switch (param) {
        case SAMPLE_RATE:
            assert(valueInt > 0);
            track_t& track = mState.tracks[ mActiveTrack ];
            if (track.setResampler(uint32_t(valueInt), mSampleRate)) {
                ALOGV("setParameter(RESAMPLE, SAMPLE_RATE, %u)",
                        uint32_t(valueInt));
                invalidateState(1<<mActiveTrack);
                invalidateState(1 << name);
            }
            } break;
        case RESET: {
            track_t& track = mState.tracks[ mActiveTrack ];
            break;
        case RESET:
            track.resetResampler();
            invalidateState(1<<mActiveTrack);
            } break;
            invalidateState(1 << name);
            break;
        default:
            // bad name
            // bad param
            assert(false);
        }
        break;

    case RAMP_VOLUME:
    case VOLUME:
        switch (name) {
        switch (param) {
        case VOLUME0:
        case VOLUME1: {
            track_t& track = mState.tracks[ mActiveTrack ];
            if (track.volume[name-VOLUME0] != valueInt) {
        case VOLUME1:
            if (track.volume[param-VOLUME0] != valueInt) {
                ALOGV("setParameter(VOLUME, VOLUME0/1: %04x)", valueInt);
                track.prevVolume[name-VOLUME0] = track.volume[name-VOLUME0] << 16;
                track.volume[name-VOLUME0] = valueInt;
                track.prevVolume[param-VOLUME0] = track.volume[param-VOLUME0] << 16;
                track.volume[param-VOLUME0] = valueInt;
                if (target == VOLUME) {
                    track.prevVolume[name-VOLUME0] = valueInt << 16;
                    track.volumeInc[name-VOLUME0] = 0;
                    track.prevVolume[param-VOLUME0] = valueInt << 16;
                    track.volumeInc[param-VOLUME0] = 0;
                } else {
                    int32_t d = (valueInt<<16) - track.prevVolume[name-VOLUME0];
                    int32_t d = (valueInt<<16) - track.prevVolume[param-VOLUME0];
                    int32_t volInc = d / int32_t(mState.frameCount);
                    track.volumeInc[name-VOLUME0] = volInc;
                    track.volumeInc[param-VOLUME0] = volInc;
                    if (volInc == 0) {
                        track.prevVolume[name-VOLUME0] = valueInt << 16;
                        track.prevVolume[param-VOLUME0] = valueInt << 16;
                    }
                }
                invalidateState(1<<mActiveTrack);
                invalidateState(1 << name);
            }
            } break;
        case AUXLEVEL: {
            track_t& track = mState.tracks[ mActiveTrack ];
            break;
        case AUXLEVEL:
            if (track.auxLevel != valueInt) {
                ALOGV("setParameter(VOLUME, AUXLEVEL: %04x)", valueInt);
                track.prevAuxLevel = track.auxLevel << 16;
@@ -268,11 +268,11 @@ void AudioMixer::setParameter(int target, int name, void *value)
                        track.prevAuxLevel = valueInt << 16;
                    }
                }
                invalidateState(1<<mActiveTrack);
                invalidateState(1 << name);
            }
            } break;
            break;
        default:
            // bad name
            // bad param
            assert(false);
        }
        break;
@@ -330,9 +330,11 @@ void AudioMixer::track_t::adjustVolumeRamp(bool aux)
}


void AudioMixer::setBufferProvider(AudioBufferProvider* buffer)
void AudioMixer::setBufferProvider(int name, AudioBufferProvider* buffer)
{
    mState.tracks[ mActiveTrack ].bufferProvider = buffer;
    name -= TRACK0;
    assert(uint32_t(name) < MAX_NUM_TRACKS);
    mState.tracks[name].bufferProvider = buffer;
}


+7 −7
Original line number Diff line number Diff line
@@ -47,7 +47,7 @@ public:

    enum { // names

        // track units (MAX_NUM_TRACKS units)
        // track names (MAX_NUM_TRACKS units)
        TRACK0          = 0x1000,

        // 0x2000 is unused
@@ -74,16 +74,16 @@ public:
    };


    // For all APIs with "name": TRACK0 <= name < TRACK0 + MAX_NUM_TRACKS
    int         getTrackName();
    void        deleteTrackName(int name);

    void        enable();
    void        disable();
    void        enable(int name);
    void        disable(int name);

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

    void        setBufferProvider(AudioBufferProvider* bufferProvider);
    void        setBufferProvider(int name, AudioBufferProvider* bufferProvider);
    void        process();

    uint32_t    trackNames() const { return mTrackNames; }
@@ -178,7 +178,7 @@ private:
        track_t         tracks[MAX_NUM_TRACKS]; __attribute__((aligned(32)));
    };

    int             mActiveTrack;
    // bitmask of allocated track names, where bit 0 corresponds to TRACK0 etc.
    uint32_t        mTrackNames;
    const uint32_t  mSampleRate;