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/* Downmix pairs of interleaved stereo input 16-bit samples to mono output 16-bit samples. 48 * Parameters: 49 * dst Destination buffer 50 * src Source buffer 51 * count Number of stereo frames to downmix 52 * The destination and source buffers must be completely separate (non-overlapping). 53 * The current implementation truncates the sum rather than dither, but this may change. 54 */ 55void downmix_to_mono_i16_from_stereo_i16(int16_t *dst, const int16_t *src, size_t count); 56 57/* Upmix mono input 16-bit samples to pairs of interleaved stereo output 16-bit samples by 58 * duplicating. 59 * Parameters: 60 * dst Destination buffer 61 * src Source buffer 62 * count Number of mono samples to upmix 63 * The destination and source buffers must be completely separate (non-overlapping). 64 */ 65void upmix_to_stereo_i16_from_mono_i16(int16_t *dst, const int16_t *src, size_t count); 66 67/** 68 * Clamp (aka hard limit or clip) a signed 32-bit sample to 16-bit range. 69 */ 70static inline int16_t clamp16(int32_t sample) 71{ 72 if ((sample>>15) ^ (sample>>31)) 73 sample = 0x7FFF ^ (sample>>31); 74 return sample; 75} 76 77/** 78 * Multiply-accumulate 16-bit terms with 32-bit result: return a + in*v. 79 */ 80static inline 81int32_t mulAdd(int16_t in, int16_t v, int32_t a) 82{ 83#if defined(__arm__) && !defined(__thumb__) 84 int32_t out; 85 asm( "smlabb %[out], %[in], %[v], %[a] \n" 86 : [out]"=r"(out) 87 : [in]"%r"(in), [v]"r"(v), [a]"r"(a) 88 : ); 89 return out; 90#else 91 return a + in * (int32_t)v; 92#endif 93} 94 95/** 96 * Multiply 16-bit terms with 32-bit result: return in*v. 97 */ 98static inline 99int32_t mul(int16_t in, int16_t v) 100{ 101#if defined(__arm__) && !defined(__thumb__) 102 int32_t out; 103 asm( "smulbb %[out], %[in], %[v] \n" 104 : [out]"=r"(out) 105 : [in]"%r"(in), [v]"r"(v) 106 : ); 107 return out; 108#else 109 return in * (int32_t)v; 110#endif 111} 112 113/** 114 * Similar to mulAdd, but the 16-bit terms are extracted from a 32-bit interleaved stereo pair. 115 */ 116static inline 117int32_t mulAddRL(int left, uint32_t inRL, uint32_t vRL, int32_t a) 118{ 119#if defined(__arm__) && !defined(__thumb__) 120 int32_t out; 121 if (left) { 122 asm( "smlabb %[out], %[inRL], %[vRL], %[a] \n" 123 : [out]"=r"(out) 124 : [inRL]"%r"(inRL), [vRL]"r"(vRL), [a]"r"(a) 125 : ); 126 } else { 127 asm( "smlatt %[out], %[inRL], %[vRL], %[a] \n" 128 : [out]"=r"(out) 129 : [inRL]"%r"(inRL), [vRL]"r"(vRL), [a]"r"(a) 130 : ); 131 } 132 return out; 133#else 134 if (left) { 135 return a + (int16_t)(inRL&0xFFFF) * (int16_t)(vRL&0xFFFF); 136 } else { 137 return a + (int16_t)(inRL>>16) * (int16_t)(vRL>>16); 138 } 139#endif 140} 141 142/** 143 * Similar to mul, but the 16-bit terms are extracted from a 32-bit interleaved stereo pair. 144 */ 145static inline 146int32_t mulRL(int left, uint32_t inRL, uint32_t vRL) 147{ 148#if defined(__arm__) && !defined(__thumb__) 149 int32_t out; 150 if (left) { 151 asm( "smulbb %[out], %[inRL], %[vRL] \n" 152 : [out]"=r"(out) 153 : [inRL]"%r"(inRL), [vRL]"r"(vRL) 154 : ); 155 } else { 156 asm( "smultt %[out], %[inRL], %[vRL] \n" 157 : [out]"=r"(out) 158 : [inRL]"%r"(inRL), [vRL]"r"(vRL) 159 : ); 160 } 161 return out; 162#else 163 if (left) { 164 return (int16_t)(inRL&0xFFFF) * (int16_t)(vRL&0xFFFF); 165 } else { 166 return (int16_t)(inRL>>16) * (int16_t)(vRL>>16); 167 } 168#endif 169} 170 171__END_DECLS 172 173#endif // ANDROID_AUDIO_PRIMITIVES_H 174