1/* /android/src/frameworks/base/media/libeffects/AudioFormatAdapter.h 2** 3** Copyright 2009, The Android Open Source Project 4** 5** Licensed under the Apache License, Version 2.0 (the "License"); 6** you may not use this file except in compliance with the License. 7** You may obtain a copy of the License at 8** 9** http://www.apache.org/licenses/LICENSE-2.0 10** 11** Unless required by applicable law or agreed to in writing, software 12** distributed under the License is distributed on an "AS IS" BASIS, 13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14** See the License for the specific language governing permissions and 15** limitations under the License. 16*/ 17 18#ifndef AUDIOFORMATADAPTER_H_ 19#define AUDIOFORMATADAPTER_H_ 20 21#include <media/EffectApi.h> 22 23 24#define min(x,y) (((x) < (y)) ? (x) : (y)) 25 26namespace android { 27 28// An adapter for an audio processor working on audio_sample_t samples with a 29// buffer override behavior to arbitrary sample formats and buffer behaviors. 30// The adapter may work on any processing class which has a processing function 31// with the following signature: 32// void process(const audio_sample_t * pIn, 33// audio_sample_t * pOut, 34// int frameCount); 35// It is assumed that the underlying processor works in S7.24 format and an 36// overwrite behavior. 37// 38// Usage is simple: just work with the processor normally, but instead of 39// calling its process() function directly, work with the process() function of 40// the adapter. 41// The adapter supports re-configuration to a different format on the fly. 42// 43// T The processor class. 44// bufSize The maximum number of samples (single channel) to process on a 45// single call to the underlying processor. Setting this to a small 46// number will save a little memory, but will cost function call 47// overhead, resulting from multiple calls to the underlying process() 48// per a single call to this class's process(). 49template<class T, size_t bufSize> 50class AudioFormatAdapter { 51public: 52 // Configure the adapter. 53 // processor The underlying audio processor. 54 // nChannels Number of input and output channels. The adapter does not do 55 // channel conversion - this parameter must be in sync with the 56 // actual processor. 57 // pcmFormat The desired input/output sample format. 58 // behavior The desired behavior (overwrite or accumulate). 59 void configure(T & processor, int nChannels, uint8_t pcmFormat, 60 uint32_t behavior) { 61 mpProcessor = &processor; 62 mNumChannels = nChannels; 63 mPcmFormat = pcmFormat; 64 mBehavior = behavior; 65 mMaxSamplesPerCall = bufSize / nChannels; 66 } 67 68 // Process a block of samples. 69 // pIn A buffer of samples with the format specified on 70 // configure(). 71 // pOut A buffer of samples with the format specified on 72 // configure(). May be the same as pIn. 73 // numSamples The number of multi-channel samples to process. 74 void process(const void * pIn, void * pOut, uint32_t numSamples) { 75 while (numSamples > 0) { 76 uint32_t numSamplesIter = min(numSamples, mMaxSamplesPerCall); 77 uint32_t nSamplesChannels = numSamplesIter * mNumChannels; 78 if (mPcmFormat == SAMPLE_FORMAT_PCM_S7_24) { 79 if (mBehavior == EFFECT_BUFFER_ACCESS_WRITE) { 80 mpProcessor->process( 81 reinterpret_cast<const audio_sample_t *> (pIn), 82 reinterpret_cast<audio_sample_t *> (pOut), 83 numSamplesIter); 84 } else if (mBehavior == EFFECT_BUFFER_ACCESS_ACCUMULATE) { 85 mpProcessor->process( 86 reinterpret_cast<const audio_sample_t *> (pIn), 87 mBuffer, numSamplesIter); 88 MixOutput(pOut, numSamplesIter); 89 } else { 90 assert(false); 91 } 92 pIn = reinterpret_cast<const audio_sample_t *> (pIn) 93 + nSamplesChannels; 94 pOut = reinterpret_cast<audio_sample_t *> (pOut) 95 + nSamplesChannels; 96 } else { 97 ConvertInput(pIn, nSamplesChannels); 98 mpProcessor->process(mBuffer, mBuffer, numSamplesIter); 99 ConvertOutput(pOut, nSamplesChannels); 100 } 101 numSamples -= numSamplesIter; 102 } 103 } 104 105private: 106 // The underlying processor. 107 T * mpProcessor; 108 // The number of input/output channels. 109 int mNumChannels; 110 // The desired PCM format. 111 uint8_t mPcmFormat; 112 // The desired buffer behavior. 113 uint32_t mBehavior; 114 // An intermediate buffer for processing. 115 audio_sample_t mBuffer[bufSize]; 116 // The buffer size, divided by the number of channels - represents the 117 // maximum number of multi-channel samples that can be stored in the 118 // intermediate buffer. 119 size_t mMaxSamplesPerCall; 120 121 // Converts a buffer of input samples to audio_sample_t format. 122 // Output is written to the intermediate buffer. 123 // pIn The input buffer with the format designated in configure(). 124 // When function exist will point to the next unread input 125 // sample. 126 // numSamples The number of single-channel samples to process. 127 void ConvertInput(const void *& pIn, uint32_t numSamples) { 128 if (mPcmFormat == SAMPLE_FORMAT_PCM_S15) { 129 const int16_t * pIn16 = reinterpret_cast<const int16_t *>(pIn); 130 audio_sample_t * pOut = mBuffer; 131 while (numSamples-- > 0) { 132 *(pOut++) = s15_to_audio_sample_t(*(pIn16++)); 133 } 134 pIn = pIn16; 135 } else { 136 assert(false); 137 } 138 } 139 140 // Converts audio_sample_t samples from the intermediate buffer to the 141 // output buffer, converting to the desired format and buffer behavior. 142 // pOut The buffer to write the output to. 143 // When function exist will point to the next output sample. 144 // numSamples The number of single-channel samples to process. 145 void ConvertOutput(void *& pOut, uint32_t numSamples) { 146 if (mPcmFormat == SAMPLE_FORMAT_PCM_S15) { 147 const audio_sample_t * pIn = mBuffer; 148 int16_t * pOut16 = reinterpret_cast<int16_t *>(pOut); 149 if (mBehavior == EFFECT_BUFFER_ACCESS_WRITE) { 150 while (numSamples-- > 0) { 151 *(pOut16++) = audio_sample_t_to_s15_clip(*(pIn++)); 152 } 153 } else if (mBehavior == EFFECT_BUFFER_ACCESS_ACCUMULATE) { 154 while (numSamples-- > 0) { 155 *(pOut16++) += audio_sample_t_to_s15_clip(*(pIn++)); 156 } 157 } else { 158 assert(false); 159 } 160 pOut = pOut16; 161 } else { 162 assert(false); 163 } 164 } 165 166 // Accumulate data from the intermediate buffer to the output. Output is 167 // assumed to be of audio_sample_t type. 168 // pOut The buffer to mix the output to. 169 // When function exist will point to the next output sample. 170 // numSamples The number of single-channel samples to process. 171 void MixOutput(void *& pOut, uint32_t numSamples) { 172 const audio_sample_t * pIn = mBuffer; 173 audio_sample_t * pOut24 = reinterpret_cast<audio_sample_t *>(pOut); 174 numSamples *= mNumChannels; 175 while (numSamples-- > 0) { 176 *(pOut24++) += *(pIn++); 177 } 178 pOut = pOut24; 179 } 180}; 181 182} 183 184#endif // AUDIOFORMATADAPTER_H_ 185