Merge "Remove the notion of "active track" from mixer"

This commit is contained in:
Glenn Kasten
2012-01-05 08:20:10 -08:00
committed by Android (Google) Code Review
3 changed files with 89 additions and 81 deletions

View File

@@ -2102,12 +2102,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:
@@ -2133,7 +2134,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++;
@@ -2146,8 +2147,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());
}
}
@@ -2160,7 +2161,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
@@ -2212,26 +2213,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());
@@ -2239,7 +2245,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();
}
@@ -2251,7 +2257,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);
@@ -2259,7 +2265,7 @@ uint32_t AudioFlinger::MixerThread::prepareTracks_l(const SortedVector< wp<Track
mixerStatus = MIXER_TRACKS_ENABLED;
}
}
mAudioMixer->disable();
mAudioMixer->disable(name);
}
}

View File

@@ -41,7 +41,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);
@@ -140,120 +140,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;
@@ -269,11 +269,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;
@@ -348,9 +348,11 @@ size_t AudioMixer::getUnreleasedFrames(int name)
return 0;
}
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;
}

View File

@@ -42,7 +42,7 @@ public:
enum { // names
// track units (MAX_NUM_TRACKS units)
// track names (MAX_NUM_TRACKS units)
TRACK0 = 0x1000,
// 0x2000 is unused
@@ -69,16 +69,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; }
@@ -171,7 +171,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;