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>
21e252f7e4bcb506da9f0f845ee0ca576d13d6a3f4Glenn Kasten#include <stdlib.h>
22632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten#include <sys/cdefs.h>
23632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten
24632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten__BEGIN_DECLS
25632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten
26632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten/**
27632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten * Dither and clamp pairs of 32-bit input samples (sums) to 16-bit output samples (out).
28632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten * Each 32-bit input sample is a signed fixed-point Q19.12.
29632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten * The .12 fraction is dithered, and the integer portion is then clamped to Q15.
30632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten * For interleaved stereo, c is the number of sample pairs,
31632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten * and out is an array of interleaved pairs of 16-bit samples per channel.
32632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten * For mono, c is the number of samples / 2, and out is an array of 16-bit samples.
33632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten * The name "dither" is a misnomer; the current implementation does not actually dither
34632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten * but uses truncation.  This may change.
35632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten */
36632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kastenvoid ditherAndClamp(int32_t* out, const int32_t *sums, size_t c);
37632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten
38ddb2e930bef3d1be1627c613fb8f3df848166ac7Glenn Kasten/* Expand and copy samples from unsigned 8-bit offset by 0x80 to signed 16-bit.
39ddb2e930bef3d1be1627c613fb8f3df848166ac7Glenn Kasten * Parameters:
40ddb2e930bef3d1be1627c613fb8f3df848166ac7Glenn Kasten *  dst     Destination buffer
41ddb2e930bef3d1be1627c613fb8f3df848166ac7Glenn Kasten *  src     Source buffer
42ddb2e930bef3d1be1627c613fb8f3df848166ac7Glenn Kasten *  count   Number of samples to copy
43ddb2e930bef3d1be1627c613fb8f3df848166ac7Glenn Kasten * The destination and source buffers must either be completely separate (non-overlapping), or
44ddb2e930bef3d1be1627c613fb8f3df848166ac7Glenn Kasten * they must both start at the same address.  Partially overlapping buffers are not supported.
45ddb2e930bef3d1be1627c613fb8f3df848166ac7Glenn Kasten */
46ddb2e930bef3d1be1627c613fb8f3df848166ac7Glenn Kastenvoid memcpy_to_i16_from_u8(int16_t *dst, const uint8_t *src, size_t count);
47ddb2e930bef3d1be1627c613fb8f3df848166ac7Glenn Kasten
4878da2acdd7aa14fe9920d1ad3074e445332de27dGlenn Kasten/* Shrink and copy samples from signed 16-bit to unsigned 8-bit offset by 0x80.
4978da2acdd7aa14fe9920d1ad3074e445332de27dGlenn Kasten * Parameters:
5078da2acdd7aa14fe9920d1ad3074e445332de27dGlenn Kasten *  dst     Destination buffer
5178da2acdd7aa14fe9920d1ad3074e445332de27dGlenn Kasten *  src     Source buffer
5278da2acdd7aa14fe9920d1ad3074e445332de27dGlenn Kasten *  count   Number of samples to copy
5378da2acdd7aa14fe9920d1ad3074e445332de27dGlenn Kasten * The destination and source buffers must either be completely separate (non-overlapping), or
5478da2acdd7aa14fe9920d1ad3074e445332de27dGlenn Kasten * they must both start at the same address.  Partially overlapping buffers are not supported.
5578da2acdd7aa14fe9920d1ad3074e445332de27dGlenn Kasten * The conversion is done by truncation, without dithering, so it loses resolution.
5678da2acdd7aa14fe9920d1ad3074e445332de27dGlenn Kasten */
5778da2acdd7aa14fe9920d1ad3074e445332de27dGlenn Kastenvoid memcpy_to_u8_from_i16(uint8_t *dst, const int16_t *src, size_t count);
5878da2acdd7aa14fe9920d1ad3074e445332de27dGlenn Kasten
597a0bacaf9634d6bf0abbea9608fb15e94a675358Glenn Kasten/* Downmix pairs of interleaved stereo input 16-bit samples to mono output 16-bit samples.
607a0bacaf9634d6bf0abbea9608fb15e94a675358Glenn Kasten * Parameters:
617a0bacaf9634d6bf0abbea9608fb15e94a675358Glenn Kasten *  dst     Destination buffer
627a0bacaf9634d6bf0abbea9608fb15e94a675358Glenn Kasten *  src     Source buffer
637a0bacaf9634d6bf0abbea9608fb15e94a675358Glenn Kasten *  count   Number of stereo frames to downmix
647a0bacaf9634d6bf0abbea9608fb15e94a675358Glenn Kasten * The destination and source buffers must be completely separate (non-overlapping).
657a0bacaf9634d6bf0abbea9608fb15e94a675358Glenn Kasten * The current implementation truncates the sum rather than dither, but this may change.
667a0bacaf9634d6bf0abbea9608fb15e94a675358Glenn Kasten */
677a0bacaf9634d6bf0abbea9608fb15e94a675358Glenn Kastenvoid downmix_to_mono_i16_from_stereo_i16(int16_t *dst, const int16_t *src, size_t count);
687a0bacaf9634d6bf0abbea9608fb15e94a675358Glenn Kasten
697a0bacaf9634d6bf0abbea9608fb15e94a675358Glenn Kasten/* Upmix mono input 16-bit samples to pairs of interleaved stereo output 16-bit samples by
707a0bacaf9634d6bf0abbea9608fb15e94a675358Glenn Kasten * duplicating.
717a0bacaf9634d6bf0abbea9608fb15e94a675358Glenn Kasten * Parameters:
727a0bacaf9634d6bf0abbea9608fb15e94a675358Glenn Kasten *  dst     Destination buffer
737a0bacaf9634d6bf0abbea9608fb15e94a675358Glenn Kasten *  src     Source buffer
747a0bacaf9634d6bf0abbea9608fb15e94a675358Glenn Kasten *  count   Number of mono samples to upmix
757a0bacaf9634d6bf0abbea9608fb15e94a675358Glenn Kasten * The destination and source buffers must be completely separate (non-overlapping).
767a0bacaf9634d6bf0abbea9608fb15e94a675358Glenn Kasten */
777a0bacaf9634d6bf0abbea9608fb15e94a675358Glenn Kastenvoid upmix_to_stereo_i16_from_mono_i16(int16_t *dst, const int16_t *src, size_t count);
787a0bacaf9634d6bf0abbea9608fb15e94a675358Glenn Kasten
79632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten/**
80632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten * Clamp (aka hard limit or clip) a signed 32-bit sample to 16-bit range.
81632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten */
82632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kastenstatic inline int16_t clamp16(int32_t sample)
83632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten{
84632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten    if ((sample>>15) ^ (sample>>31))
85632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten        sample = 0x7FFF ^ (sample>>31);
86632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten    return sample;
87632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten}
88632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten
89632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten/**
90632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten * Multiply-accumulate 16-bit terms with 32-bit result: return a + in*v.
91632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten */
92632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kastenstatic inline
93632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kastenint32_t mulAdd(int16_t in, int16_t v, int32_t a)
94632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten{
95632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten#if defined(__arm__) && !defined(__thumb__)
96632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten    int32_t out;
97632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten    asm( "smlabb %[out], %[in], %[v], %[a] \n"
98632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten         : [out]"=r"(out)
99632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten         : [in]"%r"(in), [v]"r"(v), [a]"r"(a)
100632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten         : );
101632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten    return out;
102632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten#else
103632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten    return a + in * (int32_t)v;
104632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten#endif
105632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten}
106632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten
107632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten/**
108632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten * Multiply 16-bit terms with 32-bit result: return in*v.
109632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten */
110632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kastenstatic inline
111632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kastenint32_t mul(int16_t in, int16_t v)
112632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten{
113632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten#if defined(__arm__) && !defined(__thumb__)
114632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten    int32_t out;
115632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten    asm( "smulbb %[out], %[in], %[v] \n"
116632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten         : [out]"=r"(out)
117632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten         : [in]"%r"(in), [v]"r"(v)
118632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten         : );
119632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten    return out;
120632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten#else
121632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten    return in * (int32_t)v;
122632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten#endif
123632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten}
124632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten
125632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten/**
126632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten * Similar to mulAdd, but the 16-bit terms are extracted from a 32-bit interleaved stereo pair.
127632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten */
128632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kastenstatic inline
129632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kastenint32_t mulAddRL(int left, uint32_t inRL, uint32_t vRL, int32_t a)
130632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten{
131632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten#if defined(__arm__) && !defined(__thumb__)
132632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten    int32_t out;
133632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten    if (left) {
134632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten        asm( "smlabb %[out], %[inRL], %[vRL], %[a] \n"
135632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten             : [out]"=r"(out)
136632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten             : [inRL]"%r"(inRL), [vRL]"r"(vRL), [a]"r"(a)
137632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten             : );
138632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten    } else {
139632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten        asm( "smlatt %[out], %[inRL], %[vRL], %[a] \n"
140632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten             : [out]"=r"(out)
141632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten             : [inRL]"%r"(inRL), [vRL]"r"(vRL), [a]"r"(a)
142632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten             : );
143632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten    }
144632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten    return out;
145632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten#else
146632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten    if (left) {
147632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten        return a + (int16_t)(inRL&0xFFFF) * (int16_t)(vRL&0xFFFF);
148632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten    } else {
149632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten        return a + (int16_t)(inRL>>16) * (int16_t)(vRL>>16);
150632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten    }
151632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten#endif
152632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten}
153632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten
154632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten/**
155632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten * Similar to mul, but the 16-bit terms are extracted from a 32-bit interleaved stereo pair.
156632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten */
157632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kastenstatic inline
158632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kastenint32_t mulRL(int left, uint32_t inRL, uint32_t vRL)
159632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten{
160632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten#if defined(__arm__) && !defined(__thumb__)
161632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten    int32_t out;
162632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten    if (left) {
163632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten        asm( "smulbb %[out], %[inRL], %[vRL] \n"
164632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten             : [out]"=r"(out)
165632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten             : [inRL]"%r"(inRL), [vRL]"r"(vRL)
166632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten             : );
167632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten    } else {
168632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten        asm( "smultt %[out], %[inRL], %[vRL] \n"
169632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten             : [out]"=r"(out)
170632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten             : [inRL]"%r"(inRL), [vRL]"r"(vRL)
171632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten             : );
172632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten    }
173632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten    return out;
174632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten#else
175632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten    if (left) {
176632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten        return (int16_t)(inRL&0xFFFF) * (int16_t)(vRL&0xFFFF);
177632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten    } else {
178632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten        return (int16_t)(inRL>>16) * (int16_t)(vRL>>16);
179632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten    }
180632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten#endif
181632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten}
182632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten
183632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten__END_DECLS
184632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten
185632e0c016c9a518b36f09988b740b3bc1199c3e4Glenn Kasten#endif  // ANDROID_AUDIO_PRIMITIVES_H
186