Loading media/libaudioprocessing/AudioMixer.cpp +15 −58 Original line number Diff line number Diff line Loading @@ -108,15 +108,11 @@ bool AudioMixer::setChannelMasks(int name, if (track->mHapticChannelCount > 0) { track->mAdjustInChannelCount = track->channelCount + track->mHapticChannelCount; track->mAdjustOutChannelCount = track->channelCount + track->mMixerHapticChannelCount; track->mAdjustNonDestructiveInChannelCount = track->mAdjustOutChannelCount; track->mAdjustNonDestructiveOutChannelCount = track->channelCount; track->mAdjustOutChannelCount = track->channelCount; track->mKeepContractedChannels = track->mHapticPlaybackEnabled; } else { track->mAdjustInChannelCount = 0; track->mAdjustOutChannelCount = 0; track->mAdjustNonDestructiveInChannelCount = 0; track->mAdjustNonDestructiveOutChannelCount = 0; track->mKeepContractedChannels = false; } Loading @@ -131,8 +127,7 @@ bool AudioMixer::setChannelMasks(int name, // do it after downmix since track format may change! track->prepareForReformat(); track->prepareForAdjustChannelsNonDestructive(mFrameCount); track->prepareForAdjustChannels(); track->prepareForAdjustChannels(mFrameCount); // Resampler channels may have changed. track->recreateResampler(mSampleRate); Loading Loading @@ -283,48 +278,20 @@ void AudioMixer::Track::unprepareForAdjustChannels() } } status_t AudioMixer::Track::prepareForAdjustChannels() status_t AudioMixer::Track::prepareForAdjustChannels(size_t frames) { ALOGV("AudioMixer::prepareForAdjustChannels(%p) with inChannelCount: %u, outChannelCount: %u", this, mAdjustInChannelCount, mAdjustOutChannelCount); unprepareForAdjustChannels(); if (mAdjustInChannelCount != mAdjustOutChannelCount) { mAdjustChannelsBufferProvider.reset(new AdjustChannelsBufferProvider( mFormat, mAdjustInChannelCount, mAdjustOutChannelCount, kCopyBufferFrameCount)); reconfigureBufferProviders(); } return NO_ERROR; } void AudioMixer::Track::unprepareForAdjustChannelsNonDestructive() { ALOGV("AUDIOMIXER::unprepareForAdjustChannelsNonDestructive"); if (mContractChannelsNonDestructiveBufferProvider.get() != nullptr) { mContractChannelsNonDestructiveBufferProvider.reset(nullptr); reconfigureBufferProviders(); } } status_t AudioMixer::Track::prepareForAdjustChannelsNonDestructive(size_t frames) { ALOGV("AudioMixer::prepareForAdjustChannelsNonDestructive(%p) with inChannelCount: %u, " "outChannelCount: %u, keepContractedChannels: %d", this, mAdjustNonDestructiveInChannelCount, mAdjustNonDestructiveOutChannelCount, mKeepContractedChannels); unprepareForAdjustChannelsNonDestructive(); if (mAdjustNonDestructiveInChannelCount != mAdjustNonDestructiveOutChannelCount) { uint8_t* buffer = mKeepContractedChannels ? (uint8_t*)mainBuffer + frames * audio_bytes_per_frame( mMixerChannelCount, mMixerFormat) : NULL; mContractChannelsNonDestructiveBufferProvider.reset( new AdjustChannelsBufferProvider( mFormat, mAdjustNonDestructiveInChannelCount, mAdjustNonDestructiveOutChannelCount, frames, : nullptr; mAdjustChannelsBufferProvider.reset(new AdjustChannelsBufferProvider( mFormat, mAdjustInChannelCount, mAdjustOutChannelCount, frames, mKeepContractedChannels ? mMixerFormat : AUDIO_FORMAT_INVALID, buffer)); buffer, mMixerHapticChannelCount)); reconfigureBufferProviders(); } return NO_ERROR; Loading @@ -332,9 +299,9 @@ status_t AudioMixer::Track::prepareForAdjustChannelsNonDestructive(size_t frames void AudioMixer::Track::clearContractedBuffer() { if (mContractChannelsNonDestructiveBufferProvider.get() != nullptr) { if (mAdjustChannelsBufferProvider.get() != nullptr) { static_cast<AdjustChannelsBufferProvider*>( mContractChannelsNonDestructiveBufferProvider.get())->clearContractedFrames(); mAdjustChannelsBufferProvider.get())->clearContractedFrames(); } } Loading @@ -346,10 +313,6 @@ void AudioMixer::Track::reconfigureBufferProviders() mAdjustChannelsBufferProvider->setBufferProvider(bufferProvider); bufferProvider = mAdjustChannelsBufferProvider.get(); } if (mContractChannelsNonDestructiveBufferProvider.get() != nullptr) { mContractChannelsNonDestructiveBufferProvider->setBufferProvider(bufferProvider); bufferProvider = mContractChannelsNonDestructiveBufferProvider.get(); } if (mReformatBufferProvider.get() != nullptr) { mReformatBufferProvider->setBufferProvider(bufferProvider); bufferProvider = mReformatBufferProvider.get(); Loading Loading @@ -395,7 +358,7 @@ void AudioMixer::setParameter(int name, int target, int param, void *value) track->mainBuffer = valueBuf; ALOGV("setParameter(TRACK, MAIN_BUFFER, %p)", valueBuf); if (track->mKeepContractedChannels) { track->prepareForAdjustChannelsNonDestructive(mFrameCount); track->prepareForAdjustChannels(mFrameCount); } invalidate(); } Loading Loading @@ -423,7 +386,7 @@ void AudioMixer::setParameter(int name, int target, int param, void *value) track->mMixerFormat = format; ALOGV("setParameter(TRACK, MIXER_FORMAT, %#x)", format); if (track->mKeepContractedChannels) { track->prepareForAdjustChannelsNonDestructive(mFrameCount); track->prepareForAdjustChannels(mFrameCount); } } } break; Loading @@ -442,8 +405,7 @@ void AudioMixer::setParameter(int name, int target, int param, void *value) if (track->mHapticPlaybackEnabled != hapticPlaybackEnabled) { track->mHapticPlaybackEnabled = hapticPlaybackEnabled; track->mKeepContractedChannels = hapticPlaybackEnabled; track->prepareForAdjustChannelsNonDestructive(mFrameCount); track->prepareForAdjustChannels(); track->prepareForAdjustChannels(mFrameCount); } } break; case HAPTIC_INTENSITY: { Loading Loading @@ -536,8 +498,6 @@ void AudioMixer::setBufferProvider(int name, AudioBufferProvider* bufferProvider track->mDownmixerBufferProvider->reset(); } else if (track->mReformatBufferProvider.get() != nullptr) { track->mReformatBufferProvider->reset(); } else if (track->mContractChannelsNonDestructiveBufferProvider.get() != nullptr) { track->mContractChannelsNonDestructiveBufferProvider->reset(); } else if (track->mAdjustChannelsBufferProvider.get() != nullptr) { track->mAdjustChannelsBufferProvider->reset(); } Loading Loading @@ -581,9 +541,7 @@ status_t AudioMixer::postCreateTrack(TrackBase *track) t->mMixerHapticChannelMask = AUDIO_CHANNEL_NONE; t->mMixerHapticChannelCount = 0; t->mAdjustInChannelCount = t->channelCount + t->mHapticChannelCount; t->mAdjustOutChannelCount = t->channelCount + t->mMixerHapticChannelCount; t->mAdjustNonDestructiveInChannelCount = t->mAdjustOutChannelCount; t->mAdjustNonDestructiveOutChannelCount = t->channelCount; t->mAdjustOutChannelCount = t->channelCount; t->mKeepContractedChannels = false; // Check the downmixing (or upmixing) requirements. status_t status = t->prepareForDownmix(); Loading @@ -594,8 +552,7 @@ status_t AudioMixer::postCreateTrack(TrackBase *track) // prepareForDownmix() may change mDownmixRequiresFormat ALOGVV("mMixerFormat:%#x mMixerInFormat:%#x\n", t->mMixerFormat, t->mMixerInFormat); t->prepareForReformat(); t->prepareForAdjustChannelsNonDestructive(mFrameCount); t->prepareForAdjustChannels(); t->prepareForAdjustChannels(mFrameCount); return OK; } Loading media/libaudioprocessing/BufferProviders.cpp +45 −23 Original line number Diff line number Diff line Loading @@ -653,7 +653,8 @@ void TimestretchBufferProvider::processFrames(void *dstBuffer, size_t *dstFrames AdjustChannelsBufferProvider::AdjustChannelsBufferProvider( audio_format_t format, size_t inChannelCount, size_t outChannelCount, size_t frameCount, audio_format_t contractedFormat, void* contractedBuffer) : size_t frameCount, audio_format_t contractedFormat, void* contractedBuffer, size_t contractedOutChannelCount) : CopyBufferProvider( audio_bytes_per_frame(inChannelCount, format), audio_bytes_per_frame(std::max(inChannelCount, outChannelCount), format), Loading @@ -663,15 +664,22 @@ AdjustChannelsBufferProvider::AdjustChannelsBufferProvider( mOutChannelCount(outChannelCount), mSampleSizeInBytes(audio_bytes_per_sample(format)), mFrameCount(frameCount), mContractedChannelCount(inChannelCount - outChannelCount), mContractedFormat(contractedFormat), mContractedFormat(inChannelCount > outChannelCount ? contractedFormat : AUDIO_FORMAT_INVALID), mContractedInChannelCount(inChannelCount > outChannelCount ? inChannelCount - outChannelCount : 0), mContractedOutChannelCount(contractedOutChannelCount), mContractedSampleSizeInBytes(audio_bytes_per_sample(contractedFormat)), mContractedInputFrameSize(mContractedInChannelCount * mContractedSampleSizeInBytes), mContractedBuffer(contractedBuffer), mContractedWrittenFrames(0) { ALOGV("AdjustChannelsBufferProvider(%p)(%#x, %zu, %zu, %zu, %#x, %p)", this, format, inChannelCount, outChannelCount, frameCount, contractedFormat, contractedBuffer); ALOGV("AdjustChannelsBufferProvider(%p)(%#x, %zu, %zu, %zu, %#x, %p, %zu)", this, format, inChannelCount, outChannelCount, frameCount, contractedFormat, contractedBuffer, contractedOutChannelCount); if (mContractedFormat != AUDIO_FORMAT_INVALID && mInChannelCount > mOutChannelCount) { mContractedFrameSize = audio_bytes_per_frame(mContractedChannelCount, mContractedFormat); mContractedOutputFrameSize = audio_bytes_per_frame(mContractedOutChannelCount, mContractedFormat); } } Loading @@ -690,7 +698,6 @@ status_t AdjustChannelsBufferProvider::getNextBuffer(AudioBufferProvider::Buffer void AdjustChannelsBufferProvider::copyFrames(void *dst, const void *src, size_t frames) { if (mInChannelCount > mOutChannelCount) { // For case multi to mono, adjust_channels has special logic that will mix first two input // channels into a single output channel. In that case, use adjust_channels_non_destructive // to keep only one channel data even when contracting to mono. Loading @@ -699,16 +706,31 @@ void AdjustChannelsBufferProvider::copyFrames(void *dst, const void *src, size_t if (mContractedFormat != AUDIO_FORMAT_INVALID && mContractedBuffer != nullptr) { const size_t contractedIdx = frames * mOutChannelCount * mSampleSizeInBytes; uint8_t* oriBuf = (uint8_t*) dst + contractedIdx; uint8_t* buf = (uint8_t*) mContractedBuffer + mContractedWrittenFrames * mContractedOutputFrameSize; if (mContractedInChannelCount > mContractedOutChannelCount) { // Adjust the channels first as the contracted buffer may not have enough // space for the data. // Use adjust_channels_non_destructive to avoid mix first two channels into one single // output channel when it is multi to mono. adjust_channels_non_destructive( oriBuf, mContractedInChannelCount, oriBuf, mContractedOutChannelCount, mSampleSizeInBytes, frames * mContractedInChannelCount * mSampleSizeInBytes); memcpy_by_audio_format( (uint8_t*) mContractedBuffer + mContractedWrittenFrames * mContractedFrameSize, mContractedFormat, (uint8_t*) dst + contractedIdx, mFormat, mContractedChannelCount * frames); mContractedWrittenFrames += frames; } buf, mContractedFormat, oriBuf, mFormat, mContractedOutChannelCount * frames); } else { // Prefer expanding data from the end of each audio frame. adjust_channels(src, mInChannelCount, dst, mOutChannelCount, mSampleSizeInBytes, frames * mInChannelCount * mSampleSizeInBytes); // Copy the data first as the dst buffer may not have enough space for extra channel. memcpy_by_audio_format( buf, mContractedFormat, oriBuf, mFormat, mContractedInChannelCount * frames); // Note that if the contracted data is from MONO to MULTICHANNEL, the first 2 channels // will be duplicated with the original single input channel and all the other channels // will be 0-filled. adjust_channels( buf, mContractedInChannelCount, buf, mContractedOutChannelCount, mContractedSampleSizeInBytes, mContractedInputFrameSize * frames); } mContractedWrittenFrames += frames; } } Loading media/libaudioprocessing/include/media/AudioMixer.h +5 −16 Original line number Diff line number Diff line Loading @@ -80,7 +80,6 @@ private: mPostDownmixReformatBufferProvider.reset(nullptr); mDownmixerBufferProvider.reset(nullptr); mReformatBufferProvider.reset(nullptr); mContractChannelsNonDestructiveBufferProvider.reset(nullptr); mAdjustChannelsBufferProvider.reset(nullptr); } Loading @@ -95,10 +94,8 @@ private: void unprepareForDownmix(); status_t prepareForReformat(); void unprepareForReformat(); status_t prepareForAdjustChannels(); status_t prepareForAdjustChannels(size_t frames); void unprepareForAdjustChannels(); status_t prepareForAdjustChannelsNonDestructive(size_t frames); void unprepareForAdjustChannelsNonDestructive(); void clearContractedBuffer(); bool setPlaybackRate(const AudioPlaybackRate &playbackRate); void reconfigureBufferProviders(); Loading @@ -114,24 +111,18 @@ private: * 2) mAdjustChannelsBufferProvider: Expands or contracts sample data from one interleaved * channel format to another. Expanded channels are filled with zeros and put at the end * of each audio frame. Contracted channels are copied to the end of the buffer. * 3) mContractChannelsNonDestructiveBufferProvider: Non-destructively contract sample data. * This is currently using at audio-haptic coupled playback to separate audio and haptic * data. Contracted channels could be written to given buffer. * 4) mReformatBufferProvider: If not NULL, performs the audio reformat to * 3) mReformatBufferProvider: If not NULL, performs the audio reformat to * match either mMixerInFormat or mDownmixRequiresFormat, if the downmixer * requires reformat. For example, it may convert floating point input to * PCM_16_bit if that's required by the downmixer. * 5) mDownmixerBufferProvider: If not NULL, performs the channel remixing to match * 4) mDownmixerBufferProvider: If not NULL, performs the channel remixing to match * the number of channels required by the mixer sink. * 6) mPostDownmixReformatBufferProvider: If not NULL, performs reformatting from * 5) mPostDownmixReformatBufferProvider: If not NULL, performs reformatting from * the downmixer requirements to the mixer engine input requirements. * 7) mTimestretchBufferProvider: Adds timestretching for playback rate * 6) mTimestretchBufferProvider: Adds timestretching for playback rate */ AudioBufferProvider* mInputBufferProvider; // externally provided buffer provider. // TODO: combine mAdjustChannelsBufferProvider and // mContractChannelsNonDestructiveBufferProvider std::unique_ptr<PassthruBufferProvider> mAdjustChannelsBufferProvider; std::unique_ptr<PassthruBufferProvider> mContractChannelsNonDestructiveBufferProvider; std::unique_ptr<PassthruBufferProvider> mReformatBufferProvider; std::unique_ptr<PassthruBufferProvider> mDownmixerBufferProvider; std::unique_ptr<PassthruBufferProvider> mPostDownmixReformatBufferProvider; Loading @@ -153,8 +144,6 @@ private: uint32_t mMixerHapticChannelCount; uint32_t mAdjustInChannelCount; uint32_t mAdjustOutChannelCount; uint32_t mAdjustNonDestructiveInChannelCount; uint32_t mAdjustNonDestructiveOutChannelCount; bool mKeepContractedChannels; }; Loading media/libaudioprocessing/include/media/BufferProviders.h +17 −9 Original line number Diff line number Diff line Loading @@ -241,17 +241,22 @@ private: // Extra expanded channels are filled with zeros and put at the end of each audio frame. // Contracted channels are copied to the end of the output buffer(storage should be // allocated appropriately). // Contracted channels could be written to output buffer. // Contracted channels could be written to output buffer and got adjusted. When the contracted // channels are adjusted in the contracted buffer, the input channel count will be calculated // as `inChannelCount - outChannelCount`. The output channel count is provided by caller, which // is `contractedOutChannelCount`. Currently, adjusting contracted channels is used for audio // coupled haptic playback. If the device supports two haptic channels while apps only provide // single haptic channel, the second haptic channel will be duplicated with the first haptic // channel's data. If the device supports single haptic channels while apps provide two haptic // channels, the second channel will be contracted. class AdjustChannelsBufferProvider : public CopyBufferProvider { public: AdjustChannelsBufferProvider(audio_format_t format, size_t inChannelCount, size_t outChannelCount, size_t frameCount) : AdjustChannelsBufferProvider( format, inChannelCount, outChannelCount, frameCount, AUDIO_FORMAT_INVALID, nullptr) { } // Contracted data is converted to contractedFormat and put into contractedBuffer. AdjustChannelsBufferProvider(audio_format_t format, size_t inChannelCount, size_t outChannelCount, size_t frameCount, audio_format_t contractedFormat, void* contractedBuffer); size_t outChannelCount, size_t frameCount, audio_format_t contractedFormat = AUDIO_FORMAT_INVALID, void* contractedBuffer = nullptr, size_t contractedOutChannelCount = 0); //Overrides status_t getNextBuffer(Buffer* pBuffer) override; void copyFrames(void *dst, const void *src, size_t frames) override; Loading @@ -265,11 +270,14 @@ protected: const size_t mOutChannelCount; const size_t mSampleSizeInBytes; const size_t mFrameCount; const size_t mContractedChannelCount; const audio_format_t mContractedFormat; const size_t mContractedInChannelCount; const size_t mContractedOutChannelCount; const size_t mContractedSampleSizeInBytes; const size_t mContractedInputFrameSize; // contracted input frame size void *mContractedBuffer; size_t mContractedWrittenFrames; size_t mContractedFrameSize; size_t mContractedOutputFrameSize; // contracted output frame size }; // ---------------------------------------------------------------------------- } // namespace android Loading Loading
media/libaudioprocessing/AudioMixer.cpp +15 −58 Original line number Diff line number Diff line Loading @@ -108,15 +108,11 @@ bool AudioMixer::setChannelMasks(int name, if (track->mHapticChannelCount > 0) { track->mAdjustInChannelCount = track->channelCount + track->mHapticChannelCount; track->mAdjustOutChannelCount = track->channelCount + track->mMixerHapticChannelCount; track->mAdjustNonDestructiveInChannelCount = track->mAdjustOutChannelCount; track->mAdjustNonDestructiveOutChannelCount = track->channelCount; track->mAdjustOutChannelCount = track->channelCount; track->mKeepContractedChannels = track->mHapticPlaybackEnabled; } else { track->mAdjustInChannelCount = 0; track->mAdjustOutChannelCount = 0; track->mAdjustNonDestructiveInChannelCount = 0; track->mAdjustNonDestructiveOutChannelCount = 0; track->mKeepContractedChannels = false; } Loading @@ -131,8 +127,7 @@ bool AudioMixer::setChannelMasks(int name, // do it after downmix since track format may change! track->prepareForReformat(); track->prepareForAdjustChannelsNonDestructive(mFrameCount); track->prepareForAdjustChannels(); track->prepareForAdjustChannels(mFrameCount); // Resampler channels may have changed. track->recreateResampler(mSampleRate); Loading Loading @@ -283,48 +278,20 @@ void AudioMixer::Track::unprepareForAdjustChannels() } } status_t AudioMixer::Track::prepareForAdjustChannels() status_t AudioMixer::Track::prepareForAdjustChannels(size_t frames) { ALOGV("AudioMixer::prepareForAdjustChannels(%p) with inChannelCount: %u, outChannelCount: %u", this, mAdjustInChannelCount, mAdjustOutChannelCount); unprepareForAdjustChannels(); if (mAdjustInChannelCount != mAdjustOutChannelCount) { mAdjustChannelsBufferProvider.reset(new AdjustChannelsBufferProvider( mFormat, mAdjustInChannelCount, mAdjustOutChannelCount, kCopyBufferFrameCount)); reconfigureBufferProviders(); } return NO_ERROR; } void AudioMixer::Track::unprepareForAdjustChannelsNonDestructive() { ALOGV("AUDIOMIXER::unprepareForAdjustChannelsNonDestructive"); if (mContractChannelsNonDestructiveBufferProvider.get() != nullptr) { mContractChannelsNonDestructiveBufferProvider.reset(nullptr); reconfigureBufferProviders(); } } status_t AudioMixer::Track::prepareForAdjustChannelsNonDestructive(size_t frames) { ALOGV("AudioMixer::prepareForAdjustChannelsNonDestructive(%p) with inChannelCount: %u, " "outChannelCount: %u, keepContractedChannels: %d", this, mAdjustNonDestructiveInChannelCount, mAdjustNonDestructiveOutChannelCount, mKeepContractedChannels); unprepareForAdjustChannelsNonDestructive(); if (mAdjustNonDestructiveInChannelCount != mAdjustNonDestructiveOutChannelCount) { uint8_t* buffer = mKeepContractedChannels ? (uint8_t*)mainBuffer + frames * audio_bytes_per_frame( mMixerChannelCount, mMixerFormat) : NULL; mContractChannelsNonDestructiveBufferProvider.reset( new AdjustChannelsBufferProvider( mFormat, mAdjustNonDestructiveInChannelCount, mAdjustNonDestructiveOutChannelCount, frames, : nullptr; mAdjustChannelsBufferProvider.reset(new AdjustChannelsBufferProvider( mFormat, mAdjustInChannelCount, mAdjustOutChannelCount, frames, mKeepContractedChannels ? mMixerFormat : AUDIO_FORMAT_INVALID, buffer)); buffer, mMixerHapticChannelCount)); reconfigureBufferProviders(); } return NO_ERROR; Loading @@ -332,9 +299,9 @@ status_t AudioMixer::Track::prepareForAdjustChannelsNonDestructive(size_t frames void AudioMixer::Track::clearContractedBuffer() { if (mContractChannelsNonDestructiveBufferProvider.get() != nullptr) { if (mAdjustChannelsBufferProvider.get() != nullptr) { static_cast<AdjustChannelsBufferProvider*>( mContractChannelsNonDestructiveBufferProvider.get())->clearContractedFrames(); mAdjustChannelsBufferProvider.get())->clearContractedFrames(); } } Loading @@ -346,10 +313,6 @@ void AudioMixer::Track::reconfigureBufferProviders() mAdjustChannelsBufferProvider->setBufferProvider(bufferProvider); bufferProvider = mAdjustChannelsBufferProvider.get(); } if (mContractChannelsNonDestructiveBufferProvider.get() != nullptr) { mContractChannelsNonDestructiveBufferProvider->setBufferProvider(bufferProvider); bufferProvider = mContractChannelsNonDestructiveBufferProvider.get(); } if (mReformatBufferProvider.get() != nullptr) { mReformatBufferProvider->setBufferProvider(bufferProvider); bufferProvider = mReformatBufferProvider.get(); Loading Loading @@ -395,7 +358,7 @@ void AudioMixer::setParameter(int name, int target, int param, void *value) track->mainBuffer = valueBuf; ALOGV("setParameter(TRACK, MAIN_BUFFER, %p)", valueBuf); if (track->mKeepContractedChannels) { track->prepareForAdjustChannelsNonDestructive(mFrameCount); track->prepareForAdjustChannels(mFrameCount); } invalidate(); } Loading Loading @@ -423,7 +386,7 @@ void AudioMixer::setParameter(int name, int target, int param, void *value) track->mMixerFormat = format; ALOGV("setParameter(TRACK, MIXER_FORMAT, %#x)", format); if (track->mKeepContractedChannels) { track->prepareForAdjustChannelsNonDestructive(mFrameCount); track->prepareForAdjustChannels(mFrameCount); } } } break; Loading @@ -442,8 +405,7 @@ void AudioMixer::setParameter(int name, int target, int param, void *value) if (track->mHapticPlaybackEnabled != hapticPlaybackEnabled) { track->mHapticPlaybackEnabled = hapticPlaybackEnabled; track->mKeepContractedChannels = hapticPlaybackEnabled; track->prepareForAdjustChannelsNonDestructive(mFrameCount); track->prepareForAdjustChannels(); track->prepareForAdjustChannels(mFrameCount); } } break; case HAPTIC_INTENSITY: { Loading Loading @@ -536,8 +498,6 @@ void AudioMixer::setBufferProvider(int name, AudioBufferProvider* bufferProvider track->mDownmixerBufferProvider->reset(); } else if (track->mReformatBufferProvider.get() != nullptr) { track->mReformatBufferProvider->reset(); } else if (track->mContractChannelsNonDestructiveBufferProvider.get() != nullptr) { track->mContractChannelsNonDestructiveBufferProvider->reset(); } else if (track->mAdjustChannelsBufferProvider.get() != nullptr) { track->mAdjustChannelsBufferProvider->reset(); } Loading Loading @@ -581,9 +541,7 @@ status_t AudioMixer::postCreateTrack(TrackBase *track) t->mMixerHapticChannelMask = AUDIO_CHANNEL_NONE; t->mMixerHapticChannelCount = 0; t->mAdjustInChannelCount = t->channelCount + t->mHapticChannelCount; t->mAdjustOutChannelCount = t->channelCount + t->mMixerHapticChannelCount; t->mAdjustNonDestructiveInChannelCount = t->mAdjustOutChannelCount; t->mAdjustNonDestructiveOutChannelCount = t->channelCount; t->mAdjustOutChannelCount = t->channelCount; t->mKeepContractedChannels = false; // Check the downmixing (or upmixing) requirements. status_t status = t->prepareForDownmix(); Loading @@ -594,8 +552,7 @@ status_t AudioMixer::postCreateTrack(TrackBase *track) // prepareForDownmix() may change mDownmixRequiresFormat ALOGVV("mMixerFormat:%#x mMixerInFormat:%#x\n", t->mMixerFormat, t->mMixerInFormat); t->prepareForReformat(); t->prepareForAdjustChannelsNonDestructive(mFrameCount); t->prepareForAdjustChannels(); t->prepareForAdjustChannels(mFrameCount); return OK; } Loading
media/libaudioprocessing/BufferProviders.cpp +45 −23 Original line number Diff line number Diff line Loading @@ -653,7 +653,8 @@ void TimestretchBufferProvider::processFrames(void *dstBuffer, size_t *dstFrames AdjustChannelsBufferProvider::AdjustChannelsBufferProvider( audio_format_t format, size_t inChannelCount, size_t outChannelCount, size_t frameCount, audio_format_t contractedFormat, void* contractedBuffer) : size_t frameCount, audio_format_t contractedFormat, void* contractedBuffer, size_t contractedOutChannelCount) : CopyBufferProvider( audio_bytes_per_frame(inChannelCount, format), audio_bytes_per_frame(std::max(inChannelCount, outChannelCount), format), Loading @@ -663,15 +664,22 @@ AdjustChannelsBufferProvider::AdjustChannelsBufferProvider( mOutChannelCount(outChannelCount), mSampleSizeInBytes(audio_bytes_per_sample(format)), mFrameCount(frameCount), mContractedChannelCount(inChannelCount - outChannelCount), mContractedFormat(contractedFormat), mContractedFormat(inChannelCount > outChannelCount ? contractedFormat : AUDIO_FORMAT_INVALID), mContractedInChannelCount(inChannelCount > outChannelCount ? inChannelCount - outChannelCount : 0), mContractedOutChannelCount(contractedOutChannelCount), mContractedSampleSizeInBytes(audio_bytes_per_sample(contractedFormat)), mContractedInputFrameSize(mContractedInChannelCount * mContractedSampleSizeInBytes), mContractedBuffer(contractedBuffer), mContractedWrittenFrames(0) { ALOGV("AdjustChannelsBufferProvider(%p)(%#x, %zu, %zu, %zu, %#x, %p)", this, format, inChannelCount, outChannelCount, frameCount, contractedFormat, contractedBuffer); ALOGV("AdjustChannelsBufferProvider(%p)(%#x, %zu, %zu, %zu, %#x, %p, %zu)", this, format, inChannelCount, outChannelCount, frameCount, contractedFormat, contractedBuffer, contractedOutChannelCount); if (mContractedFormat != AUDIO_FORMAT_INVALID && mInChannelCount > mOutChannelCount) { mContractedFrameSize = audio_bytes_per_frame(mContractedChannelCount, mContractedFormat); mContractedOutputFrameSize = audio_bytes_per_frame(mContractedOutChannelCount, mContractedFormat); } } Loading @@ -690,7 +698,6 @@ status_t AdjustChannelsBufferProvider::getNextBuffer(AudioBufferProvider::Buffer void AdjustChannelsBufferProvider::copyFrames(void *dst, const void *src, size_t frames) { if (mInChannelCount > mOutChannelCount) { // For case multi to mono, adjust_channels has special logic that will mix first two input // channels into a single output channel. In that case, use adjust_channels_non_destructive // to keep only one channel data even when contracting to mono. Loading @@ -699,16 +706,31 @@ void AdjustChannelsBufferProvider::copyFrames(void *dst, const void *src, size_t if (mContractedFormat != AUDIO_FORMAT_INVALID && mContractedBuffer != nullptr) { const size_t contractedIdx = frames * mOutChannelCount * mSampleSizeInBytes; uint8_t* oriBuf = (uint8_t*) dst + contractedIdx; uint8_t* buf = (uint8_t*) mContractedBuffer + mContractedWrittenFrames * mContractedOutputFrameSize; if (mContractedInChannelCount > mContractedOutChannelCount) { // Adjust the channels first as the contracted buffer may not have enough // space for the data. // Use adjust_channels_non_destructive to avoid mix first two channels into one single // output channel when it is multi to mono. adjust_channels_non_destructive( oriBuf, mContractedInChannelCount, oriBuf, mContractedOutChannelCount, mSampleSizeInBytes, frames * mContractedInChannelCount * mSampleSizeInBytes); memcpy_by_audio_format( (uint8_t*) mContractedBuffer + mContractedWrittenFrames * mContractedFrameSize, mContractedFormat, (uint8_t*) dst + contractedIdx, mFormat, mContractedChannelCount * frames); mContractedWrittenFrames += frames; } buf, mContractedFormat, oriBuf, mFormat, mContractedOutChannelCount * frames); } else { // Prefer expanding data from the end of each audio frame. adjust_channels(src, mInChannelCount, dst, mOutChannelCount, mSampleSizeInBytes, frames * mInChannelCount * mSampleSizeInBytes); // Copy the data first as the dst buffer may not have enough space for extra channel. memcpy_by_audio_format( buf, mContractedFormat, oriBuf, mFormat, mContractedInChannelCount * frames); // Note that if the contracted data is from MONO to MULTICHANNEL, the first 2 channels // will be duplicated with the original single input channel and all the other channels // will be 0-filled. adjust_channels( buf, mContractedInChannelCount, buf, mContractedOutChannelCount, mContractedSampleSizeInBytes, mContractedInputFrameSize * frames); } mContractedWrittenFrames += frames; } } Loading
media/libaudioprocessing/include/media/AudioMixer.h +5 −16 Original line number Diff line number Diff line Loading @@ -80,7 +80,6 @@ private: mPostDownmixReformatBufferProvider.reset(nullptr); mDownmixerBufferProvider.reset(nullptr); mReformatBufferProvider.reset(nullptr); mContractChannelsNonDestructiveBufferProvider.reset(nullptr); mAdjustChannelsBufferProvider.reset(nullptr); } Loading @@ -95,10 +94,8 @@ private: void unprepareForDownmix(); status_t prepareForReformat(); void unprepareForReformat(); status_t prepareForAdjustChannels(); status_t prepareForAdjustChannels(size_t frames); void unprepareForAdjustChannels(); status_t prepareForAdjustChannelsNonDestructive(size_t frames); void unprepareForAdjustChannelsNonDestructive(); void clearContractedBuffer(); bool setPlaybackRate(const AudioPlaybackRate &playbackRate); void reconfigureBufferProviders(); Loading @@ -114,24 +111,18 @@ private: * 2) mAdjustChannelsBufferProvider: Expands or contracts sample data from one interleaved * channel format to another. Expanded channels are filled with zeros and put at the end * of each audio frame. Contracted channels are copied to the end of the buffer. * 3) mContractChannelsNonDestructiveBufferProvider: Non-destructively contract sample data. * This is currently using at audio-haptic coupled playback to separate audio and haptic * data. Contracted channels could be written to given buffer. * 4) mReformatBufferProvider: If not NULL, performs the audio reformat to * 3) mReformatBufferProvider: If not NULL, performs the audio reformat to * match either mMixerInFormat or mDownmixRequiresFormat, if the downmixer * requires reformat. For example, it may convert floating point input to * PCM_16_bit if that's required by the downmixer. * 5) mDownmixerBufferProvider: If not NULL, performs the channel remixing to match * 4) mDownmixerBufferProvider: If not NULL, performs the channel remixing to match * the number of channels required by the mixer sink. * 6) mPostDownmixReformatBufferProvider: If not NULL, performs reformatting from * 5) mPostDownmixReformatBufferProvider: If not NULL, performs reformatting from * the downmixer requirements to the mixer engine input requirements. * 7) mTimestretchBufferProvider: Adds timestretching for playback rate * 6) mTimestretchBufferProvider: Adds timestretching for playback rate */ AudioBufferProvider* mInputBufferProvider; // externally provided buffer provider. // TODO: combine mAdjustChannelsBufferProvider and // mContractChannelsNonDestructiveBufferProvider std::unique_ptr<PassthruBufferProvider> mAdjustChannelsBufferProvider; std::unique_ptr<PassthruBufferProvider> mContractChannelsNonDestructiveBufferProvider; std::unique_ptr<PassthruBufferProvider> mReformatBufferProvider; std::unique_ptr<PassthruBufferProvider> mDownmixerBufferProvider; std::unique_ptr<PassthruBufferProvider> mPostDownmixReformatBufferProvider; Loading @@ -153,8 +144,6 @@ private: uint32_t mMixerHapticChannelCount; uint32_t mAdjustInChannelCount; uint32_t mAdjustOutChannelCount; uint32_t mAdjustNonDestructiveInChannelCount; uint32_t mAdjustNonDestructiveOutChannelCount; bool mKeepContractedChannels; }; Loading
media/libaudioprocessing/include/media/BufferProviders.h +17 −9 Original line number Diff line number Diff line Loading @@ -241,17 +241,22 @@ private: // Extra expanded channels are filled with zeros and put at the end of each audio frame. // Contracted channels are copied to the end of the output buffer(storage should be // allocated appropriately). // Contracted channels could be written to output buffer. // Contracted channels could be written to output buffer and got adjusted. When the contracted // channels are adjusted in the contracted buffer, the input channel count will be calculated // as `inChannelCount - outChannelCount`. The output channel count is provided by caller, which // is `contractedOutChannelCount`. Currently, adjusting contracted channels is used for audio // coupled haptic playback. If the device supports two haptic channels while apps only provide // single haptic channel, the second haptic channel will be duplicated with the first haptic // channel's data. If the device supports single haptic channels while apps provide two haptic // channels, the second channel will be contracted. class AdjustChannelsBufferProvider : public CopyBufferProvider { public: AdjustChannelsBufferProvider(audio_format_t format, size_t inChannelCount, size_t outChannelCount, size_t frameCount) : AdjustChannelsBufferProvider( format, inChannelCount, outChannelCount, frameCount, AUDIO_FORMAT_INVALID, nullptr) { } // Contracted data is converted to contractedFormat and put into contractedBuffer. AdjustChannelsBufferProvider(audio_format_t format, size_t inChannelCount, size_t outChannelCount, size_t frameCount, audio_format_t contractedFormat, void* contractedBuffer); size_t outChannelCount, size_t frameCount, audio_format_t contractedFormat = AUDIO_FORMAT_INVALID, void* contractedBuffer = nullptr, size_t contractedOutChannelCount = 0); //Overrides status_t getNextBuffer(Buffer* pBuffer) override; void copyFrames(void *dst, const void *src, size_t frames) override; Loading @@ -265,11 +270,14 @@ protected: const size_t mOutChannelCount; const size_t mSampleSizeInBytes; const size_t mFrameCount; const size_t mContractedChannelCount; const audio_format_t mContractedFormat; const size_t mContractedInChannelCount; const size_t mContractedOutChannelCount; const size_t mContractedSampleSizeInBytes; const size_t mContractedInputFrameSize; // contracted input frame size void *mContractedBuffer; size_t mContractedWrittenFrames; size_t mContractedFrameSize; size_t mContractedOutputFrameSize; // contracted output frame size }; // ---------------------------------------------------------------------------- } // namespace android Loading