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 477a0bacaf9634d6bf0abbea9608fb15e94a675358Glenn Kasten/* Downmix pairs of interleaved stereo input 16-bit samples to mono output 16-bit samples. 487a0bacaf9634d6bf0abbea9608fb15e94a675358Glenn Kasten * Parameters: 497a0bacaf9634d6bf0abbea9608fb15e94a675358Glenn Kasten * dst Destination buffer 507a0bacaf9634d6bf0abbea9608fb15e94a675358Glenn Kasten * src Source buffer 517a0bacaf9634d6bf0abbea9608fb15e94a675358Glenn Kasten * count Number of stereo frames to downmix 527a0bacaf9634d6bf0abbea9608fb15e94a675358Glenn Kasten * The destination and source buffers must be completely separate (non-overlapping). 537a0bacaf9634d6bf0abbea9608fb15e94a675358Glenn Kasten * The current implementation truncates the sum rather than dither, but this may change. 547a0bacaf9634d6bf0abbea9608fb15e94a675358Glenn Kasten */ 557a0bacaf9634d6bf0abbea9608fb15e94a675358Glenn Kastenvoid downmix_to_mono_i16_from_stereo_i16(int16_t *dst, const int16_t *src, size_t count); 567a0bacaf9634d6bf0abbea9608fb15e94a675358Glenn Kasten 577a0bacaf9634d6bf0abbea9608fb15e94a675358Glenn Kasten/* Upmix mono input 16-bit samples to pairs of interleaved stereo output 16-bit samples by 587a0bacaf9634d6bf0abbea9608fb15e94a675358Glenn Kasten * duplicating. 597a0bacaf9634d6bf0abbea9608fb15e94a675358Glenn Kasten * Parameters: 607a0bacaf9634d6bf0abbea9608fb15e94a675358Glenn Kasten * dst Destination buffer 617a0bacaf9634d6bf0abbea9608fb15e94a675358Glenn Kasten * src Source buffer 627a0bacaf9634d6bf0abbea9608fb15e94a675358Glenn Kasten * count Number of mono samples to upmix 637a0bacaf9634d6bf0abbea9608fb15e94a675358Glenn Kasten * The destination and source buffers must be completely separate (non-overlapping). 647a0bacaf9634d6bf0abbea9608fb15e94a675358Glenn Kasten */ 657a0bacaf9634d6bf0abbea9608fb15e94a675358Glenn Kastenvoid upmix_to_stereo_i16_from_mono_i16(int16_t *dst, const int16_t *src, size_t count); 667a0bacaf9634d6bf0abbea9608fb15e94a675358Glenn Kasten 67632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten/** 68632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten * Clamp (aka hard limit or clip) a signed 32-bit sample to 16-bit range. 69632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten */ 70632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kastenstatic inline int16_t clamp16(int32_t sample) 71632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten{ 72632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten if ((sample>>15) ^ (sample>>31)) 73632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten sample = 0x7FFF ^ (sample>>31); 74632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten return sample; 75632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten} 76632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten 77632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten/** 78632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten * Multiply-accumulate 16-bit terms with 32-bit result: return a + in*v. 79632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten */ 80632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kastenstatic inline 81632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kastenint32_t mulAdd(int16_t in, int16_t v, int32_t a) 82632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten{ 83632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten#if defined(__arm__) && !defined(__thumb__) 84632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten int32_t out; 85632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten asm( "smlabb %[out], %[in], %[v], %[a] \n" 86632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten : [out]"=r"(out) 87632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten : [in]"%r"(in), [v]"r"(v), [a]"r"(a) 88632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten : ); 89632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten return out; 90632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten#else 91632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten return a + in * (int32_t)v; 92632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten#endif 93632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten} 94632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten 95632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten/** 96632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten * Multiply 16-bit terms with 32-bit result: return in*v. 97632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten */ 98632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kastenstatic inline 99632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kastenint32_t mul(int16_t in, int16_t v) 100632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten{ 101632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten#if defined(__arm__) && !defined(__thumb__) 102632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten int32_t out; 103632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten asm( "smulbb %[out], %[in], %[v] \n" 104632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten : [out]"=r"(out) 105632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten : [in]"%r"(in), [v]"r"(v) 106632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten : ); 107632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten return out; 108632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten#else 109632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten return in * (int32_t)v; 110632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten#endif 111632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten} 112632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten 113632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten/** 114632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten * Similar to mulAdd, but the 16-bit terms are extracted from a 32-bit interleaved stereo pair. 115632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten */ 116632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kastenstatic inline 117632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kastenint32_t mulAddRL(int left, uint32_t inRL, uint32_t vRL, int32_t a) 118632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten{ 119632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten#if defined(__arm__) && !defined(__thumb__) 120632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten int32_t out; 121632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten if (left) { 122632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten asm( "smlabb %[out], %[inRL], %[vRL], %[a] \n" 123632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten : [out]"=r"(out) 124632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten : [inRL]"%r"(inRL), [vRL]"r"(vRL), [a]"r"(a) 125632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten : ); 126632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten } else { 127632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten asm( "smlatt %[out], %[inRL], %[vRL], %[a] \n" 128632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten : [out]"=r"(out) 129632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten : [inRL]"%r"(inRL), [vRL]"r"(vRL), [a]"r"(a) 130632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten : ); 131632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten } 132632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten return out; 133632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten#else 134632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten if (left) { 135632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten return a + (int16_t)(inRL&0xFFFF) * (int16_t)(vRL&0xFFFF); 136632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten } else { 137632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten return a + (int16_t)(inRL>>16) * (int16_t)(vRL>>16); 138632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten } 139632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten#endif 140632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten} 141632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten 142632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten/** 143632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten * Similar to mul, but the 16-bit terms are extracted from a 32-bit interleaved stereo pair. 144632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten */ 145632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kastenstatic inline 146632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kastenint32_t mulRL(int left, uint32_t inRL, uint32_t vRL) 147632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten{ 148632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten#if defined(__arm__) && !defined(__thumb__) 149632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten int32_t out; 150632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten if (left) { 151632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten asm( "smulbb %[out], %[inRL], %[vRL] \n" 152632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten : [out]"=r"(out) 153632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten : [inRL]"%r"(inRL), [vRL]"r"(vRL) 154632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten : ); 155632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten } else { 156632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten asm( "smultt %[out], %[inRL], %[vRL] \n" 157632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten : [out]"=r"(out) 158632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten : [inRL]"%r"(inRL), [vRL]"r"(vRL) 159632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten : ); 160632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten } 161632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten return out; 162632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten#else 163632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten if (left) { 164632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten return (int16_t)(inRL&0xFFFF) * (int16_t)(vRL&0xFFFF); 165632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten } else { 166632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten return (int16_t)(inRL>>16) * (int16_t)(vRL>>16); 167632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten } 168632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten#endif 169632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten} 170632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten 171632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten__END_DECLS 172632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten 173632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten#endif // ANDROID_AUDIO_PRIMITIVES_H 174