Refactor adjust channels buffer provider.

Combine adjust channels buffer provider and adjust channels non-destructive
buffer provider.
When contracting mono + haptic channels to mono, do not use
adjust_channels to avoid mixing haptic channel into audio channel.

Bug: 125915810
Test: play audio-haptic coupled files
Change-Id: I39916a3e0628a44ed4a148c265564af7135a2176
gugelfrei
jiabin 5 years ago
parent bb08e4d99b
commit ea8fa7a5ee

@ -273,7 +273,7 @@ private:
mPostDownmixReformatBufferProvider.reset(nullptr);
mDownmixerBufferProvider.reset(nullptr);
mReformatBufferProvider.reset(nullptr);
mAdjustChannelsNonDestructiveBufferProvider.reset(nullptr);
mContractChannelsNonDestructiveBufferProvider.reset(nullptr);
mAdjustChannelsBufferProvider.reset(nullptr);
}
@ -347,8 +347,12 @@ private:
* all pre-mixer track buffer conversions outside the AudioMixer class.
*
* 1) mInputBufferProvider: The AudioTrack buffer provider.
* 2) mAdjustChannelsBufferProvider: Expend or contracts data
* 3) mAdjustChannelsNonDestructiveBufferProvider: Non-destructively adjust sample data
* 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
* match either mMixerInFormat or mDownmixRequiresFormat, if the downmixer
* requires reformat. For example, it may convert floating point input to
@ -360,9 +364,10 @@ private:
* 7) mTimestretchBufferProvider: Adds timestretching for playback rate
*/
AudioBufferProvider* mInputBufferProvider; // externally provided buffer provider.
// TODO: combine AdjustChannelsBufferProvider and AdjustChannelsNonDestructiveBufferProvider
// TODO: combine mAdjustChannelsBufferProvider and
// mContractChannelsNonDestructiveBufferProvider
std::unique_ptr<PassthruBufferProvider> mAdjustChannelsBufferProvider;
std::unique_ptr<PassthruBufferProvider> mAdjustChannelsNonDestructiveBufferProvider;
std::unique_ptr<PassthruBufferProvider> mContractChannelsNonDestructiveBufferProvider;
std::unique_ptr<PassthruBufferProvider> mReformatBufferProvider;
std::unique_ptr<PassthruBufferProvider> mDownmixerBufferProvider;
std::unique_ptr<PassthruBufferProvider> mPostDownmixReformatBufferProvider;

@ -408,8 +408,8 @@ status_t AudioMixer::Track::prepareForAdjustChannels()
void AudioMixer::Track::unprepareForAdjustChannelsNonDestructive()
{
ALOGV("AUDIOMIXER::unprepareForAdjustChannelsNonDestructive");
if (mAdjustChannelsNonDestructiveBufferProvider.get() != nullptr) {
mAdjustChannelsNonDestructiveBufferProvider.reset(nullptr);
if (mContractChannelsNonDestructiveBufferProvider.get() != nullptr) {
mContractChannelsNonDestructiveBufferProvider.reset(nullptr);
reconfigureBufferProviders();
}
}
@ -426,13 +426,13 @@ status_t AudioMixer::Track::prepareForAdjustChannelsNonDestructive(size_t frames
? (uint8_t*)mainBuffer + frames * audio_bytes_per_frame(
mMixerChannelCount, mMixerFormat)
: NULL;
mAdjustChannelsNonDestructiveBufferProvider.reset(
new AdjustChannelsNonDestructiveBufferProvider(
mContractChannelsNonDestructiveBufferProvider.reset(
new AdjustChannelsBufferProvider(
mFormat,
mAdjustNonDestructiveInChannelCount,
mAdjustNonDestructiveOutChannelCount,
mKeepContractedChannels ? mMixerFormat : AUDIO_FORMAT_INVALID,
frames,
mKeepContractedChannels ? mMixerFormat : AUDIO_FORMAT_INVALID,
buffer));
reconfigureBufferProviders();
}
@ -441,9 +441,9 @@ status_t AudioMixer::Track::prepareForAdjustChannelsNonDestructive(size_t frames
void AudioMixer::Track::clearContractedBuffer()
{
if (mAdjustChannelsNonDestructiveBufferProvider.get() != nullptr) {
static_cast<AdjustChannelsNonDestructiveBufferProvider*>(
mAdjustChannelsNonDestructiveBufferProvider.get())->clearContractedFrames();
if (mContractChannelsNonDestructiveBufferProvider.get() != nullptr) {
static_cast<AdjustChannelsBufferProvider*>(
mContractChannelsNonDestructiveBufferProvider.get())->clearContractedFrames();
}
}
@ -455,9 +455,9 @@ void AudioMixer::Track::reconfigureBufferProviders()
mAdjustChannelsBufferProvider->setBufferProvider(bufferProvider);
bufferProvider = mAdjustChannelsBufferProvider.get();
}
if (mAdjustChannelsNonDestructiveBufferProvider.get() != nullptr) {
mAdjustChannelsNonDestructiveBufferProvider->setBufferProvider(bufferProvider);
bufferProvider = mAdjustChannelsNonDestructiveBufferProvider.get();
if (mContractChannelsNonDestructiveBufferProvider.get() != nullptr) {
mContractChannelsNonDestructiveBufferProvider->setBufferProvider(bufferProvider);
bufferProvider = mContractChannelsNonDestructiveBufferProvider.get();
}
if (mReformatBufferProvider.get() != nullptr) {
mReformatBufferProvider->setBufferProvider(bufferProvider);
@ -966,8 +966,8 @@ void AudioMixer::setBufferProvider(int name, AudioBufferProvider* bufferProvider
track->mDownmixerBufferProvider->reset();
} else if (track->mReformatBufferProvider.get() != nullptr) {
track->mReformatBufferProvider->reset();
} else if (track->mAdjustChannelsNonDestructiveBufferProvider.get() != nullptr) {
track->mAdjustChannelsNonDestructiveBufferProvider->reset();
} else if (track->mContractChannelsNonDestructiveBufferProvider.get() != nullptr) {
track->mContractChannelsNonDestructiveBufferProvider->reset();
} else if (track->mAdjustChannelsBufferProvider.get() != nullptr) {
track->mAdjustChannelsBufferProvider->reset();
}

@ -627,79 +627,68 @@ void TimestretchBufferProvider::processFrames(void *dstBuffer, size_t *dstFrames
}
}
AdjustChannelsBufferProvider::AdjustChannelsBufferProvider(audio_format_t format,
size_t inChannelCount, size_t outChannelCount, size_t frameCount) :
CopyBufferProvider(
audio_bytes_per_frame(inChannelCount, format),
audio_bytes_per_frame(outChannelCount, format),
frameCount),
mFormat(format),
mInChannelCount(inChannelCount),
mOutChannelCount(outChannelCount),
mSampleSizeInBytes(audio_bytes_per_sample(format))
{
ALOGV("AdjustBufferProvider(%p)(%#x, %zu, %zu, %zu)",
this, format, inChannelCount, outChannelCount, frameCount);
}
void AdjustChannelsBufferProvider::copyFrames(void *dst, const void *src, size_t frames)
{
adjust_channels(src, mInChannelCount, dst, mOutChannelCount, mSampleSizeInBytes,
frames * mInChannelCount * mSampleSizeInBytes);
}
AdjustChannelsNonDestructiveBufferProvider::AdjustChannelsNonDestructiveBufferProvider(
AdjustChannelsBufferProvider::AdjustChannelsBufferProvider(
audio_format_t format, size_t inChannelCount, size_t outChannelCount,
audio_format_t contractedFormat, size_t contractedFrameCount, void* contractedBuffer) :
size_t frameCount, audio_format_t contractedFormat, void* contractedBuffer) :
CopyBufferProvider(
audio_bytes_per_frame(inChannelCount, format),
audio_bytes_per_frame(std::max(inChannelCount, outChannelCount), format),
audio_bytes_per_frame(std::max(inChannelCount, outChannelCount), format),
contractedFrameCount),
frameCount),
mFormat(format),
mInChannelCount(inChannelCount),
mOutChannelCount(outChannelCount),
mSampleSizeInBytes(audio_bytes_per_sample(format)),
mFrameCount(frameCount),
mContractedChannelCount(inChannelCount - outChannelCount),
mContractedFormat(contractedFormat),
mContractedFrameCount(contractedFrameCount),
mContractedBuffer(contractedBuffer),
mContractedWrittenFrames(0)
{
ALOGV("AdjustChannelsNonDestructiveBufferProvider(%p)(%#x, %zu, %zu, %#x, %p)",
this, format, inChannelCount, outChannelCount, contractedFormat, contractedBuffer);
ALOGV("AdjustChannelsBufferProvider(%p)(%#x, %zu, %zu, %zu, %#x, %p)", this, format,
inChannelCount, outChannelCount, frameCount, contractedFormat, contractedBuffer);
if (mContractedFormat != AUDIO_FORMAT_INVALID && mInChannelCount > mOutChannelCount) {
mContractedFrameSize = audio_bytes_per_frame(mContractedChannelCount, mContractedFormat);
}
}
status_t AdjustChannelsNonDestructiveBufferProvider::getNextBuffer(
AudioBufferProvider::Buffer* pBuffer)
status_t AdjustChannelsBufferProvider::getNextBuffer(AudioBufferProvider::Buffer* pBuffer)
{
const size_t outFramesLeft = mContractedFrameCount - mContractedWrittenFrames;
if (outFramesLeft < pBuffer->frameCount) {
// Restrict the frame count so that we don't write over the size of the output buffer.
pBuffer->frameCount = outFramesLeft;
if (mContractedBuffer != nullptr) {
// Restrict frame count only when it is needed to save contracted frames.
const size_t outFramesLeft = mFrameCount - mContractedWrittenFrames;
if (outFramesLeft < pBuffer->frameCount) {
// Restrict the frame count so that we don't write over the size of the output buffer.
pBuffer->frameCount = outFramesLeft;
}
}
return CopyBufferProvider::getNextBuffer(pBuffer);
}
void AdjustChannelsNonDestructiveBufferProvider::copyFrames(
void *dst, const void *src, size_t frames)
void AdjustChannelsBufferProvider::copyFrames(void *dst, const void *src, size_t frames)
{
adjust_channels_non_destructive(src, mInChannelCount, dst, mOutChannelCount, mSampleSizeInBytes,
frames * mInChannelCount * mSampleSizeInBytes);
if (mContractedFormat != AUDIO_FORMAT_INVALID && mContractedBuffer != NULL
&& mInChannelCount > mOutChannelCount) {
const size_t contractedIdx = frames * mOutChannelCount * mSampleSizeInBytes;
memcpy_by_audio_format(
(uint8_t*)mContractedBuffer + mContractedWrittenFrames * mContractedFrameSize,
mContractedFormat, (uint8_t*)dst + contractedIdx, mFormat,
mContractedChannelCount * frames);
mContractedWrittenFrames += 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.
adjust_channels_non_destructive(src, mInChannelCount, dst, mOutChannelCount,
mSampleSizeInBytes, frames * mInChannelCount * mSampleSizeInBytes);
if (mContractedFormat != AUDIO_FORMAT_INVALID
&& mContractedBuffer != nullptr) {
const size_t contractedIdx = frames * mOutChannelCount * mSampleSizeInBytes;
memcpy_by_audio_format(
(uint8_t*) mContractedBuffer + mContractedWrittenFrames * mContractedFrameSize,
mContractedFormat, (uint8_t*) dst + contractedIdx, mFormat,
mContractedChannelCount * frames);
mContractedWrittenFrames += frames;
}
} else {
// Prefer expanding data from the end of each audio frame.
adjust_channels(src, mInChannelCount, dst, mOutChannelCount,
mSampleSizeInBytes, frames * mInChannelCount * mSampleSizeInBytes);
}
}
void AdjustChannelsNonDestructiveBufferProvider::reset()
void AdjustChannelsBufferProvider::reset()
{
mContractedWrittenFrames = 0;
CopyBufferProvider::reset();

@ -218,33 +218,21 @@ private:
bool mAudioPlaybackRateValid; // flag for current parameters validity
};
// AdjustBufferProvider derives from CopyBufferProvider to adjust sample data.
// AdjustChannelsBufferProvider derives from CopyBufferProvider to adjust sample data.
// 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 omitted from the end of each audio frame.
// 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.
class AdjustChannelsBufferProvider : public CopyBufferProvider {
public:
AdjustChannelsBufferProvider(audio_format_t format, size_t inChannelCount,
size_t outChannelCount, size_t frameCount);
//Overrides
void copyFrames(void *dst, const void *src, size_t frames) override;
protected:
const audio_format_t mFormat;
const size_t mInChannelCount;
const size_t mOutChannelCount;
const size_t mSampleSizeInBytes;
};
// AdjustChannelsNonDestructiveBufferProvider derives from CopyBufferProvider to adjust sample data.
// Expands or contracts sample data from one interleaved channel format to another.
// Extra expanded channels are interleaved in from the end of the input buffer.
// Contracted channels are copied to the end of the output buffer.
// Contracted channels could be written to output buffer.
class AdjustChannelsNonDestructiveBufferProvider : public CopyBufferProvider {
public:
AdjustChannelsNonDestructiveBufferProvider(audio_format_t format, size_t inChannelCount,
size_t outChannelCount, audio_format_t contractedFormat, size_t contractedFrameCount,
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);
//Overrides
status_t getNextBuffer(Buffer* pBuffer) override;
@ -258,9 +246,9 @@ protected:
const size_t mInChannelCount;
const size_t mOutChannelCount;
const size_t mSampleSizeInBytes;
const size_t mFrameCount;
const size_t mContractedChannelCount;
const audio_format_t mContractedFormat;
const size_t mContractedFrameCount;
void *mContractedBuffer;
size_t mContractedWrittenFrames;
size_t mContractedFrameSize;

Loading…
Cancel
Save