primitives.h revision ddb2e930bef3d1be1627c613fb8f3df848166ac7
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/* Expand and copy samples from unsigned 8-bit offset by 0x80 to signed 16-bit. 38 * Parameters: 39 * dst Destination buffer 40 * src Source buffer 41 * count Number of samples to copy 42 * The destination and source buffers must either be completely separate (non-overlapping), or 43 * they must both start at the same address. Partially overlapping buffers are not supported. 44 */ 45void memcpy_to_i16_from_u8(int16_t *dst, const uint8_t *src, size_t count); 46 47/** 48 * Clamp (aka hard limit or clip) a signed 32-bit sample to 16-bit range. 49 */ 50static inline int16_t clamp16(int32_t sample) 51{ 52 if ((sample>>15) ^ (sample>>31)) 53 sample = 0x7FFF ^ (sample>>31); 54 return sample; 55} 56 57/** 58 * Multiply-accumulate 16-bit terms with 32-bit result: return a + in*v. 59 */ 60static inline 61int32_t mulAdd(int16_t in, int16_t v, int32_t a) 62{ 63#if defined(__arm__) && !defined(__thumb__) 64 int32_t out; 65 asm( "smlabb %[out], %[in], %[v], %[a] \n" 66 : [out]"=r"(out) 67 : [in]"%r"(in), [v]"r"(v), [a]"r"(a) 68 : ); 69 return out; 70#else 71 return a + in * (int32_t)v; 72#endif 73} 74 75/** 76 * Multiply 16-bit terms with 32-bit result: return in*v. 77 */ 78static inline 79int32_t mul(int16_t in, int16_t v) 80{ 81#if defined(__arm__) && !defined(__thumb__) 82 int32_t out; 83 asm( "smulbb %[out], %[in], %[v] \n" 84 : [out]"=r"(out) 85 : [in]"%r"(in), [v]"r"(v) 86 : ); 87 return out; 88#else 89 return in * (int32_t)v; 90#endif 91} 92 93/** 94 * Similar to mulAdd, but the 16-bit terms are extracted from a 32-bit interleaved stereo pair. 95 */ 96static inline 97int32_t mulAddRL(int left, uint32_t inRL, uint32_t vRL, int32_t a) 98{ 99#if defined(__arm__) && !defined(__thumb__) 100 int32_t out; 101 if (left) { 102 asm( "smlabb %[out], %[inRL], %[vRL], %[a] \n" 103 : [out]"=r"(out) 104 : [inRL]"%r"(inRL), [vRL]"r"(vRL), [a]"r"(a) 105 : ); 106 } else { 107 asm( "smlatt %[out], %[inRL], %[vRL], %[a] \n" 108 : [out]"=r"(out) 109 : [inRL]"%r"(inRL), [vRL]"r"(vRL), [a]"r"(a) 110 : ); 111 } 112 return out; 113#else 114 if (left) { 115 return a + (int16_t)(inRL&0xFFFF) * (int16_t)(vRL&0xFFFF); 116 } else { 117 return a + (int16_t)(inRL>>16) * (int16_t)(vRL>>16); 118 } 119#endif 120} 121 122/** 123 * Similar to mul, but the 16-bit terms are extracted from a 32-bit interleaved stereo pair. 124 */ 125static inline 126int32_t mulRL(int left, uint32_t inRL, uint32_t vRL) 127{ 128#if defined(__arm__) && !defined(__thumb__) 129 int32_t out; 130 if (left) { 131 asm( "smulbb %[out], %[inRL], %[vRL] \n" 132 : [out]"=r"(out) 133 : [inRL]"%r"(inRL), [vRL]"r"(vRL) 134 : ); 135 } else { 136 asm( "smultt %[out], %[inRL], %[vRL] \n" 137 : [out]"=r"(out) 138 : [inRL]"%r"(inRL), [vRL]"r"(vRL) 139 : ); 140 } 141 return out; 142#else 143 if (left) { 144 return (int16_t)(inRL&0xFFFF) * (int16_t)(vRL&0xFFFF); 145 } else { 146 return (int16_t)(inRL>>16) * (int16_t)(vRL>>16); 147 } 148#endif 149} 150 151__END_DECLS 152 153#endif // ANDROID_AUDIO_PRIMITIVES_H 154