primitives.h revision ddb2e930bef3d1be1627c613fb8f3df848166ac7
1632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten/* 2632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten * Copyright (C) 2011 The Android Open Source Project 3632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten * 4632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten * Licensed under the Apache License, Version 2.0 (the "License"); 5632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten * you may not use this file except in compliance with the License. 6632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten * You may obtain a copy of the License at 7632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten * 8632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten * http://www.apache.org/licenses/LICENSE-2.0 9632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten * 10632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten * Unless required by applicable law or agreed to in writing, software 11632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten * distributed under the License is distributed on an "AS IS" BASIS, 12632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten * See the License for the specific language governing permissions and 14632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten * limitations under the License. 15632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten */ 16632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten 17632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten#ifndef ANDROID_AUDIO_PRIMITIVES_H 18632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten#define ANDROID_AUDIO_PRIMITIVES_H 19632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten 20632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten#include <stdint.h> 21632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten#include <sys/cdefs.h> 22632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten 23632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten__BEGIN_DECLS 24632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten 25632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten/** 26632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten * Dither and clamp pairs of 32-bit input samples (sums) to 16-bit output samples (out). 27632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten * Each 32-bit input sample is a signed fixed-point Q19.12. 28632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten * The .12 fraction is dithered, and the integer portion is then clamped to Q15. 29632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten * For interleaved stereo, c is the number of sample pairs, 30632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten * and out is an array of interleaved pairs of 16-bit samples per channel. 31632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten * For mono, c is the number of samples / 2, and out is an array of 16-bit samples. 32632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten * The name "dither" is a misnomer; the current implementation does not actually dither 33632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten * but uses truncation. This may change. 34632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten */ 35632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kastenvoid ditherAndClamp(int32_t* out, const int32_t *sums, size_t c); 36632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten 37ddb2e930bef3d1be1627c613fb8f3df848166ac7Glenn Kasten/* Expand and copy samples from unsigned 8-bit offset by 0x80 to signed 16-bit. 38ddb2e930bef3d1be1627c613fb8f3df848166ac7Glenn Kasten * Parameters: 39ddb2e930bef3d1be1627c613fb8f3df848166ac7Glenn Kasten * dst Destination buffer 40ddb2e930bef3d1be1627c613fb8f3df848166ac7Glenn Kasten * src Source buffer 41ddb2e930bef3d1be1627c613fb8f3df848166ac7Glenn Kasten * count Number of samples to copy 42ddb2e930bef3d1be1627c613fb8f3df848166ac7Glenn Kasten * The destination and source buffers must either be completely separate (non-overlapping), or 43ddb2e930bef3d1be1627c613fb8f3df848166ac7Glenn Kasten * they must both start at the same address. Partially overlapping buffers are not supported. 44ddb2e930bef3d1be1627c613fb8f3df848166ac7Glenn Kasten */ 45ddb2e930bef3d1be1627c613fb8f3df848166ac7Glenn Kastenvoid memcpy_to_i16_from_u8(int16_t *dst, const uint8_t *src, size_t count); 46ddb2e930bef3d1be1627c613fb8f3df848166ac7Glenn Kasten 47632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten/** 48632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten * Clamp (aka hard limit or clip) a signed 32-bit sample to 16-bit range. 49632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten */ 50632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kastenstatic inline int16_t clamp16(int32_t sample) 51632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten{ 52632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten if ((sample>>15) ^ (sample>>31)) 53632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten sample = 0x7FFF ^ (sample>>31); 54632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten return sample; 55632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten} 56632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten 57632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten/** 58632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten * Multiply-accumulate 16-bit terms with 32-bit result: return a + in*v. 59632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten */ 60632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kastenstatic inline 61632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kastenint32_t mulAdd(int16_t in, int16_t v, int32_t a) 62632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten{ 63632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten#if defined(__arm__) && !defined(__thumb__) 64632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten int32_t out; 65632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten asm( "smlabb %[out], %[in], %[v], %[a] \n" 66632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten : [out]"=r"(out) 67632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten : [in]"%r"(in), [v]"r"(v), [a]"r"(a) 68632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten : ); 69632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten return out; 70632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten#else 71632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten return a + in * (int32_t)v; 72632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten#endif 73632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten} 74632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten 75632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten/** 76632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten * Multiply 16-bit terms with 32-bit result: return in*v. 77632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten */ 78632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kastenstatic inline 79632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kastenint32_t mul(int16_t in, int16_t v) 80632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten{ 81632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten#if defined(__arm__) && !defined(__thumb__) 82632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten int32_t out; 83632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten asm( "smulbb %[out], %[in], %[v] \n" 84632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten : [out]"=r"(out) 85632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten : [in]"%r"(in), [v]"r"(v) 86632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten : ); 87632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten return out; 88632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten#else 89632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten return in * (int32_t)v; 90632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten#endif 91632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten} 92632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten 93632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten/** 94632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten * Similar to mulAdd, but the 16-bit terms are extracted from a 32-bit interleaved stereo pair. 95632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten */ 96632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kastenstatic inline 97632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kastenint32_t mulAddRL(int left, uint32_t inRL, uint32_t vRL, int32_t a) 98632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten{ 99632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten#if defined(__arm__) && !defined(__thumb__) 100632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten int32_t out; 101632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten if (left) { 102632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten asm( "smlabb %[out], %[inRL], %[vRL], %[a] \n" 103632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten : [out]"=r"(out) 104632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten : [inRL]"%r"(inRL), [vRL]"r"(vRL), [a]"r"(a) 105632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten : ); 106632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten } else { 107632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten asm( "smlatt %[out], %[inRL], %[vRL], %[a] \n" 108632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten : [out]"=r"(out) 109632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten : [inRL]"%r"(inRL), [vRL]"r"(vRL), [a]"r"(a) 110632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten : ); 111632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten } 112632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten return out; 113632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten#else 114632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten if (left) { 115632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten return a + (int16_t)(inRL&0xFFFF) * (int16_t)(vRL&0xFFFF); 116632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten } else { 117632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten return a + (int16_t)(inRL>>16) * (int16_t)(vRL>>16); 118632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten } 119632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten#endif 120632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten} 121632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten 122632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten/** 123632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten * Similar to mul, but the 16-bit terms are extracted from a 32-bit interleaved stereo pair. 124632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten */ 125632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kastenstatic inline 126632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kastenint32_t mulRL(int left, uint32_t inRL, uint32_t vRL) 127632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten{ 128632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten#if defined(__arm__) && !defined(__thumb__) 129632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten int32_t out; 130632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten if (left) { 131632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten asm( "smulbb %[out], %[inRL], %[vRL] \n" 132632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten : [out]"=r"(out) 133632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten : [inRL]"%r"(inRL), [vRL]"r"(vRL) 134632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten : ); 135632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten } else { 136632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten asm( "smultt %[out], %[inRL], %[vRL] \n" 137632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten : [out]"=r"(out) 138632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten : [inRL]"%r"(inRL), [vRL]"r"(vRL) 139632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten : ); 140632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten } 141632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten return out; 142632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten#else 143632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten if (left) { 144632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten return (int16_t)(inRL&0xFFFF) * (int16_t)(vRL&0xFFFF); 145632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten } else { 146632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten return (int16_t)(inRL>>16) * (int16_t)(vRL>>16); 147632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten } 148632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten#endif 149632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten} 150632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten 151632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten__END_DECLS 152632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten 153632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten#endif // ANDROID_AUDIO_PRIMITIVES_H 154