primitives.h revision 632e0c016c9a518b36f09988b740b3bc1199c3e4
1/* 2 * Copyright (C) 2011 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#ifndef ANDROID_AUDIO_PRIMITIVES_H 18#define ANDROID_AUDIO_PRIMITIVES_H 19 20#include <stdint.h> 21#include <sys/cdefs.h> 22 23__BEGIN_DECLS 24 25/** 26 * Dither and clamp pairs of 32-bit input samples (sums) to 16-bit output samples (out). 27 * Each 32-bit input sample is a signed fixed-point Q19.12. 28 * The .12 fraction is dithered, and the integer portion is then clamped to Q15. 29 * For interleaved stereo, c is the number of sample pairs, 30 * and out is an array of interleaved pairs of 16-bit samples per channel. 31 * For mono, c is the number of samples / 2, and out is an array of 16-bit samples. 32 * The name "dither" is a misnomer; the current implementation does not actually dither 33 * but uses truncation. This may change. 34 */ 35void ditherAndClamp(int32_t* out, const int32_t *sums, size_t c); 36 37/** 38 * Clamp (aka hard limit or clip) a signed 32-bit sample to 16-bit range. 39 */ 40static inline int16_t clamp16(int32_t sample) 41{ 42 if ((sample>>15) ^ (sample>>31)) 43 sample = 0x7FFF ^ (sample>>31); 44 return sample; 45} 46 47/** 48 * Multiply-accumulate 16-bit terms with 32-bit result: return a + in*v. 49 */ 50static inline 51int32_t mulAdd(int16_t in, int16_t v, int32_t a) 52{ 53#if defined(__arm__) && !defined(__thumb__) 54 int32_t out; 55 asm( "smlabb %[out], %[in], %[v], %[a] \n" 56 : [out]"=r"(out) 57 : [in]"%r"(in), [v]"r"(v), [a]"r"(a) 58 : ); 59 return out; 60#else 61 return a + in * (int32_t)v; 62#endif 63} 64 65/** 66 * Multiply 16-bit terms with 32-bit result: return in*v. 67 */ 68static inline 69int32_t mul(int16_t in, int16_t v) 70{ 71#if defined(__arm__) && !defined(__thumb__) 72 int32_t out; 73 asm( "smulbb %[out], %[in], %[v] \n" 74 : [out]"=r"(out) 75 : [in]"%r"(in), [v]"r"(v) 76 : ); 77 return out; 78#else 79 return in * (int32_t)v; 80#endif 81} 82 83/** 84 * Similar to mulAdd, but the 16-bit terms are extracted from a 32-bit interleaved stereo pair. 85 */ 86static inline 87int32_t mulAddRL(int left, uint32_t inRL, uint32_t vRL, int32_t a) 88{ 89#if defined(__arm__) && !defined(__thumb__) 90 int32_t out; 91 if (left) { 92 asm( "smlabb %[out], %[inRL], %[vRL], %[a] \n" 93 : [out]"=r"(out) 94 : [inRL]"%r"(inRL), [vRL]"r"(vRL), [a]"r"(a) 95 : ); 96 } else { 97 asm( "smlatt %[out], %[inRL], %[vRL], %[a] \n" 98 : [out]"=r"(out) 99 : [inRL]"%r"(inRL), [vRL]"r"(vRL), [a]"r"(a) 100 : ); 101 } 102 return out; 103#else 104 if (left) { 105 return a + (int16_t)(inRL&0xFFFF) * (int16_t)(vRL&0xFFFF); 106 } else { 107 return a + (int16_t)(inRL>>16) * (int16_t)(vRL>>16); 108 } 109#endif 110} 111 112/** 113 * Similar to mul, but the 16-bit terms are extracted from a 32-bit interleaved stereo pair. 114 */ 115static inline 116int32_t mulRL(int left, uint32_t inRL, uint32_t vRL) 117{ 118#if defined(__arm__) && !defined(__thumb__) 119 int32_t out; 120 if (left) { 121 asm( "smulbb %[out], %[inRL], %[vRL] \n" 122 : [out]"=r"(out) 123 : [inRL]"%r"(inRL), [vRL]"r"(vRL) 124 : ); 125 } else { 126 asm( "smultt %[out], %[inRL], %[vRL] \n" 127 : [out]"=r"(out) 128 : [inRL]"%r"(inRL), [vRL]"r"(vRL) 129 : ); 130 } 131 return out; 132#else 133 if (left) { 134 return (int16_t)(inRL&0xFFFF) * (int16_t)(vRL&0xFFFF); 135 } else { 136 return (int16_t)(inRL>>16) * (int16_t)(vRL>>16); 137 } 138#endif 139} 140 141__END_DECLS 142 143#endif // ANDROID_AUDIO_PRIMITIVES_H 144