1 /*
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
20 #include <algorithm>
21
22 #include <audio_utils/primitives.h>
23 #include <audio_utils/format.h>
24 #include <audio_utils/channels.h>
25 #include <sonic.h>
26 #include <media/audiohal/EffectBufferHalInterface.h>
27 #include <media/audiohal/EffectHalInterface.h>
28 #include <media/audiohal/EffectsFactoryHalInterface.h>
29 #include <media/AudioResamplerPublic.h>
30 #include <media/BufferProviders.h>
31 #include <system/audio_effects/effect_downmix.h>
32 #include <utils/Log.h>
33
34 #ifndef ARRAY_SIZE
35 #define ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0]))
36 #endif
37
38 namespace android {
39
40 // ----------------------------------------------------------------------------
CopyBufferProvider(size_t inputFrameSize,size_t outputFrameSize,size_t bufferFrameCount)41 CopyBufferProvider::CopyBufferProvider(size_t inputFrameSize,
42 size_t outputFrameSize, size_t bufferFrameCount) :
43 mInputFrameSize(inputFrameSize),
44 mOutputFrameSize(outputFrameSize),
45 mLocalBufferFrameCount(bufferFrameCount),
46 mLocalBufferData(NULL),
47 mConsumed(0)
48 {
49 ALOGV("CopyBufferProvider(%p)(%zu, %zu, %zu)", this,
50 inputFrameSize, outputFrameSize, bufferFrameCount);
51 LOG_ALWAYS_FATAL_IF(inputFrameSize < outputFrameSize && bufferFrameCount == 0,
52 "Requires local buffer if inputFrameSize(%zu) < outputFrameSize(%zu)",
53 inputFrameSize, outputFrameSize);
54 if (mLocalBufferFrameCount) {
55 (void)posix_memalign(&mLocalBufferData, 32, mLocalBufferFrameCount * mOutputFrameSize);
56 }
57 mBuffer.frameCount = 0;
58 }
59
~CopyBufferProvider()60 CopyBufferProvider::~CopyBufferProvider()
61 {
62 ALOGV("%s(%p) %zu %p %p",
63 __func__, this, mBuffer.frameCount, mTrackBufferProvider, mLocalBufferData);
64 if (mBuffer.frameCount != 0) {
65 mTrackBufferProvider->releaseBuffer(&mBuffer);
66 }
67 free(mLocalBufferData);
68 }
69
getNextBuffer(AudioBufferProvider::Buffer * pBuffer)70 status_t CopyBufferProvider::getNextBuffer(AudioBufferProvider::Buffer *pBuffer)
71 {
72 //ALOGV("CopyBufferProvider(%p)::getNextBuffer(%p (%zu))",
73 // this, pBuffer, pBuffer->frameCount);
74 if (mLocalBufferFrameCount == 0) {
75 status_t res = mTrackBufferProvider->getNextBuffer(pBuffer);
76 if (res == OK) {
77 copyFrames(pBuffer->raw, pBuffer->raw, pBuffer->frameCount);
78 }
79 return res;
80 }
81 if (mBuffer.frameCount == 0) {
82 mBuffer.frameCount = pBuffer->frameCount;
83 status_t res = mTrackBufferProvider->getNextBuffer(&mBuffer);
84 // At one time an upstream buffer provider had
85 // res == OK and mBuffer.frameCount == 0, doesn't seem to happen now 7/18/2014.
86 //
87 // By API spec, if res != OK, then mBuffer.frameCount == 0.
88 // but there may be improper implementations.
89 ALOG_ASSERT(res == OK || mBuffer.frameCount == 0);
90 if (res != OK || mBuffer.frameCount == 0) { // not needed by API spec, but to be safe.
91 pBuffer->raw = NULL;
92 pBuffer->frameCount = 0;
93 return res;
94 }
95 mConsumed = 0;
96 }
97 ALOG_ASSERT(mConsumed < mBuffer.frameCount);
98 size_t count = std::min(mLocalBufferFrameCount, mBuffer.frameCount - mConsumed);
99 count = std::min(count, pBuffer->frameCount);
100 pBuffer->raw = mLocalBufferData;
101 pBuffer->frameCount = count;
102 copyFrames(pBuffer->raw, (uint8_t*)mBuffer.raw + mConsumed * mInputFrameSize,
103 pBuffer->frameCount);
104 return OK;
105 }
106
releaseBuffer(AudioBufferProvider::Buffer * pBuffer)107 void CopyBufferProvider::releaseBuffer(AudioBufferProvider::Buffer *pBuffer)
108 {
109 //ALOGV("CopyBufferProvider(%p)::releaseBuffer(%p(%zu))",
110 // this, pBuffer, pBuffer->frameCount);
111 if (mLocalBufferFrameCount == 0) {
112 mTrackBufferProvider->releaseBuffer(pBuffer);
113 return;
114 }
115 // LOG_ALWAYS_FATAL_IF(pBuffer->frameCount == 0, "Invalid framecount");
116 mConsumed += pBuffer->frameCount; // TODO: update for efficiency to reuse existing content
117 if (mConsumed != 0 && mConsumed >= mBuffer.frameCount) {
118 mTrackBufferProvider->releaseBuffer(&mBuffer);
119 ALOG_ASSERT(mBuffer.frameCount == 0);
120 }
121 pBuffer->raw = NULL;
122 pBuffer->frameCount = 0;
123 }
124
reset()125 void CopyBufferProvider::reset()
126 {
127 if (mBuffer.frameCount != 0) {
128 mTrackBufferProvider->releaseBuffer(&mBuffer);
129 }
130 mConsumed = 0;
131 }
132
setBufferProvider(AudioBufferProvider * p)133 void CopyBufferProvider::setBufferProvider(AudioBufferProvider *p) {
134 ALOGV("%s(%p): mTrackBufferProvider:%p mBuffer.frameCount:%zu",
135 __func__, p, mTrackBufferProvider, mBuffer.frameCount);
136 if (mTrackBufferProvider == p) {
137 return;
138 }
139 mBuffer.frameCount = 0;
140 PassthruBufferProvider::setBufferProvider(p);
141 }
142
DownmixerBufferProvider(audio_channel_mask_t inputChannelMask,audio_channel_mask_t outputChannelMask,audio_format_t format,uint32_t sampleRate,int32_t sessionId,size_t bufferFrameCount)143 DownmixerBufferProvider::DownmixerBufferProvider(
144 audio_channel_mask_t inputChannelMask,
145 audio_channel_mask_t outputChannelMask, audio_format_t format,
146 uint32_t sampleRate, int32_t sessionId, size_t bufferFrameCount) :
147 CopyBufferProvider(
148 audio_bytes_per_sample(format) * audio_channel_count_from_out_mask(inputChannelMask),
149 audio_bytes_per_sample(format) * audio_channel_count_from_out_mask(outputChannelMask),
150 bufferFrameCount) // set bufferFrameCount to 0 to do in-place
151 {
152 ALOGV("DownmixerBufferProvider(%p)(%#x, %#x, %#x %u %d %d)",
153 this, inputChannelMask, outputChannelMask, format,
154 sampleRate, sessionId, (int)bufferFrameCount);
155 if (!sIsMultichannelCapable) {
156 ALOGE("DownmixerBufferProvider() error: not multichannel capable");
157 return;
158 }
159 mEffectsFactory = EffectsFactoryHalInterface::create();
160 if (mEffectsFactory == 0) {
161 ALOGE("DownmixerBufferProvider() error: could not obtain the effects factory");
162 return;
163 }
164 if (mEffectsFactory->createEffect(&sDwnmFxDesc.uuid,
165 sessionId,
166 SESSION_ID_INVALID_AND_IGNORED,
167 &mDownmixInterface) != 0) {
168 ALOGE("DownmixerBufferProvider() error creating downmixer effect");
169 mDownmixInterface.clear();
170 mEffectsFactory.clear();
171 return;
172 }
173 // channel input configuration will be overridden per-track
174 mDownmixConfig.inputCfg.channels = inputChannelMask; // FIXME: Should be bits
175 mDownmixConfig.outputCfg.channels = outputChannelMask; // FIXME: should be bits
176 mDownmixConfig.inputCfg.format = format;
177 mDownmixConfig.outputCfg.format = format;
178 mDownmixConfig.inputCfg.samplingRate = sampleRate;
179 mDownmixConfig.outputCfg.samplingRate = sampleRate;
180 mDownmixConfig.inputCfg.accessMode = EFFECT_BUFFER_ACCESS_READ;
181 mDownmixConfig.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_WRITE;
182 // input and output buffer provider, and frame count will not be used as the downmix effect
183 // process() function is called directly (see DownmixerBufferProvider::getNextBuffer())
184 mDownmixConfig.inputCfg.mask = EFFECT_CONFIG_SMP_RATE | EFFECT_CONFIG_CHANNELS |
185 EFFECT_CONFIG_FORMAT | EFFECT_CONFIG_ACC_MODE;
186 mDownmixConfig.outputCfg.mask = mDownmixConfig.inputCfg.mask;
187
188 mInFrameSize =
189 audio_bytes_per_sample(format) * audio_channel_count_from_out_mask(inputChannelMask);
190 mOutFrameSize =
191 audio_bytes_per_sample(format) * audio_channel_count_from_out_mask(outputChannelMask);
192 status_t status;
193 status = mEffectsFactory->mirrorBuffer(
194 nullptr, mInFrameSize * bufferFrameCount, &mInBuffer);
195 if (status != 0) {
196 ALOGE("DownmixerBufferProvider() error %d while creating input buffer", status);
197 mDownmixInterface.clear();
198 mEffectsFactory.clear();
199 return;
200 }
201 status = mEffectsFactory->mirrorBuffer(
202 nullptr, mOutFrameSize * bufferFrameCount, &mOutBuffer);
203 if (status != 0) {
204 ALOGE("DownmixerBufferProvider() error %d while creating output buffer", status);
205 mInBuffer.clear();
206 mDownmixInterface.clear();
207 mEffectsFactory.clear();
208 return;
209 }
210 mDownmixInterface->setInBuffer(mInBuffer);
211 mDownmixInterface->setOutBuffer(mOutBuffer);
212
213 int cmdStatus;
214 uint32_t replySize = sizeof(int);
215
216 // Configure downmixer
217 status = mDownmixInterface->command(
218 EFFECT_CMD_SET_CONFIG /*cmdCode*/, sizeof(effect_config_t) /*cmdSize*/,
219 &mDownmixConfig /*pCmdData*/,
220 &replySize, &cmdStatus /*pReplyData*/);
221 if (status != 0 || cmdStatus != 0) {
222 ALOGE("DownmixerBufferProvider() error %d cmdStatus %d while configuring downmixer",
223 status, cmdStatus);
224 mOutBuffer.clear();
225 mInBuffer.clear();
226 mDownmixInterface.clear();
227 mEffectsFactory.clear();
228 return;
229 }
230
231 // Enable downmixer
232 replySize = sizeof(int);
233 status = mDownmixInterface->command(
234 EFFECT_CMD_ENABLE /*cmdCode*/, 0 /*cmdSize*/, NULL /*pCmdData*/,
235 &replySize, &cmdStatus /*pReplyData*/);
236 if (status != 0 || cmdStatus != 0) {
237 ALOGE("DownmixerBufferProvider() error %d cmdStatus %d while enabling downmixer",
238 status, cmdStatus);
239 mOutBuffer.clear();
240 mInBuffer.clear();
241 mDownmixInterface.clear();
242 mEffectsFactory.clear();
243 return;
244 }
245
246 // Set downmix type
247 // parameter size rounded for padding on 32bit boundary
248 const int psizePadded = ((sizeof(downmix_params_t) - 1)/sizeof(int) + 1) * sizeof(int);
249 const int downmixParamSize =
250 sizeof(effect_param_t) + psizePadded + sizeof(downmix_type_t);
251 effect_param_t * const param = (effect_param_t *) malloc(downmixParamSize);
252 param->psize = sizeof(downmix_params_t);
253 const downmix_params_t downmixParam = DOWNMIX_PARAM_TYPE;
254 memcpy(param->data, &downmixParam, param->psize);
255 const downmix_type_t downmixType = DOWNMIX_TYPE_FOLD;
256 param->vsize = sizeof(downmix_type_t);
257 memcpy(param->data + psizePadded, &downmixType, param->vsize);
258 replySize = sizeof(int);
259 status = mDownmixInterface->command(
260 EFFECT_CMD_SET_PARAM /* cmdCode */, downmixParamSize /* cmdSize */,
261 param /*pCmdData*/, &replySize, &cmdStatus /*pReplyData*/);
262 free(param);
263 if (status != 0 || cmdStatus != 0) {
264 ALOGE("DownmixerBufferProvider() error %d cmdStatus %d while setting downmix type",
265 status, cmdStatus);
266 mOutBuffer.clear();
267 mInBuffer.clear();
268 mDownmixInterface.clear();
269 mEffectsFactory.clear();
270 return;
271 }
272 ALOGV("DownmixerBufferProvider() downmix type set to %d", (int) downmixType);
273 }
274
~DownmixerBufferProvider()275 DownmixerBufferProvider::~DownmixerBufferProvider()
276 {
277 ALOGV("~DownmixerBufferProvider (%p)", this);
278 if (mDownmixInterface != 0) {
279 mDownmixInterface->close();
280 }
281 }
282
copyFrames(void * dst,const void * src,size_t frames)283 void DownmixerBufferProvider::copyFrames(void *dst, const void *src, size_t frames)
284 {
285 mInBuffer->setExternalData(const_cast<void*>(src));
286 mInBuffer->setFrameCount(frames);
287 mInBuffer->update(mInFrameSize * frames);
288 mOutBuffer->setFrameCount(frames);
289 mOutBuffer->setExternalData(dst);
290 if (dst != src) {
291 // Downmix may be accumulating, need to populate the output buffer
292 // with the dst data.
293 mOutBuffer->update(mOutFrameSize * frames);
294 }
295 // may be in-place if src == dst.
296 status_t res = mDownmixInterface->process();
297 if (res == OK) {
298 mOutBuffer->commit(mOutFrameSize * frames);
299 } else {
300 ALOGE("DownmixBufferProvider error %d", res);
301 }
302 }
303
304 /* call once in a pthread_once handler. */
init()305 /*static*/ status_t DownmixerBufferProvider::init()
306 {
307 // find multichannel downmix effect if we have to play multichannel content
308 sp<EffectsFactoryHalInterface> effectsFactory = EffectsFactoryHalInterface::create();
309 if (effectsFactory == 0) {
310 ALOGE("AudioMixer() error: could not obtain the effects factory");
311 return NO_INIT;
312 }
313 uint32_t numEffects = 0;
314 int ret = effectsFactory->queryNumberEffects(&numEffects);
315 if (ret != 0) {
316 ALOGE("AudioMixer() error %d querying number of effects", ret);
317 return NO_INIT;
318 }
319 ALOGV("EffectQueryNumberEffects() numEffects=%d", numEffects);
320
321 for (uint32_t i = 0 ; i < numEffects ; i++) {
322 if (effectsFactory->getDescriptor(i, &sDwnmFxDesc) == 0) {
323 ALOGV("effect %d is called %s", i, sDwnmFxDesc.name);
324 if (memcmp(&sDwnmFxDesc.type, EFFECT_UIID_DOWNMIX, sizeof(effect_uuid_t)) == 0) {
325 ALOGI("found effect \"%s\" from %s",
326 sDwnmFxDesc.name, sDwnmFxDesc.implementor);
327 sIsMultichannelCapable = true;
328 break;
329 }
330 }
331 }
332 ALOGW_IF(!sIsMultichannelCapable, "unable to find downmix effect");
333 return NO_INIT;
334 }
335
336 /*static*/ bool DownmixerBufferProvider::sIsMultichannelCapable = false;
337 /*static*/ effect_descriptor_t DownmixerBufferProvider::sDwnmFxDesc;
338
RemixBufferProvider(audio_channel_mask_t inputChannelMask,audio_channel_mask_t outputChannelMask,audio_format_t format,size_t bufferFrameCount)339 RemixBufferProvider::RemixBufferProvider(audio_channel_mask_t inputChannelMask,
340 audio_channel_mask_t outputChannelMask, audio_format_t format,
341 size_t bufferFrameCount) :
342 CopyBufferProvider(
343 audio_bytes_per_sample(format)
344 * audio_channel_count_from_out_mask(inputChannelMask),
345 audio_bytes_per_sample(format)
346 * audio_channel_count_from_out_mask(outputChannelMask),
347 bufferFrameCount),
348 mFormat(format),
349 mSampleSize(audio_bytes_per_sample(format)),
350 mInputChannels(audio_channel_count_from_out_mask(inputChannelMask)),
351 mOutputChannels(audio_channel_count_from_out_mask(outputChannelMask))
352 {
353 ALOGV("RemixBufferProvider(%p)(%#x, %#x, %#x) %zu %zu",
354 this, format, inputChannelMask, outputChannelMask,
355 mInputChannels, mOutputChannels);
356 (void) memcpy_by_index_array_initialization_from_channel_mask(
357 mIdxAry, ARRAY_SIZE(mIdxAry), outputChannelMask, inputChannelMask);
358 }
359
copyFrames(void * dst,const void * src,size_t frames)360 void RemixBufferProvider::copyFrames(void *dst, const void *src, size_t frames)
361 {
362 memcpy_by_index_array(dst, mOutputChannels,
363 src, mInputChannels, mIdxAry, mSampleSize, frames);
364 }
365
ReformatBufferProvider(int32_t channelCount,audio_format_t inputFormat,audio_format_t outputFormat,size_t bufferFrameCount)366 ReformatBufferProvider::ReformatBufferProvider(int32_t channelCount,
367 audio_format_t inputFormat, audio_format_t outputFormat,
368 size_t bufferFrameCount) :
369 CopyBufferProvider(
370 channelCount * audio_bytes_per_sample(inputFormat),
371 channelCount * audio_bytes_per_sample(outputFormat),
372 bufferFrameCount),
373 mChannelCount(channelCount),
374 mInputFormat(inputFormat),
375 mOutputFormat(outputFormat)
376 {
377 ALOGV("ReformatBufferProvider(%p)(%u, %#x, %#x)",
378 this, channelCount, inputFormat, outputFormat);
379 }
380
copyFrames(void * dst,const void * src,size_t frames)381 void ReformatBufferProvider::copyFrames(void *dst, const void *src, size_t frames)
382 {
383 memcpy_by_audio_format(dst, mOutputFormat, src, mInputFormat, frames * mChannelCount);
384 }
385
ClampFloatBufferProvider(int32_t channelCount,size_t bufferFrameCount)386 ClampFloatBufferProvider::ClampFloatBufferProvider(int32_t channelCount, size_t bufferFrameCount) :
387 CopyBufferProvider(
388 channelCount * audio_bytes_per_sample(AUDIO_FORMAT_PCM_FLOAT),
389 channelCount * audio_bytes_per_sample(AUDIO_FORMAT_PCM_FLOAT),
390 bufferFrameCount),
391 mChannelCount(channelCount)
392 {
393 ALOGV("ClampFloatBufferProvider(%p)(%u)", this, channelCount);
394 }
395
copyFrames(void * dst,const void * src,size_t frames)396 void ClampFloatBufferProvider::copyFrames(void *dst, const void *src, size_t frames)
397 {
398 memcpy_to_float_from_float_with_clamping((float*)dst, (const float*)src,
399 frames * mChannelCount,
400 FLOAT_NOMINAL_RANGE_HEADROOM);
401 }
402
TimestretchBufferProvider(int32_t channelCount,audio_format_t format,uint32_t sampleRate,const AudioPlaybackRate & playbackRate)403 TimestretchBufferProvider::TimestretchBufferProvider(int32_t channelCount,
404 audio_format_t format, uint32_t sampleRate, const AudioPlaybackRate &playbackRate) :
405 mChannelCount(channelCount),
406 mFormat(format),
407 mSampleRate(sampleRate),
408 mFrameSize(channelCount * audio_bytes_per_sample(format)),
409 mLocalBufferFrameCount(0),
410 mLocalBufferData(NULL),
411 mRemaining(0),
412 mSonicStream(sonicCreateStream(sampleRate, mChannelCount)),
413 mFallbackFailErrorShown(false),
414 mAudioPlaybackRateValid(false)
415 {
416 LOG_ALWAYS_FATAL_IF(mSonicStream == NULL,
417 "TimestretchBufferProvider can't allocate Sonic stream");
418
419 setPlaybackRate(playbackRate);
420 ALOGV("TimestretchBufferProvider(%p)(%u, %#x, %u %f %f %d %d)",
421 this, channelCount, format, sampleRate, playbackRate.mSpeed,
422 playbackRate.mPitch, playbackRate.mStretchMode, playbackRate.mFallbackMode);
423 mBuffer.frameCount = 0;
424 }
425
~TimestretchBufferProvider()426 TimestretchBufferProvider::~TimestretchBufferProvider()
427 {
428 ALOGV("~TimestretchBufferProvider(%p)", this);
429 sonicDestroyStream(mSonicStream);
430 if (mBuffer.frameCount != 0) {
431 mTrackBufferProvider->releaseBuffer(&mBuffer);
432 }
433 free(mLocalBufferData);
434 }
435
getNextBuffer(AudioBufferProvider::Buffer * pBuffer)436 status_t TimestretchBufferProvider::getNextBuffer(
437 AudioBufferProvider::Buffer *pBuffer)
438 {
439 ALOGV("TimestretchBufferProvider(%p)::getNextBuffer(%p (%zu))",
440 this, pBuffer, pBuffer->frameCount);
441
442 // BYPASS
443 //return mTrackBufferProvider->getNextBuffer(pBuffer);
444
445 // check if previously processed data is sufficient.
446 if (pBuffer->frameCount <= mRemaining) {
447 ALOGV("previous sufficient");
448 pBuffer->raw = mLocalBufferData;
449 return OK;
450 }
451
452 // do we need to resize our buffer?
453 if (pBuffer->frameCount > mLocalBufferFrameCount) {
454 void *newmem;
455 if (posix_memalign(&newmem, 32, pBuffer->frameCount * mFrameSize) == OK) {
456 if (mRemaining != 0) {
457 memcpy(newmem, mLocalBufferData, mRemaining * mFrameSize);
458 }
459 free(mLocalBufferData);
460 mLocalBufferData = newmem;
461 mLocalBufferFrameCount = pBuffer->frameCount;
462 }
463 }
464
465 // need to fetch more data
466 const size_t outputDesired = pBuffer->frameCount - mRemaining;
467 size_t dstAvailable;
468 do {
469 mBuffer.frameCount = mPlaybackRate.mSpeed == AUDIO_TIMESTRETCH_SPEED_NORMAL
470 ? outputDesired : outputDesired * mPlaybackRate.mSpeed + 1;
471
472 status_t res = mTrackBufferProvider->getNextBuffer(&mBuffer);
473
474 ALOG_ASSERT(res == OK || mBuffer.frameCount == 0);
475 if (res != OK || mBuffer.frameCount == 0) { // not needed by API spec, but to be safe.
476 ALOGV("upstream provider cannot provide data");
477 if (mRemaining == 0) {
478 pBuffer->raw = NULL;
479 pBuffer->frameCount = 0;
480 return res;
481 } else { // return partial count
482 pBuffer->raw = mLocalBufferData;
483 pBuffer->frameCount = mRemaining;
484 return OK;
485 }
486 }
487
488 // time-stretch the data
489 dstAvailable = std::min(mLocalBufferFrameCount - mRemaining, outputDesired);
490 size_t srcAvailable = mBuffer.frameCount;
491 processFrames((uint8_t*)mLocalBufferData + mRemaining * mFrameSize, &dstAvailable,
492 mBuffer.raw, &srcAvailable);
493
494 // release all data consumed
495 mBuffer.frameCount = srcAvailable;
496 mTrackBufferProvider->releaseBuffer(&mBuffer);
497 } while (dstAvailable == 0); // try until we get output data or upstream provider fails.
498
499 // update buffer vars with the actual data processed and return with buffer
500 mRemaining += dstAvailable;
501
502 pBuffer->raw = mLocalBufferData;
503 pBuffer->frameCount = mRemaining;
504
505 return OK;
506 }
507
releaseBuffer(AudioBufferProvider::Buffer * pBuffer)508 void TimestretchBufferProvider::releaseBuffer(AudioBufferProvider::Buffer *pBuffer)
509 {
510 ALOGV("TimestretchBufferProvider(%p)::releaseBuffer(%p (%zu))",
511 this, pBuffer, pBuffer->frameCount);
512
513 // BYPASS
514 //return mTrackBufferProvider->releaseBuffer(pBuffer);
515
516 // LOG_ALWAYS_FATAL_IF(pBuffer->frameCount == 0, "Invalid framecount");
517 if (pBuffer->frameCount < mRemaining) {
518 memcpy(mLocalBufferData,
519 (uint8_t*)mLocalBufferData + pBuffer->frameCount * mFrameSize,
520 (mRemaining - pBuffer->frameCount) * mFrameSize);
521 mRemaining -= pBuffer->frameCount;
522 } else if (pBuffer->frameCount == mRemaining) {
523 mRemaining = 0;
524 } else {
525 LOG_ALWAYS_FATAL("Releasing more frames(%zu) than available(%zu)",
526 pBuffer->frameCount, mRemaining);
527 }
528
529 pBuffer->raw = NULL;
530 pBuffer->frameCount = 0;
531 }
532
reset()533 void TimestretchBufferProvider::reset()
534 {
535 mRemaining = 0;
536 }
537
setBufferProvider(AudioBufferProvider * p)538 void TimestretchBufferProvider::setBufferProvider(AudioBufferProvider *p) {
539 ALOGV("%s(%p): mTrackBufferProvider:%p mBuffer.frameCount:%zu",
540 __func__, p, mTrackBufferProvider, mBuffer.frameCount);
541 if (mTrackBufferProvider == p) {
542 return;
543 }
544 mBuffer.frameCount = 0;
545 PassthruBufferProvider::setBufferProvider(p);
546 }
547
setPlaybackRate(const AudioPlaybackRate & playbackRate)548 status_t TimestretchBufferProvider::setPlaybackRate(const AudioPlaybackRate &playbackRate)
549 {
550 mPlaybackRate = playbackRate;
551 mFallbackFailErrorShown = false;
552 sonicSetSpeed(mSonicStream, mPlaybackRate.mSpeed);
553 //TODO: pitch is ignored for now
554 //TODO: optimize: if parameters are the same, don't do any extra computation.
555
556 mAudioPlaybackRateValid = isAudioPlaybackRateValid(mPlaybackRate);
557 return OK;
558 }
559
processFrames(void * dstBuffer,size_t * dstFrames,const void * srcBuffer,size_t * srcFrames)560 void TimestretchBufferProvider::processFrames(void *dstBuffer, size_t *dstFrames,
561 const void *srcBuffer, size_t *srcFrames)
562 {
563 ALOGV("processFrames(%zu %zu) remaining(%zu)", *dstFrames, *srcFrames, mRemaining);
564 // Note dstFrames is the required number of frames.
565
566 if (!mAudioPlaybackRateValid) {
567 //fallback mode
568 // Ensure consumption from src is as expected.
569 // TODO: add logic to track "very accurate" consumption related to speed, original sampling
570 // rate, actual frames processed.
571
572 const size_t targetSrc = *dstFrames * mPlaybackRate.mSpeed;
573 if (*srcFrames < targetSrc) { // limit dst frames to that possible
574 *dstFrames = *srcFrames / mPlaybackRate.mSpeed;
575 } else if (*srcFrames > targetSrc + 1) {
576 *srcFrames = targetSrc + 1;
577 }
578 if (*dstFrames > 0) {
579 switch(mPlaybackRate.mFallbackMode) {
580 case AUDIO_TIMESTRETCH_FALLBACK_CUT_REPEAT:
581 if (*dstFrames <= *srcFrames) {
582 size_t copySize = mFrameSize * *dstFrames;
583 memcpy(dstBuffer, srcBuffer, copySize);
584 } else {
585 // cyclically repeat the source.
586 for (size_t count = 0; count < *dstFrames; count += *srcFrames) {
587 size_t remaining = std::min(*srcFrames, *dstFrames - count);
588 memcpy((uint8_t*)dstBuffer + mFrameSize * count,
589 srcBuffer, mFrameSize * remaining);
590 }
591 }
592 break;
593 case AUDIO_TIMESTRETCH_FALLBACK_DEFAULT:
594 case AUDIO_TIMESTRETCH_FALLBACK_MUTE:
595 memset(dstBuffer,0, mFrameSize * *dstFrames);
596 break;
597 case AUDIO_TIMESTRETCH_FALLBACK_FAIL:
598 default:
599 if(!mFallbackFailErrorShown) {
600 ALOGE("invalid parameters in TimestretchBufferProvider fallbackMode:%d",
601 mPlaybackRate.mFallbackMode);
602 mFallbackFailErrorShown = true;
603 }
604 break;
605 }
606 }
607 } else {
608 switch (mFormat) {
609 case AUDIO_FORMAT_PCM_FLOAT:
610 if (sonicWriteFloatToStream(mSonicStream, (float*)srcBuffer, *srcFrames) != 1) {
611 ALOGE("sonicWriteFloatToStream cannot realloc");
612 *srcFrames = 0; // cannot consume all of srcBuffer
613 }
614 *dstFrames = sonicReadFloatFromStream(mSonicStream, (float*)dstBuffer, *dstFrames);
615 break;
616 case AUDIO_FORMAT_PCM_16_BIT:
617 if (sonicWriteShortToStream(mSonicStream, (short*)srcBuffer, *srcFrames) != 1) {
618 ALOGE("sonicWriteShortToStream cannot realloc");
619 *srcFrames = 0; // cannot consume all of srcBuffer
620 }
621 *dstFrames = sonicReadShortFromStream(mSonicStream, (short*)dstBuffer, *dstFrames);
622 break;
623 default:
624 // could also be caught on construction
625 LOG_ALWAYS_FATAL("invalid format %#x for TimestretchBufferProvider", mFormat);
626 }
627 }
628 }
629
AdjustChannelsBufferProvider(audio_format_t format,size_t inChannelCount,size_t outChannelCount,size_t frameCount,audio_format_t contractedFormat,void * contractedBuffer)630 AdjustChannelsBufferProvider::AdjustChannelsBufferProvider(
631 audio_format_t format, size_t inChannelCount, size_t outChannelCount,
632 size_t frameCount, audio_format_t contractedFormat, void* contractedBuffer) :
633 CopyBufferProvider(
634 audio_bytes_per_frame(inChannelCount, format),
635 audio_bytes_per_frame(std::max(inChannelCount, outChannelCount), format),
636 frameCount),
637 mFormat(format),
638 mInChannelCount(inChannelCount),
639 mOutChannelCount(outChannelCount),
640 mSampleSizeInBytes(audio_bytes_per_sample(format)),
641 mFrameCount(frameCount),
642 mContractedChannelCount(inChannelCount - outChannelCount),
643 mContractedFormat(contractedFormat),
644 mContractedBuffer(contractedBuffer),
645 mContractedWrittenFrames(0)
646 {
647 ALOGV("AdjustChannelsBufferProvider(%p)(%#x, %zu, %zu, %zu, %#x, %p)", this, format,
648 inChannelCount, outChannelCount, frameCount, contractedFormat, contractedBuffer);
649 if (mContractedFormat != AUDIO_FORMAT_INVALID && mInChannelCount > mOutChannelCount) {
650 mContractedFrameSize = audio_bytes_per_frame(mContractedChannelCount, mContractedFormat);
651 }
652 }
653
getNextBuffer(AudioBufferProvider::Buffer * pBuffer)654 status_t AdjustChannelsBufferProvider::getNextBuffer(AudioBufferProvider::Buffer* pBuffer)
655 {
656 if (mContractedBuffer != nullptr) {
657 // Restrict frame count only when it is needed to save contracted frames.
658 const size_t outFramesLeft = mFrameCount - mContractedWrittenFrames;
659 if (outFramesLeft < pBuffer->frameCount) {
660 // Restrict the frame count so that we don't write over the size of the output buffer.
661 pBuffer->frameCount = outFramesLeft;
662 }
663 }
664 return CopyBufferProvider::getNextBuffer(pBuffer);
665 }
666
copyFrames(void * dst,const void * src,size_t frames)667 void AdjustChannelsBufferProvider::copyFrames(void *dst, const void *src, size_t frames)
668 {
669 if (mInChannelCount > mOutChannelCount) {
670 // For case multi to mono, adjust_channels has special logic that will mix first two input
671 // channels into a single output channel. In that case, use adjust_channels_non_destructive
672 // to keep only one channel data even when contracting to mono.
673 adjust_channels_non_destructive(src, mInChannelCount, dst, mOutChannelCount,
674 mSampleSizeInBytes, frames * mInChannelCount * mSampleSizeInBytes);
675 if (mContractedFormat != AUDIO_FORMAT_INVALID
676 && mContractedBuffer != nullptr) {
677 const size_t contractedIdx = frames * mOutChannelCount * mSampleSizeInBytes;
678 memcpy_by_audio_format(
679 (uint8_t*) mContractedBuffer + mContractedWrittenFrames * mContractedFrameSize,
680 mContractedFormat, (uint8_t*) dst + contractedIdx, mFormat,
681 mContractedChannelCount * frames);
682 mContractedWrittenFrames += frames;
683 }
684 } else {
685 // Prefer expanding data from the end of each audio frame.
686 adjust_channels(src, mInChannelCount, dst, mOutChannelCount,
687 mSampleSizeInBytes, frames * mInChannelCount * mSampleSizeInBytes);
688 }
689 }
690
reset()691 void AdjustChannelsBufferProvider::reset()
692 {
693 mContractedWrittenFrames = 0;
694 CopyBufferProvider::reset();
695 }
696 // ----------------------------------------------------------------------------
697 } // namespace android
698