FastMixer.cpp revision c263ca0ad8b6bdf5b0693996bc5f2f5916e0cd49
1d2fa56687f8bd5ac6ebf9d9468d0efd714986a54Ted Kremenek/* 2d2fa56687f8bd5ac6ebf9d9468d0efd714986a54Ted Kremenek * Copyright (C) 2012 The Android Open Source Project 3d2fa56687f8bd5ac6ebf9d9468d0efd714986a54Ted Kremenek * 4d2fa56687f8bd5ac6ebf9d9468d0efd714986a54Ted Kremenek * Licensed under the Apache License, Version 2.0 (the "License"); 5d2fa56687f8bd5ac6ebf9d9468d0efd714986a54Ted Kremenek * you may not use this file except in compliance with the License. 6d2fa56687f8bd5ac6ebf9d9468d0efd714986a54Ted Kremenek * You may obtain a copy of the License at 7d2fa56687f8bd5ac6ebf9d9468d0efd714986a54Ted Kremenek * 8d2fa56687f8bd5ac6ebf9d9468d0efd714986a54Ted Kremenek * http://www.apache.org/licenses/LICENSE-2.0 9d2fa56687f8bd5ac6ebf9d9468d0efd714986a54Ted Kremenek * 10d2fa56687f8bd5ac6ebf9d9468d0efd714986a54Ted Kremenek * Unless required by applicable law or agreed to in writing, software 11d2fa56687f8bd5ac6ebf9d9468d0efd714986a54Ted Kremenek * distributed under the License is distributed on an "AS IS" BASIS, 12d2fa56687f8bd5ac6ebf9d9468d0efd714986a54Ted Kremenek * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13d2fa56687f8bd5ac6ebf9d9468d0efd714986a54Ted Kremenek * See the License for the specific language governing permissions and 14d2fa56687f8bd5ac6ebf9d9468d0efd714986a54Ted Kremenek * limitations under the License. 15d2fa56687f8bd5ac6ebf9d9468d0efd714986a54Ted Kremenek */ 16d2fa56687f8bd5ac6ebf9d9468d0efd714986a54Ted Kremenek 17d2fa56687f8bd5ac6ebf9d9468d0efd714986a54Ted Kremenek// <IMPORTANT_WARNING> 18d2fa56687f8bd5ac6ebf9d9468d0efd714986a54Ted Kremenek// Design rules for threadLoop() are given in the comments at section "Fast mixer thread" of 1988145034694ed5267fa6fa5febc54fadc02bd479Steve Naroff// StateQueue.h. In particular, avoid library and system calls except at well-known points. 203d31560343856c573376a04558a7111e7afad4f7Chandler Carruth// The design rules are only for threadLoop(), and don't apply to FastMixerDumpState methods. 210a812cf707da15dadd19fdeb0178b9707f4e01a6Douglas Gregor// </IMPORTANT_WARNING> 2288145034694ed5267fa6fa5febc54fadc02bd479Steve Naroff 23db2a685287e57d9dfec09c867152c465af6fc6b0Arnaud A. de Grandmaison#define LOG_TAG "FastMixer" 24db2a685287e57d9dfec09c867152c465af6fc6b0Arnaud A. de Grandmaison//#define LOG_NDEBUG 0 25db2a685287e57d9dfec09c867152c465af6fc6b0Arnaud A. de Grandmaison 264d9eff53c49a2c1b9b460b899c95dcdbb3e056e1Argyrios Kyrtzidis#define ATRACE_TAG ATRACE_TAG_AUDIO 274d9eff53c49a2c1b9b460b899c95dcdbb3e056e1Argyrios Kyrtzidis 284d9eff53c49a2c1b9b460b899c95dcdbb3e056e1Argyrios Kyrtzidis#include "Configuration.h" 294d9eff53c49a2c1b9b460b899c95dcdbb3e056e1Argyrios Kyrtzidis#include <sys/atomics.h> 304d9eff53c49a2c1b9b460b899c95dcdbb3e056e1Argyrios Kyrtzidis#include <time.h> 314d9eff53c49a2c1b9b460b899c95dcdbb3e056e1Argyrios Kyrtzidis#include <utils/Log.h> 324d9eff53c49a2c1b9b460b899c95dcdbb3e056e1Argyrios Kyrtzidis#include <utils/Trace.h> 334d9eff53c49a2c1b9b460b899c95dcdbb3e056e1Argyrios Kyrtzidis#include <system/audio.h> 34ca9805a79dad01f12fa13c245f48724203699f08Argyrios Kyrtzidis#ifdef FAST_MIXER_STATISTICS 352d5c133d3dd95507db63147997109f06e8cfa833Argyrios Kyrtzidis#include <cpustats/CentralTendencyStatistics.h> 36ca9805a79dad01f12fa13c245f48724203699f08Argyrios Kyrtzidis#ifdef CPU_FREQUENCY_STATISTICS 37ca9805a79dad01f12fa13c245f48724203699f08Argyrios Kyrtzidis#include <cpustats/ThreadCpuUsage.h> 38ca9805a79dad01f12fa13c245f48724203699f08Argyrios Kyrtzidis#endif 39ca9805a79dad01f12fa13c245f48724203699f08Argyrios Kyrtzidis#endif 40ca9805a79dad01f12fa13c245f48724203699f08Argyrios Kyrtzidis#include <audio_utils/format.h> 41ca9805a79dad01f12fa13c245f48724203699f08Argyrios Kyrtzidis#include "AudioMixer.h" 42ca9805a79dad01f12fa13c245f48724203699f08Argyrios Kyrtzidis#include "FastMixer.h" 43ca9805a79dad01f12fa13c245f48724203699f08Argyrios Kyrtzidis 44ca9805a79dad01f12fa13c245f48724203699f08Argyrios Kyrtzidis#define FCC_2 2 // fixed channel count assumption 45ca9805a79dad01f12fa13c245f48724203699f08Argyrios Kyrtzidis 46ca9805a79dad01f12fa13c245f48724203699f08Argyrios Kyrtzidisnamespace android { 47ca9805a79dad01f12fa13c245f48724203699f08Argyrios Kyrtzidis 48ca9805a79dad01f12fa13c245f48724203699f08Argyrios Kyrtzidis/*static*/ const FastMixerState FastMixer::initial; 49ca9805a79dad01f12fa13c245f48724203699f08Argyrios Kyrtzidis 50ca9805a79dad01f12fa13c245f48724203699f08Argyrios KyrtzidisFastMixer::FastMixer() : FastThread(), 51ca9805a79dad01f12fa13c245f48724203699f08Argyrios Kyrtzidis slopNs(0), 52ca9805a79dad01f12fa13c245f48724203699f08Argyrios Kyrtzidis // fastTrackNames 53ca9805a79dad01f12fa13c245f48724203699f08Argyrios Kyrtzidis // generations 54d2fa56687f8bd5ac6ebf9d9468d0efd714986a54Ted Kremenek outputSink(NULL), 55d2fa56687f8bd5ac6ebf9d9468d0efd714986a54Ted Kremenek outputSinkGen(0), 56d2fa56687f8bd5ac6ebf9d9468d0efd714986a54Ted Kremenek mixer(NULL), 57d2fa56687f8bd5ac6ebf9d9468d0efd714986a54Ted Kremenek mSinkBuffer(NULL), 5887fb9404cd962b78c98947d75d68be1691c4e737Douglas Gregor mSinkBufferSize(0), 5920d416c36b46dd19ee0b1ea2d0266ae43be86e51Douglas Gregor mMixerBuffer(NULL), 601efcf3d137c11fb6b21c385911e0d2ca59ca94c3Daniel Dunbar mMixerBufferSize(0), 61f55254472e496340cbb4f0a24cff398e441475b5Douglas Gregor mMixerBufferFormat(AUDIO_FORMAT_PCM_16_BIT), 62f55254472e496340cbb4f0a24cff398e441475b5Douglas Gregor mMixerBufferState(UNDEFINED), 63f55254472e496340cbb4f0a24cff398e441475b5Douglas Gregor format(Format_Invalid), 64f55254472e496340cbb4f0a24cff398e441475b5Douglas Gregor sampleRate(0), 65f55254472e496340cbb4f0a24cff398e441475b5Douglas Gregor fastTracksGen(0), 661efcf3d137c11fb6b21c385911e0d2ca59ca94c3Daniel Dunbar totalNativeFramesWritten(0), 67f55254472e496340cbb4f0a24cff398e441475b5Douglas Gregor // timestamp 68f55254472e496340cbb4f0a24cff398e441475b5Douglas Gregor nativeFramesWrittenButNotPresented(0) // the = 0 is to silence the compiler 69f55254472e496340cbb4f0a24cff398e441475b5Douglas Gregor{ 701efcf3d137c11fb6b21c385911e0d2ca59ca94c3Daniel Dunbar // FIXME pass initial as parameter to base class constructor, and make it static local 711efcf3d137c11fb6b21c385911e0d2ca59ca94c3Daniel Dunbar previous = &initial; 72f55254472e496340cbb4f0a24cff398e441475b5Douglas Gregor current = &initial; 7320d416c36b46dd19ee0b1ea2d0266ae43be86e51Douglas Gregor 7420d416c36b46dd19ee0b1ea2d0266ae43be86e51Douglas Gregor mDummyDumpState = &dummyDumpState; 7520d416c36b46dd19ee0b1ea2d0266ae43be86e51Douglas Gregor 761efcf3d137c11fb6b21c385911e0d2ca59ca94c3Daniel Dunbar unsigned i; 777f17376e0931a337d544b75d9030bc92763be287Douglas Gregor for (i = 0; i < FastMixerState::kMaxFastTracks; ++i) { 787f17376e0931a337d544b75d9030bc92763be287Douglas Gregor fastTrackNames[i] = -1; 797f17376e0931a337d544b75d9030bc92763be287Douglas Gregor generations[i] = 0; 807f17376e0931a337d544b75d9030bc92763be287Douglas Gregor } 817f17376e0931a337d544b75d9030bc92763be287Douglas Gregor#ifdef FAST_MIXER_STATISTICS 82600866cc7d6d9ec2e27d4b6d6ec461f6463b5ab6Steve Naroff oldLoad.tv_sec = 0; 837f17376e0931a337d544b75d9030bc92763be287Douglas Gregor oldLoad.tv_nsec = 0; 847f17376e0931a337d544b75d9030bc92763be287Douglas Gregor#endif 857f17376e0931a337d544b75d9030bc92763be287Douglas Gregor} 860a90d32523bfe5fa63e11b648686c9699f786d15Ted Kremenek 87600866cc7d6d9ec2e27d4b6d6ec461f6463b5ab6Steve NaroffFastMixer::~FastMixer() 887f17376e0931a337d544b75d9030bc92763be287Douglas Gregor{ 89c42fefa51f7555bb3644a7cde2ca4bfd0d848d74Douglas Gregor} 90c42fefa51f7555bb3644a7cde2ca4bfd0d848d74Douglas Gregor 917f17376e0931a337d544b75d9030bc92763be287Douglas GregorFastMixerStateQueue* FastMixer::sq() 92c42fefa51f7555bb3644a7cde2ca4bfd0d848d74Douglas Gregor{ 931efcf3d137c11fb6b21c385911e0d2ca59ca94c3Daniel Dunbar return &mSQ; 94735df88a38e80c1ca70daa889aa516b8b9f54b50Douglas Gregor} 95735df88a38e80c1ca70daa889aa516b8b9f54b50Douglas Gregor 96735df88a38e80c1ca70daa889aa516b8b9f54b50Douglas Gregorconst FastThreadState *FastMixer::poll() 97735df88a38e80c1ca70daa889aa516b8b9f54b50Douglas Gregor{ 98735df88a38e80c1ca70daa889aa516b8b9f54b50Douglas Gregor return mSQ.poll(); 99735df88a38e80c1ca70daa889aa516b8b9f54b50Douglas Gregor} 100735df88a38e80c1ca70daa889aa516b8b9f54b50Douglas Gregor 101735df88a38e80c1ca70daa889aa516b8b9f54b50Douglas Gregorvoid FastMixer::setLog(NBLog::Writer *logWriter) 1021efcf3d137c11fb6b21c385911e0d2ca59ca94c3Daniel Dunbar{ 1031efcf3d137c11fb6b21c385911e0d2ca59ca94c3Daniel Dunbar if (mixer != NULL) { 104735df88a38e80c1ca70daa889aa516b8b9f54b50Douglas Gregor mixer->setLog(logWriter); 105735df88a38e80c1ca70daa889aa516b8b9f54b50Douglas Gregor } 106735df88a38e80c1ca70daa889aa516b8b9f54b50Douglas Gregor} 107735df88a38e80c1ca70daa889aa516b8b9f54b50Douglas Gregor 108735df88a38e80c1ca70daa889aa516b8b9f54b50Douglas Gregorvoid FastMixer::onIdle() 1091efcf3d137c11fb6b21c385911e0d2ca59ca94c3Daniel Dunbar{ 110c8dfe5ece04e683106eb96c58a2999f70b53ac21Douglas Gregor preIdle = *(const FastMixerState *)current; 111735df88a38e80c1ca70daa889aa516b8b9f54b50Douglas Gregor current = &preIdle; 112735df88a38e80c1ca70daa889aa516b8b9f54b50Douglas Gregor} 113735df88a38e80c1ca70daa889aa516b8b9f54b50Douglas Gregor 114735df88a38e80c1ca70daa889aa516b8b9f54b50Douglas Gregorvoid FastMixer::onExit() 115c8dfe5ece04e683106eb96c58a2999f70b53ac21Douglas Gregor{ 116735df88a38e80c1ca70daa889aa516b8b9f54b50Douglas Gregor delete mixer; 117735df88a38e80c1ca70daa889aa516b8b9f54b50Douglas Gregor free(mMixerBuffer); 118735df88a38e80c1ca70daa889aa516b8b9f54b50Douglas Gregor free(mSinkBuffer); 119735df88a38e80c1ca70daa889aa516b8b9f54b50Douglas Gregor} 120076c22a99ed82e11b59e8fbf57d8467ceb3fec77Peter Collingbourne 121076c22a99ed82e11b59e8fbf57d8467ceb3fec77Peter Collingbournebool FastMixer::isSubClassCommand(FastThreadState::Command command) 122076c22a99ed82e11b59e8fbf57d8467ceb3fec77Peter Collingbourne{ 123076c22a99ed82e11b59e8fbf57d8467ceb3fec77Peter Collingbourne switch ((FastMixerState::Command) command) { 124076c22a99ed82e11b59e8fbf57d8467ceb3fec77Peter Collingbourne case FastMixerState::MIX: 12558ddb60f409125eda5436c4a1f070f7fa4744295Douglas Gregor case FastMixerState::WRITE: 126076c22a99ed82e11b59e8fbf57d8467ceb3fec77Peter Collingbourne case FastMixerState::MIX_WRITE: 127076c22a99ed82e11b59e8fbf57d8467ceb3fec77Peter Collingbourne return true; 128076c22a99ed82e11b59e8fbf57d8467ceb3fec77Peter Collingbourne default: 12958ddb60f409125eda5436c4a1f070f7fa4744295Douglas Gregor return false; 130076c22a99ed82e11b59e8fbf57d8467ceb3fec77Peter Collingbourne } 131076c22a99ed82e11b59e8fbf57d8467ceb3fec77Peter Collingbourne} 132076c22a99ed82e11b59e8fbf57d8467ceb3fec77Peter Collingbourne 133076c22a99ed82e11b59e8fbf57d8467ceb3fec77Peter Collingbournevoid FastMixer::onStateChange() 13458ddb60f409125eda5436c4a1f070f7fa4744295Douglas Gregor{ 135076c22a99ed82e11b59e8fbf57d8467ceb3fec77Peter Collingbourne const FastMixerState * const current = (const FastMixerState *) this->current; 136076c22a99ed82e11b59e8fbf57d8467ceb3fec77Peter Collingbourne const FastMixerState * const previous = (const FastMixerState *) this->previous; 137076c22a99ed82e11b59e8fbf57d8467ceb3fec77Peter Collingbourne FastMixerDumpState * const dumpState = (FastMixerDumpState *) this->dumpState; 138d12059673dcef32bc2b6bae5321654d33863afe6Erik Verbruggen const size_t frameCount = current->mFrameCount; 139d12059673dcef32bc2b6bae5321654d33863afe6Erik Verbruggen 140d12059673dcef32bc2b6bae5321654d33863afe6Erik Verbruggen // handle state change here, but since we want to diff the state, 141d12059673dcef32bc2b6bae5321654d33863afe6Erik Verbruggen // we're prepared for previous == &initial the first time through 142d12059673dcef32bc2b6bae5321654d33863afe6Erik Verbruggen unsigned previousTrackMask; 143d12059673dcef32bc2b6bae5321654d33863afe6Erik Verbruggen 14458ddb60f409125eda5436c4a1f070f7fa4744295Douglas Gregor // check for change in output HAL configuration 145cc889664dec7776ebb598e4584e7df5ba2f59ab4Douglas Gregor NBAIO_Format previousFormat = format; 146cc889664dec7776ebb598e4584e7df5ba2f59ab4Douglas Gregor if (current->mOutputSinkGen != outputSinkGen) { 147cc889664dec7776ebb598e4584e7df5ba2f59ab4Douglas Gregor outputSink = current->mOutputSink; 148cc889664dec7776ebb598e4584e7df5ba2f59ab4Douglas Gregor outputSinkGen = current->mOutputSinkGen; 149cc889664dec7776ebb598e4584e7df5ba2f59ab4Douglas Gregor if (outputSink == NULL) { 150cc889664dec7776ebb598e4584e7df5ba2f59ab4Douglas Gregor format = Format_Invalid; 151cc889664dec7776ebb598e4584e7df5ba2f59ab4Douglas Gregor sampleRate = 0; 152cc889664dec7776ebb598e4584e7df5ba2f59ab4Douglas Gregor } else { 153cc889664dec7776ebb598e4584e7df5ba2f59ab4Douglas Gregor format = outputSink->format(); 154cc889664dec7776ebb598e4584e7df5ba2f59ab4Douglas Gregor sampleRate = Format_sampleRate(format); 155cc889664dec7776ebb598e4584e7df5ba2f59ab4Douglas Gregor ALOG_ASSERT(Format_channelCount(format) == FCC_2); 156cc889664dec7776ebb598e4584e7df5ba2f59ab4Douglas Gregor } 157cc889664dec7776ebb598e4584e7df5ba2f59ab4Douglas Gregor dumpState->mSampleRate = sampleRate; 158cc889664dec7776ebb598e4584e7df5ba2f59ab4Douglas Gregor } 159cc889664dec7776ebb598e4584e7df5ba2f59ab4Douglas Gregor 160cc889664dec7776ebb598e4584e7df5ba2f59ab4Douglas Gregor if ((!Format_isEqual(format, previousFormat)) || (frameCount != previous->mFrameCount)) { 161cc889664dec7776ebb598e4584e7df5ba2f59ab4Douglas Gregor // FIXME to avoid priority inversion, don't delete here 162cc889664dec7776ebb598e4584e7df5ba2f59ab4Douglas Gregor delete mixer; 163cc889664dec7776ebb598e4584e7df5ba2f59ab4Douglas Gregor mixer = NULL; 164cc889664dec7776ebb598e4584e7df5ba2f59ab4Douglas Gregor free(mMixerBuffer); 165cc889664dec7776ebb598e4584e7df5ba2f59ab4Douglas Gregor mMixerBuffer = NULL; 166cc889664dec7776ebb598e4584e7df5ba2f59ab4Douglas Gregor free(mSinkBuffer); 167cc889664dec7776ebb598e4584e7df5ba2f59ab4Douglas Gregor mSinkBuffer = NULL; 16858ddb60f409125eda5436c4a1f070f7fa4744295Douglas Gregor if (frameCount > 0 && sampleRate > 0) { 1697f17376e0931a337d544b75d9030bc92763be287Douglas Gregor // FIXME new may block for unbounded time at internal mutex of the heap 1707eee0184570366285589d788bcd7f5dda8345915James Dennett // implementation; it would be better to have normal mixer allocate for us 1717eee0184570366285589d788bcd7f5dda8345915James Dennett // to avoid blocking here and to prevent possible priority inversion 1727eee0184570366285589d788bcd7f5dda8345915James Dennett mixer = new AudioMixer(frameCount, sampleRate, FastMixerState::kMaxFastTracks); 173e56b4baeba5097852e04bc41ca2e0396cf729955Steve Naroff const size_t mixerFrameSize = FCC_2 * audio_bytes_per_sample(mMixerBufferFormat); 174e56b4baeba5097852e04bc41ca2e0396cf729955Steve Naroff mMixerBufferSize = mixerFrameSize * frameCount; 175e56b4baeba5097852e04bc41ca2e0396cf729955Steve Naroff (void)posix_memalign(&mMixerBuffer, 32, mMixerBufferSize); 1761efcf3d137c11fb6b21c385911e0d2ca59ca94c3Daniel Dunbar const size_t sinkFrameSize = FCC_2 * audio_bytes_per_sample(format.mFormat); 177e56b4baeba5097852e04bc41ca2e0396cf729955Steve Naroff if (sinkFrameSize > mixerFrameSize) { // need a sink buffer 178e56b4baeba5097852e04bc41ca2e0396cf729955Steve Naroff mSinkBufferSize = sinkFrameSize * frameCount; 179e56b4baeba5097852e04bc41ca2e0396cf729955Steve Naroff (void)posix_memalign(&mSinkBuffer, 32, mSinkBufferSize); 180b4ece6377d95e35a8df01cd010d910c34d690f67Steve Naroff } 181b4ece6377d95e35a8df01cd010d910c34d690f67Steve Naroff periodNs = (frameCount * 1000000000LL) / sampleRate; // 1.00 1827eee0184570366285589d788bcd7f5dda8345915James Dennett underrunNs = (frameCount * 1750000000LL) / sampleRate; // 1.75 1830a812cf707da15dadd19fdeb0178b9707f4e01a6Douglas Gregor overrunNs = (frameCount * 500000000LL) / sampleRate; // 0.50 1840a812cf707da15dadd19fdeb0178b9707f4e01a6Douglas Gregor forceNs = (frameCount * 950000000LL) / sampleRate; // 0.95 185b4ece6377d95e35a8df01cd010d910c34d690f67Steve Naroff warmupNs = (frameCount * 500000000LL) / sampleRate; // 0.50 186b4ece6377d95e35a8df01cd010d910c34d690f67Steve Naroff } else { 187b4ece6377d95e35a8df01cd010d910c34d690f67Steve Naroff periodNs = 0; 188b4ece6377d95e35a8df01cd010d910c34d690f67Steve Naroff underrunNs = 0; 189b4ece6377d95e35a8df01cd010d910c34d690f67Steve Naroff overrunNs = 0; 190b4ece6377d95e35a8df01cd010d910c34d690f67Steve Naroff forceNs = 0; 1911efcf3d137c11fb6b21c385911e0d2ca59ca94c3Daniel Dunbar warmupNs = 0; 192002a528ab0189fc60cfbf9328962c96ccbe567eeDouglas Gregor } 193b4ece6377d95e35a8df01cd010d910c34d690f67Steve Naroff mMixerBufferState = UNDEFINED; 194b4ece6377d95e35a8df01cd010d910c34d690f67Steve Naroff#if !LOG_NDEBUG 195b4ece6377d95e35a8df01cd010d910c34d690f67Steve Naroff for (unsigned i = 0; i < FastMixerState::kMaxFastTracks; ++i) { 196b4ece6377d95e35a8df01cd010d910c34d690f67Steve Naroff fastTrackNames[i] = -1; 197fd9f23464bfd35314c87c4df410f3937d59eb96dDaniel Dunbar } 198fd9f23464bfd35314c87c4df410f3937d59eb96dDaniel Dunbar#endif 199fd9f23464bfd35314c87c4df410f3937d59eb96dDaniel Dunbar // we need to reconfigure all active tracks 200b2cd48756119f4d8d2a865b4b3e0e8efd02e26a0Douglas Gregor previousTrackMask = 0; 201b2cd48756119f4d8d2a865b4b3e0e8efd02e26a0Douglas Gregor fastTracksGen = current->mFastTracksGen - 1; 202b4ece6377d95e35a8df01cd010d910c34d690f67Steve Naroff dumpState->mFrameCount = frameCount; 2037eee0184570366285589d788bcd7f5dda8345915James Dennett } else { 204b4ece6377d95e35a8df01cd010d910c34d690f67Steve Naroff previousTrackMask = previous->mTrackMask; 205b4ece6377d95e35a8df01cd010d910c34d690f67Steve Naroff } 206b4ece6377d95e35a8df01cd010d910c34d690f67Steve Naroff 207b4ece6377d95e35a8df01cd010d910c34d690f67Steve Naroff // check for change in active track set 208e56b4baeba5097852e04bc41ca2e0396cf729955Steve Naroff const unsigned currentTrackMask = current->mTrackMask; 2090a812cf707da15dadd19fdeb0178b9707f4e01a6Douglas Gregor dumpState->mTrackMask = currentTrackMask; 2100a812cf707da15dadd19fdeb0178b9707f4e01a6Douglas Gregor if (current->mFastTracksGen != fastTracksGen) { 211896b70ffc348f6e2c680b5fb5841984d5785b7b5Ted Kremenek ALOG_ASSERT(mMixerBuffer != NULL); 2120087e1a12b67b6bb032a72ea485a863daeccf55bDouglas Gregor int name; 2130087e1a12b67b6bb032a72ea485a863daeccf55bDouglas Gregor 2140087e1a12b67b6bb032a72ea485a863daeccf55bDouglas Gregor // process removed tracks first to avoid running out of track names 2150087e1a12b67b6bb032a72ea485a863daeccf55bDouglas Gregor unsigned removedTracks = previousTrackMask & ~currentTrackMask; 2160087e1a12b67b6bb032a72ea485a863daeccf55bDouglas Gregor while (removedTracks != 0) { 2170087e1a12b67b6bb032a72ea485a863daeccf55bDouglas Gregor int i = __builtin_ctz(removedTracks); 2188506dde586459887b7e14e23a30af8ac5be5adb6Daniel Dunbar removedTracks &= ~(1 << i); 2191efcf3d137c11fb6b21c385911e0d2ca59ca94c3Daniel Dunbar const FastTrack* fastTrack = ¤t->mFastTracks[i]; 220fdc1795acc9d5d73a767cc7d43ad1546e93adbbaArgyrios Kyrtzidis ALOG_ASSERT(fastTrack->mBufferProvider == NULL); 221fdc1795acc9d5d73a767cc7d43ad1546e93adbbaArgyrios Kyrtzidis if (mixer != NULL) { 222fdc1795acc9d5d73a767cc7d43ad1546e93adbbaArgyrios Kyrtzidis name = fastTrackNames[i]; 223fdc1795acc9d5d73a767cc7d43ad1546e93adbbaArgyrios Kyrtzidis ALOG_ASSERT(name >= 0); 224fdc1795acc9d5d73a767cc7d43ad1546e93adbbaArgyrios Kyrtzidis mixer->deleteTrackName(name); 225fdc1795acc9d5d73a767cc7d43ad1546e93adbbaArgyrios Kyrtzidis } 226fdc1795acc9d5d73a767cc7d43ad1546e93adbbaArgyrios Kyrtzidis#if !LOG_NDEBUG 227fdc1795acc9d5d73a767cc7d43ad1546e93adbbaArgyrios Kyrtzidis fastTrackNames[i] = -1; 228fdc1795acc9d5d73a767cc7d43ad1546e93adbbaArgyrios Kyrtzidis#endif 2297eee0184570366285589d788bcd7f5dda8345915James Dennett // don't reset track dump state, since other side is ignoring it 2307eee0184570366285589d788bcd7f5dda8345915James Dennett generations[i] = fastTrack->mGeneration; 2317eee0184570366285589d788bcd7f5dda8345915James Dennett } 232fdc1795acc9d5d73a767cc7d43ad1546e93adbbaArgyrios Kyrtzidis 233fdc1795acc9d5d73a767cc7d43ad1546e93adbbaArgyrios Kyrtzidis // now process added tracks 234fdc1795acc9d5d73a767cc7d43ad1546e93adbbaArgyrios Kyrtzidis unsigned addedTracks = currentTrackMask & ~previousTrackMask; 235fdc1795acc9d5d73a767cc7d43ad1546e93adbbaArgyrios Kyrtzidis while (addedTracks != 0) { 236fdc1795acc9d5d73a767cc7d43ad1546e93adbbaArgyrios Kyrtzidis int i = __builtin_ctz(addedTracks); 237fdc1795acc9d5d73a767cc7d43ad1546e93adbbaArgyrios Kyrtzidis addedTracks &= ~(1 << i); 2387eee0184570366285589d788bcd7f5dda8345915James Dennett const FastTrack* fastTrack = ¤t->mFastTracks[i]; 2397eee0184570366285589d788bcd7f5dda8345915James Dennett AudioBufferProvider *bufferProvider = fastTrack->mBufferProvider; 2407eee0184570366285589d788bcd7f5dda8345915James Dennett ALOG_ASSERT(bufferProvider != NULL && fastTrackNames[i] == -1); 241fdc1795acc9d5d73a767cc7d43ad1546e93adbbaArgyrios Kyrtzidis if (mixer != NULL) { 242fdc1795acc9d5d73a767cc7d43ad1546e93adbbaArgyrios Kyrtzidis name = mixer->getTrackName(fastTrack->mChannelMask, 243fdc1795acc9d5d73a767cc7d43ad1546e93adbbaArgyrios Kyrtzidis fastTrack->mFormat, AUDIO_SESSION_OUTPUT_MIX); 244fdc1795acc9d5d73a767cc7d43ad1546e93adbbaArgyrios Kyrtzidis ALOG_ASSERT(name >= 0); 245fdc1795acc9d5d73a767cc7d43ad1546e93adbbaArgyrios Kyrtzidis fastTrackNames[i] = name; 246fdc1795acc9d5d73a767cc7d43ad1546e93adbbaArgyrios Kyrtzidis mixer->setBufferProvider(name, bufferProvider); 247fdc1795acc9d5d73a767cc7d43ad1546e93adbbaArgyrios Kyrtzidis mixer->setParameter(name, AudioMixer::TRACK, AudioMixer::MAIN_BUFFER, 248fdc1795acc9d5d73a767cc7d43ad1546e93adbbaArgyrios Kyrtzidis (void *) mMixerBuffer); 249fdc1795acc9d5d73a767cc7d43ad1546e93adbbaArgyrios Kyrtzidis // newly allocated track names default to full scale volume 250fdc1795acc9d5d73a767cc7d43ad1546e93adbbaArgyrios Kyrtzidis mixer->setParameter( 251fdc1795acc9d5d73a767cc7d43ad1546e93adbbaArgyrios Kyrtzidis name, 252fdc1795acc9d5d73a767cc7d43ad1546e93adbbaArgyrios Kyrtzidis AudioMixer::TRACK, 253fdc1795acc9d5d73a767cc7d43ad1546e93adbbaArgyrios Kyrtzidis AudioMixer::MIXER_FORMAT, (void *)mMixerBufferFormat); 254fdc1795acc9d5d73a767cc7d43ad1546e93adbbaArgyrios Kyrtzidis mixer->setParameter(name, AudioMixer::TRACK, AudioMixer::FORMAT, 2557eee0184570366285589d788bcd7f5dda8345915James Dennett (void *)(uintptr_t)fastTrack->mFormat); 256fdc1795acc9d5d73a767cc7d43ad1546e93adbbaArgyrios Kyrtzidis mixer->enable(name); 257fdc1795acc9d5d73a767cc7d43ad1546e93adbbaArgyrios Kyrtzidis } 258fdc1795acc9d5d73a767cc7d43ad1546e93adbbaArgyrios Kyrtzidis generations[i] = fastTrack->mGeneration; 259fdc1795acc9d5d73a767cc7d43ad1546e93adbbaArgyrios Kyrtzidis } 260fdc1795acc9d5d73a767cc7d43ad1546e93adbbaArgyrios Kyrtzidis 261fdc1795acc9d5d73a767cc7d43ad1546e93adbbaArgyrios Kyrtzidis // finally process (potentially) modified tracks; these use the same slot 262fdc1795acc9d5d73a767cc7d43ad1546e93adbbaArgyrios Kyrtzidis // but may have a different buffer provider or volume provider 263fdc1795acc9d5d73a767cc7d43ad1546e93adbbaArgyrios Kyrtzidis unsigned modifiedTracks = currentTrackMask & previousTrackMask; 264fdc1795acc9d5d73a767cc7d43ad1546e93adbbaArgyrios Kyrtzidis while (modifiedTracks != 0) { 265fdc1795acc9d5d73a767cc7d43ad1546e93adbbaArgyrios Kyrtzidis int i = __builtin_ctz(modifiedTracks); 266fdc1795acc9d5d73a767cc7d43ad1546e93adbbaArgyrios Kyrtzidis modifiedTracks &= ~(1 << i); 267fdc1795acc9d5d73a767cc7d43ad1546e93adbbaArgyrios Kyrtzidis const FastTrack* fastTrack = ¤t->mFastTracks[i]; 268fdc1795acc9d5d73a767cc7d43ad1546e93adbbaArgyrios Kyrtzidis if (fastTrack->mGeneration != generations[i]) { 269fdc1795acc9d5d73a767cc7d43ad1546e93adbbaArgyrios Kyrtzidis // this track was actually modified 270fdc1795acc9d5d73a767cc7d43ad1546e93adbbaArgyrios Kyrtzidis AudioBufferProvider *bufferProvider = fastTrack->mBufferProvider; 271fdc1795acc9d5d73a767cc7d43ad1546e93adbbaArgyrios Kyrtzidis ALOG_ASSERT(bufferProvider != NULL); 272fdc1795acc9d5d73a767cc7d43ad1546e93adbbaArgyrios Kyrtzidis if (mixer != NULL) { 273fdc1795acc9d5d73a767cc7d43ad1546e93adbbaArgyrios Kyrtzidis name = fastTrackNames[i]; 274fdc1795acc9d5d73a767cc7d43ad1546e93adbbaArgyrios Kyrtzidis ALOG_ASSERT(name >= 0); 275fdc1795acc9d5d73a767cc7d43ad1546e93adbbaArgyrios Kyrtzidis mixer->setBufferProvider(name, bufferProvider); 276fdc1795acc9d5d73a767cc7d43ad1546e93adbbaArgyrios Kyrtzidis if (fastTrack->mVolumeProvider == NULL) { 2771efcf3d137c11fb6b21c385911e0d2ca59ca94c3Daniel Dunbar float f = AudioMixer::UNITY_GAIN_FLOAT; 278c42fefa51f7555bb3644a7cde2ca4bfd0d848d74Douglas Gregor mixer->setParameter(name, AudioMixer::VOLUME, AudioMixer::VOLUME0, &f); 279f55254472e496340cbb4f0a24cff398e441475b5Douglas Gregor mixer->setParameter(name, AudioMixer::VOLUME, AudioMixer::VOLUME1, &f); 280f55254472e496340cbb4f0a24cff398e441475b5Douglas Gregor } 281f55254472e496340cbb4f0a24cff398e441475b5Douglas Gregor mixer->setParameter(name, AudioMixer::RESAMPLE, 2821efcf3d137c11fb6b21c385911e0d2ca59ca94c3Daniel Dunbar AudioMixer::REMOVE, NULL); 283f55254472e496340cbb4f0a24cff398e441475b5Douglas Gregor mixer->setParameter( 284f55254472e496340cbb4f0a24cff398e441475b5Douglas Gregor name, 285f55254472e496340cbb4f0a24cff398e441475b5Douglas Gregor AudioMixer::TRACK, 286f55254472e496340cbb4f0a24cff398e441475b5Douglas Gregor AudioMixer::MIXER_FORMAT, (void *)mMixerBufferFormat); 2871efcf3d137c11fb6b21c385911e0d2ca59ca94c3Daniel Dunbar mixer->setParameter(name, AudioMixer::TRACK, AudioMixer::FORMAT, 288f55254472e496340cbb4f0a24cff398e441475b5Douglas Gregor (void *)(uintptr_t)fastTrack->mFormat); 289f55254472e496340cbb4f0a24cff398e441475b5Douglas Gregor mixer->setParameter(name, AudioMixer::TRACK, AudioMixer::CHANNEL_MASK, 290f55254472e496340cbb4f0a24cff398e441475b5Douglas Gregor (void *)(uintptr_t) fastTrack->mChannelMask); 29188145034694ed5267fa6fa5febc54fadc02bd479Steve Naroff // already enabled 29274844072411bae91d5dbb89955d200cbe1e0a1c8Ted Kremenek } 2931efcf3d137c11fb6b21c385911e0d2ca59ca94c3Daniel Dunbar generations[i] = fastTrack->mGeneration; 294f55254472e496340cbb4f0a24cff398e441475b5Douglas Gregor } 295f55254472e496340cbb4f0a24cff398e441475b5Douglas Gregor } 296f55254472e496340cbb4f0a24cff398e441475b5Douglas Gregor 29708b0e8daeb683686b876d72674962ad96df21d45Douglas Gregor fastTracksGen = current->mFastTracksGen; 29888145034694ed5267fa6fa5febc54fadc02bd479Steve Naroff 2993c7313d96cd4a18cd8c1fcd3ddd8128c2fcbe58fDouglas Gregor dumpState->mNumTracks = popcount(currentTrackMask); 300dd3e5549e3c11e217078938aacf72f042eea5343Douglas Gregor } 301dd3e5549e3c11e217078938aacf72f042eea5343Douglas Gregor} 3027eee0184570366285589d788bcd7f5dda8345915James Dennett 303dd3e5549e3c11e217078938aacf72f042eea5343Douglas Gregorvoid FastMixer::onWork() 304dd3e5549e3c11e217078938aacf72f042eea5343Douglas Gregor{ 305dd3e5549e3c11e217078938aacf72f042eea5343Douglas Gregor const FastMixerState * const current = (const FastMixerState *) this->current; 306dd3e5549e3c11e217078938aacf72f042eea5343Douglas Gregor FastMixerDumpState * const dumpState = (FastMixerDumpState *) this->dumpState; 307dd3e5549e3c11e217078938aacf72f042eea5343Douglas Gregor const FastMixerState::Command command = this->command; 308b979034b100be14de2223f2b8f6cc7a3275cbe4fDouglas Gregor const size_t frameCount = current->mFrameCount; 309b979034b100be14de2223f2b8f6cc7a3275cbe4fDouglas Gregor 310b979034b100be14de2223f2b8f6cc7a3275cbe4fDouglas Gregor if ((command & FastMixerState::MIX) && (mixer != NULL) && isWarm) { 3111efcf3d137c11fb6b21c385911e0d2ca59ca94c3Daniel Dunbar ALOG_ASSERT(mMixerBuffer != NULL); 312b979034b100be14de2223f2b8f6cc7a3275cbe4fDouglas Gregor // for each track, update volume and check for underrun 313b979034b100be14de2223f2b8f6cc7a3275cbe4fDouglas Gregor unsigned currentTrackMask = current->mTrackMask; 314b979034b100be14de2223f2b8f6cc7a3275cbe4fDouglas Gregor while (currentTrackMask != 0) { 315b979034b100be14de2223f2b8f6cc7a3275cbe4fDouglas Gregor int i = __builtin_ctz(currentTrackMask); 316b979034b100be14de2223f2b8f6cc7a3275cbe4fDouglas Gregor currentTrackMask &= ~(1 << i); 3171efcf3d137c11fb6b21c385911e0d2ca59ca94c3Daniel Dunbar const FastTrack* fastTrack = ¤t->mFastTracks[i]; 318b979034b100be14de2223f2b8f6cc7a3275cbe4fDouglas Gregor 3191efcf3d137c11fb6b21c385911e0d2ca59ca94c3Daniel Dunbar // Refresh the per-track timestamp 320b979034b100be14de2223f2b8f6cc7a3275cbe4fDouglas Gregor if (timestampStatus == NO_ERROR) { 321f55254472e496340cbb4f0a24cff398e441475b5Douglas Gregor uint32_t trackFramesWrittenButNotPresented = 322f55254472e496340cbb4f0a24cff398e441475b5Douglas Gregor nativeFramesWrittenButNotPresented; 323f55254472e496340cbb4f0a24cff398e441475b5Douglas Gregor uint32_t trackFramesWritten = fastTrack->mBufferProvider->framesReleased(); 324f55254472e496340cbb4f0a24cff398e441475b5Douglas Gregor // Can't provide an AudioTimestamp before first frame presented, 325f55254472e496340cbb4f0a24cff398e441475b5Douglas Gregor // or during the brief 32-bit wraparound window 326f55254472e496340cbb4f0a24cff398e441475b5Douglas Gregor if (trackFramesWritten >= trackFramesWrittenButNotPresented) { 327f55254472e496340cbb4f0a24cff398e441475b5Douglas Gregor AudioTimestamp perTrackTimestamp; 328f55254472e496340cbb4f0a24cff398e441475b5Douglas Gregor perTrackTimestamp.mPosition = 329f55254472e496340cbb4f0a24cff398e441475b5Douglas Gregor trackFramesWritten - trackFramesWrittenButNotPresented; 330f55254472e496340cbb4f0a24cff398e441475b5Douglas Gregor perTrackTimestamp.mTime = timestamp.mTime; 331f55254472e496340cbb4f0a24cff398e441475b5Douglas Gregor fastTrack->mBufferProvider->onTimestamp(perTrackTimestamp); 332f55254472e496340cbb4f0a24cff398e441475b5Douglas Gregor } 333f55254472e496340cbb4f0a24cff398e441475b5Douglas Gregor } 334f55254472e496340cbb4f0a24cff398e441475b5Douglas Gregor 335f55254472e496340cbb4f0a24cff398e441475b5Douglas Gregor int name = fastTrackNames[i]; 3361efcf3d137c11fb6b21c385911e0d2ca59ca94c3Daniel Dunbar ALOG_ASSERT(name >= 0); 337f55254472e496340cbb4f0a24cff398e441475b5Douglas Gregor if (fastTrack->mVolumeProvider != NULL) { 3381db19dea8d221f27be46332d668d1e2decb7f1abDouglas Gregor gain_minifloat_packed_t vlr = fastTrack->mVolumeProvider->getVolumeLR(); 3391db19dea8d221f27be46332d668d1e2decb7f1abDouglas Gregor float vlf = float_from_gain(gain_minifloat_unpack_left(vlr)); 3401db19dea8d221f27be46332d668d1e2decb7f1abDouglas Gregor float vrf = float_from_gain(gain_minifloat_unpack_right(vlr)); 34120174221af145554b76a0b0f5e4eb3ac70d05945Chandler Carruth 342a9b06d4c246d6c301e3dd1844f5dba669ed9c631Douglas Gregor mixer->setParameter(name, AudioMixer::VOLUME, AudioMixer::VOLUME0, &vlf); 3433c7313d96cd4a18cd8c1fcd3ddd8128c2fcbe58fDouglas Gregor mixer->setParameter(name, AudioMixer::VOLUME, AudioMixer::VOLUME1, &vrf); 3443c7313d96cd4a18cd8c1fcd3ddd8128c2fcbe58fDouglas Gregor } 3455352ac06d8f6194825bb2a99ffa009b61bafb503Douglas Gregor // FIXME The current implementation of framesReady() for fast tracks 3461db19dea8d221f27be46332d668d1e2decb7f1abDouglas Gregor // takes a tryLock, which can block 3473c7313d96cd4a18cd8c1fcd3ddd8128c2fcbe58fDouglas Gregor // up to 1 ms. If enough active tracks all blocked in sequence, this would result 348fe6fd3d41a7f48317d6856c9327b6cead32c3498Ted Kremenek // in the overall fast mix cycle being delayed. Should use a non-blocking FIFO. 3493c7313d96cd4a18cd8c1fcd3ddd8128c2fcbe58fDouglas Gregor size_t framesReady = fastTrack->mBufferProvider->framesReady(); 350d52864bd33c66aacc84133460d8c9c0dfcdd5c18Daniel Dunbar if (ATRACE_ENABLED()) { 3513c7313d96cd4a18cd8c1fcd3ddd8128c2fcbe58fDouglas Gregor // I wish we had formatted trace names 3521db19dea8d221f27be46332d668d1e2decb7f1abDouglas Gregor char traceName[16]; 3531db19dea8d221f27be46332d668d1e2decb7f1abDouglas Gregor strcpy(traceName, "fRdy"); 3543c7313d96cd4a18cd8c1fcd3ddd8128c2fcbe58fDouglas Gregor traceName[4] = i + (i < 10 ? '0' : 'A' - 10); 3553c7313d96cd4a18cd8c1fcd3ddd8128c2fcbe58fDouglas Gregor traceName[5] = '\0'; 3565352ac06d8f6194825bb2a99ffa009b61bafb503Douglas Gregor ATRACE_INT(traceName, framesReady); 3571db19dea8d221f27be46332d668d1e2decb7f1abDouglas Gregor } 3581db19dea8d221f27be46332d668d1e2decb7f1abDouglas Gregor FastTrackDump *ftDump = &dumpState->mTracks[i]; 3593c7313d96cd4a18cd8c1fcd3ddd8128c2fcbe58fDouglas Gregor FastTrackUnderruns underruns = ftDump->mUnderruns; 360fe6fd3d41a7f48317d6856c9327b6cead32c3498Ted Kremenek if (framesReady < frameCount) { 3611db19dea8d221f27be46332d668d1e2decb7f1abDouglas Gregor if (framesReady == 0) { 362b979034b100be14de2223f2b8f6cc7a3275cbe4fDouglas Gregor underruns.mBitFields.mEmpty++; 363b979034b100be14de2223f2b8f6cc7a3275cbe4fDouglas Gregor underruns.mBitFields.mMostRecent = UNDERRUN_EMPTY; 364f9c21665faa7e4936d484396469ee7afc46e1f00NAKAMURA Takumi mixer->disable(name); 3651efcf3d137c11fb6b21c385911e0d2ca59ca94c3Daniel Dunbar } else { 366b979034b100be14de2223f2b8f6cc7a3275cbe4fDouglas Gregor // allow mixing partial buffer 3677eee0184570366285589d788bcd7f5dda8345915James Dennett underruns.mBitFields.mPartial++; 3681efcf3d137c11fb6b21c385911e0d2ca59ca94c3Daniel Dunbar underruns.mBitFields.mMostRecent = UNDERRUN_PARTIAL; 369b979034b100be14de2223f2b8f6cc7a3275cbe4fDouglas Gregor mixer->enable(name); 370b979034b100be14de2223f2b8f6cc7a3275cbe4fDouglas Gregor } 371b979034b100be14de2223f2b8f6cc7a3275cbe4fDouglas Gregor } else { 372b979034b100be14de2223f2b8f6cc7a3275cbe4fDouglas Gregor underruns.mBitFields.mFull++; 373b979034b100be14de2223f2b8f6cc7a3275cbe4fDouglas Gregor underruns.mBitFields.mMostRecent = UNDERRUN_FULL; 374b979034b100be14de2223f2b8f6cc7a3275cbe4fDouglas Gregor mixer->enable(name); 375b979034b100be14de2223f2b8f6cc7a3275cbe4fDouglas Gregor } 3761efcf3d137c11fb6b21c385911e0d2ca59ca94c3Daniel Dunbar ftDump->mUnderruns = underruns; 377b979034b100be14de2223f2b8f6cc7a3275cbe4fDouglas Gregor ftDump->mFramesReady = framesReady; 3781efcf3d137c11fb6b21c385911e0d2ca59ca94c3Daniel Dunbar } 3791efcf3d137c11fb6b21c385911e0d2ca59ca94c3Daniel Dunbar 380b979034b100be14de2223f2b8f6cc7a3275cbe4fDouglas Gregor int64_t pts; 381b979034b100be14de2223f2b8f6cc7a3275cbe4fDouglas Gregor if (outputSink == NULL || (OK != outputSink->getNextWriteTimestamp(&pts))) { 382b979034b100be14de2223f2b8f6cc7a3275cbe4fDouglas Gregor pts = AudioBufferProvider::kInvalidPTS; 383b979034b100be14de2223f2b8f6cc7a3275cbe4fDouglas Gregor } 384b979034b100be14de2223f2b8f6cc7a3275cbe4fDouglas Gregor 38583889a7f1f338e343ef72aeeef9c27f7b62c0f0fDavid Chisnall // process() is CPU-bound 38683889a7f1f338e343ef72aeeef9c27f7b62c0f0fDavid Chisnall mixer->process(pts); 38783889a7f1f338e343ef72aeeef9c27f7b62c0f0fDavid Chisnall mMixerBufferState = MIXED; 38883889a7f1f338e343ef72aeeef9c27f7b62c0f0fDavid Chisnall } else if (mMixerBufferState == MIXED) { 38983889a7f1f338e343ef72aeeef9c27f7b62c0f0fDavid Chisnall mMixerBufferState = UNDEFINED; 39083889a7f1f338e343ef72aeeef9c27f7b62c0f0fDavid Chisnall } 39183889a7f1f338e343ef72aeeef9c27f7b62c0f0fDavid Chisnall //bool didFullWrite = false; // dumpsys could display a count of partial writes 3921efcf3d137c11fb6b21c385911e0d2ca59ca94c3Daniel Dunbar if ((command & FastMixerState::WRITE) && (outputSink != NULL) && (mMixerBuffer != NULL)) { 393b979034b100be14de2223f2b8f6cc7a3275cbe4fDouglas Gregor if (mMixerBufferState == UNDEFINED) { 3945352ac06d8f6194825bb2a99ffa009b61bafb503Douglas Gregor memset(mMixerBuffer, 0, mMixerBufferSize); 3955352ac06d8f6194825bb2a99ffa009b61bafb503Douglas Gregor mMixerBufferState = ZEROED; 396f9c21665faa7e4936d484396469ee7afc46e1f00NAKAMURA Takumi } 397896b70ffc348f6e2c680b5fb5841984d5785b7b5Ted Kremenek void *buffer = mSinkBuffer != NULL ? mSinkBuffer : mMixerBuffer; 3985352ac06d8f6194825bb2a99ffa009b61bafb503Douglas Gregor if (format.mFormat != mMixerBufferFormat) { // sink format not the same as mixer format 399b979034b100be14de2223f2b8f6cc7a3275cbe4fDouglas Gregor memcpy_by_audio_format(buffer, format.mFormat, mMixerBuffer, mMixerBufferFormat, 400b979034b100be14de2223f2b8f6cc7a3275cbe4fDouglas Gregor frameCount * Format_channelCount(format)); 401b979034b100be14de2223f2b8f6cc7a3275cbe4fDouglas Gregor } 402b979034b100be14de2223f2b8f6cc7a3275cbe4fDouglas Gregor // if non-NULL, then duplicate write() to this non-blocking sink 403b979034b100be14de2223f2b8f6cc7a3275cbe4fDouglas Gregor NBAIO_Sink* teeSink; 4041efcf3d137c11fb6b21c385911e0d2ca59ca94c3Daniel Dunbar if ((teeSink = current->mTeeSink) != NULL) { 405b979034b100be14de2223f2b8f6cc7a3275cbe4fDouglas Gregor (void) teeSink->write(mMixerBuffer, frameCount); 406ab4e83b904d81d8ab1f8c594655822a023cad87dDouglas Gregor } 407ab4e83b904d81d8ab1f8c594655822a023cad87dDouglas Gregor // FIXME write() is non-blocking and lock-free for a properly implemented NBAIO sink, 408ab4e83b904d81d8ab1f8c594655822a023cad87dDouglas Gregor // but this code should be modified to handle both non-blocking and blocking sinks 409ab4e83b904d81d8ab1f8c594655822a023cad87dDouglas Gregor dumpState->mWriteSequence++; 410ab4e83b904d81d8ab1f8c594655822a023cad87dDouglas Gregor ATRACE_BEGIN("write"); 411ab4e83b904d81d8ab1f8c594655822a023cad87dDouglas Gregor ssize_t framesWritten = outputSink->write(buffer, frameCount); 412ab4e83b904d81d8ab1f8c594655822a023cad87dDouglas Gregor ATRACE_END(); 413ab4e83b904d81d8ab1f8c594655822a023cad87dDouglas Gregor dumpState->mWriteSequence++; 4141824d54df85a462ada812dadda18130f951d40f3Dmitri Gribenko if (framesWritten >= 0) { 415de5db649fd5f9aedde200f443ad73d62517b1c88Argyrios Kyrtzidis ALOG_ASSERT((size_t) framesWritten <= frameCount); 416733dbc805facad7cebec5420f6c47c83848cee5fErik Verbruggen totalNativeFramesWritten += framesWritten; 417de5db649fd5f9aedde200f443ad73d62517b1c88Argyrios Kyrtzidis dumpState->mFramesWritten = totalNativeFramesWritten; 418de5db649fd5f9aedde200f443ad73d62517b1c88Argyrios Kyrtzidis //if ((size_t) framesWritten == frameCount) { 41946766dc31c09d89024de5aba9e22112a56eadbdfDouglas Gregor // didFullWrite = true; 42046766dc31c09d89024de5aba9e22112a56eadbdfDouglas Gregor //} 4211db19dea8d221f27be46332d668d1e2decb7f1abDouglas Gregor } else { 42220174221af145554b76a0b0f5e4eb3ac70d05945Chandler Carruth dumpState->mWriteErrors++; 42320174221af145554b76a0b0f5e4eb3ac70d05945Chandler Carruth } 424a9b06d4c246d6c301e3dd1844f5dba669ed9c631Douglas Gregor attemptedWrite = true; 4251efcf3d137c11fb6b21c385911e0d2ca59ca94c3Daniel Dunbar // FIXME count # of writes blocked excessively, CPU usage, etc. for dump 4261efcf3d137c11fb6b21c385911e0d2ca59ca94c3Daniel Dunbar 4271db19dea8d221f27be46332d668d1e2decb7f1abDouglas Gregor timestampStatus = outputSink->getTimestamp(timestamp); 4281efcf3d137c11fb6b21c385911e0d2ca59ca94c3Daniel Dunbar if (timestampStatus == NO_ERROR) { 4291db19dea8d221f27be46332d668d1e2decb7f1abDouglas Gregor uint32_t totalNativeFramesPresented = timestamp.mPosition; 4301db19dea8d221f27be46332d668d1e2decb7f1abDouglas Gregor if (totalNativeFramesPresented <= totalNativeFramesWritten) { 4311efcf3d137c11fb6b21c385911e0d2ca59ca94c3Daniel Dunbar nativeFramesWrittenButNotPresented = 4321db19dea8d221f27be46332d668d1e2decb7f1abDouglas Gregor totalNativeFramesWritten - totalNativeFramesPresented; 4331db19dea8d221f27be46332d668d1e2decb7f1abDouglas Gregor } else { 4341efcf3d137c11fb6b21c385911e0d2ca59ca94c3Daniel Dunbar // HAL reported that more frames were presented than were written 4351efcf3d137c11fb6b21c385911e0d2ca59ca94c3Daniel Dunbar timestampStatus = INVALID_OPERATION; 43646766dc31c09d89024de5aba9e22112a56eadbdfDouglas Gregor } 43746766dc31c09d89024de5aba9e22112a56eadbdfDouglas Gregor } 43846766dc31c09d89024de5aba9e22112a56eadbdfDouglas Gregor } 4391db19dea8d221f27be46332d668d1e2decb7f1abDouglas Gregor} 44020174221af145554b76a0b0f5e4eb3ac70d05945Chandler Carruth 44120174221af145554b76a0b0f5e4eb3ac70d05945Chandler CarruthFastMixerDumpState::FastMixerDumpState( 44220174221af145554b76a0b0f5e4eb3ac70d05945Chandler Carruth#ifdef FAST_MIXER_STATISTICS 44320174221af145554b76a0b0f5e4eb3ac70d05945Chandler Carruth uint32_t samplingN 44420174221af145554b76a0b0f5e4eb3ac70d05945Chandler Carruth#endif 44520174221af145554b76a0b0f5e4eb3ac70d05945Chandler Carruth ) : FastThreadDumpState(), 44620174221af145554b76a0b0f5e4eb3ac70d05945Chandler Carruth mWriteSequence(0), mFramesWritten(0), 447e6be34d8f77312edf9ed38034e52cb4d22c8e1c1Argyrios Kyrtzidis mNumTracks(0), mWriteErrors(0), 448e6be34d8f77312edf9ed38034e52cb4d22c8e1c1Argyrios Kyrtzidis mSampleRate(0), mFrameCount(0), 449e6be34d8f77312edf9ed38034e52cb4d22c8e1c1Argyrios Kyrtzidis mTrackMask(0) 450e6be34d8f77312edf9ed38034e52cb4d22c8e1c1Argyrios Kyrtzidis{ 451e6be34d8f77312edf9ed38034e52cb4d22c8e1c1Argyrios Kyrtzidis#ifdef FAST_MIXER_STATISTICS 4527eee0184570366285589d788bcd7f5dda8345915James Dennett increaseSamplingN(samplingN); 453e6be34d8f77312edf9ed38034e52cb4d22c8e1c1Argyrios Kyrtzidis#endif 454e6be34d8f77312edf9ed38034e52cb4d22c8e1c1Argyrios Kyrtzidis} 455e6be34d8f77312edf9ed38034e52cb4d22c8e1c1Argyrios Kyrtzidis 456e6be34d8f77312edf9ed38034e52cb4d22c8e1c1Argyrios Kyrtzidis#ifdef FAST_MIXER_STATISTICS 457e6be34d8f77312edf9ed38034e52cb4d22c8e1c1Argyrios Kyrtzidisvoid FastMixerDumpState::increaseSamplingN(uint32_t samplingN) 458e6be34d8f77312edf9ed38034e52cb4d22c8e1c1Argyrios Kyrtzidis{ 4597eee0184570366285589d788bcd7f5dda8345915James Dennett if (samplingN <= mSamplingN || samplingN > kSamplingN || roundup(samplingN) != samplingN) { 460e6be34d8f77312edf9ed38034e52cb4d22c8e1c1Argyrios Kyrtzidis return; 461e6be34d8f77312edf9ed38034e52cb4d22c8e1c1Argyrios Kyrtzidis } 462e6be34d8f77312edf9ed38034e52cb4d22c8e1c1Argyrios Kyrtzidis uint32_t additional = samplingN - mSamplingN; 463e6be34d8f77312edf9ed38034e52cb4d22c8e1c1Argyrios Kyrtzidis // sample arrays aren't accessed atomically with respect to the bounds, 464e6be34d8f77312edf9ed38034e52cb4d22c8e1c1Argyrios Kyrtzidis // so clearing reduces chance for dumpsys to read random uninitialized samples 465e6be34d8f77312edf9ed38034e52cb4d22c8e1c1Argyrios Kyrtzidis memset(&mMonotonicNs[mSamplingN], 0, sizeof(mMonotonicNs[0]) * additional); 466e6be34d8f77312edf9ed38034e52cb4d22c8e1c1Argyrios Kyrtzidis memset(&mLoadNs[mSamplingN], 0, sizeof(mLoadNs[0]) * additional); 467e6be34d8f77312edf9ed38034e52cb4d22c8e1c1Argyrios Kyrtzidis#ifdef CPU_FREQUENCY_STATISTICS 468e6be34d8f77312edf9ed38034e52cb4d22c8e1c1Argyrios Kyrtzidis memset(&mCpukHz[mSamplingN], 0, sizeof(mCpukHz[0]) * additional); 469e6be34d8f77312edf9ed38034e52cb4d22c8e1c1Argyrios Kyrtzidis#endif 470e6be34d8f77312edf9ed38034e52cb4d22c8e1c1Argyrios Kyrtzidis mSamplingN = samplingN; 471e6be34d8f77312edf9ed38034e52cb4d22c8e1c1Argyrios Kyrtzidis} 472e6be34d8f77312edf9ed38034e52cb4d22c8e1c1Argyrios Kyrtzidis#endif 473e6be34d8f77312edf9ed38034e52cb4d22c8e1c1Argyrios Kyrtzidis 474e6be34d8f77312edf9ed38034e52cb4d22c8e1c1Argyrios KyrtzidisFastMixerDumpState::~FastMixerDumpState() 475e6be34d8f77312edf9ed38034e52cb4d22c8e1c1Argyrios Kyrtzidis{ 476e6be34d8f77312edf9ed38034e52cb4d22c8e1c1Argyrios Kyrtzidis} 477e6be34d8f77312edf9ed38034e52cb4d22c8e1c1Argyrios Kyrtzidis 478e6be34d8f77312edf9ed38034e52cb4d22c8e1c1Argyrios Kyrtzidis// helper function called by qsort() 479e6be34d8f77312edf9ed38034e52cb4d22c8e1c1Argyrios Kyrtzidisstatic int compare_uint32_t(const void *pa, const void *pb) 480e6be34d8f77312edf9ed38034e52cb4d22c8e1c1Argyrios Kyrtzidis{ 481e6be34d8f77312edf9ed38034e52cb4d22c8e1c1Argyrios Kyrtzidis uint32_t a = *(const uint32_t *)pa; 482e6be34d8f77312edf9ed38034e52cb4d22c8e1c1Argyrios Kyrtzidis uint32_t b = *(const uint32_t *)pb; 483e6be34d8f77312edf9ed38034e52cb4d22c8e1c1Argyrios Kyrtzidis if (a < b) { 484e6be34d8f77312edf9ed38034e52cb4d22c8e1c1Argyrios Kyrtzidis return -1; 485e6be34d8f77312edf9ed38034e52cb4d22c8e1c1Argyrios Kyrtzidis } else if (a > b) { 486e6be34d8f77312edf9ed38034e52cb4d22c8e1c1Argyrios Kyrtzidis return 1; 487e6be34d8f77312edf9ed38034e52cb4d22c8e1c1Argyrios Kyrtzidis } else { 488e6be34d8f77312edf9ed38034e52cb4d22c8e1c1Argyrios Kyrtzidis return 0; 489e6be34d8f77312edf9ed38034e52cb4d22c8e1c1Argyrios Kyrtzidis } 490e6be34d8f77312edf9ed38034e52cb4d22c8e1c1Argyrios Kyrtzidis} 491e6be34d8f77312edf9ed38034e52cb4d22c8e1c1Argyrios Kyrtzidis 49220174221af145554b76a0b0f5e4eb3ac70d05945Chandler Carruthvoid FastMixerDumpState::dump(int fd) const 49320174221af145554b76a0b0f5e4eb3ac70d05945Chandler Carruth{ 49420174221af145554b76a0b0f5e4eb3ac70d05945Chandler Carruth if (mCommand == FastMixerState::INITIAL) { 49520174221af145554b76a0b0f5e4eb3ac70d05945Chandler Carruth fdprintf(fd, " FastMixer not initialized\n"); 4967eee0184570366285589d788bcd7f5dda8345915James Dennett return; 49720174221af145554b76a0b0f5e4eb3ac70d05945Chandler Carruth } 49820174221af145554b76a0b0f5e4eb3ac70d05945Chandler Carruth#define COMMAND_MAX 32 4991db19dea8d221f27be46332d668d1e2decb7f1abDouglas Gregor char string[COMMAND_MAX]; 5001db19dea8d221f27be46332d668d1e2decb7f1abDouglas Gregor switch (mCommand) { 5011db19dea8d221f27be46332d668d1e2decb7f1abDouglas Gregor case FastMixerState::INITIAL: 50246766dc31c09d89024de5aba9e22112a56eadbdfDouglas Gregor strcpy(string, "INITIAL"); 50346766dc31c09d89024de5aba9e22112a56eadbdfDouglas Gregor break; 504e69517ce61638f12c9abe4605753a45275ac4e37Douglas Gregor case FastMixerState::HOT_IDLE: 505e69517ce61638f12c9abe4605753a45275ac4e37Douglas Gregor strcpy(string, "HOT_IDLE"); 506a9b06d4c246d6c301e3dd1844f5dba669ed9c631Douglas Gregor break; 507a9b06d4c246d6c301e3dd1844f5dba669ed9c631Douglas Gregor case FastMixerState::COLD_IDLE: 508a9b06d4c246d6c301e3dd1844f5dba669ed9c631Douglas Gregor strcpy(string, "COLD_IDLE"); 509a9b06d4c246d6c301e3dd1844f5dba669ed9c631Douglas Gregor break; 510a9b06d4c246d6c301e3dd1844f5dba669ed9c631Douglas Gregor case FastMixerState::EXIT: 511a9b06d4c246d6c301e3dd1844f5dba669ed9c631Douglas Gregor strcpy(string, "EXIT"); 512a9b06d4c246d6c301e3dd1844f5dba669ed9c631Douglas Gregor break; 513a9b06d4c246d6c301e3dd1844f5dba669ed9c631Douglas Gregor case FastMixerState::MIX: 514a9b06d4c246d6c301e3dd1844f5dba669ed9c631Douglas Gregor strcpy(string, "MIX"); 515a9b06d4c246d6c301e3dd1844f5dba669ed9c631Douglas Gregor break; 516a9b06d4c246d6c301e3dd1844f5dba669ed9c631Douglas Gregor case FastMixerState::WRITE: 517a9b06d4c246d6c301e3dd1844f5dba669ed9c631Douglas Gregor strcpy(string, "WRITE"); 518a9b06d4c246d6c301e3dd1844f5dba669ed9c631Douglas Gregor break; 519a9b06d4c246d6c301e3dd1844f5dba669ed9c631Douglas Gregor case FastMixerState::MIX_WRITE: 520a9b06d4c246d6c301e3dd1844f5dba669ed9c631Douglas Gregor strcpy(string, "MIX_WRITE"); 521a9b06d4c246d6c301e3dd1844f5dba669ed9c631Douglas Gregor break; 522a9b06d4c246d6c301e3dd1844f5dba669ed9c631Douglas Gregor default: 523a9b06d4c246d6c301e3dd1844f5dba669ed9c631Douglas Gregor snprintf(string, COMMAND_MAX, "%d", mCommand); 524a9b06d4c246d6c301e3dd1844f5dba669ed9c631Douglas Gregor break; 525a9b06d4c246d6c301e3dd1844f5dba669ed9c631Douglas Gregor } 526a9b06d4c246d6c301e3dd1844f5dba669ed9c631Douglas Gregor double measuredWarmupMs = (mMeasuredWarmupTs.tv_sec * 1000.0) + 527a9b06d4c246d6c301e3dd1844f5dba669ed9c631Douglas Gregor (mMeasuredWarmupTs.tv_nsec / 1000000.0); 528a9b06d4c246d6c301e3dd1844f5dba669ed9c631Douglas Gregor double mixPeriodSec = (double) mFrameCount / (double) mSampleRate; 529a9b06d4c246d6c301e3dd1844f5dba669ed9c631Douglas Gregor fdprintf(fd, " FastMixer command=%s writeSequence=%u framesWritten=%u\n" 530a9b06d4c246d6c301e3dd1844f5dba669ed9c631Douglas Gregor " numTracks=%u writeErrors=%u underruns=%u overruns=%u\n" 531a9b06d4c246d6c301e3dd1844f5dba669ed9c631Douglas Gregor " sampleRate=%u frameCount=%zu measuredWarmup=%.3g ms, warmupCycles=%u\n" 5322d5c133d3dd95507db63147997109f06e8cfa833Argyrios Kyrtzidis " mixPeriod=%.2f ms\n", 5332d5c133d3dd95507db63147997109f06e8cfa833Argyrios Kyrtzidis string, mWriteSequence, mFramesWritten, 5342d5c133d3dd95507db63147997109f06e8cfa833Argyrios Kyrtzidis mNumTracks, mWriteErrors, mUnderruns, mOverruns, 5352d5c133d3dd95507db63147997109f06e8cfa833Argyrios Kyrtzidis mSampleRate, mFrameCount, measuredWarmupMs, mWarmupCycles, 5362d5c133d3dd95507db63147997109f06e8cfa833Argyrios Kyrtzidis mixPeriodSec * 1e3); 5372d5c133d3dd95507db63147997109f06e8cfa833Argyrios Kyrtzidis#ifdef FAST_MIXER_STATISTICS 5382d5c133d3dd95507db63147997109f06e8cfa833Argyrios Kyrtzidis // find the interval of valid samples 5392d5c133d3dd95507db63147997109f06e8cfa833Argyrios Kyrtzidis uint32_t bounds = mBounds; 5402d5c133d3dd95507db63147997109f06e8cfa833Argyrios Kyrtzidis uint32_t newestOpen = bounds & 0xFFFF; 5412d5c133d3dd95507db63147997109f06e8cfa833Argyrios Kyrtzidis uint32_t oldestClosed = bounds >> 16; 5422d5c133d3dd95507db63147997109f06e8cfa833Argyrios Kyrtzidis uint32_t n = (newestOpen - oldestClosed) & 0xFFFF; 5432d5c133d3dd95507db63147997109f06e8cfa833Argyrios Kyrtzidis if (n > mSamplingN) { 5442d5c133d3dd95507db63147997109f06e8cfa833Argyrios Kyrtzidis ALOGE("too many samples %u", n); 5452d5c133d3dd95507db63147997109f06e8cfa833Argyrios Kyrtzidis n = mSamplingN; 5462d5c133d3dd95507db63147997109f06e8cfa833Argyrios Kyrtzidis } 5472d5c133d3dd95507db63147997109f06e8cfa833Argyrios Kyrtzidis // statistics for monotonic (wall clock) time, thread raw CPU load in time, CPU clock frequency, 5482d5c133d3dd95507db63147997109f06e8cfa833Argyrios Kyrtzidis // and adjusted CPU load in MHz normalized for CPU clock frequency 5492d5c133d3dd95507db63147997109f06e8cfa833Argyrios Kyrtzidis CentralTendencyStatistics wall, loadNs; 5502d5c133d3dd95507db63147997109f06e8cfa833Argyrios Kyrtzidis#ifdef CPU_FREQUENCY_STATISTICS 5512d5c133d3dd95507db63147997109f06e8cfa833Argyrios Kyrtzidis CentralTendencyStatistics kHz, loadMHz; 5522d5c133d3dd95507db63147997109f06e8cfa833Argyrios Kyrtzidis uint32_t previousCpukHz = 0; 5532d5c133d3dd95507db63147997109f06e8cfa833Argyrios Kyrtzidis#endif 5542d5c133d3dd95507db63147997109f06e8cfa833Argyrios Kyrtzidis // Assuming a normal distribution for cycle times, three standard deviations on either side of 5552d5c133d3dd95507db63147997109f06e8cfa833Argyrios Kyrtzidis // the mean account for 99.73% of the population. So if we take each tail to be 1/1000 of the 5562d5c133d3dd95507db63147997109f06e8cfa833Argyrios Kyrtzidis // sample set, we get 99.8% combined, or close to three standard deviations. 5572d5c133d3dd95507db63147997109f06e8cfa833Argyrios Kyrtzidis static const uint32_t kTailDenominator = 1000; 5582d5c133d3dd95507db63147997109f06e8cfa833Argyrios Kyrtzidis uint32_t *tail = n >= kTailDenominator ? new uint32_t[n] : NULL; 5592d5c133d3dd95507db63147997109f06e8cfa833Argyrios Kyrtzidis // loop over all the samples 5602d5c133d3dd95507db63147997109f06e8cfa833Argyrios Kyrtzidis for (uint32_t j = 0; j < n; ++j) { 561a9b06d4c246d6c301e3dd1844f5dba669ed9c631Douglas Gregor size_t i = oldestClosed++ & (mSamplingN - 1); 562a9b06d4c246d6c301e3dd1844f5dba669ed9c631Douglas Gregor uint32_t wallNs = mMonotonicNs[i]; 5631efcf3d137c11fb6b21c385911e0d2ca59ca94c3Daniel Dunbar if (tail != NULL) { 5641efcf3d137c11fb6b21c385911e0d2ca59ca94c3Daniel Dunbar tail[j] = wallNs; 5651db19dea8d221f27be46332d668d1e2decb7f1abDouglas Gregor } 5661db19dea8d221f27be46332d668d1e2decb7f1abDouglas Gregor wall.sample(wallNs); 5671db19dea8d221f27be46332d668d1e2decb7f1abDouglas Gregor uint32_t sampleLoadNs = mLoadNs[i]; 5681db19dea8d221f27be46332d668d1e2decb7f1abDouglas Gregor loadNs.sample(sampleLoadNs); 5691efcf3d137c11fb6b21c385911e0d2ca59ca94c3Daniel Dunbar#ifdef CPU_FREQUENCY_STATISTICS 5701efcf3d137c11fb6b21c385911e0d2ca59ca94c3Daniel Dunbar uint32_t sampleCpukHz = mCpukHz[i]; 5711db19dea8d221f27be46332d668d1e2decb7f1abDouglas Gregor // skip bad kHz samples 5721db19dea8d221f27be46332d668d1e2decb7f1abDouglas Gregor if ((sampleCpukHz & ~0xF) != 0) { 5731db19dea8d221f27be46332d668d1e2decb7f1abDouglas Gregor kHz.sample(sampleCpukHz >> 4); 574f55254472e496340cbb4f0a24cff398e441475b5Douglas Gregor if (sampleCpukHz == previousCpukHz) { 575f55254472e496340cbb4f0a24cff398e441475b5Douglas Gregor double megacycles = (double) sampleLoadNs * (double) (sampleCpukHz >> 4) * 1e-12; 576f55254472e496340cbb4f0a24cff398e441475b5Douglas Gregor double adjMHz = megacycles / mixPeriodSec; // _not_ wallNs * 1e9 577c42fefa51f7555bb3644a7cde2ca4bfd0d848d74Douglas Gregor loadMHz.sample(adjMHz); 578c42fefa51f7555bb3644a7cde2ca4bfd0d848d74Douglas Gregor } 5795352ac06d8f6194825bb2a99ffa009b61bafb503Douglas Gregor } 5805352ac06d8f6194825bb2a99ffa009b61bafb503Douglas Gregor previousCpukHz = sampleCpukHz; 5815352ac06d8f6194825bb2a99ffa009b61bafb503Douglas Gregor#endif 5825352ac06d8f6194825bb2a99ffa009b61bafb503Douglas Gregor } 5835352ac06d8f6194825bb2a99ffa009b61bafb503Douglas Gregor if (n) { 5845352ac06d8f6194825bb2a99ffa009b61bafb503Douglas Gregor fdprintf(fd, " Simple moving statistics over last %.1f seconds:\n", 5855352ac06d8f6194825bb2a99ffa009b61bafb503Douglas Gregor wall.n() * mixPeriodSec); 5865352ac06d8f6194825bb2a99ffa009b61bafb503Douglas Gregor fdprintf(fd, " wall clock time in ms per mix cycle:\n" 5875352ac06d8f6194825bb2a99ffa009b61bafb503Douglas Gregor " mean=%.2f min=%.2f max=%.2f stddev=%.2f\n", 5885352ac06d8f6194825bb2a99ffa009b61bafb503Douglas Gregor wall.mean()*1e-6, wall.minimum()*1e-6, wall.maximum()*1e-6, 589896b70ffc348f6e2c680b5fb5841984d5785b7b5Ted Kremenek wall.stddev()*1e-6); 5905352ac06d8f6194825bb2a99ffa009b61bafb503Douglas Gregor fdprintf(fd, " raw CPU load in us per mix cycle:\n" 5915352ac06d8f6194825bb2a99ffa009b61bafb503Douglas Gregor " mean=%.0f min=%.0f max=%.0f stddev=%.0f\n", 5925352ac06d8f6194825bb2a99ffa009b61bafb503Douglas Gregor loadNs.mean()*1e-3, loadNs.minimum()*1e-3, loadNs.maximum()*1e-3, 593896b70ffc348f6e2c680b5fb5841984d5785b7b5Ted Kremenek loadNs.stddev()*1e-3); 5945352ac06d8f6194825bb2a99ffa009b61bafb503Douglas Gregor } else { 5955352ac06d8f6194825bb2a99ffa009b61bafb503Douglas Gregor fdprintf(fd, " No FastMixer statistics available currently\n"); 5965352ac06d8f6194825bb2a99ffa009b61bafb503Douglas Gregor } 5975352ac06d8f6194825bb2a99ffa009b61bafb503Douglas Gregor#ifdef CPU_FREQUENCY_STATISTICS 5985352ac06d8f6194825bb2a99ffa009b61bafb503Douglas Gregor fdprintf(fd, " CPU clock frequency in MHz:\n" 5995352ac06d8f6194825bb2a99ffa009b61bafb503Douglas Gregor " mean=%.0f min=%.0f max=%.0f stddev=%.0f\n", 6005352ac06d8f6194825bb2a99ffa009b61bafb503Douglas Gregor kHz.mean()*1e-3, kHz.minimum()*1e-3, kHz.maximum()*1e-3, kHz.stddev()*1e-3); 6015352ac06d8f6194825bb2a99ffa009b61bafb503Douglas Gregor fdprintf(fd, " adjusted CPU load in MHz (i.e. normalized for CPU clock frequency):\n" 6025352ac06d8f6194825bb2a99ffa009b61bafb503Douglas Gregor " mean=%.1f min=%.1f max=%.1f stddev=%.1f\n", 6035352ac06d8f6194825bb2a99ffa009b61bafb503Douglas Gregor loadMHz.mean(), loadMHz.minimum(), loadMHz.maximum(), loadMHz.stddev()); 6045352ac06d8f6194825bb2a99ffa009b61bafb503Douglas Gregor#endif 6055352ac06d8f6194825bb2a99ffa009b61bafb503Douglas Gregor if (tail != NULL) { 6065352ac06d8f6194825bb2a99ffa009b61bafb503Douglas Gregor qsort(tail, n, sizeof(uint32_t), compare_uint32_t); 6075352ac06d8f6194825bb2a99ffa009b61bafb503Douglas Gregor // assume same number of tail samples on each side, left and right 6085352ac06d8f6194825bb2a99ffa009b61bafb503Douglas Gregor uint32_t count = n / kTailDenominator; 6095352ac06d8f6194825bb2a99ffa009b61bafb503Douglas Gregor CentralTendencyStatistics left, right; 6105352ac06d8f6194825bb2a99ffa009b61bafb503Douglas Gregor for (uint32_t i = 0; i < count; ++i) { 6115352ac06d8f6194825bb2a99ffa009b61bafb503Douglas Gregor left.sample(tail[i]); 6125352ac06d8f6194825bb2a99ffa009b61bafb503Douglas Gregor right.sample(tail[n - (i + 1)]); 6135352ac06d8f6194825bb2a99ffa009b61bafb503Douglas Gregor } 6145352ac06d8f6194825bb2a99ffa009b61bafb503Douglas Gregor fdprintf(fd, " Distribution of mix cycle times in ms for the tails (> ~3 stddev outliers):\n" 6155352ac06d8f6194825bb2a99ffa009b61bafb503Douglas Gregor " left tail: mean=%.2f min=%.2f max=%.2f stddev=%.2f\n" 6165352ac06d8f6194825bb2a99ffa009b61bafb503Douglas Gregor " right tail: mean=%.2f min=%.2f max=%.2f stddev=%.2f\n", 6175352ac06d8f6194825bb2a99ffa009b61bafb503Douglas Gregor left.mean()*1e-6, left.minimum()*1e-6, left.maximum()*1e-6, left.stddev()*1e-6, 6185352ac06d8f6194825bb2a99ffa009b61bafb503Douglas Gregor right.mean()*1e-6, right.minimum()*1e-6, right.maximum()*1e-6, 6195352ac06d8f6194825bb2a99ffa009b61bafb503Douglas Gregor right.stddev()*1e-6); 6205352ac06d8f6194825bb2a99ffa009b61bafb503Douglas Gregor delete[] tail; 6215352ac06d8f6194825bb2a99ffa009b61bafb503Douglas Gregor } 6225352ac06d8f6194825bb2a99ffa009b61bafb503Douglas Gregor#endif 6235352ac06d8f6194825bb2a99ffa009b61bafb503Douglas Gregor // The active track mask and track states are updated non-atomically. 6245352ac06d8f6194825bb2a99ffa009b61bafb503Douglas Gregor // So if we relied on isActive to decide whether to display, 6255352ac06d8f6194825bb2a99ffa009b61bafb503Douglas Gregor // then we might display an obsolete track or omit an active track. 626153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek // Instead we always display all tracks, with an indication 627153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek // of whether we think the track is active. 628153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek uint32_t trackMask = mTrackMask; 629153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek fdprintf(fd, " Fast tracks: kMaxFastTracks=%u activeMask=%#x\n", 630153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek FastMixerState::kMaxFastTracks, trackMask); 631153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek fdprintf(fd, " Index Active Full Partial Empty Recent Ready\n"); 632153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek for (uint32_t i = 0; i < FastMixerState::kMaxFastTracks; ++i, trackMask >>= 1) { 633153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek bool isActive = trackMask & 1; 634153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek const FastTrackDump *ftDump = &mTracks[i]; 635153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek const FastTrackUnderruns& underruns = ftDump->mUnderruns; 636153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek const char *mostRecent; 637153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek switch (underruns.mBitFields.mMostRecent) { 6387eee0184570366285589d788bcd7f5dda8345915James Dennett case UNDERRUN_FULL: 639153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek mostRecent = "full"; 640153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek break; 641153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek case UNDERRUN_PARTIAL: 642153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek mostRecent = "partial"; 643153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek break; 644153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek case UNDERRUN_EMPTY: 645153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek mostRecent = "empty"; 646153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek break; 647153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek default: 648153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek mostRecent = "?"; 649153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek break; 650153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek } 651153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek fdprintf(fd, " %5u %6s %4u %7u %5u %7s %5zu\n", i, isActive ? "yes" : "no", 652153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek (underruns.mBitFields.mFull) & UNDERRUN_MASK, 653153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek (underruns.mBitFields.mPartial) & UNDERRUN_MASK, 654153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek (underruns.mBitFields.mEmpty) & UNDERRUN_MASK, 655153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek mostRecent, ftDump->mFramesReady); 656153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek } 657153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek} 658153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek 659153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek} // namespace android 660153221717e39ce41323d5bc6b8b8bf130923c1bdTed Kremenek