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