• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 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 "AAudioService"
18 //#define LOG_NDEBUG 0
19 #include <utils/Log.h>
20 
21 #include <cstring>
22 #include "AAudioMixer.h"
23 
24 using android::WrappingBuffer;
25 using android::FifoBuffer;
26 using android::fifo_frames_t;
27 
~AAudioMixer()28 AAudioMixer::~AAudioMixer() {
29     delete[] mOutputBuffer;
30 }
31 
allocate(int32_t samplesPerFrame,int32_t framesPerBurst)32 void AAudioMixer::allocate(int32_t samplesPerFrame, int32_t framesPerBurst) {
33     mSamplesPerFrame = samplesPerFrame;
34     mFramesPerBurst = framesPerBurst;
35     int32_t samplesPerBuffer = samplesPerFrame * framesPerBurst;
36     mOutputBuffer = new float[samplesPerBuffer];
37     mBufferSizeInBytes = samplesPerBuffer * sizeof(float);
38 }
39 
clear()40 void AAudioMixer::clear() {
41     memset(mOutputBuffer, 0, mBufferSizeInBytes);
42 }
43 
mix(FifoBuffer * fifo,float volume)44 bool AAudioMixer::mix(FifoBuffer *fifo, float volume) {
45     WrappingBuffer wrappingBuffer;
46     float *destination = mOutputBuffer;
47     fifo_frames_t framesLeft = mFramesPerBurst;
48 
49     // Gather the data from the client. May be in two parts.
50     fifo->getFullDataAvailable(&wrappingBuffer);
51 
52     // Mix data in one or two parts.
53     int partIndex = 0;
54     while (framesLeft > 0 && partIndex < WrappingBuffer::SIZE) {
55         fifo_frames_t framesToMix = framesLeft;
56         fifo_frames_t framesAvailable = wrappingBuffer.numFrames[partIndex];
57         if (framesAvailable > 0) {
58             if (framesToMix > framesAvailable) {
59                 framesToMix = framesAvailable;
60             }
61             mixPart(destination, (float *)wrappingBuffer.data[partIndex], framesToMix, volume);
62 
63             destination += framesToMix * mSamplesPerFrame;
64             framesLeft -= framesToMix;
65         }
66         partIndex++;
67     }
68     fifo->getFifoControllerBase()->advanceReadIndex(mFramesPerBurst - framesLeft);
69     if (framesLeft > 0) {
70         //ALOGW("AAudioMixer::mix() UNDERFLOW by %d / %d frames ----- UNDERFLOW !!!!!!!!!!",
71         //      framesLeft, mFramesPerBurst);
72     }
73     return (framesLeft > 0); // did not get all the frames we needed, ie. "underflow"
74 }
75 
mixPart(float * destination,float * source,int32_t numFrames,float volume)76 void AAudioMixer::mixPart(float *destination, float *source, int32_t numFrames, float volume) {
77     int32_t numSamples = numFrames * mSamplesPerFrame;
78     // TODO maybe optimize using SIMD
79     for (int sampleIndex = 0; sampleIndex < numSamples; sampleIndex++) {
80         *destination++ += *source++ * volume;
81     }
82 }
83 
getOutputBuffer()84 float *AAudioMixer::getOutputBuffer() {
85     return mOutputBuffer;
86 }
87