blob: fe92d43b70301b7e279857ef07862d4a7df02573 [file] [log] [blame]
Andy Hung857d5a22015-03-26 18:46:00 -07001/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "BufferProvider"
18//#define LOG_NDEBUG 0
19
Andy Hung857d5a22015-03-26 18:46:00 -070020#include <audio_utils/primitives.h>
21#include <audio_utils/format.h>
jiabindce8f8c2018-12-10 17:49:31 -080022#include <audio_utils/channels.h>
Dan Willemsen9c99f152018-11-16 15:30:38 -080023#include <sonic.h>
Mikhail Naganov022b9952017-01-04 16:36:51 -080024#include <media/audiohal/EffectBufferHalInterface.h>
Mikhail Naganova0c91332016-09-19 10:01:12 -070025#include <media/audiohal/EffectHalInterface.h>
26#include <media/audiohal/EffectsFactoryHalInterface.h>
Andy Hungc5656cc2015-03-26 19:04:33 -070027#include <media/AudioResamplerPublic.h>
Andy Hung068561c2017-01-03 17:09:32 -080028#include <media/BufferProviders.h>
Mikhail Naganov9fe94012016-10-14 14:57:40 -070029#include <system/audio_effects/effect_downmix.h>
Andy Hung857d5a22015-03-26 18:46:00 -070030#include <utils/Log.h>
31
Andy Hung857d5a22015-03-26 18:46:00 -070032#ifndef ARRAY_SIZE
33#define ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0]))
34#endif
35
36namespace android {
37
38// ----------------------------------------------------------------------------
39
40template <typename T>
41static inline T min(const T& a, const T& b)
42{
43 return a < b ? a : b;
44}
45
46CopyBufferProvider::CopyBufferProvider(size_t inputFrameSize,
47 size_t outputFrameSize, size_t bufferFrameCount) :
48 mInputFrameSize(inputFrameSize),
49 mOutputFrameSize(outputFrameSize),
50 mLocalBufferFrameCount(bufferFrameCount),
51 mLocalBufferData(NULL),
52 mConsumed(0)
53{
54 ALOGV("CopyBufferProvider(%p)(%zu, %zu, %zu)", this,
55 inputFrameSize, outputFrameSize, bufferFrameCount);
56 LOG_ALWAYS_FATAL_IF(inputFrameSize < outputFrameSize && bufferFrameCount == 0,
57 "Requires local buffer if inputFrameSize(%zu) < outputFrameSize(%zu)",
58 inputFrameSize, outputFrameSize);
59 if (mLocalBufferFrameCount) {
60 (void)posix_memalign(&mLocalBufferData, 32, mLocalBufferFrameCount * mOutputFrameSize);
61 }
62 mBuffer.frameCount = 0;
63}
64
65CopyBufferProvider::~CopyBufferProvider()
66{
Andy Hung930bbf92018-09-11 18:44:27 -070067 ALOGV("%s(%p) %zu %p %p",
68 __func__, this, mBuffer.frameCount, mTrackBufferProvider, mLocalBufferData);
Andy Hung857d5a22015-03-26 18:46:00 -070069 if (mBuffer.frameCount != 0) {
70 mTrackBufferProvider->releaseBuffer(&mBuffer);
71 }
72 free(mLocalBufferData);
73}
74
Glenn Kastend79072e2016-01-06 08:41:20 -080075status_t CopyBufferProvider::getNextBuffer(AudioBufferProvider::Buffer *pBuffer)
Andy Hung857d5a22015-03-26 18:46:00 -070076{
Glenn Kastend79072e2016-01-06 08:41:20 -080077 //ALOGV("CopyBufferProvider(%p)::getNextBuffer(%p (%zu))",
78 // this, pBuffer, pBuffer->frameCount);
Andy Hung857d5a22015-03-26 18:46:00 -070079 if (mLocalBufferFrameCount == 0) {
Glenn Kastend79072e2016-01-06 08:41:20 -080080 status_t res = mTrackBufferProvider->getNextBuffer(pBuffer);
Andy Hung857d5a22015-03-26 18:46:00 -070081 if (res == OK) {
82 copyFrames(pBuffer->raw, pBuffer->raw, pBuffer->frameCount);
83 }
84 return res;
85 }
86 if (mBuffer.frameCount == 0) {
87 mBuffer.frameCount = pBuffer->frameCount;
Glenn Kastend79072e2016-01-06 08:41:20 -080088 status_t res = mTrackBufferProvider->getNextBuffer(&mBuffer);
Andy Hung857d5a22015-03-26 18:46:00 -070089 // At one time an upstream buffer provider had
90 // res == OK and mBuffer.frameCount == 0, doesn't seem to happen now 7/18/2014.
91 //
92 // By API spec, if res != OK, then mBuffer.frameCount == 0.
93 // but there may be improper implementations.
94 ALOG_ASSERT(res == OK || mBuffer.frameCount == 0);
95 if (res != OK || mBuffer.frameCount == 0) { // not needed by API spec, but to be safe.
96 pBuffer->raw = NULL;
97 pBuffer->frameCount = 0;
98 return res;
99 }
100 mConsumed = 0;
101 }
102 ALOG_ASSERT(mConsumed < mBuffer.frameCount);
103 size_t count = min(mLocalBufferFrameCount, mBuffer.frameCount - mConsumed);
104 count = min(count, pBuffer->frameCount);
105 pBuffer->raw = mLocalBufferData;
106 pBuffer->frameCount = count;
107 copyFrames(pBuffer->raw, (uint8_t*)mBuffer.raw + mConsumed * mInputFrameSize,
108 pBuffer->frameCount);
109 return OK;
110}
111
112void CopyBufferProvider::releaseBuffer(AudioBufferProvider::Buffer *pBuffer)
113{
114 //ALOGV("CopyBufferProvider(%p)::releaseBuffer(%p(%zu))",
115 // this, pBuffer, pBuffer->frameCount);
116 if (mLocalBufferFrameCount == 0) {
117 mTrackBufferProvider->releaseBuffer(pBuffer);
118 return;
119 }
120 // LOG_ALWAYS_FATAL_IF(pBuffer->frameCount == 0, "Invalid framecount");
121 mConsumed += pBuffer->frameCount; // TODO: update for efficiency to reuse existing content
122 if (mConsumed != 0 && mConsumed >= mBuffer.frameCount) {
123 mTrackBufferProvider->releaseBuffer(&mBuffer);
124 ALOG_ASSERT(mBuffer.frameCount == 0);
125 }
126 pBuffer->raw = NULL;
127 pBuffer->frameCount = 0;
128}
129
130void CopyBufferProvider::reset()
131{
132 if (mBuffer.frameCount != 0) {
133 mTrackBufferProvider->releaseBuffer(&mBuffer);
134 }
135 mConsumed = 0;
136}
137
Andy Hung930bbf92018-09-11 18:44:27 -0700138void CopyBufferProvider::setBufferProvider(AudioBufferProvider *p) {
139 ALOGV("%s(%p): mTrackBufferProvider:%p mBuffer.frameCount:%zu",
140 __func__, p, mTrackBufferProvider, mBuffer.frameCount);
141 if (mTrackBufferProvider == p) {
142 return;
143 }
144 mBuffer.frameCount = 0;
145 PassthruBufferProvider::setBufferProvider(p);
146}
147
Andy Hung857d5a22015-03-26 18:46:00 -0700148DownmixerBufferProvider::DownmixerBufferProvider(
149 audio_channel_mask_t inputChannelMask,
150 audio_channel_mask_t outputChannelMask, audio_format_t format,
151 uint32_t sampleRate, int32_t sessionId, size_t bufferFrameCount) :
152 CopyBufferProvider(
153 audio_bytes_per_sample(format) * audio_channel_count_from_out_mask(inputChannelMask),
154 audio_bytes_per_sample(format) * audio_channel_count_from_out_mask(outputChannelMask),
155 bufferFrameCount) // set bufferFrameCount to 0 to do in-place
156{
Mikhail Naganov66916c22017-01-24 17:46:33 -0800157 ALOGV("DownmixerBufferProvider(%p)(%#x, %#x, %#x %u %d %d)",
Andy Hung857d5a22015-03-26 18:46:00 -0700158 this, inputChannelMask, outputChannelMask, format,
Mikhail Naganov66916c22017-01-24 17:46:33 -0800159 sampleRate, sessionId, (int)bufferFrameCount);
Mikhail Naganov4a3d5c22016-08-15 13:47:42 -0700160 if (!sIsMultichannelCapable) {
161 ALOGE("DownmixerBufferProvider() error: not multichannel capable");
162 return;
163 }
164 mEffectsFactory = EffectsFactoryHalInterface::create();
Mikhail Naganov1dc98672016-08-18 17:50:29 -0700165 if (mEffectsFactory == 0) {
Mikhail Naganov4a3d5c22016-08-15 13:47:42 -0700166 ALOGE("DownmixerBufferProvider() error: could not obtain the effects factory");
167 return;
168 }
169 if (mEffectsFactory->createEffect(&sDwnmFxDesc.uuid,
170 sessionId,
171 SESSION_ID_INVALID_AND_IGNORED,
172 &mDownmixInterface) != 0) {
Andy Hung857d5a22015-03-26 18:46:00 -0700173 ALOGE("DownmixerBufferProvider() error creating downmixer effect");
Mikhail Naganov4a3d5c22016-08-15 13:47:42 -0700174 mDownmixInterface.clear();
175 mEffectsFactory.clear();
Andy Hung857d5a22015-03-26 18:46:00 -0700176 return;
177 }
178 // channel input configuration will be overridden per-track
179 mDownmixConfig.inputCfg.channels = inputChannelMask; // FIXME: Should be bits
180 mDownmixConfig.outputCfg.channels = outputChannelMask; // FIXME: should be bits
181 mDownmixConfig.inputCfg.format = format;
182 mDownmixConfig.outputCfg.format = format;
183 mDownmixConfig.inputCfg.samplingRate = sampleRate;
184 mDownmixConfig.outputCfg.samplingRate = sampleRate;
185 mDownmixConfig.inputCfg.accessMode = EFFECT_BUFFER_ACCESS_READ;
186 mDownmixConfig.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_WRITE;
187 // input and output buffer provider, and frame count will not be used as the downmix effect
188 // process() function is called directly (see DownmixerBufferProvider::getNextBuffer())
189 mDownmixConfig.inputCfg.mask = EFFECT_CONFIG_SMP_RATE | EFFECT_CONFIG_CHANNELS |
190 EFFECT_CONFIG_FORMAT | EFFECT_CONFIG_ACC_MODE;
191 mDownmixConfig.outputCfg.mask = mDownmixConfig.inputCfg.mask;
192
Mikhail Naganov66916c22017-01-24 17:46:33 -0800193 mInFrameSize =
194 audio_bytes_per_sample(format) * audio_channel_count_from_out_mask(inputChannelMask);
195 mOutFrameSize =
196 audio_bytes_per_sample(format) * audio_channel_count_from_out_mask(outputChannelMask);
Mikhail Naganov022b9952017-01-04 16:36:51 -0800197 status_t status;
Kevin Rocard7588ff42018-01-08 11:11:30 -0800198 status = mEffectsFactory->mirrorBuffer(
Mikhail Naganov66916c22017-01-24 17:46:33 -0800199 nullptr, mInFrameSize * bufferFrameCount, &mInBuffer);
Mikhail Naganov022b9952017-01-04 16:36:51 -0800200 if (status != 0) {
201 ALOGE("DownmixerBufferProvider() error %d while creating input buffer", status);
202 mDownmixInterface.clear();
203 mEffectsFactory.clear();
204 return;
205 }
Kevin Rocard7588ff42018-01-08 11:11:30 -0800206 status = mEffectsFactory->mirrorBuffer(
Mikhail Naganov66916c22017-01-24 17:46:33 -0800207 nullptr, mOutFrameSize * bufferFrameCount, &mOutBuffer);
Mikhail Naganov022b9952017-01-04 16:36:51 -0800208 if (status != 0) {
209 ALOGE("DownmixerBufferProvider() error %d while creating output buffer", status);
210 mInBuffer.clear();
211 mDownmixInterface.clear();
212 mEffectsFactory.clear();
213 return;
214 }
Mikhail Naganov2f607552017-01-11 16:09:03 -0800215 mDownmixInterface->setInBuffer(mInBuffer);
216 mDownmixInterface->setOutBuffer(mOutBuffer);
Mikhail Naganov022b9952017-01-04 16:36:51 -0800217
Andy Hung857d5a22015-03-26 18:46:00 -0700218 int cmdStatus;
219 uint32_t replySize = sizeof(int);
220
221 // Configure downmixer
Mikhail Naganov022b9952017-01-04 16:36:51 -0800222 status = mDownmixInterface->command(
Andy Hung857d5a22015-03-26 18:46:00 -0700223 EFFECT_CMD_SET_CONFIG /*cmdCode*/, sizeof(effect_config_t) /*cmdSize*/,
224 &mDownmixConfig /*pCmdData*/,
225 &replySize, &cmdStatus /*pReplyData*/);
226 if (status != 0 || cmdStatus != 0) {
227 ALOGE("DownmixerBufferProvider() error %d cmdStatus %d while configuring downmixer",
228 status, cmdStatus);
Mikhail Naganov022b9952017-01-04 16:36:51 -0800229 mOutBuffer.clear();
230 mInBuffer.clear();
Mikhail Naganov4a3d5c22016-08-15 13:47:42 -0700231 mDownmixInterface.clear();
232 mEffectsFactory.clear();
Andy Hung857d5a22015-03-26 18:46:00 -0700233 return;
234 }
235
236 // Enable downmixer
237 replySize = sizeof(int);
Mikhail Naganov4a3d5c22016-08-15 13:47:42 -0700238 status = mDownmixInterface->command(
Andy Hung857d5a22015-03-26 18:46:00 -0700239 EFFECT_CMD_ENABLE /*cmdCode*/, 0 /*cmdSize*/, NULL /*pCmdData*/,
240 &replySize, &cmdStatus /*pReplyData*/);
241 if (status != 0 || cmdStatus != 0) {
242 ALOGE("DownmixerBufferProvider() error %d cmdStatus %d while enabling downmixer",
243 status, cmdStatus);
Mikhail Naganov022b9952017-01-04 16:36:51 -0800244 mOutBuffer.clear();
245 mInBuffer.clear();
Mikhail Naganov4a3d5c22016-08-15 13:47:42 -0700246 mDownmixInterface.clear();
247 mEffectsFactory.clear();
Andy Hung857d5a22015-03-26 18:46:00 -0700248 return;
249 }
250
251 // Set downmix type
252 // parameter size rounded for padding on 32bit boundary
253 const int psizePadded = ((sizeof(downmix_params_t) - 1)/sizeof(int) + 1) * sizeof(int);
254 const int downmixParamSize =
255 sizeof(effect_param_t) + psizePadded + sizeof(downmix_type_t);
256 effect_param_t * const param = (effect_param_t *) malloc(downmixParamSize);
257 param->psize = sizeof(downmix_params_t);
258 const downmix_params_t downmixParam = DOWNMIX_PARAM_TYPE;
259 memcpy(param->data, &downmixParam, param->psize);
260 const downmix_type_t downmixType = DOWNMIX_TYPE_FOLD;
261 param->vsize = sizeof(downmix_type_t);
262 memcpy(param->data + psizePadded, &downmixType, param->vsize);
263 replySize = sizeof(int);
Mikhail Naganov4a3d5c22016-08-15 13:47:42 -0700264 status = mDownmixInterface->command(
Andy Hung857d5a22015-03-26 18:46:00 -0700265 EFFECT_CMD_SET_PARAM /* cmdCode */, downmixParamSize /* cmdSize */,
266 param /*pCmdData*/, &replySize, &cmdStatus /*pReplyData*/);
267 free(param);
268 if (status != 0 || cmdStatus != 0) {
269 ALOGE("DownmixerBufferProvider() error %d cmdStatus %d while setting downmix type",
270 status, cmdStatus);
Mikhail Naganov022b9952017-01-04 16:36:51 -0800271 mOutBuffer.clear();
272 mInBuffer.clear();
Mikhail Naganov4a3d5c22016-08-15 13:47:42 -0700273 mDownmixInterface.clear();
274 mEffectsFactory.clear();
Andy Hung857d5a22015-03-26 18:46:00 -0700275 return;
276 }
277 ALOGV("DownmixerBufferProvider() downmix type set to %d", (int) downmixType);
278}
279
280DownmixerBufferProvider::~DownmixerBufferProvider()
281{
282 ALOGV("~DownmixerBufferProvider (%p)", this);
Mikhail Naganov022b9952017-01-04 16:36:51 -0800283 if (mDownmixInterface != 0) {
284 mDownmixInterface->close();
285 }
Andy Hung857d5a22015-03-26 18:46:00 -0700286}
287
288void DownmixerBufferProvider::copyFrames(void *dst, const void *src, size_t frames)
289{
Mikhail Naganov022b9952017-01-04 16:36:51 -0800290 mInBuffer->setExternalData(const_cast<void*>(src));
291 mInBuffer->setFrameCount(frames);
Mikhail Naganov66916c22017-01-24 17:46:33 -0800292 mInBuffer->update(mInFrameSize * frames);
Mikhail Naganov022b9952017-01-04 16:36:51 -0800293 mOutBuffer->setFrameCount(frames);
Mikhail Naganov66916c22017-01-24 17:46:33 -0800294 mOutBuffer->setExternalData(dst);
295 if (dst != src) {
296 // Downmix may be accumulating, need to populate the output buffer
297 // with the dst data.
298 mOutBuffer->update(mOutFrameSize * frames);
299 }
Andy Hung857d5a22015-03-26 18:46:00 -0700300 // may be in-place if src == dst.
Mikhail Naganov022b9952017-01-04 16:36:51 -0800301 status_t res = mDownmixInterface->process();
302 if (res == OK) {
Mikhail Naganov66916c22017-01-24 17:46:33 -0800303 mOutBuffer->commit(mOutFrameSize * frames);
Mikhail Naganov022b9952017-01-04 16:36:51 -0800304 } else {
305 ALOGE("DownmixBufferProvider error %d", res);
306 }
Andy Hung857d5a22015-03-26 18:46:00 -0700307}
308
309/* call once in a pthread_once handler. */
310/*static*/ status_t DownmixerBufferProvider::init()
311{
312 // find multichannel downmix effect if we have to play multichannel content
Mikhail Naganov4a3d5c22016-08-15 13:47:42 -0700313 sp<EffectsFactoryHalInterface> effectsFactory = EffectsFactoryHalInterface::create();
Mikhail Naganov1dc98672016-08-18 17:50:29 -0700314 if (effectsFactory == 0) {
Mikhail Naganov4a3d5c22016-08-15 13:47:42 -0700315 ALOGE("AudioMixer() error: could not obtain the effects factory");
316 return NO_INIT;
317 }
Andy Hung857d5a22015-03-26 18:46:00 -0700318 uint32_t numEffects = 0;
Mikhail Naganov4a3d5c22016-08-15 13:47:42 -0700319 int ret = effectsFactory->queryNumberEffects(&numEffects);
Andy Hung857d5a22015-03-26 18:46:00 -0700320 if (ret != 0) {
321 ALOGE("AudioMixer() error %d querying number of effects", ret);
322 return NO_INIT;
323 }
324 ALOGV("EffectQueryNumberEffects() numEffects=%d", numEffects);
325
326 for (uint32_t i = 0 ; i < numEffects ; i++) {
Mikhail Naganov4a3d5c22016-08-15 13:47:42 -0700327 if (effectsFactory->getDescriptor(i, &sDwnmFxDesc) == 0) {
Andy Hung857d5a22015-03-26 18:46:00 -0700328 ALOGV("effect %d is called %s", i, sDwnmFxDesc.name);
329 if (memcmp(&sDwnmFxDesc.type, EFFECT_UIID_DOWNMIX, sizeof(effect_uuid_t)) == 0) {
330 ALOGI("found effect \"%s\" from %s",
331 sDwnmFxDesc.name, sDwnmFxDesc.implementor);
332 sIsMultichannelCapable = true;
333 break;
334 }
335 }
336 }
337 ALOGW_IF(!sIsMultichannelCapable, "unable to find downmix effect");
338 return NO_INIT;
339}
340
341/*static*/ bool DownmixerBufferProvider::sIsMultichannelCapable = false;
342/*static*/ effect_descriptor_t DownmixerBufferProvider::sDwnmFxDesc;
343
344RemixBufferProvider::RemixBufferProvider(audio_channel_mask_t inputChannelMask,
345 audio_channel_mask_t outputChannelMask, audio_format_t format,
346 size_t bufferFrameCount) :
347 CopyBufferProvider(
348 audio_bytes_per_sample(format)
349 * audio_channel_count_from_out_mask(inputChannelMask),
350 audio_bytes_per_sample(format)
351 * audio_channel_count_from_out_mask(outputChannelMask),
352 bufferFrameCount),
353 mFormat(format),
354 mSampleSize(audio_bytes_per_sample(format)),
355 mInputChannels(audio_channel_count_from_out_mask(inputChannelMask)),
356 mOutputChannels(audio_channel_count_from_out_mask(outputChannelMask))
357{
358 ALOGV("RemixBufferProvider(%p)(%#x, %#x, %#x) %zu %zu",
359 this, format, inputChannelMask, outputChannelMask,
360 mInputChannels, mOutputChannels);
Andy Hung18aa2702015-05-05 23:48:38 -0700361 (void) memcpy_by_index_array_initialization_from_channel_mask(
362 mIdxAry, ARRAY_SIZE(mIdxAry), outputChannelMask, inputChannelMask);
Andy Hung857d5a22015-03-26 18:46:00 -0700363}
364
365void RemixBufferProvider::copyFrames(void *dst, const void *src, size_t frames)
366{
367 memcpy_by_index_array(dst, mOutputChannels,
368 src, mInputChannels, mIdxAry, mSampleSize, frames);
369}
370
371ReformatBufferProvider::ReformatBufferProvider(int32_t channelCount,
372 audio_format_t inputFormat, audio_format_t outputFormat,
373 size_t bufferFrameCount) :
374 CopyBufferProvider(
375 channelCount * audio_bytes_per_sample(inputFormat),
376 channelCount * audio_bytes_per_sample(outputFormat),
377 bufferFrameCount),
378 mChannelCount(channelCount),
379 mInputFormat(inputFormat),
380 mOutputFormat(outputFormat)
381{
382 ALOGV("ReformatBufferProvider(%p)(%u, %#x, %#x)",
383 this, channelCount, inputFormat, outputFormat);
384}
385
386void ReformatBufferProvider::copyFrames(void *dst, const void *src, size_t frames)
387{
388 memcpy_by_audio_format(dst, mOutputFormat, src, mInputFormat, frames * mChannelCount);
389}
390
Kevin Rocarde053bfa2017-11-09 22:07:34 -0800391ClampFloatBufferProvider::ClampFloatBufferProvider(int32_t channelCount, size_t bufferFrameCount) :
392 CopyBufferProvider(
393 channelCount * audio_bytes_per_sample(AUDIO_FORMAT_PCM_FLOAT),
394 channelCount * audio_bytes_per_sample(AUDIO_FORMAT_PCM_FLOAT),
395 bufferFrameCount),
396 mChannelCount(channelCount)
397{
398 ALOGV("ClampFloatBufferProvider(%p)(%u)", this, channelCount);
399}
400
401void ClampFloatBufferProvider::copyFrames(void *dst, const void *src, size_t frames)
402{
403 memcpy_to_float_from_float_with_clamping((float*)dst, (const float*)src,
404 frames * mChannelCount,
405 FLOAT_NOMINAL_RANGE_HEADROOM);
406}
407
Andy Hungc5656cc2015-03-26 19:04:33 -0700408TimestretchBufferProvider::TimestretchBufferProvider(int32_t channelCount,
Ricardo Garcia5a8a95d2015-04-18 14:47:04 -0700409 audio_format_t format, uint32_t sampleRate, const AudioPlaybackRate &playbackRate) :
Andy Hungc5656cc2015-03-26 19:04:33 -0700410 mChannelCount(channelCount),
411 mFormat(format),
412 mSampleRate(sampleRate),
413 mFrameSize(channelCount * audio_bytes_per_sample(format)),
Andy Hungc5656cc2015-03-26 19:04:33 -0700414 mLocalBufferFrameCount(0),
415 mLocalBufferData(NULL),
Ricardo Garciaf097cae2015-04-13 12:17:21 -0700416 mRemaining(0),
Ricardo Garcia5a8a95d2015-04-18 14:47:04 -0700417 mSonicStream(sonicCreateStream(sampleRate, mChannelCount)),
Ricardo Garcia6c7f0622015-04-30 18:39:16 -0700418 mFallbackFailErrorShown(false),
419 mAudioPlaybackRateValid(false)
Andy Hungc5656cc2015-03-26 19:04:33 -0700420{
Ricardo Garciaf097cae2015-04-13 12:17:21 -0700421 LOG_ALWAYS_FATAL_IF(mSonicStream == NULL,
422 "TimestretchBufferProvider can't allocate Sonic stream");
Ricardo Garcia5a8a95d2015-04-18 14:47:04 -0700423
424 setPlaybackRate(playbackRate);
425 ALOGV("TimestretchBufferProvider(%p)(%u, %#x, %u %f %f %d %d)",
426 this, channelCount, format, sampleRate, playbackRate.mSpeed,
427 playbackRate.mPitch, playbackRate.mStretchMode, playbackRate.mFallbackMode);
428 mBuffer.frameCount = 0;
Andy Hungc5656cc2015-03-26 19:04:33 -0700429}
430
431TimestretchBufferProvider::~TimestretchBufferProvider()
432{
433 ALOGV("~TimestretchBufferProvider(%p)", this);
Ricardo Garciaf097cae2015-04-13 12:17:21 -0700434 sonicDestroyStream(mSonicStream);
Andy Hungc5656cc2015-03-26 19:04:33 -0700435 if (mBuffer.frameCount != 0) {
436 mTrackBufferProvider->releaseBuffer(&mBuffer);
437 }
438 free(mLocalBufferData);
439}
440
441status_t TimestretchBufferProvider::getNextBuffer(
Glenn Kastend79072e2016-01-06 08:41:20 -0800442 AudioBufferProvider::Buffer *pBuffer)
Andy Hungc5656cc2015-03-26 19:04:33 -0700443{
Glenn Kastend79072e2016-01-06 08:41:20 -0800444 ALOGV("TimestretchBufferProvider(%p)::getNextBuffer(%p (%zu))",
445 this, pBuffer, pBuffer->frameCount);
Andy Hungc5656cc2015-03-26 19:04:33 -0700446
447 // BYPASS
Glenn Kastend79072e2016-01-06 08:41:20 -0800448 //return mTrackBufferProvider->getNextBuffer(pBuffer);
Andy Hungc5656cc2015-03-26 19:04:33 -0700449
450 // check if previously processed data is sufficient.
451 if (pBuffer->frameCount <= mRemaining) {
452 ALOGV("previous sufficient");
453 pBuffer->raw = mLocalBufferData;
454 return OK;
455 }
456
457 // do we need to resize our buffer?
458 if (pBuffer->frameCount > mLocalBufferFrameCount) {
459 void *newmem;
460 if (posix_memalign(&newmem, 32, pBuffer->frameCount * mFrameSize) == OK) {
461 if (mRemaining != 0) {
462 memcpy(newmem, mLocalBufferData, mRemaining * mFrameSize);
463 }
464 free(mLocalBufferData);
465 mLocalBufferData = newmem;
466 mLocalBufferFrameCount = pBuffer->frameCount;
467 }
468 }
469
470 // need to fetch more data
471 const size_t outputDesired = pBuffer->frameCount - mRemaining;
Andy Hung6d626692015-08-21 12:53:46 -0700472 size_t dstAvailable;
473 do {
474 mBuffer.frameCount = mPlaybackRate.mSpeed == AUDIO_TIMESTRETCH_SPEED_NORMAL
475 ? outputDesired : outputDesired * mPlaybackRate.mSpeed + 1;
Andy Hungc5656cc2015-03-26 19:04:33 -0700476
Glenn Kastend79072e2016-01-06 08:41:20 -0800477 status_t res = mTrackBufferProvider->getNextBuffer(&mBuffer);
Andy Hungc5656cc2015-03-26 19:04:33 -0700478
Andy Hung6d626692015-08-21 12:53:46 -0700479 ALOG_ASSERT(res == OK || mBuffer.frameCount == 0);
480 if (res != OK || mBuffer.frameCount == 0) { // not needed by API spec, but to be safe.
481 ALOGV("upstream provider cannot provide data");
482 if (mRemaining == 0) {
483 pBuffer->raw = NULL;
484 pBuffer->frameCount = 0;
485 return res;
486 } else { // return partial count
487 pBuffer->raw = mLocalBufferData;
488 pBuffer->frameCount = mRemaining;
489 return OK;
490 }
Andy Hungc5656cc2015-03-26 19:04:33 -0700491 }
Andy Hungc5656cc2015-03-26 19:04:33 -0700492
Andy Hung6d626692015-08-21 12:53:46 -0700493 // time-stretch the data
494 dstAvailable = min(mLocalBufferFrameCount - mRemaining, outputDesired);
495 size_t srcAvailable = mBuffer.frameCount;
496 processFrames((uint8_t*)mLocalBufferData + mRemaining * mFrameSize, &dstAvailable,
497 mBuffer.raw, &srcAvailable);
Andy Hungc5656cc2015-03-26 19:04:33 -0700498
Andy Hung6d626692015-08-21 12:53:46 -0700499 // release all data consumed
500 mBuffer.frameCount = srcAvailable;
501 mTrackBufferProvider->releaseBuffer(&mBuffer);
502 } while (dstAvailable == 0); // try until we get output data or upstream provider fails.
Andy Hungc5656cc2015-03-26 19:04:33 -0700503
504 // update buffer vars with the actual data processed and return with buffer
505 mRemaining += dstAvailable;
506
507 pBuffer->raw = mLocalBufferData;
508 pBuffer->frameCount = mRemaining;
509
510 return OK;
511}
512
513void TimestretchBufferProvider::releaseBuffer(AudioBufferProvider::Buffer *pBuffer)
514{
515 ALOGV("TimestretchBufferProvider(%p)::releaseBuffer(%p (%zu))",
516 this, pBuffer, pBuffer->frameCount);
517
518 // BYPASS
519 //return mTrackBufferProvider->releaseBuffer(pBuffer);
520
521 // LOG_ALWAYS_FATAL_IF(pBuffer->frameCount == 0, "Invalid framecount");
522 if (pBuffer->frameCount < mRemaining) {
523 memcpy(mLocalBufferData,
524 (uint8_t*)mLocalBufferData + pBuffer->frameCount * mFrameSize,
525 (mRemaining - pBuffer->frameCount) * mFrameSize);
526 mRemaining -= pBuffer->frameCount;
527 } else if (pBuffer->frameCount == mRemaining) {
528 mRemaining = 0;
529 } else {
530 LOG_ALWAYS_FATAL("Releasing more frames(%zu) than available(%zu)",
531 pBuffer->frameCount, mRemaining);
532 }
533
534 pBuffer->raw = NULL;
535 pBuffer->frameCount = 0;
536}
537
538void TimestretchBufferProvider::reset()
539{
540 mRemaining = 0;
541}
542
Andy Hung930bbf92018-09-11 18:44:27 -0700543void TimestretchBufferProvider::setBufferProvider(AudioBufferProvider *p) {
544 ALOGV("%s(%p): mTrackBufferProvider:%p mBuffer.frameCount:%zu",
545 __func__, p, mTrackBufferProvider, mBuffer.frameCount);
546 if (mTrackBufferProvider == p) {
547 return;
548 }
549 mBuffer.frameCount = 0;
550 PassthruBufferProvider::setBufferProvider(p);
551}
552
Ricardo Garcia5a8a95d2015-04-18 14:47:04 -0700553status_t TimestretchBufferProvider::setPlaybackRate(const AudioPlaybackRate &playbackRate)
Andy Hungc5656cc2015-03-26 19:04:33 -0700554{
Ricardo Garcia5a8a95d2015-04-18 14:47:04 -0700555 mPlaybackRate = playbackRate;
556 mFallbackFailErrorShown = false;
557 sonicSetSpeed(mSonicStream, mPlaybackRate.mSpeed);
Ricardo Garciaf097cae2015-04-13 12:17:21 -0700558 //TODO: pitch is ignored for now
Ricardo Garcia5a8a95d2015-04-18 14:47:04 -0700559 //TODO: optimize: if parameters are the same, don't do any extra computation.
Ricardo Garcia6c7f0622015-04-30 18:39:16 -0700560
561 mAudioPlaybackRateValid = isAudioPlaybackRateValid(mPlaybackRate);
Andy Hungc5656cc2015-03-26 19:04:33 -0700562 return OK;
563}
564
565void TimestretchBufferProvider::processFrames(void *dstBuffer, size_t *dstFrames,
566 const void *srcBuffer, size_t *srcFrames)
567{
568 ALOGV("processFrames(%zu %zu) remaining(%zu)", *dstFrames, *srcFrames, mRemaining);
569 // Note dstFrames is the required number of frames.
570
Ricardo Garcia6c7f0622015-04-30 18:39:16 -0700571 if (!mAudioPlaybackRateValid) {
Ricardo Garcia5a8a95d2015-04-18 14:47:04 -0700572 //fallback mode
Andy Hungcf8d2c82016-08-10 16:02:01 -0700573 // Ensure consumption from src is as expected.
574 // TODO: add logic to track "very accurate" consumption related to speed, original sampling
575 // rate, actual frames processed.
576
577 const size_t targetSrc = *dstFrames * mPlaybackRate.mSpeed;
578 if (*srcFrames < targetSrc) { // limit dst frames to that possible
579 *dstFrames = *srcFrames / mPlaybackRate.mSpeed;
580 } else if (*srcFrames > targetSrc + 1) {
581 *srcFrames = targetSrc + 1;
582 }
Ricardo Garcia5a8a95d2015-04-18 14:47:04 -0700583 if (*dstFrames > 0) {
584 switch(mPlaybackRate.mFallbackMode) {
585 case AUDIO_TIMESTRETCH_FALLBACK_CUT_REPEAT:
586 if (*dstFrames <= *srcFrames) {
587 size_t copySize = mFrameSize * *dstFrames;
588 memcpy(dstBuffer, srcBuffer, copySize);
589 } else {
590 // cyclically repeat the source.
591 for (size_t count = 0; count < *dstFrames; count += *srcFrames) {
592 size_t remaining = min(*srcFrames, *dstFrames - count);
593 memcpy((uint8_t*)dstBuffer + mFrameSize * count,
594 srcBuffer, mFrameSize * remaining);
595 }
596 }
597 break;
598 case AUDIO_TIMESTRETCH_FALLBACK_DEFAULT:
599 case AUDIO_TIMESTRETCH_FALLBACK_MUTE:
600 memset(dstBuffer,0, mFrameSize * *dstFrames);
601 break;
602 case AUDIO_TIMESTRETCH_FALLBACK_FAIL:
603 default:
604 if(!mFallbackFailErrorShown) {
605 ALOGE("invalid parameters in TimestretchBufferProvider fallbackMode:%d",
606 mPlaybackRate.mFallbackMode);
607 mFallbackFailErrorShown = true;
608 }
609 break;
610 }
Andy Hungc5656cc2015-03-26 19:04:33 -0700611 }
Ricardo Garcia5a8a95d2015-04-18 14:47:04 -0700612 } else {
613 switch (mFormat) {
614 case AUDIO_FORMAT_PCM_FLOAT:
615 if (sonicWriteFloatToStream(mSonicStream, (float*)srcBuffer, *srcFrames) != 1) {
616 ALOGE("sonicWriteFloatToStream cannot realloc");
617 *srcFrames = 0; // cannot consume all of srcBuffer
618 }
619 *dstFrames = sonicReadFloatFromStream(mSonicStream, (float*)dstBuffer, *dstFrames);
620 break;
621 case AUDIO_FORMAT_PCM_16_BIT:
622 if (sonicWriteShortToStream(mSonicStream, (short*)srcBuffer, *srcFrames) != 1) {
623 ALOGE("sonicWriteShortToStream cannot realloc");
624 *srcFrames = 0; // cannot consume all of srcBuffer
625 }
626 *dstFrames = sonicReadShortFromStream(mSonicStream, (short*)dstBuffer, *dstFrames);
627 break;
628 default:
629 // could also be caught on construction
630 LOG_ALWAYS_FATAL("invalid format %#x for TimestretchBufferProvider", mFormat);
Ricardo Garciaf097cae2015-04-13 12:17:21 -0700631 }
Andy Hungc5656cc2015-03-26 19:04:33 -0700632 }
633}
jiabindce8f8c2018-12-10 17:49:31 -0800634
635AdjustChannelsBufferProvider::AdjustChannelsBufferProvider(audio_format_t format,
636 size_t inChannelCount, size_t outChannelCount, size_t frameCount) :
637 CopyBufferProvider(
638 audio_bytes_per_frame(inChannelCount, format),
639 audio_bytes_per_frame(outChannelCount, format),
640 frameCount),
641 mFormat(format),
642 mInChannelCount(inChannelCount),
643 mOutChannelCount(outChannelCount),
644 mSampleSizeInBytes(audio_bytes_per_sample(format))
645{
646 ALOGV("AdjustBufferProvider(%p)(%#x, %zu, %zu, %zu)",
647 this, format, inChannelCount, outChannelCount, frameCount);
648}
649
650void AdjustChannelsBufferProvider::copyFrames(void *dst, const void *src, size_t frames)
651{
652 adjust_channels(src, mInChannelCount, dst, mOutChannelCount, mSampleSizeInBytes,
653 frames * mInChannelCount * mSampleSizeInBytes);
654}
655
656AdjustChannelsNonDestructiveBufferProvider::AdjustChannelsNonDestructiveBufferProvider(
657 audio_format_t format, size_t inChannelCount, size_t outChannelCount,
658 audio_format_t contractedFormat, size_t contractedFrameCount, void* contractedBuffer) :
659 CopyBufferProvider(
660 audio_bytes_per_frame(inChannelCount, format),
661 audio_bytes_per_frame(outChannelCount, format),
662 0 /*bufferFrameCount*/),
663 mFormat(format),
664 mInChannelCount(inChannelCount),
665 mOutChannelCount(outChannelCount),
666 mSampleSizeInBytes(audio_bytes_per_sample(format)),
667 mContractedChannelCount(inChannelCount - outChannelCount),
668 mContractedFormat(contractedFormat),
669 mContractedFrameCount(contractedFrameCount),
670 mContractedBuffer(contractedBuffer),
671 mContractedWrittenFrames(0)
672{
673 ALOGV("AdjustChannelsNonDestructiveBufferProvider(%p)(%#x, %zu, %zu, %#x, %p)",
674 this, format, inChannelCount, outChannelCount, contractedFormat, contractedBuffer);
675 if (mContractedFormat != AUDIO_FORMAT_INVALID && mInChannelCount > mOutChannelCount) {
676 mContractedFrameSize = audio_bytes_per_frame(mContractedChannelCount, mContractedFormat);
677 }
678}
679
680status_t AdjustChannelsNonDestructiveBufferProvider::getNextBuffer(
681 AudioBufferProvider::Buffer* pBuffer)
682{
683 const size_t outFramesLeft = mContractedFrameCount - mContractedWrittenFrames;
684 if (outFramesLeft < pBuffer->frameCount) {
685 // Restrict the frame count so that we don't write over the size of the output buffer.
686 pBuffer->frameCount = outFramesLeft;
687 }
688 return CopyBufferProvider::getNextBuffer(pBuffer);
689}
690
691void AdjustChannelsNonDestructiveBufferProvider::copyFrames(
692 void *dst, const void *src, size_t frames)
693{
694 adjust_channels_non_destructive(src, mInChannelCount, dst, mOutChannelCount, mSampleSizeInBytes,
695 frames * mInChannelCount * mSampleSizeInBytes);
696 if (mContractedFormat != AUDIO_FORMAT_INVALID && mContractedBuffer != NULL
697 && mInChannelCount > mOutChannelCount) {
698 const size_t contractedIdx = frames * mOutChannelCount * mSampleSizeInBytes;
699 memcpy_by_audio_format(
700 (uint8_t*)mContractedBuffer + mContractedWrittenFrames * mContractedFrameSize,
701 mContractedFormat, (uint8_t*)dst + contractedIdx, mFormat,
702 mContractedChannelCount * frames);
703 mContractedWrittenFrames += frames;
704 }
705}
706
707void AdjustChannelsNonDestructiveBufferProvider::reset()
708{
709 mContractedWrittenFrames = 0;
710 CopyBufferProvider::reset();
711}
Andy Hung857d5a22015-03-26 18:46:00 -0700712// ----------------------------------------------------------------------------
713} // namespace android