//roarfloat.c: /* * Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2010-2011 * * This file is part of libroar a part of RoarAudio, * a cross-platform sound system for both, home and professional use. * See README for details. * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 * as published by the Free Software Foundation. * * libroar is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this software; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * * NOTE for everyone want's to change something and send patches: * read README and HACKING! There a addition information on * the license of this document you need to read before you send * any patches. * * NOTE for uses of non-GPL (LGPL,...) software using libesd, libartsc * or libpulse*: * The libs libroaresd, libroararts and libroarpulse link this lib * and are therefore GPL. Because of this it may be illigal to use * them with any software that uses libesd, libartsc or libpulse*. */ #include "libroar.h" #ifdef ROAR_HAVE_LIBM #include #endif union c4f { unsigned char c[4]; roarfloat32 f; }; roarfloat32 roar_ufloat32_build(const uint16_t mul, const uint16_t scale) { union c4f ret; ROAR_DBG("roar_ufloat32_build(mul=%u, scale=%u) = ?", (unsigned int)mul, (unsigned int)scale); ret.c[0] = (scale & 0xFF00) >> 8; ret.c[1] = (scale & 0x00FF) >> 0; ret.c[2] = (mul & 0xFF00) >> 8; ret.c[3] = (mul & 0x00FF) >> 0; return ret.f; } uint16_t roar_ufloat32_scale(const roarfloat32 f) { const union c4f p = {.f = f}; ROAR_DBG("roar_ufloat32_scale(f=?): p.c[] = {%u, %u, %u, %u}", (unsigned int)p.c[0], (unsigned int)p.c[1], (unsigned int)p.c[2], (unsigned int)p.c[3]); return (p.c[0] << 8) | p.c[1]; } uint16_t roar_ufloat32_mul(const roarfloat32 f) { const union c4f p = {.f = f}; return (p.c[2] << 8) | p.c[3]; } roarfloat32 roar_ufloat32_from_float(const float f) { uint16_t scale; if ( f < 0 ) return ROAR_UFLOAT32_NNAN; if ( f == 0 ) return ROAR_UFLOAT32_ZERO; if ( f > ROAR_UFLOAT32_MAX ) return ROAR_UFLOAT32_PINF; if ( f <= 1 ) { scale = ROAR_UFLOAT32_MAX; } else { scale = (float)ROAR_UFLOAT32_MAX/f; } ROAR_DBG("roar_ufloat32_from_float(f=%f): scale=%u", f, (unsigned int)scale); return roar_ufloat32_build(f*(float)scale, scale); } float roar_ufloat32_to_float (const roarfloat32 f) { float mul = roar_ufloat32_mul(f); float scale = roar_ufloat32_scale(f); ROAR_DBG("roar_ufloat32_to_float(f=?): mul=%f, scale=%f", mul, scale); if ( roar_float32_iszero(f) ) return 0; #ifdef INFINITY if ( roar_float32_isinf(f) ) return INFINITY; #endif #ifdef NAN if ( roar_float32_isnan(f) ) return NAN; #endif return mul/scale; } int roar_float32_iszero(const roarfloat32 f) { const union c4f p = {.f = f}; return p.c[2] == 0 && p.c[3] == 0; } int roar_float32_isinf(const roarfloat32 f) { const union c4f p = {.f = f}; if ( p.c[0] != 0 || p.c[1] != 0 ) return 0; if ( p.c[2] == 0x00 && p.c[3] == 0x01 ) { return 1; } else if ( p.c[2] == 0xFF && p.c[3] == 0xFF ) { return -1; } else { return 0; } } int roar_float32_isnan(const roarfloat32 f) { const union c4f p = {.f = f}; if ( p.c[0] != 0 || p.c[1] != 0 ) return 0; if ( p.c[2] == 0x7F && p.c[3] == 0xFF ) { return 1; } else if ( p.c[2] == 0x80 && p.c[3] == 0x00 ) { return -1; } else { return 0; } } //ll