1 /* 2 * Copyright (C) 2015 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_NDEBUG 0 18 #define LOG_TAG "audio_utils_mono_blend" 19 20 #include <math.h> 21 #include <audio_utils/mono_blend.h> 22 #include <log/log.h> 23 #include <audio_utils/limiter.h> 24 25 // TODO: Speed up for special case of 2 channels? 26 void mono_blend(void *buf, audio_format_t format, size_t channelCount, size_t frames, bool limit) { 27 if (channelCount < 2) { 28 return; 29 } 30 switch (format) { 31 case AUDIO_FORMAT_PCM_16_BIT: { 32 int16_t *out = (int16_t *)buf; 33 for (size_t i = 0; i < frames; ++i) { 34 const int16_t *in = out; 35 int accum = 0; 36 for (size_t j = 0; j < channelCount; ++j) { 37 accum += *in++; 38 } 39 accum /= channelCount; // round to 0 40 for (size_t j = 0; j < channelCount; ++j) { 41 *out++ = accum; 42 } 43 } 44 } break; 45 case AUDIO_FORMAT_PCM_FLOAT: { 46 float *out = (float *)buf; 47 const float recipdiv = 1. / channelCount; 48 for (size_t i = 0; i < frames; ++i) { 49 const float *in = out; 50 float accum = 0; 51 for (size_t j = 0; j < channelCount; ++j) { 52 accum += *in++; 53 } 54 if (limit && channelCount == 2) { 55 accum = limiter(accum * M_SQRT1_2); 56 } else { 57 accum *= recipdiv; 58 } 59 for (size_t j = 0; j < channelCount; ++j) { 60 *out++ = accum; 61 } 62 } 63 } break; 64 default: 65 ALOGE("mono_blend: invalid format %d", format); 66 break; 67 } 68 } 69