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 <hardware/audio_effect.h> 22 23 24 #define min(x,y) (((x) < (y)) ? (x) : (y)) 25 26 namespace 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(). 49 template<class T, size_t bufSize> 50 class AudioFormatAdapter { 51 public: 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). configure(T & processor,int nChannels,uint8_t pcmFormat,uint32_t behavior)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. process(const void * pIn,void * pOut,uint32_t numSamples)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 // This branch of "if" is untested 79 if (mPcmFormat == AUDIO_FORMAT_PCM_8_24_BIT) { 80 if (mBehavior == EFFECT_BUFFER_ACCESS_WRITE) { 81 mpProcessor->process( 82 reinterpret_cast<const audio_sample_t *> (pIn), 83 reinterpret_cast<audio_sample_t *> (pOut), 84 numSamplesIter); 85 } else if (mBehavior == EFFECT_BUFFER_ACCESS_ACCUMULATE) { 86 mpProcessor->process( 87 reinterpret_cast<const audio_sample_t *> (pIn), 88 mBuffer, numSamplesIter); 89 MixOutput(pOut, numSamplesIter); 90 } else { 91 assert(false); 92 } 93 pIn = reinterpret_cast<const audio_sample_t *> (pIn) 94 + nSamplesChannels; 95 pOut = reinterpret_cast<audio_sample_t *> (pOut) 96 + nSamplesChannels; 97 } else { 98 ConvertInput(pIn, nSamplesChannels); 99 mpProcessor->process(mBuffer, mBuffer, numSamplesIter); 100 ConvertOutput(pOut, nSamplesChannels); 101 } 102 numSamples -= numSamplesIter; 103 } 104 } 105 106 private: 107 // The underlying processor. 108 T * mpProcessor; 109 // The number of input/output channels. 110 int mNumChannels; 111 // The desired PCM format. 112 uint8_t mPcmFormat; 113 // The desired buffer behavior. 114 uint32_t mBehavior; 115 // An intermediate buffer for processing. 116 audio_sample_t mBuffer[bufSize]; 117 // The buffer size, divided by the number of channels - represents the 118 // maximum number of multi-channel samples that can be stored in the 119 // intermediate buffer. 120 size_t mMaxSamplesPerCall; 121 122 // Converts a buffer of input samples to audio_sample_t format. 123 // Output is written to the intermediate buffer. 124 // pIn The input buffer with the format designated in configure(). 125 // When function exist will point to the next unread input 126 // sample. 127 // numSamples The number of single-channel samples to process. ConvertInput(const void * & pIn,uint32_t numSamples)128 void ConvertInput(const void *& pIn, uint32_t numSamples) { 129 if (mPcmFormat == AUDIO_FORMAT_PCM_16_BIT) { 130 const int16_t * pIn16 = reinterpret_cast<const int16_t *>(pIn); 131 audio_sample_t * pOut = mBuffer; 132 while (numSamples-- > 0) { 133 *(pOut++) = s15_to_audio_sample_t(*(pIn16++)); 134 } 135 pIn = pIn16; 136 } else { 137 assert(false); 138 } 139 } 140 141 // Converts audio_sample_t samples from the intermediate buffer to the 142 // output buffer, converting to the desired format and buffer behavior. 143 // pOut The buffer to write the output to. 144 // When function exist will point to the next output sample. 145 // numSamples The number of single-channel samples to process. ConvertOutput(void * & pOut,uint32_t numSamples)146 void ConvertOutput(void *& pOut, uint32_t numSamples) { 147 if (mPcmFormat == AUDIO_FORMAT_PCM_16_BIT) { 148 const audio_sample_t * pIn = mBuffer; 149 int16_t * pOut16 = reinterpret_cast<int16_t *>(pOut); 150 if (mBehavior == EFFECT_BUFFER_ACCESS_WRITE) { 151 while (numSamples-- > 0) { 152 *(pOut16++) = audio_sample_t_to_s15_clip(*(pIn++)); 153 } 154 } else if (mBehavior == EFFECT_BUFFER_ACCESS_ACCUMULATE) { 155 while (numSamples-- > 0) { 156 *(pOut16++) += audio_sample_t_to_s15_clip(*(pIn++)); 157 } 158 } else { 159 assert(false); 160 } 161 pOut = pOut16; 162 } else { 163 assert(false); 164 } 165 } 166 167 // Accumulate data from the intermediate buffer to the output. Output is 168 // assumed to be of audio_sample_t type. 169 // pOut The buffer to mix the output to. 170 // When function exist will point to the next output sample. 171 // numSamples The number of single-channel samples to process. MixOutput(void * & pOut,uint32_t numSamples)172 void MixOutput(void *& pOut, uint32_t numSamples) { 173 const audio_sample_t * pIn = mBuffer; 174 audio_sample_t * pOut24 = reinterpret_cast<audio_sample_t *>(pOut); 175 numSamples *= mNumChannels; 176 while (numSamples-- > 0) { 177 *(pOut24++) += *(pIn++); 178 } 179 pOut = pOut24; 180 } 181 }; 182 183 } 184 185 #endif // AUDIOFORMATADAPTER_H_ 186