diff options
Diffstat (limited to 'media/libmedia/AudioTrack.cpp')
| -rw-r--r-- | media/libmedia/AudioTrack.cpp | 348 |
1 files changed, 217 insertions, 131 deletions
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index b2c067b1290f..8529a8e46fa1 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -32,9 +32,9 @@ #include <media/AudioTrack.h> #include <utils/Log.h> -#include <utils/MemoryDealer.h> -#include <utils/Parcel.h> -#include <utils/IPCThreadState.h> +#include <binder/MemoryDealer.h> +#include <binder/Parcel.h> +#include <binder/IPCThreadState.h> #include <utils/Timers.h> #include <cutils/atomic.h> @@ -54,7 +54,7 @@ AudioTrack::AudioTrack( int streamType, uint32_t sampleRate, int format, - int channelCount, + int channels, int frameCount, uint32_t flags, callback_t cbf, @@ -62,7 +62,7 @@ AudioTrack::AudioTrack( int notificationFrames) : mStatus(NO_INIT) { - mStatus = set(streamType, sampleRate, format, channelCount, + mStatus = set(streamType, sampleRate, format, channels, frameCount, flags, cbf, user, notificationFrames, 0); } @@ -70,7 +70,7 @@ AudioTrack::AudioTrack( int streamType, uint32_t sampleRate, int format, - int channelCount, + int channels, const sp<IMemory>& sharedBuffer, uint32_t flags, callback_t cbf, @@ -78,7 +78,7 @@ AudioTrack::AudioTrack( int notificationFrames) : mStatus(NO_INIT) { - mStatus = set(streamType, sampleRate, format, channelCount, + mStatus = set(streamType, sampleRate, format, channels, 0, flags, cbf, user, notificationFrames, sharedBuffer); } @@ -97,6 +97,7 @@ AudioTrack::~AudioTrack() } mAudioTrack.clear(); IPCThreadState::self()->flushCommands(); + AudioSystem::releaseOutput(getOutput()); } } @@ -104,7 +105,7 @@ status_t AudioTrack::set( int streamType, uint32_t sampleRate, int format, - int channelCount, + int channels, int frameCount, uint32_t flags, callback_t cbf, @@ -121,11 +122,6 @@ status_t AudioTrack::set( return INVALID_OPERATION; } - const sp<IAudioFlinger>& audioFlinger = AudioSystem::get_audio_flinger(); - if (audioFlinger == 0) { - LOGE("Could not get audioflinger"); - return NO_INIT; - } int afSampleRate; if (AudioSystem::getOutputSamplingRate(&afSampleRate, streamType) != NO_ERROR) { return NO_INIT; @@ -150,73 +146,82 @@ status_t AudioTrack::set( if (format == 0) { format = AudioSystem::PCM_16_BIT; } - if (channelCount == 0) { - channelCount = 2; + if (channels == 0) { + channels = AudioSystem::CHANNEL_OUT_STEREO; } // validate parameters - if (((format != AudioSystem::PCM_8_BIT) || sharedBuffer != 0) && - (format != AudioSystem::PCM_16_BIT)) { + if (!AudioSystem::isValidFormat(format)) { LOGE("Invalid format"); return BAD_VALUE; } - if (channelCount != 1 && channelCount != 2) { - LOGE("Invalid channel number"); + + // force direct flag if format is not linear PCM + if (!AudioSystem::isLinearPCM(format)) { + flags |= AudioSystem::OUTPUT_FLAG_DIRECT; + } + + if (!AudioSystem::isOutputChannel(channels)) { + LOGE("Invalid channel mask"); return BAD_VALUE; } + uint32_t channelCount = AudioSystem::popCount(channels); - // Ensure that buffer depth covers at least audio hardware latency - uint32_t minBufCount = afLatency / ((1000 * afFrameCount)/afSampleRate); - if (minBufCount < 2) minBufCount = 2; + audio_io_handle_t output = AudioSystem::getOutput((AudioSystem::stream_type)streamType, + sampleRate, format, channels, (AudioSystem::output_flags)flags); - // When playing from shared buffer, playback will start even if last audioflinger - // block is partly filled. - if (sharedBuffer != 0 && minBufCount > 1) { - minBufCount--; + if (output == 0) { + LOGE("Could not get audio output for stream type %d", streamType); + return BAD_VALUE; } - int minFrameCount = (afFrameCount*sampleRate*minBufCount)/afSampleRate; - - if (sharedBuffer == 0) { - if (frameCount == 0) { - frameCount = minFrameCount; - } - if (notificationFrames == 0) { - notificationFrames = frameCount/2; - } - // Make sure that application is notified with sufficient margin - // before underrun - if (notificationFrames > frameCount/2) { - notificationFrames = frameCount/2; + if (!AudioSystem::isLinearPCM(format)) { + if (sharedBuffer != 0) { + frameCount = sharedBuffer->size(); } } else { - // Ensure that buffer alignment matches channelcount - if (((uint32_t)sharedBuffer->pointer() & (channelCount | 1)) != 0) { - LOGE("Invalid buffer alignement: address %p, channelCount %d", sharedBuffer->pointer(), channelCount); - return BAD_VALUE; - } - frameCount = sharedBuffer->size()/channelCount/sizeof(int16_t); - } + // Ensure that buffer depth covers at least audio hardware latency + uint32_t minBufCount = afLatency / ((1000 * afFrameCount)/afSampleRate); + if (minBufCount < 2) minBufCount = 2; - if (frameCount < minFrameCount) { - LOGE("Invalid buffer size: minFrameCount %d, frameCount %d", minFrameCount, frameCount); - return BAD_VALUE; + int minFrameCount = (afFrameCount*sampleRate*minBufCount)/afSampleRate; + + if (sharedBuffer == 0) { + if (frameCount == 0) { + frameCount = minFrameCount; + } + if (notificationFrames == 0) { + notificationFrames = frameCount/2; + } + // Make sure that application is notified with sufficient margin + // before underrun + if (notificationFrames > frameCount/2) { + notificationFrames = frameCount/2; + } + if (frameCount < minFrameCount) { + LOGE("Invalid buffer size: minFrameCount %d, frameCount %d", minFrameCount, frameCount); + return BAD_VALUE; + } + } else { + // Ensure that buffer alignment matches channelcount + if (((uint32_t)sharedBuffer->pointer() & (channelCount | 1)) != 0) { + LOGE("Invalid buffer alignement: address %p, channelCount %d", sharedBuffer->pointer(), channelCount); + return BAD_VALUE; + } + frameCount = sharedBuffer->size()/channelCount/sizeof(int16_t); + } } - // create the track - status_t status; - sp<IAudioTrack> track = audioFlinger->createTrack(getpid(), - streamType, sampleRate, format, channelCount, frameCount, flags, sharedBuffer, &status); + mVolume[LEFT] = 1.0f; + mVolume[RIGHT] = 1.0f; + // create the IAudioTrack + status_t status = createTrack(streamType, sampleRate, format, channelCount, + frameCount, flags, sharedBuffer, output); - if (track == 0) { - LOGE("AudioFlinger could not create track, status: %d", status); + if (status != NO_ERROR) { return status; } - sp<IMemory> cblk = track->getCblk(); - if (cblk == 0) { - LOGE("Could not get control block"); - return NO_INIT; - } + if (cbf != 0) { mAudioTrackThread = new AudioTrackThread(*this, threadCanCallJava); if (mAudioTrackThread == 0) { @@ -227,24 +232,9 @@ status_t AudioTrack::set( mStatus = NO_ERROR; - mAudioTrack = track; - mCblkMemory = cblk; - mCblk = static_cast<audio_track_cblk_t*>(cblk->pointer()); - mCblk->out = 1; - // Update buffer size in case it has been limited by AudioFlinger during track creation - mFrameCount = mCblk->frameCount; - if (sharedBuffer == 0) { - mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t); - } else { - mCblk->buffers = sharedBuffer->pointer(); - // Force buffer full condition as data is already present in shared memory - mCblk->stepUser(mFrameCount); - } - mCblk->volume[0] = mCblk->volume[1] = 0x1000; - mVolume[LEFT] = 1.0f; - mVolume[RIGHT] = 1.0f; mStreamType = streamType; mFormat = format; + mChannels = channels; mChannelCount = channelCount; mSharedBuffer = sharedBuffer; mMuted = false; @@ -259,6 +249,7 @@ status_t AudioTrack::set( mMarkerReached = false; mNewPosition = 0; mUpdatePeriod = 0; + mFlags = flags; return NO_ERROR; } @@ -297,7 +288,11 @@ uint32_t AudioTrack::frameCount() const int AudioTrack::frameSize() const { - return channelCount()*((format() == AudioSystem::PCM_8_BIT) ? sizeof(uint8_t) : sizeof(int16_t)); + if (AudioSystem::isLinearPCM(mFormat)) { + return channelCount()*((format() == AudioSystem::PCM_8_BIT) ? sizeof(uint8_t) : sizeof(int16_t)); + } else { + return sizeof(uint8_t); + } } sp<IMemory>& AudioTrack::sharedBuffer() @@ -323,15 +318,27 @@ void AudioTrack::start() } if (android_atomic_or(1, &mActive) == 0) { - mNewPosition = mCblk->server + mUpdatePeriod; - mCblk->bufferTimeoutMs = MAX_STARTUP_TIMEOUT_MS; - mCblk->waitTimeMs = 0; - if (t != 0) { - t->run("AudioTrackThread", THREAD_PRIORITY_AUDIO_CLIENT); + audio_io_handle_t output = AudioTrack::getOutput(); + status_t status = mAudioTrack->start(); + if (status == DEAD_OBJECT) { + LOGV("start() dead IAudioTrack: creating a new one"); + status = createTrack(mStreamType, mCblk->sampleRate, mFormat, mChannelCount, + mFrameCount, mFlags, mSharedBuffer, output); + } + if (status == NO_ERROR) { + AudioSystem::startOutput(output, (AudioSystem::stream_type)mStreamType); + mNewPosition = mCblk->server + mUpdatePeriod; + mCblk->bufferTimeoutMs = MAX_STARTUP_TIMEOUT_MS; + mCblk->waitTimeMs = 0; + if (t != 0) { + t->run("AudioTrackThread", THREAD_PRIORITY_AUDIO_CLIENT); + } else { + setpriority(PRIO_PROCESS, 0, THREAD_PRIORITY_AUDIO_CLIENT); + } } else { - setpriority(PRIO_PROCESS, 0, THREAD_PRIORITY_AUDIO_CLIENT); + LOGV("start() failed"); + android_atomic_and(~1, &mActive); } - mAudioTrack->start(); } if (t != 0) { @@ -367,6 +374,7 @@ void AudioTrack::stop() } else { setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_NORMAL); } + AudioSystem::stopOutput(getOutput(), (AudioSystem::stream_type)mStreamType); } if (t != 0) { @@ -382,12 +390,12 @@ bool AudioTrack::stopped() const void AudioTrack::flush() { LOGV("flush"); - + // clear playback marker and periodic update counter mMarkerPosition = 0; mMarkerReached = false; mUpdatePeriod = 0; - + if (!mActive) { mAudioTrack->flush(); @@ -403,6 +411,7 @@ void AudioTrack::pause() if (android_atomic_and(~1, &mActive) == 1) { mActive = 0; mAudioTrack->pause(); + AudioSystem::stopOutput(getOutput(), (AudioSystem::stream_type)mStreamType); } } @@ -455,7 +464,6 @@ status_t AudioTrack::setLoop(uint32_t loopStart, uint32_t loopEnd, int loopCount { audio_track_cblk_t* cblk = mCblk; - Mutex::Autolock _l(cblk->lock); if (loopCount == 0) { @@ -476,7 +484,7 @@ status_t AudioTrack::setLoop(uint32_t loopStart, uint32_t loopEnd, int loopCount LOGE("setLoop invalid value: loop markers beyond data: loopStart %d, loopEnd %d, framecount %d", loopStart, loopEnd, mFrameCount); return BAD_VALUE; - } + } cblk->loopStart = loopStart; cblk->loopEnd = loopEnd; @@ -555,7 +563,7 @@ status_t AudioTrack::setPosition(uint32_t position) mCblk->server = position; mCblk->forceReady = 1; - + return NO_ERROR; } @@ -571,7 +579,7 @@ status_t AudioTrack::getPosition(uint32_t *position) status_t AudioTrack::reload() { if (!stopped()) return INVALID_OPERATION; - + flush(); mCblk->stepUser(mFrameCount); @@ -579,12 +587,75 @@ status_t AudioTrack::reload() return NO_ERROR; } +audio_io_handle_t AudioTrack::getOutput() +{ + return AudioSystem::getOutput((AudioSystem::stream_type)mStreamType, + mCblk->sampleRate, mFormat, mChannels, (AudioSystem::output_flags)mFlags); +} + // ------------------------------------------------------------------------- +status_t AudioTrack::createTrack( + int streamType, + uint32_t sampleRate, + int format, + int channelCount, + int frameCount, + uint32_t flags, + const sp<IMemory>& sharedBuffer, + audio_io_handle_t output) +{ + status_t status; + const sp<IAudioFlinger>& audioFlinger = AudioSystem::get_audio_flinger(); + if (audioFlinger == 0) { + LOGE("Could not get audioflinger"); + return NO_INIT; + } + + sp<IAudioTrack> track = audioFlinger->createTrack(getpid(), + streamType, + sampleRate, + format, + channelCount, + frameCount, + ((uint16_t)flags) << 16, + sharedBuffer, + output, + &status); + + if (track == 0) { + LOGE("AudioFlinger could not create track, status: %d", status); + return status; + } + sp<IMemory> cblk = track->getCblk(); + if (cblk == 0) { + LOGE("Could not get control block"); + return NO_INIT; + } + mAudioTrack.clear(); + mAudioTrack = track; + mCblkMemory.clear(); + mCblkMemory = cblk; + mCblk = static_cast<audio_track_cblk_t*>(cblk->pointer()); + mCblk->out = 1; + // Update buffer size in case it has been limited by AudioFlinger during track creation + mFrameCount = mCblk->frameCount; + if (sharedBuffer == 0) { + mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t); + } else { + mCblk->buffers = sharedBuffer->pointer(); + // Force buffer full condition as data is already present in shared memory + mCblk->stepUser(mFrameCount); + } + + mCblk->volumeLR = (int32_t(int16_t(mVolume[LEFT] * 0x1000)) << 16) | int16_t(mVolume[RIGHT] * 0x1000); + + return NO_ERROR; +} + status_t AudioTrack::obtainBuffer(Buffer* audioBuffer, int32_t waitCount) { int active; - int timeout = 0; status_t result; audio_track_cblk_t* cblk = mCblk; uint32_t framesReq = audioBuffer->frameCount; @@ -596,19 +667,22 @@ status_t AudioTrack::obtainBuffer(Buffer* audioBuffer, int32_t waitCount) uint32_t framesAvail = cblk->framesAvailable(); if (framesAvail == 0) { - Mutex::Autolock _l(cblk->lock); + cblk->lock.lock(); goto start_loop_here; while (framesAvail == 0) { active = mActive; if (UNLIKELY(!active)) { LOGV("Not active and NO_MORE_BUFFERS"); + cblk->lock.unlock(); return NO_MORE_BUFFERS; } - if (UNLIKELY(!waitCount)) + if (UNLIKELY(!waitCount)) { + cblk->lock.unlock(); return WOULD_BLOCK; - timeout = 0; + } + result = cblk->cv.waitRelative(cblk->lock, milliseconds(waitTimeMs)); - if (__builtin_expect(result!=NO_ERROR, false)) { + if (__builtin_expect(result!=NO_ERROR, false)) { cblk->waitTimeMs += waitTimeMs; if (cblk->waitTimeMs >= cblk->bufferTimeoutMs) { // timing out when a loop has been set and we have already written upto loop end @@ -616,16 +690,25 @@ status_t AudioTrack::obtainBuffer(Buffer* audioBuffer, int32_t waitCount) if (cblk->user < cblk->loopEnd) { LOGW( "obtainBuffer timed out (is the CPU pegged?) %p " "user=%08x, server=%08x", this, cblk->user, cblk->server); - //unlock cblk mutex before calling mAudioTrack->start() (see issue #1617140) + //unlock cblk mutex before calling mAudioTrack->start() (see issue #1617140) cblk->lock.unlock(); - mAudioTrack->start(); + result = mAudioTrack->start(); + if (result == DEAD_OBJECT) { + LOGW("obtainBuffer() dead IAudioTrack: creating a new one"); + result = createTrack(mStreamType, cblk->sampleRate, mFormat, mChannelCount, + mFrameCount, mFlags, mSharedBuffer, getOutput()); + if (result == NO_ERROR) { + cblk = mCblk; + cblk->bufferTimeoutMs = MAX_RUN_TIMEOUT_MS; + } + } cblk->lock.lock(); - timeout = 1; } cblk->waitTimeMs = 0; } - + if (--waitCount == 0) { + cblk->lock.unlock(); return TIMED_OUT; } } @@ -633,10 +716,11 @@ status_t AudioTrack::obtainBuffer(Buffer* audioBuffer, int32_t waitCount) start_loop_here: framesAvail = cblk->framesAvailable_l(); } + cblk->lock.unlock(); } cblk->waitTimeMs = 0; - + if (framesReq > framesAvail) { framesReq = framesAvail; } @@ -648,17 +732,16 @@ status_t AudioTrack::obtainBuffer(Buffer* audioBuffer, int32_t waitCount) framesReq = bufferEnd - u; } - LOGW_IF(timeout, - "*** SERIOUS WARNING *** obtainBuffer() timed out " - "but didn't need to be locked. We recovered, but " - "this shouldn't happen (user=%08x, server=%08x)", cblk->user, cblk->server); - - audioBuffer->flags = mMuted ? Buffer::MUTE : 0; - audioBuffer->channelCount= mChannelCount; - audioBuffer->format = AudioSystem::PCM_16_BIT; - audioBuffer->frameCount = framesReq; - audioBuffer->size = framesReq*mChannelCount*sizeof(int16_t); - audioBuffer->raw = (int8_t *)cblk->buffer(u); + audioBuffer->flags = mMuted ? Buffer::MUTE : 0; + audioBuffer->channelCount = mChannelCount; + audioBuffer->frameCount = framesReq; + audioBuffer->size = framesReq * cblk->frameSize; + if (AudioSystem::isLinearPCM(mFormat)) { + audioBuffer->format = AudioSystem::PCM_16_BIT; + } else { + audioBuffer->format = mFormat; + } + audioBuffer->raw = (int8_t *)cblk->buffer(u); active = mActive; return active ? status_t(NO_ERROR) : status_t(STOPPED); } @@ -690,10 +773,8 @@ ssize_t AudioTrack::write(const void* buffer, size_t userSize) Buffer audioBuffer; do { - audioBuffer.frameCount = userSize/mChannelCount; - if (mFormat == AudioSystem::PCM_16_BIT) { - audioBuffer.frameCount >>= 1; - } + audioBuffer.frameCount = userSize/frameSize(); + // Calling obtainBuffer() with a negative wait count causes // an (almost) infinite wait time. status_t err = obtainBuffer(&audioBuffer, -1); @@ -705,7 +786,8 @@ ssize_t AudioTrack::write(const void* buffer, size_t userSize) } size_t toWrite; - if (mFormat == AudioSystem::PCM_8_BIT) { + + if (mFormat == AudioSystem::PCM_8_BIT && !(mFlags & AudioSystem::OUTPUT_FLAG_DIRECT)) { // Divide capacity by 2 to take expansion into account toWrite = audioBuffer.size>>1; // 8 to 16 bit conversion @@ -714,7 +796,7 @@ ssize_t AudioTrack::write(const void* buffer, size_t userSize) while(count--) { *dst++ = (int16_t)(*src++^0x80) << 8; } - }else { + } else { toWrite = audioBuffer.size; memcpy(audioBuffer.i8, src, toWrite); src += toWrite; @@ -742,13 +824,13 @@ bool AudioTrack::processAudioBuffer(const sp<AudioTrackThread>& thread) if (mCblk->flowControlFlag == 0) { mCbf(EVENT_UNDERRUN, mUserData, 0); if (mCblk->server == mCblk->frameCount) { - mCbf(EVENT_BUFFER_END, mUserData, 0); + mCbf(EVENT_BUFFER_END, mUserData, 0); } mCblk->flowControlFlag = 1; if (mSharedBuffer != 0) return false; } } - + // Manage loop end callback while (mLoopCount > mCblk->loopCount) { int loopCount = -1; @@ -767,7 +849,7 @@ bool AudioTrack::processAudioBuffer(const sp<AudioTrackThread>& thread) } // Manage new position callback - if(mUpdatePeriod > 0) { + if (mUpdatePeriod > 0) { while (mCblk->server >= mNewPosition) { mCbf(EVENT_NEW_POS, mUserData, (void *)&mNewPosition); mNewPosition += mUpdatePeriod; @@ -784,10 +866,10 @@ bool AudioTrack::processAudioBuffer(const sp<AudioTrackThread>& thread) do { audioBuffer.frameCount = frames; - - // Calling obtainBuffer() with a wait count of 1 - // limits wait time to WAIT_PERIOD_MS. This prevents from being - // stuck here not being able to handle timed events (position, markers, loops). + + // Calling obtainBuffer() with a wait count of 1 + // limits wait time to WAIT_PERIOD_MS. This prevents from being + // stuck here not being able to handle timed events (position, markers, loops). status_t err = obtainBuffer(&audioBuffer, 1); if (err < NO_ERROR) { if (err != TIMED_OUT) { @@ -801,7 +883,7 @@ bool AudioTrack::processAudioBuffer(const sp<AudioTrackThread>& thread) // Divide buffer size by 2 to take into account the expansion // due to 8 to 16 bit conversion: the callback must fill only half // of the destination buffer - if (mFormat == AudioSystem::PCM_8_BIT) { + if (mFormat == AudioSystem::PCM_8_BIT && !(mFlags & AudioSystem::OUTPUT_FLAG_DIRECT)) { audioBuffer.size >>= 1; } @@ -820,7 +902,7 @@ bool AudioTrack::processAudioBuffer(const sp<AudioTrackThread>& thread) } if (writtenSize > reqSize) writtenSize = reqSize; - if (mFormat == AudioSystem::PCM_8_BIT) { + if (mFormat == AudioSystem::PCM_8_BIT && !(mFlags & AudioSystem::OUTPUT_FLAG_DIRECT)) { // 8 to 16 bit conversion const int8_t *src = audioBuffer.i8 + writtenSize-1; int count = writtenSize; @@ -832,7 +914,11 @@ bool AudioTrack::processAudioBuffer(const sp<AudioTrackThread>& thread) } audioBuffer.size = writtenSize; - audioBuffer.frameCount = writtenSize/mChannelCount/sizeof(int16_t); + // NOTE: mCblk->frameSize is not equal to AudioTrack::frameSize() for + // 8 bit PCM data: in this case, mCblk->frameSize is based on a sampel size of + // 16 bit. + audioBuffer.frameCount = writtenSize/mCblk->frameSize; + frames -= audioBuffer.frameCount; releaseBuffer(&audioBuffer); @@ -891,7 +977,7 @@ void AudioTrack::AudioTrackThread::onFirstRef() // ========================================================================= audio_track_cblk_t::audio_track_cblk_t() - : user(0), server(0), userBase(0), serverBase(0), buffers(0), frameCount(0), + : lock(Mutex::SHARED), user(0), server(0), userBase(0), serverBase(0), buffers(0), frameCount(0), loopStart(UINT_MAX), loopEnd(UINT_MAX), loopCount(0), volumeLR(0), flowControlFlag(1), forceReady(0) { } @@ -948,8 +1034,8 @@ bool audio_track_cblk_t::stepServer(uint32_t frameCount) // Mark that we have read the first buffer so that next time stepUser() is called // we switch to normal obtainBuffer() timeout period if (bufferTimeoutMs == MAX_STARTUP_TIMEOUT_MS) { - bufferTimeoutMs = MAX_RUN_TIMEOUT_MS - 1; - } + bufferTimeoutMs = MAX_STARTUP_TIMEOUT_MS - 1; + } // It is possible that we receive a flush() // while the mixer is processing a block: in this case, // stepServer() is called After the flush() has reset u & s and @@ -981,7 +1067,7 @@ bool audio_track_cblk_t::stepServer(uint32_t frameCount) void* audio_track_cblk_t::buffer(uint32_t offset) const { - return (int16_t *)this->buffers + (offset-userBase)*this->channels; + return (int8_t *)this->buffers + (offset - userBase) * this->frameSize; } uint32_t audio_track_cblk_t::framesAvailable() |