• 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 "RecordBufferConverter"
18 //#define LOG_NDEBUG 0
19 
20 #include <audio_utils/primitives.h>
21 #include <audio_utils/format.h>
22 #include <media/AudioMixer.h>  // for UNITY_GAIN_FLOAT
23 #include <media/AudioResampler.h>
24 #include <media/BufferProviders.h>
25 #include <media/RecordBufferConverter.h>
26 #include <utils/Log.h>
27 
28 #ifndef ARRAY_SIZE
29 #define ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0]))
30 #endif
31 
32 template <typename T>
max(const T & a,const T & b)33 static inline T max(const T& a, const T& b)
34 {
35     return a > b ? a : b;
36 }
37 
38 namespace android {
39 
RecordBufferConverter(audio_channel_mask_t srcChannelMask,audio_format_t srcFormat,uint32_t srcSampleRate,audio_channel_mask_t dstChannelMask,audio_format_t dstFormat,uint32_t dstSampleRate)40 RecordBufferConverter::RecordBufferConverter(
41         audio_channel_mask_t srcChannelMask, audio_format_t srcFormat,
42         uint32_t srcSampleRate,
43         audio_channel_mask_t dstChannelMask, audio_format_t dstFormat,
44         uint32_t dstSampleRate) :
45             mSrcChannelMask(AUDIO_CHANNEL_INVALID), // updateParameters will set following vars
46             // mSrcFormat
47             // mSrcSampleRate
48             // mDstChannelMask
49             // mDstFormat
50             // mDstSampleRate
51             // mSrcChannelCount
52             // mDstChannelCount
53             // mDstFrameSize
54             mBuf(NULL), mBufFrames(0), mBufFrameSize(0),
55             mResampler(NULL),
56             mIsLegacyDownmix(false),
57             mIsLegacyUpmix(false),
58             mRequiresFloat(false),
59             mInputConverterProvider(NULL)
60 {
61     (void)updateParameters(srcChannelMask, srcFormat, srcSampleRate,
62             dstChannelMask, dstFormat, dstSampleRate);
63 }
64 
~RecordBufferConverter()65 RecordBufferConverter::~RecordBufferConverter() {
66     free(mBuf);
67     delete mResampler;
68     delete mInputConverterProvider;
69 }
70 
reset()71 void RecordBufferConverter::reset() {
72     if (mResampler != NULL) {
73         mResampler->reset();
74     }
75 }
76 
convert(void * dst,AudioBufferProvider * provider,size_t frames)77 size_t RecordBufferConverter::convert(void *dst,
78         AudioBufferProvider *provider, size_t frames)
79 {
80     if (mInputConverterProvider != NULL) {
81         mInputConverterProvider->setBufferProvider(provider);
82         provider = mInputConverterProvider;
83     }
84 
85     if (mResampler == NULL) {
86         ALOGV("NO RESAMPLING sampleRate:%u mSrcFormat:%#x mDstFormat:%#x",
87                 mSrcSampleRate, mSrcFormat, mDstFormat);
88 
89         AudioBufferProvider::Buffer buffer;
90         for (size_t i = frames; i > 0; ) {
91             buffer.frameCount = i;
92             status_t status = provider->getNextBuffer(&buffer);
93             if (status != OK || buffer.frameCount == 0) {
94                 frames -= i; // cannot fill request.
95                 break;
96             }
97             // format convert to destination buffer
98             convertNoResampler(dst, buffer.raw, buffer.frameCount);
99 
100             dst = (int8_t*)dst + buffer.frameCount * mDstFrameSize;
101             i -= buffer.frameCount;
102             provider->releaseBuffer(&buffer);
103         }
104     } else {
105          ALOGV("RESAMPLING mSrcSampleRate:%u mDstSampleRate:%u mSrcFormat:%#x mDstFormat:%#x",
106                  mSrcSampleRate, mDstSampleRate, mSrcFormat, mDstFormat);
107 
108          // reallocate buffer if needed
109          if (mBufFrameSize != 0 && mBufFrames < frames) {
110              free(mBuf);
111              mBufFrames = frames;
112              (void)posix_memalign(&mBuf, 32, mBufFrames * mBufFrameSize);
113          }
114         // resampler accumulates, but we only have one source track
115         memset(mBuf, 0, frames * mBufFrameSize);
116         frames = mResampler->resample((int32_t*)mBuf, frames, provider);
117         // format convert to destination buffer
118         convertResampler(dst, mBuf, frames);
119     }
120     return frames;
121 }
122 
updateParameters(audio_channel_mask_t srcChannelMask,audio_format_t srcFormat,uint32_t srcSampleRate,audio_channel_mask_t dstChannelMask,audio_format_t dstFormat,uint32_t dstSampleRate)123 status_t RecordBufferConverter::updateParameters(
124         audio_channel_mask_t srcChannelMask, audio_format_t srcFormat,
125         uint32_t srcSampleRate,
126         audio_channel_mask_t dstChannelMask, audio_format_t dstFormat,
127         uint32_t dstSampleRate)
128 {
129     // quick evaluation if there is any change.
130     if (mSrcFormat == srcFormat
131             && mSrcChannelMask == srcChannelMask
132             && mSrcSampleRate == srcSampleRate
133             && mDstFormat == dstFormat
134             && mDstChannelMask == dstChannelMask
135             && mDstSampleRate == dstSampleRate) {
136         return NO_ERROR;
137     }
138 
139     ALOGV("RecordBufferConverter updateParameters srcMask:%#x dstMask:%#x"
140             "  srcFormat:%#x dstFormat:%#x  srcRate:%u dstRate:%u",
141             srcChannelMask, dstChannelMask, srcFormat, dstFormat, srcSampleRate, dstSampleRate);
142     const bool valid =
143             audio_is_input_channel(srcChannelMask)
144             && audio_is_input_channel(dstChannelMask)
145             && audio_is_valid_format(srcFormat) && audio_is_linear_pcm(srcFormat)
146             && audio_is_valid_format(dstFormat) && audio_is_linear_pcm(dstFormat)
147             && (srcSampleRate <= dstSampleRate * AUDIO_RESAMPLER_DOWN_RATIO_MAX)
148             ; // no upsampling checks for now
149     if (!valid) {
150         return BAD_VALUE;
151     }
152 
153     mSrcFormat = srcFormat;
154     mSrcChannelMask = srcChannelMask;
155     mSrcSampleRate = srcSampleRate;
156     mDstFormat = dstFormat;
157     mDstChannelMask = dstChannelMask;
158     mDstSampleRate = dstSampleRate;
159 
160     // compute derived parameters
161     mSrcChannelCount = audio_channel_count_from_in_mask(srcChannelMask);
162     mDstChannelCount = audio_channel_count_from_in_mask(dstChannelMask);
163     mDstFrameSize = mDstChannelCount * audio_bytes_per_sample(mDstFormat);
164 
165     // do we need to resample?
166     delete mResampler;
167     mResampler = NULL;
168     if (mSrcSampleRate != mDstSampleRate) {
169         mResampler = AudioResampler::create(AUDIO_FORMAT_PCM_FLOAT,
170                 mSrcChannelCount, mDstSampleRate);
171         mResampler->setSampleRate(mSrcSampleRate);
172         mResampler->setVolume(AudioMixer::UNITY_GAIN_FLOAT, AudioMixer::UNITY_GAIN_FLOAT);
173     }
174 
175     // are we running legacy channel conversion modes?
176     mIsLegacyDownmix = (mSrcChannelMask == AUDIO_CHANNEL_IN_STEREO
177                             || mSrcChannelMask == AUDIO_CHANNEL_IN_FRONT_BACK)
178                    && mDstChannelMask == AUDIO_CHANNEL_IN_MONO;
179     mIsLegacyUpmix = mSrcChannelMask == AUDIO_CHANNEL_IN_MONO
180                    && (mDstChannelMask == AUDIO_CHANNEL_IN_STEREO
181                             || mDstChannelMask == AUDIO_CHANNEL_IN_FRONT_BACK);
182 
183     // do we need to process in float?
184     mRequiresFloat = mResampler != NULL || mIsLegacyDownmix || mIsLegacyUpmix;
185 
186     // do we need a staging buffer to convert for destination (we can still optimize this)?
187     // we use mBufFrameSize > 0 to indicate both frame size as well as buffer necessity
188     if (mResampler != NULL) {
189         mBufFrameSize = max(mSrcChannelCount, (uint32_t)FCC_2)
190                 * audio_bytes_per_sample(AUDIO_FORMAT_PCM_FLOAT);
191     } else if (mIsLegacyUpmix || mIsLegacyDownmix) { // legacy modes always float
192         mBufFrameSize = mDstChannelCount * audio_bytes_per_sample(AUDIO_FORMAT_PCM_FLOAT);
193     } else if (mSrcChannelMask != mDstChannelMask && mDstFormat != mSrcFormat) {
194         mBufFrameSize = mDstChannelCount * audio_bytes_per_sample(mSrcFormat);
195     } else {
196         mBufFrameSize = 0;
197     }
198     mBufFrames = 0; // force the buffer to be resized.
199 
200     // do we need an input converter buffer provider to give us float?
201     delete mInputConverterProvider;
202     mInputConverterProvider = NULL;
203     if (mRequiresFloat && mSrcFormat != AUDIO_FORMAT_PCM_FLOAT) {
204         mInputConverterProvider = new ReformatBufferProvider(
205                 audio_channel_count_from_in_mask(mSrcChannelMask),
206                 mSrcFormat,
207                 AUDIO_FORMAT_PCM_FLOAT,
208                 256 /* provider buffer frame count */);
209     }
210 
211     // do we need a remixer to do channel mask conversion
212     if (!mIsLegacyDownmix && !mIsLegacyUpmix && mSrcChannelMask != mDstChannelMask) {
213         (void) memcpy_by_index_array_initialization_from_channel_mask(
214                 mIdxAry, ARRAY_SIZE(mIdxAry), mDstChannelMask, mSrcChannelMask);
215     }
216     return NO_ERROR;
217 }
218 
convertNoResampler(void * dst,const void * src,size_t frames)219 void RecordBufferConverter::convertNoResampler(
220         void *dst, const void *src, size_t frames)
221 {
222     // src is native type unless there is legacy upmix or downmix, whereupon it is float.
223     if (mBufFrameSize != 0 && mBufFrames < frames) {
224         free(mBuf);
225         mBufFrames = frames;
226         (void)posix_memalign(&mBuf, 32, mBufFrames * mBufFrameSize);
227     }
228     // do we need to do legacy upmix and downmix?
229     if (mIsLegacyUpmix || mIsLegacyDownmix) {
230         void *dstBuf = mBuf != NULL ? mBuf : dst;
231         if (mIsLegacyUpmix) {
232             upmix_to_stereo_float_from_mono_float((float *)dstBuf,
233                     (const float *)src, frames);
234         } else /*mIsLegacyDownmix */ {
235             downmix_to_mono_float_from_stereo_float((float *)dstBuf,
236                     (const float *)src, frames);
237         }
238         if (mBuf != NULL) {
239             memcpy_by_audio_format(dst, mDstFormat, mBuf, AUDIO_FORMAT_PCM_FLOAT,
240                     frames * mDstChannelCount);
241         }
242         return;
243     }
244     // do we need to do channel mask conversion?
245     if (mSrcChannelMask != mDstChannelMask) {
246         void *dstBuf = mBuf != NULL ? mBuf : dst;
247         memcpy_by_index_array(dstBuf, mDstChannelCount,
248                 src, mSrcChannelCount, mIdxAry, audio_bytes_per_sample(mSrcFormat), frames);
249         if (dstBuf == dst) {
250             return; // format is the same
251         }
252     }
253     // convert to destination buffer
254     const void *convertBuf = mBuf != NULL ? mBuf : src;
255     memcpy_by_audio_format(dst, mDstFormat, convertBuf, mSrcFormat,
256             frames * mDstChannelCount);
257 }
258 
convertResampler(void * dst,void * src,size_t frames)259 void RecordBufferConverter::convertResampler(
260         void *dst, /*not-a-const*/ void *src, size_t frames)
261 {
262     // src buffer format is ALWAYS float when entering this routine
263     if (mIsLegacyUpmix) {
264         ; // mono to stereo already handled by resampler
265     } else if (mIsLegacyDownmix
266             || (mSrcChannelMask == mDstChannelMask && mSrcChannelCount == 1)) {
267         // the resampler outputs stereo for mono input channel (a feature?)
268         // must convert to mono
269         downmix_to_mono_float_from_stereo_float((float *)src,
270                 (const float *)src, frames);
271     } else if (mSrcChannelMask != mDstChannelMask) {
272         // convert to mono channel again for channel mask conversion (could be skipped
273         // with further optimization).
274         if (mSrcChannelCount == 1) {
275             downmix_to_mono_float_from_stereo_float((float *)src,
276                 (const float *)src, frames);
277         }
278         // convert to destination format (in place, OK as float is larger than other types)
279         if (mDstFormat != AUDIO_FORMAT_PCM_FLOAT) {
280             memcpy_by_audio_format(src, mDstFormat, src, AUDIO_FORMAT_PCM_FLOAT,
281                     frames * mSrcChannelCount);
282         }
283         // channel convert and save to dst
284         memcpy_by_index_array(dst, mDstChannelCount,
285                 src, mSrcChannelCount, mIdxAry, audio_bytes_per_sample(mDstFormat), frames);
286         return;
287     }
288     // convert to destination format and save to dst
289     memcpy_by_audio_format(dst, mDstFormat, src, AUDIO_FORMAT_PCM_FLOAT,
290             frames * mDstChannelCount);
291 }
292 
293 // ----------------------------------------------------------------------------
294 } // namespace android
295