1c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk/* 2c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk * Copyright (C) 2017 The Android Open Source Project 3c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk * 4c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk * Licensed under the Apache License, Version 2.0 (the "License"); 5c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk * you may not use this file except in compliance with the License. 6c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk * You may obtain a copy of the License at 7c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk * 8c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk * http://www.apache.org/licenses/LICENSE-2.0 9c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk * 10c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk * Unless required by applicable law or agreed to in writing, software 11c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk * distributed under the License is distributed on an "AS IS" BASIS, 12c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk * See the License for the specific language governing permissions and 14c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk * limitations under the License. 15c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk */ 16c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk 17c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk#define LOG_TAG "AAudioService" 18c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk//#define LOG_NDEBUG 0 19c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk#include <utils/Log.h> 20c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk 21c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk#include <cstring> 22c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk#include "AAudioMixer.h" 23c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk 24c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burkusing android::WrappingBuffer; 25c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burkusing android::FifoBuffer; 26c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burkusing android::fifo_frames_t; 27c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk 28c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil BurkAAudioMixer::~AAudioMixer() { 29c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk delete[] mOutputBuffer; 30c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk} 31c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk 32c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burkvoid AAudioMixer::allocate(int32_t samplesPerFrame, int32_t framesPerBurst) { 33c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk mSamplesPerFrame = samplesPerFrame; 34c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk mFramesPerBurst = framesPerBurst; 35c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk int32_t samplesPerBuffer = samplesPerFrame * framesPerBurst; 36c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk mOutputBuffer = new float[samplesPerBuffer]; 37c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk mBufferSizeInBytes = samplesPerBuffer * sizeof(float); 38c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk} 39c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk 40c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burkvoid AAudioMixer::clear() { 41c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk memset(mOutputBuffer, 0, mBufferSizeInBytes); 42c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk} 43c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk 4471f35bb687476694882a617ba4a810a0bb56fe23Phil Burkbool AAudioMixer::mix(FifoBuffer *fifo, float volume) { 45c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk WrappingBuffer wrappingBuffer; 46c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk float *destination = mOutputBuffer; 47c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk fifo_frames_t framesLeft = mFramesPerBurst; 48c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk 49c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk // Gather the data from the client. May be in two parts. 50c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk fifo->getFullDataAvailable(&wrappingBuffer); 51c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk 52c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk // Mix data in one or two parts. 53c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk int partIndex = 0; 54c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk while (framesLeft > 0 && partIndex < WrappingBuffer::SIZE) { 55c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk fifo_frames_t framesToMix = framesLeft; 56c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk fifo_frames_t framesAvailable = wrappingBuffer.numFrames[partIndex]; 57c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk if (framesAvailable > 0) { 58c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk if (framesToMix > framesAvailable) { 59c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk framesToMix = framesAvailable; 60c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk } 61c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk mixPart(destination, (float *)wrappingBuffer.data[partIndex], framesToMix, volume); 62c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk 63c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk destination += framesToMix * mSamplesPerFrame; 64c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk framesLeft -= framesToMix; 65c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk } 66c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk partIndex++; 67c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk } 68c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk fifo->getFifoControllerBase()->advanceReadIndex(mFramesPerBurst - framesLeft); 69c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk if (framesLeft > 0) { 7071f35bb687476694882a617ba4a810a0bb56fe23Phil Burk //ALOGW("AAudioMixer::mix() UNDERFLOW by %d / %d frames ----- UNDERFLOW !!!!!!!!!!", 7171f35bb687476694882a617ba4a810a0bb56fe23Phil Burk // framesLeft, mFramesPerBurst); 72c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk } 7371f35bb687476694882a617ba4a810a0bb56fe23Phil Burk return (framesLeft > 0); // did not get all the frames we needed, ie. "underflow" 74c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk} 75c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk 76c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burkvoid AAudioMixer::mixPart(float *destination, float *source, int32_t numFrames, float volume) { 77c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk int32_t numSamples = numFrames * mSamplesPerFrame; 78c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk // TODO maybe optimize using SIMD 79c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk for (int sampleIndex = 0; sampleIndex < numSamples; sampleIndex++) { 80c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk *destination++ += *source++ * volume; 81c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk } 82c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk} 83c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk 84c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burkfloat *AAudioMixer::getOutputBuffer() { 85c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk return mOutputBuffer; 86c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk} 87