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 <stdlib.h> 22#include <sys/cdefs.h> 23 24__BEGIN_DECLS 25 26/** 27 * Dither and clamp pairs of 32-bit input samples (sums) to 16-bit output samples (out). 28 * Each 32-bit input sample is a signed fixed-point Q19.12. 29 * The .12 fraction is dithered, and the integer portion is then clamped to Q15. 30 * For interleaved stereo, c is the number of sample pairs, 31 * and out is an array of interleaved pairs of 16-bit samples per channel. 32 * For mono, c is the number of samples / 2, and out is an array of 16-bit samples. 33 * The name "dither" is a misnomer; the current implementation does not actually dither 34 * but uses truncation. This may change. 35 * The out and sums buffers must either be completely separate (non-overlapping), or 36 * they must both start at the same address. Partially overlapping buffers are not supported. 37 */ 38void ditherAndClamp(int32_t* out, const int32_t *sums, size_t c); 39 40/* Expand and copy samples from unsigned 8-bit offset by 0x80 to signed 16-bit. 41 * Parameters: 42 * dst Destination buffer 43 * src Source buffer 44 * count Number of samples to copy 45 * The destination and source buffers must either be completely separate (non-overlapping), or 46 * they must both start at the same address. Partially overlapping buffers are not supported. 47 */ 48void memcpy_to_i16_from_u8(int16_t *dst, const uint8_t *src, size_t count); 49 50/* Shrink and copy samples from signed 16-bit to unsigned 8-bit offset by 0x80. 51 * Parameters: 52 * dst Destination buffer 53 * src Source buffer 54 * count Number of samples to copy 55 * The destination and source buffers must either be completely separate (non-overlapping), or 56 * they must both start at the same address. Partially overlapping buffers are not supported. 57 * The conversion is done by truncation, without dithering, so it loses resolution. 58 */ 59void memcpy_to_u8_from_i16(uint8_t *dst, const int16_t *src, size_t count); 60 61/* Shrink and copy samples from signed 32-bit fixed-point Q0.31 to signed 16-bit Q0.15. 62 * Parameters: 63 * dst Destination buffer 64 * src Source buffer 65 * count Number of samples to copy 66 * The destination and source buffers must either be completely separate (non-overlapping), or 67 * they must both start at the same address. Partially overlapping buffers are not supported. 68 * The conversion is done by truncation, without dithering, so it loses resolution. 69 */ 70void memcpy_to_i16_from_i32(int16_t *dst, const int32_t *src, size_t count); 71 72/* Shrink and copy samples from single-precision floating-point to signed 16-bit. 73 * Each float should be in the range -1.0 to 1.0. Values outside that range are clamped. 74 * Parameters: 75 * dst Destination buffer 76 * src Source buffer 77 * count Number of samples to copy 78 * The destination and source buffers must either be completely separate (non-overlapping), or 79 * they must both start at the same address. Partially overlapping buffers are not supported. 80 * The conversion is done by truncation, without dithering, so it loses resolution. 81 */ 82void memcpy_to_i16_from_float(int16_t *dst, const float *src, size_t count); 83 84/* Downmix pairs of interleaved stereo input 16-bit samples to mono output 16-bit samples. 85 * Parameters: 86 * dst Destination buffer 87 * src Source buffer 88 * count Number of stereo frames to downmix 89 * The destination and source buffers must be completely separate (non-overlapping). 90 * The current implementation truncates the sum rather than dither, but this may change. 91 */ 92void downmix_to_mono_i16_from_stereo_i16(int16_t *dst, const int16_t *src, size_t count); 93 94/* Upmix mono input 16-bit samples to pairs of interleaved stereo output 16-bit samples by 95 * duplicating. 96 * Parameters: 97 * dst Destination buffer 98 * src Source buffer 99 * count Number of mono samples to upmix 100 * The destination and source buffers must be completely separate (non-overlapping). 101 */ 102void upmix_to_stereo_i16_from_mono_i16(int16_t *dst, const int16_t *src, size_t count); 103 104/** 105 * Clamp (aka hard limit or clip) a signed 32-bit sample to 16-bit range. 106 */ 107static inline int16_t clamp16(int32_t sample) 108{ 109 if ((sample>>15) ^ (sample>>31)) 110 sample = 0x7FFF ^ (sample>>31); 111 return sample; 112} 113 114/** 115 * Multiply-accumulate 16-bit terms with 32-bit result: return a + in*v. 116 */ 117static inline 118int32_t mulAdd(int16_t in, int16_t v, int32_t a) 119{ 120#if defined(__arm__) && !defined(__thumb__) 121 int32_t out; 122 asm( "smlabb %[out], %[in], %[v], %[a] \n" 123 : [out]"=r"(out) 124 : [in]"%r"(in), [v]"r"(v), [a]"r"(a) 125 : ); 126 return out; 127#else 128 return a + in * (int32_t)v; 129#endif 130} 131 132/** 133 * Multiply 16-bit terms with 32-bit result: return in*v. 134 */ 135static inline 136int32_t mul(int16_t in, int16_t v) 137{ 138#if defined(__arm__) && !defined(__thumb__) 139 int32_t out; 140 asm( "smulbb %[out], %[in], %[v] \n" 141 : [out]"=r"(out) 142 : [in]"%r"(in), [v]"r"(v) 143 : ); 144 return out; 145#else 146 return in * (int32_t)v; 147#endif 148} 149 150/** 151 * Similar to mulAdd, but the 16-bit terms are extracted from a 32-bit interleaved stereo pair. 152 */ 153static inline 154int32_t mulAddRL(int left, uint32_t inRL, uint32_t vRL, int32_t a) 155{ 156#if defined(__arm__) && !defined(__thumb__) 157 int32_t out; 158 if (left) { 159 asm( "smlabb %[out], %[inRL], %[vRL], %[a] \n" 160 : [out]"=r"(out) 161 : [inRL]"%r"(inRL), [vRL]"r"(vRL), [a]"r"(a) 162 : ); 163 } else { 164 asm( "smlatt %[out], %[inRL], %[vRL], %[a] \n" 165 : [out]"=r"(out) 166 : [inRL]"%r"(inRL), [vRL]"r"(vRL), [a]"r"(a) 167 : ); 168 } 169 return out; 170#else 171 if (left) { 172 return a + (int16_t)(inRL&0xFFFF) * (int16_t)(vRL&0xFFFF); 173 } else { 174 return a + (int16_t)(inRL>>16) * (int16_t)(vRL>>16); 175 } 176#endif 177} 178 179/** 180 * Similar to mul, but the 16-bit terms are extracted from a 32-bit interleaved stereo pair. 181 */ 182static inline 183int32_t mulRL(int left, uint32_t inRL, uint32_t vRL) 184{ 185#if defined(__arm__) && !defined(__thumb__) 186 int32_t out; 187 if (left) { 188 asm( "smulbb %[out], %[inRL], %[vRL] \n" 189 : [out]"=r"(out) 190 : [inRL]"%r"(inRL), [vRL]"r"(vRL) 191 : ); 192 } else { 193 asm( "smultt %[out], %[inRL], %[vRL] \n" 194 : [out]"=r"(out) 195 : [inRL]"%r"(inRL), [vRL]"r"(vRL) 196 : ); 197 } 198 return out; 199#else 200 if (left) { 201 return (int16_t)(inRL&0xFFFF) * (int16_t)(vRL&0xFFFF); 202 } else { 203 return (int16_t)(inRL>>16) * (int16_t)(vRL>>16); 204 } 205#endif 206} 207 208__END_DECLS 209 210#endif // ANDROID_AUDIO_PRIMITIVES_H 211