1135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent/* /android/src/frameworks/base/media/libeffects/AudioFormatAdapter.h 2135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent** 3135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent** Copyright 2009, The Android Open Source Project 4135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent** 5135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent** Licensed under the Apache License, Version 2.0 (the "License"); 6135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent** you may not use this file except in compliance with the License. 7135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent** You may obtain a copy of the License at 8135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent** 9135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent** http://www.apache.org/licenses/LICENSE-2.0 10135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent** 11135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent** Unless required by applicable law or agreed to in writing, software 12135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent** distributed under the License is distributed on an "AS IS" BASIS, 13135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent** See the License for the specific language governing permissions and 15135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent** limitations under the License. 16135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent*/ 17135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent 18135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent#ifndef AUDIOFORMATADAPTER_H_ 19135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent#define AUDIOFORMATADAPTER_H_ 20135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent 21e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent#include <hardware/audio_effect.h> 22135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent 23135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent 24135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent#define min(x,y) (((x) < (y)) ? (x) : (y)) 25135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent 26135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurentnamespace android { 27135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent 28135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent// An adapter for an audio processor working on audio_sample_t samples with a 29135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent// buffer override behavior to arbitrary sample formats and buffer behaviors. 30135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent// The adapter may work on any processing class which has a processing function 31135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent// with the following signature: 32135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent// void process(const audio_sample_t * pIn, 33135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent// audio_sample_t * pOut, 34135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent// int frameCount); 35135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent// It is assumed that the underlying processor works in S7.24 format and an 36135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent// overwrite behavior. 37135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent// 38135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent// Usage is simple: just work with the processor normally, but instead of 39135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent// calling its process() function directly, work with the process() function of 40135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent// the adapter. 41135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent// The adapter supports re-configuration to a different format on the fly. 42135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent// 43135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent// T The processor class. 44135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent// bufSize The maximum number of samples (single channel) to process on a 45135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent// single call to the underlying processor. Setting this to a small 46135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent// number will save a little memory, but will cost function call 47135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent// overhead, resulting from multiple calls to the underlying process() 48135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent// per a single call to this class's process(). 49135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurenttemplate<class T, size_t bufSize> 50135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurentclass AudioFormatAdapter { 51135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurentpublic: 52135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent // Configure the adapter. 53135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent // processor The underlying audio processor. 54135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent // nChannels Number of input and output channels. The adapter does not do 55135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent // channel conversion - this parameter must be in sync with the 56135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent // actual processor. 57135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent // pcmFormat The desired input/output sample format. 58135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent // behavior The desired behavior (overwrite or accumulate). 59135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent void configure(T & processor, int nChannels, uint8_t pcmFormat, 60135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent uint32_t behavior) { 61135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent mpProcessor = &processor; 62135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent mNumChannels = nChannels; 63135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent mPcmFormat = pcmFormat; 64135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent mBehavior = behavior; 65135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent mMaxSamplesPerCall = bufSize / nChannels; 66135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent } 67135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent 68135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent // Process a block of samples. 69135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent // pIn A buffer of samples with the format specified on 70135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent // configure(). 71135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent // pOut A buffer of samples with the format specified on 72135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent // configure(). May be the same as pIn. 73135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent // numSamples The number of multi-channel samples to process. 74135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent void process(const void * pIn, void * pOut, uint32_t numSamples) { 75135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent while (numSamples > 0) { 76135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent uint32_t numSamplesIter = min(numSamples, mMaxSamplesPerCall); 77135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent uint32_t nSamplesChannels = numSamplesIter * mNumChannels; 78e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent if (mPcmFormat == AUDIO_FORMAT_PCM_8_24_BIT) { 79135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent if (mBehavior == EFFECT_BUFFER_ACCESS_WRITE) { 80135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent mpProcessor->process( 81135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent reinterpret_cast<const audio_sample_t *> (pIn), 82135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent reinterpret_cast<audio_sample_t *> (pOut), 83135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent numSamplesIter); 84135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent } else if (mBehavior == EFFECT_BUFFER_ACCESS_ACCUMULATE) { 85135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent mpProcessor->process( 86135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent reinterpret_cast<const audio_sample_t *> (pIn), 87135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent mBuffer, numSamplesIter); 88135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent MixOutput(pOut, numSamplesIter); 89135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent } else { 90135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent assert(false); 91135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent } 92135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent pIn = reinterpret_cast<const audio_sample_t *> (pIn) 93135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent + nSamplesChannels; 94135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent pOut = reinterpret_cast<audio_sample_t *> (pOut) 95135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent + nSamplesChannels; 96135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent } else { 97135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent ConvertInput(pIn, nSamplesChannels); 98135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent mpProcessor->process(mBuffer, mBuffer, numSamplesIter); 99135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent ConvertOutput(pOut, nSamplesChannels); 100135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent } 101135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent numSamples -= numSamplesIter; 102135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent } 103135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent } 104135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent 105135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurentprivate: 106135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent // The underlying processor. 107135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent T * mpProcessor; 108135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent // The number of input/output channels. 109135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent int mNumChannels; 110135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent // The desired PCM format. 111135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent uint8_t mPcmFormat; 112135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent // The desired buffer behavior. 113135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent uint32_t mBehavior; 114135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent // An intermediate buffer for processing. 115135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent audio_sample_t mBuffer[bufSize]; 116135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent // The buffer size, divided by the number of channels - represents the 117135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent // maximum number of multi-channel samples that can be stored in the 118135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent // intermediate buffer. 119135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent size_t mMaxSamplesPerCall; 120135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent 121135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent // Converts a buffer of input samples to audio_sample_t format. 122135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent // Output is written to the intermediate buffer. 123135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent // pIn The input buffer with the format designated in configure(). 124135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent // When function exist will point to the next unread input 125135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent // sample. 126135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent // numSamples The number of single-channel samples to process. 127135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent void ConvertInput(const void *& pIn, uint32_t numSamples) { 128e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent if (mPcmFormat == AUDIO_FORMAT_PCM_16_BIT) { 129135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent const int16_t * pIn16 = reinterpret_cast<const int16_t *>(pIn); 130135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent audio_sample_t * pOut = mBuffer; 131135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent while (numSamples-- > 0) { 132135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent *(pOut++) = s15_to_audio_sample_t(*(pIn16++)); 133135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent } 134135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent pIn = pIn16; 135135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent } else { 136135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent assert(false); 137135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent } 138135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent } 139135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent 140135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent // Converts audio_sample_t samples from the intermediate buffer to the 141135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent // output buffer, converting to the desired format and buffer behavior. 142135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent // pOut The buffer to write the output to. 143135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent // When function exist will point to the next output sample. 144135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent // numSamples The number of single-channel samples to process. 145135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent void ConvertOutput(void *& pOut, uint32_t numSamples) { 146e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent if (mPcmFormat == AUDIO_FORMAT_PCM_16_BIT) { 147135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent const audio_sample_t * pIn = mBuffer; 148135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent int16_t * pOut16 = reinterpret_cast<int16_t *>(pOut); 149135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent if (mBehavior == EFFECT_BUFFER_ACCESS_WRITE) { 150135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent while (numSamples-- > 0) { 151135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent *(pOut16++) = audio_sample_t_to_s15_clip(*(pIn++)); 152135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent } 153135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent } else if (mBehavior == EFFECT_BUFFER_ACCESS_ACCUMULATE) { 154135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent while (numSamples-- > 0) { 155135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent *(pOut16++) += audio_sample_t_to_s15_clip(*(pIn++)); 156135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent } 157135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent } else { 158135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent assert(false); 159135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent } 160135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent pOut = pOut16; 161135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent } else { 162135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent assert(false); 163135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent } 164135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent } 165135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent 166135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent // Accumulate data from the intermediate buffer to the output. Output is 167135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent // assumed to be of audio_sample_t type. 168135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent // pOut The buffer to mix the output to. 169135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent // When function exist will point to the next output sample. 170135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent // numSamples The number of single-channel samples to process. 171135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent void MixOutput(void *& pOut, uint32_t numSamples) { 172135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent const audio_sample_t * pIn = mBuffer; 173135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent audio_sample_t * pOut24 = reinterpret_cast<audio_sample_t *>(pOut); 174135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent numSamples *= mNumChannels; 175135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent while (numSamples-- > 0) { 176135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent *(pOut24++) += *(pIn++); 177135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent } 178135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent pOut = pOut24; 179135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent } 180135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent}; 181135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent 182135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent} 183135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent 184135ad07e33d30e5202deb21061a0e3ecf0ffad35Eric Laurent#endif // AUDIOFORMATADAPTER_H_ 185