/*- * Copyright (c) 2008 Ariff Abdullah * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ static __inline int32_t vseg(int32_t v, int32_t o) { int32_t r; r = o; v >>= 7; v >>= o; if (v & 0xf0) { v >>= 4; r += 4; } if (v & 0x0c) { v >>= 2; r += 2; } if (v & 0x02) r++; return (r); } static intpcm_t alaw_to_intpcm(uint8_t v) { int32_t s, t; v ^= 0x55; t = v & 0x7f; if (t < 0x10) t = (t << 4) + 8; else { s = (t >> 4) & 0x07; t = ((t & 0x0f) << 4) + 0x108; t <<= s - 1; } return (((v & 0x80) ? t : -t) << 16); } static uint8_t intpcm_to_alaw(intpcm_t v) { int32_t m, s; uint8_t a; v >>= 16; if (v >= 0) m = 0xd5; else { m = 0x55; v = -v; if (v > 0x7fff) v = 0x7fff; } if (v < 0x100) a = v >> 4; else { s = vseg(v, 1); a = (s << 4) | ((v >> (s + 3)) & 0x0f); } return (a ^ m); } static intpcm_t ulaw_to_intpcm(uint8_t v) { int32_t t; v = ~v; t = ((v & 0x0f) << 3) + 0x84; t <<= (v & 0x70) >> 4; return (((v & 0x80) ? (0x80 - t) : (t - 0x84)) << 16); } static uint8_t intpcm_to_ulaw(intpcm_t v) { int32_t m, s; uint8_t u; v >>= 16; if (v < 0) { v = 0x84 - v; m = 0x7f; } else { v += 0x84; m = 0xff; } if (v > 0x7fff) v = 0x7fff; s = vseg(v, 0); u = (s << 4) | ((v >> (s + 3)) & 0x0f); return (u ^ m); }