1296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung/* 2296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung * Copyright (C) 2014 The Android Open Source Project 3296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung * 4296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung * Licensed under the Apache License, Version 2.0 (the "License"); 5296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung * you may not use this file except in compliance with the License. 6296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung * You may obtain a copy of the License at 7296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung * 8296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung * http://www.apache.org/licenses/LICENSE-2.0 9296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung * 10296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung * Unless required by applicable law or agreed to in writing, software 11296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung * distributed under the License is distributed on an "AS IS" BASIS, 12296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung * See the License for the specific language governing permissions and 14296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung * limitations under the License. 15296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung */ 16296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung 17296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung#ifndef ANDROID_AUDIO_MIXER_OPS_H 18296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung#define ANDROID_AUDIO_MIXER_OPS_H 19296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung 20296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hungnamespace android { 21296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung 22296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung/* Behavior of is_same<>::value is true if the types are identical, 23296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung * false otherwise. Identical to the STL std::is_same. 24296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung */ 25296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hungtemplate<typename T, typename U> 26296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hungstruct is_same 27296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung{ 28296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung static const bool value = false; 29296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung}; 30296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung 31296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hungtemplate<typename T> 32296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hungstruct is_same<T, T> // partial specialization 33296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung{ 34296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung static const bool value = true; 35296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung}; 36296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung 37296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung 38296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung/* MixMul is a multiplication operator to scale an audio input signal 39296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung * by a volume gain, with the formula: 40296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung * 41296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung * O(utput) = I(nput) * V(olume) 42296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung * 43296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung * The output, input, and volume may have different types. 44296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung * There are 27 variants, of which 14 are actually defined in an 45296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung * explicitly templated class. 46296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung * 47296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung * The following type variables and the underlying meaning: 48296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung * 49296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung * Output type TO: int32_t (Q4.27) or int16_t (Q.15) or float [-1,1] 50296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung * Input signal type TI: int32_t (Q4.27) or int16_t (Q.15) or float [-1,1] 51296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung * Volume type TV: int32_t (U4.28) or int16_t (U4.12) or float [-1,1] 52296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung * 53296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung * For high precision audio, only the <TO, TI, TV> = <float, float, float> 54296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung * needs to be accelerated. This is perhaps the easiest form to do quickly as well. 55296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung */ 56296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung 57296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hungtemplate <typename TO, typename TI, typename TV> 58296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hunginline TO MixMul(TI value, TV volume) { 59296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung COMPILE_TIME_ASSERT_FUNCTION_SCOPE(false); 60296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung // should not be here :-). 61296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung // To avoid mistakes, this template is always specialized. 62296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung return value * volume; 63296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung} 64296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung 65296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hungtemplate <> 66296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hunginline int32_t MixMul<int32_t, int16_t, int16_t>(int16_t value, int16_t volume) { 67296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung return value * volume; 68296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung} 69296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung 70296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hungtemplate <> 71296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hunginline int32_t MixMul<int32_t, int32_t, int16_t>(int32_t value, int16_t volume) { 72296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung return (value >> 12) * volume; 73296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung} 74296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung 75296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hungtemplate <> 76296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hunginline int32_t MixMul<int32_t, int16_t, int32_t>(int16_t value, int32_t volume) { 77296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung return value * (volume >> 16); 78296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung} 79296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung 80296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hungtemplate <> 81296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hunginline int32_t MixMul<int32_t, int32_t, int32_t>(int32_t value, int32_t volume) { 82296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung return (value >> 12) * (volume >> 16); 83296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung} 84296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung 85296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hungtemplate <> 86296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hunginline float MixMul<float, float, int16_t>(float value, int16_t volume) { 87296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung static const float norm = 1. / (1 << 12); 88296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung return value * volume * norm; 89296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung} 90296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung 91296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hungtemplate <> 92296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hunginline float MixMul<float, float, int32_t>(float value, int32_t volume) { 93296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung static const float norm = 1. / (1 << 28); 94296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung return value * volume * norm; 95296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung} 96296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung 97296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hungtemplate <> 98296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hunginline int16_t MixMul<int16_t, float, int16_t>(float value, int16_t volume) { 99296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung return clamp16_from_float(MixMul<float, float, int16_t>(value, volume)); 100296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung} 101296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung 102296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hungtemplate <> 103296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hunginline int16_t MixMul<int16_t, float, int32_t>(float value, int32_t volume) { 104296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung return clamp16_from_float(MixMul<float, float, int32_t>(value, volume)); 105296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung} 106296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung 107296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hungtemplate <> 108296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hunginline float MixMul<float, int16_t, int16_t>(int16_t value, int16_t volume) { 109296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung static const float norm = 1. / (1 << (15 + 12)); 110296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung return static_cast<float>(value) * static_cast<float>(volume) * norm; 111296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung} 112296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung 113296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hungtemplate <> 114296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hunginline float MixMul<float, int16_t, int32_t>(int16_t value, int32_t volume) { 115296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung static const float norm = 1. / (1ULL << (15 + 28)); 116296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung return static_cast<float>(value) * static_cast<float>(volume) * norm; 117296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung} 118296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung 119296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hungtemplate <> 120296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hunginline int16_t MixMul<int16_t, int16_t, int16_t>(int16_t value, int16_t volume) { 121296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung return clamp16(MixMul<int32_t, int16_t, int16_t>(value, volume) >> 12); 122296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung} 123296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung 124296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hungtemplate <> 125296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hunginline int16_t MixMul<int16_t, int32_t, int16_t>(int32_t value, int16_t volume) { 126296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung return clamp16(MixMul<int32_t, int32_t, int16_t>(value, volume) >> 12); 127296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung} 128296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung 129296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hungtemplate <> 130296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hunginline int16_t MixMul<int16_t, int16_t, int32_t>(int16_t value, int32_t volume) { 131296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung return clamp16(MixMul<int32_t, int16_t, int32_t>(value, volume) >> 12); 132296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung} 133296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung 134296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hungtemplate <> 135296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hunginline int16_t MixMul<int16_t, int32_t, int32_t>(int32_t value, int32_t volume) { 136296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung return clamp16(MixMul<int32_t, int32_t, int32_t>(value, volume) >> 12); 137296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung} 138296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung 1395e58b0abe5b6c8f5bd96a8f78bbeeeb4d3892020Andy Hung/* Required for floating point volume. Some are needed for compilation but 1405e58b0abe5b6c8f5bd96a8f78bbeeeb4d3892020Andy Hung * are not needed in execution and should be removed from the final build by 1415e58b0abe5b6c8f5bd96a8f78bbeeeb4d3892020Andy Hung * an optimizing compiler. 1425e58b0abe5b6c8f5bd96a8f78bbeeeb4d3892020Andy Hung */ 1435e58b0abe5b6c8f5bd96a8f78bbeeeb4d3892020Andy Hungtemplate <> 1445e58b0abe5b6c8f5bd96a8f78bbeeeb4d3892020Andy Hunginline float MixMul<float, float, float>(float value, float volume) { 1455e58b0abe5b6c8f5bd96a8f78bbeeeb4d3892020Andy Hung return value * volume; 1465e58b0abe5b6c8f5bd96a8f78bbeeeb4d3892020Andy Hung} 1475e58b0abe5b6c8f5bd96a8f78bbeeeb4d3892020Andy Hung 1485e58b0abe5b6c8f5bd96a8f78bbeeeb4d3892020Andy Hungtemplate <> 1495e58b0abe5b6c8f5bd96a8f78bbeeeb4d3892020Andy Hunginline float MixMul<float, int16_t, float>(int16_t value, float volume) { 1505e58b0abe5b6c8f5bd96a8f78bbeeeb4d3892020Andy Hung static const float float_from_q_15 = 1. / (1 << 15); 1515e58b0abe5b6c8f5bd96a8f78bbeeeb4d3892020Andy Hung return value * volume * float_from_q_15; 1525e58b0abe5b6c8f5bd96a8f78bbeeeb4d3892020Andy Hung} 1535e58b0abe5b6c8f5bd96a8f78bbeeeb4d3892020Andy Hung 1545e58b0abe5b6c8f5bd96a8f78bbeeeb4d3892020Andy Hungtemplate <> 1555e58b0abe5b6c8f5bd96a8f78bbeeeb4d3892020Andy Hunginline int32_t MixMul<int32_t, int32_t, float>(int32_t value, float volume) { 1565e58b0abe5b6c8f5bd96a8f78bbeeeb4d3892020Andy Hung LOG_ALWAYS_FATAL("MixMul<int32_t, int32_t, float> Runtime Should not be here"); 1575e58b0abe5b6c8f5bd96a8f78bbeeeb4d3892020Andy Hung return value * volume; 1585e58b0abe5b6c8f5bd96a8f78bbeeeb4d3892020Andy Hung} 1595e58b0abe5b6c8f5bd96a8f78bbeeeb4d3892020Andy Hung 1605e58b0abe5b6c8f5bd96a8f78bbeeeb4d3892020Andy Hungtemplate <> 1615e58b0abe5b6c8f5bd96a8f78bbeeeb4d3892020Andy Hunginline int32_t MixMul<int32_t, int16_t, float>(int16_t value, float volume) { 1625e58b0abe5b6c8f5bd96a8f78bbeeeb4d3892020Andy Hung LOG_ALWAYS_FATAL("MixMul<int32_t, int16_t, float> Runtime Should not be here"); 1635e58b0abe5b6c8f5bd96a8f78bbeeeb4d3892020Andy Hung static const float u4_12_from_float = (1 << 12); 1645e58b0abe5b6c8f5bd96a8f78bbeeeb4d3892020Andy Hung return value * volume * u4_12_from_float; 1655e58b0abe5b6c8f5bd96a8f78bbeeeb4d3892020Andy Hung} 1665e58b0abe5b6c8f5bd96a8f78bbeeeb4d3892020Andy Hung 1675e58b0abe5b6c8f5bd96a8f78bbeeeb4d3892020Andy Hungtemplate <> 1685e58b0abe5b6c8f5bd96a8f78bbeeeb4d3892020Andy Hunginline int16_t MixMul<int16_t, int16_t, float>(int16_t value, float volume) { 1695e58b0abe5b6c8f5bd96a8f78bbeeeb4d3892020Andy Hung LOG_ALWAYS_FATAL("MixMul<int16_t, int16_t, float> Runtime Should not be here"); 1705e58b0abe5b6c8f5bd96a8f78bbeeeb4d3892020Andy Hung return value * volume; 1715e58b0abe5b6c8f5bd96a8f78bbeeeb4d3892020Andy Hung} 1725e58b0abe5b6c8f5bd96a8f78bbeeeb4d3892020Andy Hung 1735e58b0abe5b6c8f5bd96a8f78bbeeeb4d3892020Andy Hungtemplate <> 1745e58b0abe5b6c8f5bd96a8f78bbeeeb4d3892020Andy Hunginline int16_t MixMul<int16_t, float, float>(float value, float volume) { 1755e58b0abe5b6c8f5bd96a8f78bbeeeb4d3892020Andy Hung static const float q_15_from_float = (1 << 15); 1765e58b0abe5b6c8f5bd96a8f78bbeeeb4d3892020Andy Hung return value * volume * q_15_from_float; 1775e58b0abe5b6c8f5bd96a8f78bbeeeb4d3892020Andy Hung} 1785e58b0abe5b6c8f5bd96a8f78bbeeeb4d3892020Andy Hung 179296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung/* 180296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung * MixAccum is used to add into an accumulator register of a possibly different 181296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung * type. The TO and TI types are the same as MixMul. 182296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung */ 183296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung 184296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hungtemplate <typename TO, typename TI> 185296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hunginline void MixAccum(TO *auxaccum, TI value) { 186296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung if (!is_same<TO, TI>::value) { 187a4daf0b4f934b800a49f199fb8c09409391c8fc0Glenn Kasten LOG_ALWAYS_FATAL("MixAccum type not properly specialized: %zu %zu\n", 188296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung sizeof(TO), sizeof(TI)); 189296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung } 190296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung *auxaccum += value; 191296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung} 192296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung 193296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hungtemplate<> 194296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hunginline void MixAccum<float, int16_t>(float *auxaccum, int16_t value) { 195296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung static const float norm = 1. / (1 << 15); 196296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung *auxaccum += norm * value; 197296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung} 198296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung 199296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hungtemplate<> 200296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hunginline void MixAccum<float, int32_t>(float *auxaccum, int32_t value) { 201296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung static const float norm = 1. / (1 << 27); 202296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung *auxaccum += norm * value; 203296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung} 204296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung 205296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hungtemplate<> 206296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hunginline void MixAccum<int32_t, int16_t>(int32_t *auxaccum, int16_t value) { 207296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung *auxaccum += value << 12; 208296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung} 209296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung 210296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hungtemplate<> 211296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hunginline void MixAccum<int32_t, float>(int32_t *auxaccum, float value) { 212296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung *auxaccum += clampq4_27_from_float(value); 213296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung} 214296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung 215296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung/* MixMulAux is just like MixMul except it combines with 216296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung * an accumulator operation MixAccum. 217296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung */ 218296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung 219296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hungtemplate <typename TO, typename TI, typename TV, typename TA> 220296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hunginline TO MixMulAux(TI value, TV volume, TA *auxaccum) { 221296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung MixAccum<TA, TI>(auxaccum, value); 222296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung return MixMul<TO, TI, TV>(value, volume); 223296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung} 224296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung 225296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung/* MIXTYPE is used to determine how the samples in the input frame 226296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung * are mixed with volume gain into the output frame. 227296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung * See the volumeRampMulti functions below for more details. 228296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung */ 229296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hungenum { 230296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung MIXTYPE_MULTI, 231296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung MIXTYPE_MONOEXPAND, 232296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung MIXTYPE_MULTI_SAVEONLY, 233e93b6b7347a7846c8fd746542364ec11b0cd5124Andy Hung MIXTYPE_MULTI_MONOVOL, 234e93b6b7347a7846c8fd746542364ec11b0cd5124Andy Hung MIXTYPE_MULTI_SAVEONLY_MONOVOL, 235296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung}; 236296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung 237296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung/* 238296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung * The volumeRampMulti and volumeRamp functions take a MIXTYPE 239296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung * which indicates the per-frame mixing and accumulation strategy. 240296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung * 241296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung * MIXTYPE_MULTI: 242296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung * NCHAN represents number of input and output channels. 243296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung * TO: int32_t (Q4.27) or float 244296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung * TI: int32_t (Q4.27) or int16_t (Q0.15) or float 245296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung * TV: int32_t (U4.28) or int16_t (U4.12) or float 246296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung * vol: represents a volume array. 247296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung * 248296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung * This accumulates into the out pointer. 249296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung * 250296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung * MIXTYPE_MONOEXPAND: 251296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung * Single input channel. NCHAN represents number of output channels. 252296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung * TO: int32_t (Q4.27) or float 253296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung * TI: int32_t (Q4.27) or int16_t (Q0.15) or float 254296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung * TV: int32_t (U4.28) or int16_t (U4.12) or float 255296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung * Input channel count is 1. 256296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung * vol: represents volume array. 257296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung * 258296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung * This accumulates into the out pointer. 259296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung * 260296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung * MIXTYPE_MULTI_SAVEONLY: 261296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung * NCHAN represents number of input and output channels. 262296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung * TO: int16_t (Q.15) or float 263296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung * TI: int32_t (Q4.27) or int16_t (Q0.15) or float 264296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung * TV: int32_t (U4.28) or int16_t (U4.12) or float 265296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung * vol: represents a volume array. 266296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung * 267296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung * MIXTYPE_MULTI_SAVEONLY does not accumulate into the out pointer. 268e93b6b7347a7846c8fd746542364ec11b0cd5124Andy Hung * 269e93b6b7347a7846c8fd746542364ec11b0cd5124Andy Hung * MIXTYPE_MULTI_MONOVOL: 270e93b6b7347a7846c8fd746542364ec11b0cd5124Andy Hung * Same as MIXTYPE_MULTI, but uses only volume[0]. 271e93b6b7347a7846c8fd746542364ec11b0cd5124Andy Hung * 272e93b6b7347a7846c8fd746542364ec11b0cd5124Andy Hung * MIXTYPE_MULTI_SAVEONLY_MONOVOL: 273e93b6b7347a7846c8fd746542364ec11b0cd5124Andy Hung * Same as MIXTYPE_MULTI_SAVEONLY, but uses only volume[0]. 274e93b6b7347a7846c8fd746542364ec11b0cd5124Andy Hung * 275296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung */ 276296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung 277296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hungtemplate <int MIXTYPE, int NCHAN, 278296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung typename TO, typename TI, typename TV, typename TA, typename TAV> 279296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hunginline void volumeRampMulti(TO* out, size_t frameCount, 280296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung const TI* in, TA* aux, TV *vol, const TV *volinc, TAV *vola, TAV volainc) 281296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung{ 282296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung#ifdef ALOGVV 283296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung ALOGVV("volumeRampMulti, MIXTYPE:%d\n", MIXTYPE); 284296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung#endif 285296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung if (aux != NULL) { 286296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung do { 287296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung TA auxaccum = 0; 288296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung switch (MIXTYPE) { 289296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung case MIXTYPE_MULTI: 290296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung for (int i = 0; i < NCHAN; ++i) { 291296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung *out++ += MixMulAux<TO, TI, TV, TA>(*in++, vol[i], &auxaccum); 292296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung vol[i] += volinc[i]; 293296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung } 294296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung break; 295e93b6b7347a7846c8fd746542364ec11b0cd5124Andy Hung case MIXTYPE_MONOEXPAND: 296e93b6b7347a7846c8fd746542364ec11b0cd5124Andy Hung for (int i = 0; i < NCHAN; ++i) { 297e93b6b7347a7846c8fd746542364ec11b0cd5124Andy Hung *out++ += MixMulAux<TO, TI, TV, TA>(*in, vol[i], &auxaccum); 298e93b6b7347a7846c8fd746542364ec11b0cd5124Andy Hung vol[i] += volinc[i]; 299e93b6b7347a7846c8fd746542364ec11b0cd5124Andy Hung } 300e93b6b7347a7846c8fd746542364ec11b0cd5124Andy Hung in++; 301e93b6b7347a7846c8fd746542364ec11b0cd5124Andy Hung break; 302296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung case MIXTYPE_MULTI_SAVEONLY: 303296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung for (int i = 0; i < NCHAN; ++i) { 304296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung *out++ = MixMulAux<TO, TI, TV, TA>(*in++, vol[i], &auxaccum); 305296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung vol[i] += volinc[i]; 306296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung } 307296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung break; 308e93b6b7347a7846c8fd746542364ec11b0cd5124Andy Hung case MIXTYPE_MULTI_MONOVOL: 309296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung for (int i = 0; i < NCHAN; ++i) { 310e93b6b7347a7846c8fd746542364ec11b0cd5124Andy Hung *out++ += MixMulAux<TO, TI, TV, TA>(*in++, vol[0], &auxaccum); 311296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung } 312e93b6b7347a7846c8fd746542364ec11b0cd5124Andy Hung vol[0] += volinc[0]; 313e93b6b7347a7846c8fd746542364ec11b0cd5124Andy Hung break; 314e93b6b7347a7846c8fd746542364ec11b0cd5124Andy Hung case MIXTYPE_MULTI_SAVEONLY_MONOVOL: 315e93b6b7347a7846c8fd746542364ec11b0cd5124Andy Hung for (int i = 0; i < NCHAN; ++i) { 316e93b6b7347a7846c8fd746542364ec11b0cd5124Andy Hung *out++ = MixMulAux<TO, TI, TV, TA>(*in++, vol[0], &auxaccum); 317e93b6b7347a7846c8fd746542364ec11b0cd5124Andy Hung } 318e93b6b7347a7846c8fd746542364ec11b0cd5124Andy Hung vol[0] += volinc[0]; 319296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung break; 320296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung default: 321296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung LOG_ALWAYS_FATAL("invalid mixtype %d", MIXTYPE); 322296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung break; 323296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung } 324296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung auxaccum /= NCHAN; 325296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung *aux++ += MixMul<TA, TA, TAV>(auxaccum, *vola); 326296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung vola[0] += volainc; 327296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung } while (--frameCount); 328296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung } else { 329296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung do { 330296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung switch (MIXTYPE) { 331296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung case MIXTYPE_MULTI: 332296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung for (int i = 0; i < NCHAN; ++i) { 333296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung *out++ += MixMul<TO, TI, TV>(*in++, vol[i]); 334296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung vol[i] += volinc[i]; 335296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung } 336296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung break; 337e93b6b7347a7846c8fd746542364ec11b0cd5124Andy Hung case MIXTYPE_MONOEXPAND: 338e93b6b7347a7846c8fd746542364ec11b0cd5124Andy Hung for (int i = 0; i < NCHAN; ++i) { 339e93b6b7347a7846c8fd746542364ec11b0cd5124Andy Hung *out++ += MixMul<TO, TI, TV>(*in, vol[i]); 340e93b6b7347a7846c8fd746542364ec11b0cd5124Andy Hung vol[i] += volinc[i]; 341e93b6b7347a7846c8fd746542364ec11b0cd5124Andy Hung } 342e93b6b7347a7846c8fd746542364ec11b0cd5124Andy Hung in++; 343e93b6b7347a7846c8fd746542364ec11b0cd5124Andy Hung break; 344296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung case MIXTYPE_MULTI_SAVEONLY: 345296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung for (int i = 0; i < NCHAN; ++i) { 346296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung *out++ = MixMul<TO, TI, TV>(*in++, vol[i]); 347296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung vol[i] += volinc[i]; 348296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung } 349296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung break; 350e93b6b7347a7846c8fd746542364ec11b0cd5124Andy Hung case MIXTYPE_MULTI_MONOVOL: 351296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung for (int i = 0; i < NCHAN; ++i) { 352e93b6b7347a7846c8fd746542364ec11b0cd5124Andy Hung *out++ += MixMul<TO, TI, TV>(*in++, vol[0]); 353296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung } 354e93b6b7347a7846c8fd746542364ec11b0cd5124Andy Hung vol[0] += volinc[0]; 355e93b6b7347a7846c8fd746542364ec11b0cd5124Andy Hung break; 356e93b6b7347a7846c8fd746542364ec11b0cd5124Andy Hung case MIXTYPE_MULTI_SAVEONLY_MONOVOL: 357e93b6b7347a7846c8fd746542364ec11b0cd5124Andy Hung for (int i = 0; i < NCHAN; ++i) { 358e93b6b7347a7846c8fd746542364ec11b0cd5124Andy Hung *out++ = MixMul<TO, TI, TV>(*in++, vol[0]); 359e93b6b7347a7846c8fd746542364ec11b0cd5124Andy Hung } 360e93b6b7347a7846c8fd746542364ec11b0cd5124Andy Hung vol[0] += volinc[0]; 361296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung break; 362296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung default: 363296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung LOG_ALWAYS_FATAL("invalid mixtype %d", MIXTYPE); 364296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung break; 365296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung } 366296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung } while (--frameCount); 367296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung } 368296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung} 369296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung 370296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hungtemplate <int MIXTYPE, int NCHAN, 371296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung typename TO, typename TI, typename TV, typename TA, typename TAV> 372296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hunginline void volumeMulti(TO* out, size_t frameCount, 373296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung const TI* in, TA* aux, const TV *vol, TAV vola) 374296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung{ 375296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung#ifdef ALOGVV 376296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung ALOGVV("volumeMulti MIXTYPE:%d\n", MIXTYPE); 377296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung#endif 378296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung if (aux != NULL) { 379296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung do { 380296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung TA auxaccum = 0; 381296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung switch (MIXTYPE) { 382296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung case MIXTYPE_MULTI: 383296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung for (int i = 0; i < NCHAN; ++i) { 384296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung *out++ += MixMulAux<TO, TI, TV, TA>(*in++, vol[i], &auxaccum); 385296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung } 386296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung break; 387e93b6b7347a7846c8fd746542364ec11b0cd5124Andy Hung case MIXTYPE_MONOEXPAND: 388e93b6b7347a7846c8fd746542364ec11b0cd5124Andy Hung for (int i = 0; i < NCHAN; ++i) { 389e93b6b7347a7846c8fd746542364ec11b0cd5124Andy Hung *out++ += MixMulAux<TO, TI, TV, TA>(*in, vol[i], &auxaccum); 390e93b6b7347a7846c8fd746542364ec11b0cd5124Andy Hung } 391e93b6b7347a7846c8fd746542364ec11b0cd5124Andy Hung in++; 392e93b6b7347a7846c8fd746542364ec11b0cd5124Andy Hung break; 393296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung case MIXTYPE_MULTI_SAVEONLY: 394296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung for (int i = 0; i < NCHAN; ++i) { 395296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung *out++ = MixMulAux<TO, TI, TV, TA>(*in++, vol[i], &auxaccum); 396296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung } 397296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung break; 398e93b6b7347a7846c8fd746542364ec11b0cd5124Andy Hung case MIXTYPE_MULTI_MONOVOL: 399296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung for (int i = 0; i < NCHAN; ++i) { 400e93b6b7347a7846c8fd746542364ec11b0cd5124Andy Hung *out++ += MixMulAux<TO, TI, TV, TA>(*in++, vol[0], &auxaccum); 401e93b6b7347a7846c8fd746542364ec11b0cd5124Andy Hung } 402e93b6b7347a7846c8fd746542364ec11b0cd5124Andy Hung break; 403e93b6b7347a7846c8fd746542364ec11b0cd5124Andy Hung case MIXTYPE_MULTI_SAVEONLY_MONOVOL: 404e93b6b7347a7846c8fd746542364ec11b0cd5124Andy Hung for (int i = 0; i < NCHAN; ++i) { 405e93b6b7347a7846c8fd746542364ec11b0cd5124Andy Hung *out++ = MixMulAux<TO, TI, TV, TA>(*in++, vol[0], &auxaccum); 406296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung } 407296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung break; 408296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung default: 409296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung LOG_ALWAYS_FATAL("invalid mixtype %d", MIXTYPE); 410296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung break; 411296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung } 412296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung auxaccum /= NCHAN; 413296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung *aux++ += MixMul<TA, TA, TAV>(auxaccum, vola); 414296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung } while (--frameCount); 415296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung } else { 416296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung do { 417296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung switch (MIXTYPE) { 418296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung case MIXTYPE_MULTI: 419296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung for (int i = 0; i < NCHAN; ++i) { 420296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung *out++ += MixMul<TO, TI, TV>(*in++, vol[i]); 421296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung } 422296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung break; 423e93b6b7347a7846c8fd746542364ec11b0cd5124Andy Hung case MIXTYPE_MONOEXPAND: 424e93b6b7347a7846c8fd746542364ec11b0cd5124Andy Hung for (int i = 0; i < NCHAN; ++i) { 425e93b6b7347a7846c8fd746542364ec11b0cd5124Andy Hung *out++ += MixMul<TO, TI, TV>(*in, vol[i]); 426e93b6b7347a7846c8fd746542364ec11b0cd5124Andy Hung } 427e93b6b7347a7846c8fd746542364ec11b0cd5124Andy Hung in++; 428e93b6b7347a7846c8fd746542364ec11b0cd5124Andy Hung break; 429296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung case MIXTYPE_MULTI_SAVEONLY: 430296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung for (int i = 0; i < NCHAN; ++i) { 431296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung *out++ = MixMul<TO, TI, TV>(*in++, vol[i]); 432296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung } 433296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung break; 434e93b6b7347a7846c8fd746542364ec11b0cd5124Andy Hung case MIXTYPE_MULTI_MONOVOL: 435296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung for (int i = 0; i < NCHAN; ++i) { 436e93b6b7347a7846c8fd746542364ec11b0cd5124Andy Hung *out++ += MixMul<TO, TI, TV>(*in++, vol[0]); 437e93b6b7347a7846c8fd746542364ec11b0cd5124Andy Hung } 438e93b6b7347a7846c8fd746542364ec11b0cd5124Andy Hung break; 439e93b6b7347a7846c8fd746542364ec11b0cd5124Andy Hung case MIXTYPE_MULTI_SAVEONLY_MONOVOL: 440e93b6b7347a7846c8fd746542364ec11b0cd5124Andy Hung for (int i = 0; i < NCHAN; ++i) { 441e93b6b7347a7846c8fd746542364ec11b0cd5124Andy Hung *out++ = MixMul<TO, TI, TV>(*in++, vol[0]); 442296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung } 443296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung break; 444296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung default: 445296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung LOG_ALWAYS_FATAL("invalid mixtype %d", MIXTYPE); 446296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung break; 447296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung } 448296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung } while (--frameCount); 449296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung } 450296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung} 451296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung 452296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung}; 453296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung 454296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung#endif /* ANDROID_AUDIO_MIXER_OPS_H */ 455